mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
jobspec: update gateway.ingress.service Consul API fields (#20176)
Add support for further configuring `gateway.ingress.service` blocks to bring this block up-to-date with currently available Consul API fields (except for namespace and admin partition, which will need be handled under a different PR). These fields are sent to Consul as part of the job endpoint submission hook for Connect gateways. Co-authored-by: Horacio Monsalvo <horacio.monsalvo@southworks.com>
This commit is contained in:
3
.changelog/16753.txt
Normal file
3
.changelog/16753.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:improvement
|
||||||
|
consul/connect: Added support for TLS configuration, headers configuration, and request limit configuration to ingress service block
|
||||||
|
```
|
||||||
161
api/consul.go
161
api/consul.go
@@ -4,6 +4,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
@@ -400,12 +401,52 @@ func (p *ConsulGatewayProxy) Copy() *ConsulGatewayProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConsulGatewayTLSConfig is used to configure TLS for a gateway.
|
// ConsulGatewayTLSSDSConfig is used to configure the gateway's TLS listener to
|
||||||
|
// load certificates from an external Secret Discovery Service (SDS)
|
||||||
|
type ConsulGatewayTLSSDSConfig struct {
|
||||||
|
// ClusterName specifies the name of the SDS cluster where Consul should
|
||||||
|
// retrieve certificates.
|
||||||
|
ClusterName string `hcl:"cluster_name,optional" mapstructure:"cluster_name"`
|
||||||
|
|
||||||
|
// CertResource specifies an SDS resource name
|
||||||
|
CertResource string `hcl:"cert_resource,optional" mapstructure:"cert_resource"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConsulGatewayTLSSDSConfig) Copy() *ConsulGatewayTLSSDSConfig {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ConsulGatewayTLSSDSConfig{
|
||||||
|
ClusterName: c.ClusterName,
|
||||||
|
CertResource: c.CertResource,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsulGatewayTLSConfig is used to configure TLS for a gateway. Both
|
||||||
|
// ConsulIngressConfigEntry and ConsulIngressService use this struct. For more
|
||||||
|
// details, consult the Consul documentation:
|
||||||
|
// https://developer.hashicorp.com/consul/docs/connect/config-entries/ingress-gateway#listeners-services-tls
|
||||||
type ConsulGatewayTLSConfig struct {
|
type ConsulGatewayTLSConfig struct {
|
||||||
Enabled bool `hcl:"enabled,optional"`
|
|
||||||
TLSMinVersion string `hcl:"tls_min_version,optional" mapstructure:"tls_min_version"`
|
// Enabled indicates whether TLS is enabled for the configuration entry
|
||||||
TLSMaxVersion string `hcl:"tls_max_version,optional" mapstructure:"tls_max_version"`
|
Enabled bool `hcl:"enabled,optional"`
|
||||||
CipherSuites []string `hcl:"cipher_suites,optional" mapstructure:"cipher_suites"`
|
|
||||||
|
// TLSMinVersion specifies the minimum TLS version supported for gateway
|
||||||
|
// listeners.
|
||||||
|
TLSMinVersion string `hcl:"tls_min_version,optional" mapstructure:"tls_min_version"`
|
||||||
|
|
||||||
|
// TLSMaxVersion specifies the maxmimum TLS version supported for gateway
|
||||||
|
// listeners.
|
||||||
|
TLSMaxVersion string `hcl:"tls_max_version,optional" mapstructure:"tls_max_version"`
|
||||||
|
|
||||||
|
// CipherSuites specifies a list of cipher suites that gateway listeners
|
||||||
|
// support when negotiating connections using TLS 1.2 or older.
|
||||||
|
CipherSuites []string `hcl:"cipher_suites,optional" mapstructure:"cipher_suites"`
|
||||||
|
|
||||||
|
// SDS specifies parameters that configure the listener to load TLS
|
||||||
|
// certificates from an external Secrets Discovery Service (SDS).
|
||||||
|
SDS *ConsulGatewayTLSSDSConfig `hcl:"sds,block" mapstructure:"sds"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *ConsulGatewayTLSConfig) Canonicalize() {
|
func (tc *ConsulGatewayTLSConfig) Canonicalize() {
|
||||||
@@ -420,6 +461,7 @@ func (tc *ConsulGatewayTLSConfig) Copy() *ConsulGatewayTLSConfig {
|
|||||||
Enabled: tc.Enabled,
|
Enabled: tc.Enabled,
|
||||||
TLSMinVersion: tc.TLSMinVersion,
|
TLSMinVersion: tc.TLSMinVersion,
|
||||||
TLSMaxVersion: tc.TLSMaxVersion,
|
TLSMaxVersion: tc.TLSMaxVersion,
|
||||||
|
SDS: tc.SDS.Copy(),
|
||||||
}
|
}
|
||||||
if len(tc.CipherSuites) != 0 {
|
if len(tc.CipherSuites) != 0 {
|
||||||
cipherSuites := make([]string, len(tc.CipherSuites))
|
cipherSuites := make([]string, len(tc.CipherSuites))
|
||||||
@@ -430,13 +472,90 @@ func (tc *ConsulGatewayTLSConfig) Copy() *ConsulGatewayTLSConfig {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConsulIngressService is used to configure a service fronted by the ingress gateway.
|
// ConsulHTTPHeaderModifiers is a set of rules for HTTP header modification that
|
||||||
|
// should be performed by proxies as the request passes through them. It can
|
||||||
|
// operate on either request or response headers depending on the context in
|
||||||
|
// which it is used.
|
||||||
|
type ConsulHTTPHeaderModifiers struct {
|
||||||
|
// Add is a set of name -> value pairs that should be appended to the
|
||||||
|
// request or response (i.e. allowing duplicates if the same header already
|
||||||
|
// exists).
|
||||||
|
Add map[string]string `hcl:"add,block" mapstructure:"add"`
|
||||||
|
|
||||||
|
// Set is a set of name -> value pairs that should be added to the request
|
||||||
|
// or response, overwriting any existing header values of the same name.
|
||||||
|
Set map[string]string `hcl:"set,block" mapstructure:"set"`
|
||||||
|
|
||||||
|
// Remove is the set of header names that should be stripped from the
|
||||||
|
// request or response.
|
||||||
|
Remove []string `hcl:"remove,optional" mapstructure:"remove"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ConsulHTTPHeaderModifiers) Copy() *ConsulHTTPHeaderModifiers {
|
||||||
|
if h == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ConsulHTTPHeaderModifiers{
|
||||||
|
Add: maps.Clone(h.Add),
|
||||||
|
Set: maps.Clone(h.Set),
|
||||||
|
Remove: slices.Clone(h.Remove),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ConsulHTTPHeaderModifiers) Canonicalize() {
|
||||||
|
if h == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(h.Add) == 0 {
|
||||||
|
h.Add = nil
|
||||||
|
}
|
||||||
|
if len(h.Set) == 0 {
|
||||||
|
h.Set = nil
|
||||||
|
}
|
||||||
|
if len(h.Remove) == 0 {
|
||||||
|
h.Remove = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsulIngressService is used to configure a service fronted by the ingress
|
||||||
|
// gateway. For more details, consult the Consul documentation:
|
||||||
|
// https://developer.hashicorp.com/consul/docs/connect/config-entries/ingress-gateway
|
||||||
type ConsulIngressService struct {
|
type ConsulIngressService struct {
|
||||||
// Namespace is not yet supported.
|
// Namespace is not yet supported.
|
||||||
// Namespace string
|
// Namespace string
|
||||||
|
|
||||||
|
// Name of the service exposed through this listener.
|
||||||
Name string `hcl:"name,optional"`
|
Name string `hcl:"name,optional"`
|
||||||
|
|
||||||
|
// Hosts specifies one or more hosts that the listening services can receive
|
||||||
|
// requests on.
|
||||||
Hosts []string `hcl:"hosts,optional"`
|
Hosts []string `hcl:"hosts,optional"`
|
||||||
|
|
||||||
|
// TLS specifies a TLS configuration override for a specific service. If
|
||||||
|
// unset this will fallback to the ConsulIngressConfigEntry's own TLS field.
|
||||||
|
TLS *ConsulGatewayTLSConfig `hcl:"tls,block" mapstructure:"tls"`
|
||||||
|
|
||||||
|
// RequestHeaders specifies a set of HTTP-specific header modification rules
|
||||||
|
// applied to requests routed through the gateway
|
||||||
|
RequestHeaders *ConsulHTTPHeaderModifiers `hcl:"request_headers,block" mapstructure:"request_headers"`
|
||||||
|
|
||||||
|
// ResponseHeader specifies a set of HTTP-specific header modification rules
|
||||||
|
// applied to responses routed through the gateway
|
||||||
|
ResponseHeaders *ConsulHTTPHeaderModifiers `hcl:"response_headers,block" mapstructure:"response_headers"`
|
||||||
|
|
||||||
|
// MaxConnections specifies the maximum number of HTTP/1.1 connections a
|
||||||
|
// service instance is allowed to establish against the upstream
|
||||||
|
MaxConnections *uint32 `hcl:"max_connections,optional" mapstructure:"max_connections"`
|
||||||
|
|
||||||
|
// MaxPendingRequests specifies the maximum number of requests that are
|
||||||
|
// allowed to queue while waiting to establish a connection
|
||||||
|
MaxPendingRequests *uint32 `hcl:"max_pending_requests,optional" mapstructure:"max_pending_requests"`
|
||||||
|
|
||||||
|
// MaxConcurrentRequests specifies the maximum number of concurrent HTTP/2
|
||||||
|
// traffic requests that are allowed at a single point in time
|
||||||
|
MaxConcurrentRequests *uint32 `hcl:"max_concurrent_requests,optional" mapstructure:"max_concurrent_requests"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConsulIngressService) Canonicalize() {
|
func (s *ConsulIngressService) Canonicalize() {
|
||||||
@@ -447,6 +566,9 @@ func (s *ConsulIngressService) Canonicalize() {
|
|||||||
if len(s.Hosts) == 0 {
|
if len(s.Hosts) == 0 {
|
||||||
s.Hosts = nil
|
s.Hosts = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.RequestHeaders.Canonicalize()
|
||||||
|
s.ResponseHeaders.Canonicalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConsulIngressService) Copy() *ConsulIngressService {
|
func (s *ConsulIngressService) Copy() *ConsulIngressService {
|
||||||
@@ -454,16 +576,19 @@ func (s *ConsulIngressService) Copy() *ConsulIngressService {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var hosts []string = nil
|
ns := new(ConsulIngressService)
|
||||||
if n := len(s.Hosts); n > 0 {
|
*ns = *s
|
||||||
hosts = make([]string, n)
|
|
||||||
copy(hosts, s.Hosts)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ConsulIngressService{
|
ns.Hosts = slices.Clone(s.Hosts)
|
||||||
Name: s.Name,
|
ns.RequestHeaders = s.RequestHeaders.Copy()
|
||||||
Hosts: hosts,
|
ns.ResponseHeaders = s.ResponseHeaders.Copy()
|
||||||
}
|
ns.TLS = s.TLS.Copy()
|
||||||
|
|
||||||
|
ns.MaxConnections = pointerCopy(s.MaxConnections)
|
||||||
|
ns.MaxPendingRequests = pointerCopy(s.MaxPendingRequests)
|
||||||
|
ns.MaxConcurrentRequests = pointerCopy(s.MaxConcurrentRequests)
|
||||||
|
|
||||||
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -521,7 +646,11 @@ type ConsulIngressConfigEntry struct {
|
|||||||
// Namespace is not yet supported.
|
// Namespace is not yet supported.
|
||||||
// Namespace string
|
// Namespace string
|
||||||
|
|
||||||
TLS *ConsulGatewayTLSConfig `hcl:"tls,block"`
|
// TLS specifies a TLS configuration for the gateway.
|
||||||
|
TLS *ConsulGatewayTLSConfig `hcl:"tls,block"`
|
||||||
|
|
||||||
|
// Listeners specifies a list of listeners in the mesh for the
|
||||||
|
// gateway. Listeners are uniquely identified by their port number.
|
||||||
Listeners []*ConsulIngressListener `hcl:"listener,block"`
|
Listeners []*ConsulIngressListener `hcl:"listener,block"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -415,6 +415,33 @@ func TestConsulIngressConfigEntry_Copy(t *testing.T) {
|
|||||||
Services: []*ConsulIngressService{{
|
Services: []*ConsulIngressService{{
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
Hosts: []string{"1.1.1.1", "1.1.1.1:9000"},
|
Hosts: []string{"1.1.1.1", "1.1.1.1:9000"},
|
||||||
|
TLS: &ConsulGatewayTLSConfig{
|
||||||
|
SDS: &ConsulGatewayTLSSDSConfig{
|
||||||
|
ClusterName: "foo",
|
||||||
|
CertResource: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RequestHeaders: &ConsulHTTPHeaderModifiers{
|
||||||
|
Add: map[string]string{
|
||||||
|
"test": "testvalue",
|
||||||
|
},
|
||||||
|
Set: map[string]string{
|
||||||
|
"test1": "testvalue1",
|
||||||
|
},
|
||||||
|
Remove: []string{"test2"},
|
||||||
|
},
|
||||||
|
ResponseHeaders: &ConsulHTTPHeaderModifiers{
|
||||||
|
Add: map[string]string{
|
||||||
|
"test": "testvalue",
|
||||||
|
},
|
||||||
|
Set: map[string]string{
|
||||||
|
"test1": "testvalue1",
|
||||||
|
},
|
||||||
|
Remove: []string{"test2"},
|
||||||
|
},
|
||||||
|
MaxConnections: pointerOf(uint32(5120)),
|
||||||
|
MaxPendingRequests: pointerOf(uint32(512)),
|
||||||
|
MaxConcurrentRequests: pointerOf(uint32(2048)),
|
||||||
}, {
|
}, {
|
||||||
Name: "service2",
|
Name: "service2",
|
||||||
Hosts: []string{"2.2.2.2"},
|
Hosts: []string{"2.2.2.2"},
|
||||||
|
|||||||
@@ -33,3 +33,12 @@ func formatFloat(f float64, maxPrec int) string {
|
|||||||
func pointerOf[A any](a A) *A {
|
func pointerOf[A any](a A) *A {
|
||||||
return &a
|
return &a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pointerCopy returns a new pointer to a.
|
||||||
|
func pointerCopy[A any](a *A) *A {
|
||||||
|
if a == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
na := *a
|
||||||
|
return &na
|
||||||
|
}
|
||||||
|
|||||||
@@ -1745,6 +1745,18 @@ func apiConnectGatewayTLSConfig(in *api.ConsulGatewayTLSConfig) *structs.ConsulG
|
|||||||
TLSMinVersion: in.TLSMinVersion,
|
TLSMinVersion: in.TLSMinVersion,
|
||||||
TLSMaxVersion: in.TLSMaxVersion,
|
TLSMaxVersion: in.TLSMaxVersion,
|
||||||
CipherSuites: slices.Clone(in.CipherSuites),
|
CipherSuites: slices.Clone(in.CipherSuites),
|
||||||
|
SDS: apiConnectGatewayTLSSDSConfig(in.SDS),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func apiConnectGatewayTLSSDSConfig(in *api.ConsulGatewayTLSSDSConfig) *structs.ConsulGatewayTLSSDSConfig {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &structs.ConsulGatewayTLSSDSConfig{
|
||||||
|
ClusterName: in.ClusterName,
|
||||||
|
CertResource: in.CertResource,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1790,8 +1802,26 @@ func apiConnectIngressServiceToStructs(in *api.ConsulIngressService) *structs.Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &structs.ConsulIngressService{
|
return &structs.ConsulIngressService{
|
||||||
Name: in.Name,
|
Name: in.Name,
|
||||||
Hosts: slices.Clone(in.Hosts),
|
Hosts: slices.Clone(in.Hosts),
|
||||||
|
TLS: apiConnectGatewayTLSConfig(in.TLS),
|
||||||
|
RequestHeaders: apiConsulHTTPHeaderModifiersToStructs(in.RequestHeaders),
|
||||||
|
ResponseHeaders: apiConsulHTTPHeaderModifiersToStructs(in.ResponseHeaders),
|
||||||
|
MaxConnections: in.MaxConnections,
|
||||||
|
MaxPendingRequests: in.MaxPendingRequests,
|
||||||
|
MaxConcurrentRequests: in.MaxConcurrentRequests,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func apiConsulHTTPHeaderModifiersToStructs(in *api.ConsulHTTPHeaderModifiers) *structs.ConsulHTTPHeaderModifiers {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &structs.ConsulHTTPHeaderModifiers{
|
||||||
|
Add: maps.Clone(in.Add),
|
||||||
|
Set: maps.Clone(in.Set),
|
||||||
|
Remove: slices.Clone(in.Remove),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4182,6 +4182,33 @@ func TestConversion_ApiConsulConnectToStructs(t *testing.T) {
|
|||||||
Services: []*structs.ConsulIngressService{{
|
Services: []*structs.ConsulIngressService{{
|
||||||
Name: "ingress1",
|
Name: "ingress1",
|
||||||
Hosts: []string{"host1"},
|
Hosts: []string{"host1"},
|
||||||
|
TLS: &structs.ConsulGatewayTLSConfig{
|
||||||
|
SDS: &structs.ConsulGatewayTLSSDSConfig{
|
||||||
|
ClusterName: "foo",
|
||||||
|
CertResource: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RequestHeaders: &structs.ConsulHTTPHeaderModifiers{
|
||||||
|
Add: map[string]string{
|
||||||
|
"test": "testvalue",
|
||||||
|
},
|
||||||
|
Set: map[string]string{
|
||||||
|
"test1": "testvalue1",
|
||||||
|
},
|
||||||
|
Remove: []string{"test2"},
|
||||||
|
},
|
||||||
|
ResponseHeaders: &structs.ConsulHTTPHeaderModifiers{
|
||||||
|
Add: map[string]string{
|
||||||
|
"test": "testvalue",
|
||||||
|
},
|
||||||
|
Set: map[string]string{
|
||||||
|
"test1": "testvalue1",
|
||||||
|
},
|
||||||
|
Remove: []string{"test2"},
|
||||||
|
},
|
||||||
|
MaxConnections: pointer.Of(uint32(5120)),
|
||||||
|
MaxPendingRequests: pointer.Of(uint32(512)),
|
||||||
|
MaxConcurrentRequests: pointer.Of(uint32(2048)),
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@@ -4202,6 +4229,33 @@ func TestConversion_ApiConsulConnectToStructs(t *testing.T) {
|
|||||||
Services: []*api.ConsulIngressService{{
|
Services: []*api.ConsulIngressService{{
|
||||||
Name: "ingress1",
|
Name: "ingress1",
|
||||||
Hosts: []string{"host1"},
|
Hosts: []string{"host1"},
|
||||||
|
TLS: &api.ConsulGatewayTLSConfig{
|
||||||
|
SDS: &api.ConsulGatewayTLSSDSConfig{
|
||||||
|
ClusterName: "foo",
|
||||||
|
CertResource: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RequestHeaders: &api.ConsulHTTPHeaderModifiers{
|
||||||
|
Add: map[string]string{
|
||||||
|
"test": "testvalue",
|
||||||
|
},
|
||||||
|
Set: map[string]string{
|
||||||
|
"test1": "testvalue1",
|
||||||
|
},
|
||||||
|
Remove: []string{"test2"},
|
||||||
|
},
|
||||||
|
ResponseHeaders: &api.ConsulHTTPHeaderModifiers{
|
||||||
|
Add: map[string]string{
|
||||||
|
"test": "testvalue",
|
||||||
|
},
|
||||||
|
Set: map[string]string{
|
||||||
|
"test1": "testvalue1",
|
||||||
|
},
|
||||||
|
Remove: []string{"test2"},
|
||||||
|
},
|
||||||
|
MaxConnections: pointer.Of(uint32(5120)),
|
||||||
|
MaxPendingRequests: pointer.Of(uint32(512)),
|
||||||
|
MaxConcurrentRequests: pointer.Of(uint32(2048)),
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -425,10 +425,84 @@ func parseGatewayProxy(o *ast.ObjectItem) (*api.ConsulGatewayProxy, error) {
|
|||||||
return &proxy, nil
|
return &proxy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseConsulHTTPHeaderModifiers(o *ast.ObjectItem) (*api.ConsulHTTPHeaderModifiers, error) {
|
||||||
|
valid := []string{
|
||||||
|
"add",
|
||||||
|
"set",
|
||||||
|
"remove",
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := checkHCLKeys(o.Val, valid); err != nil {
|
||||||
|
return nil, multierror.Prefix(err, "httpHeaderModifiers ->")
|
||||||
|
}
|
||||||
|
|
||||||
|
var httpHeaderModifiers api.ConsulHTTPHeaderModifiers
|
||||||
|
var m map[string]interface{}
|
||||||
|
if err := hcl.DecodeObject(&m, o.Val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(m, "add")
|
||||||
|
delete(m, "set")
|
||||||
|
|
||||||
|
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||||
|
Result: &httpHeaderModifiers,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dec.Decode(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter list
|
||||||
|
var listVal *ast.ObjectList
|
||||||
|
if ot, ok := o.Val.(*ast.ObjectType); ok {
|
||||||
|
listVal = ot.List
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("'httpHeaderModifiers: should be an object")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse Add
|
||||||
|
if addO := listVal.Filter("add"); len(addO.Items) > 0 {
|
||||||
|
for _, o := range addO.Elem().Items {
|
||||||
|
var m map[string]interface{}
|
||||||
|
if err := hcl.DecodeObject(&m, o.Val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := mapstructure.WeakDecode(m, &httpHeaderModifiers.Add); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse Set
|
||||||
|
if setO := listVal.Filter("set"); len(setO.Items) > 0 {
|
||||||
|
for _, o := range setO.Elem().Items {
|
||||||
|
var m map[string]interface{}
|
||||||
|
if err := hcl.DecodeObject(&m, o.Val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := mapstructure.WeakDecode(m, &httpHeaderModifiers.Set); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &httpHeaderModifiers, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseConsulIngressService(o *ast.ObjectItem) (*api.ConsulIngressService, error) {
|
func parseConsulIngressService(o *ast.ObjectItem) (*api.ConsulIngressService, error) {
|
||||||
valid := []string{
|
valid := []string{
|
||||||
"name",
|
"name",
|
||||||
"hosts",
|
"hosts",
|
||||||
|
"tls",
|
||||||
|
"request_headers",
|
||||||
|
"response_headers",
|
||||||
|
"max_connections",
|
||||||
|
"max_pending_requests",
|
||||||
|
"max_concurrent_requests",
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkHCLKeys(o.Val, valid); err != nil {
|
if err := checkHCLKeys(o.Val, valid); err != nil {
|
||||||
@@ -441,6 +515,10 @@ func parseConsulIngressService(o *ast.ObjectItem) (*api.ConsulIngressService, er
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete(m, "tls")
|
||||||
|
delete(m, "request_headers")
|
||||||
|
delete(m, "response_headers")
|
||||||
|
|
||||||
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||||
Result: &service,
|
Result: &service,
|
||||||
})
|
})
|
||||||
@@ -452,6 +530,37 @@ func parseConsulIngressService(o *ast.ObjectItem) (*api.ConsulIngressService, er
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var listVal *ast.ObjectList
|
||||||
|
if ot, ok := o.Val.(*ast.ObjectType); ok {
|
||||||
|
listVal = ot.List
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("service: should be an object")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse TLS
|
||||||
|
if tlsO := listVal.Filter("tls"); len(tlsO.Items) > 0 {
|
||||||
|
service.TLS, err = parseConsulGatewayTLS(tlsO.Items[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse Request Headers
|
||||||
|
if rqstHO := listVal.Filter("request_headers"); len(rqstHO.Items) > 0 {
|
||||||
|
service.RequestHeaders, err = parseConsulHTTPHeaderModifiers(rqstHO.Items[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse Response Headers
|
||||||
|
if rspHO := listVal.Filter("response_headers"); len(rspHO.Items) > 0 {
|
||||||
|
service.ResponseHeaders, err = parseConsulHTTPHeaderModifiers(rspHO.Items[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &service, nil
|
return &service, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,12 +650,43 @@ func parseConsulIngressListener(o *ast.ObjectItem) (*api.ConsulIngressListener,
|
|||||||
return &listener, nil
|
return &listener, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseConsulGatewayTLSSDS(o *ast.ObjectItem) (*api.ConsulGatewayTLSSDSConfig, error) {
|
||||||
|
valid := []string{
|
||||||
|
"cluster_name",
|
||||||
|
"cert_resource",
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := checkHCLKeys(o.Val, valid); err != nil {
|
||||||
|
return nil, multierror.Prefix(err, "sds ->")
|
||||||
|
}
|
||||||
|
|
||||||
|
var sds api.ConsulGatewayTLSSDSConfig
|
||||||
|
var m map[string]interface{}
|
||||||
|
if err := hcl.DecodeObject(&m, o.Val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||||
|
Result: &sds,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dec.Decode(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sds, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseConsulGatewayTLS(o *ast.ObjectItem) (*api.ConsulGatewayTLSConfig, error) {
|
func parseConsulGatewayTLS(o *ast.ObjectItem) (*api.ConsulGatewayTLSConfig, error) {
|
||||||
valid := []string{
|
valid := []string{
|
||||||
"enabled",
|
"enabled",
|
||||||
"tls_min_version",
|
"tls_min_version",
|
||||||
"tls_max_version",
|
"tls_max_version",
|
||||||
"cipher_suites",
|
"cipher_suites",
|
||||||
|
"sds",
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkHCLKeys(o.Val, valid); err != nil {
|
if err := checkHCLKeys(o.Val, valid); err != nil {
|
||||||
@@ -559,6 +699,8 @@ func parseConsulGatewayTLS(o *ast.ObjectItem) (*api.ConsulGatewayTLSConfig, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete(m, "sds")
|
||||||
|
|
||||||
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||||
Result: &tls,
|
Result: &tls,
|
||||||
})
|
})
|
||||||
@@ -570,6 +712,22 @@ func parseConsulGatewayTLS(o *ast.ObjectItem) (*api.ConsulGatewayTLSConfig, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse SDS
|
||||||
|
var listVal *ast.ObjectList
|
||||||
|
if ot, ok := o.Val.(*ast.ObjectType); ok {
|
||||||
|
listVal = ot.List
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("tls: should be an object")
|
||||||
|
}
|
||||||
|
|
||||||
|
so := listVal.Filter("sds")
|
||||||
|
if len(so.Items) > 0 {
|
||||||
|
tls.SDS, err = parseConsulGatewayTLSSDS(so.Items[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &tls, nil
|
return &tls, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
capi "github.com/hashicorp/consul/api"
|
capi "github.com/hashicorp/consul/api"
|
||||||
"github.com/hashicorp/nomad/api"
|
"github.com/hashicorp/nomad/api"
|
||||||
"github.com/hashicorp/nomad/ci"
|
"github.com/hashicorp/nomad/ci"
|
||||||
|
"github.com/hashicorp/nomad/helper/pointer"
|
||||||
"github.com/shoenig/test/must"
|
"github.com/shoenig/test/must"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1682,6 +1683,23 @@ func TestParse(t *testing.T) {
|
|||||||
Hosts: []string{
|
Hosts: []string{
|
||||||
"2.2.2.2:8080",
|
"2.2.2.2:8080",
|
||||||
},
|
},
|
||||||
|
TLS: &api.ConsulGatewayTLSConfig{
|
||||||
|
SDS: &api.ConsulGatewayTLSSDSConfig{
|
||||||
|
ClusterName: "foo",
|
||||||
|
CertResource: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RequestHeaders: &api.ConsulHTTPHeaderModifiers{
|
||||||
|
Add: map[string]string{
|
||||||
|
"test": "testvalue",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ResponseHeaders: &api.ConsulHTTPHeaderModifiers{
|
||||||
|
Remove: []string{"test2"},
|
||||||
|
},
|
||||||
|
MaxConnections: pointer.Of(uint32(5120)),
|
||||||
|
MaxPendingRequests: pointer.Of(uint32(512)),
|
||||||
|
MaxConcurrentRequests: pointer.Of(uint32(2048)),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,6 +50,23 @@ job "connect_gateway_ingress" {
|
|||||||
service {
|
service {
|
||||||
name = "nginx"
|
name = "nginx"
|
||||||
hosts = ["2.2.2.2:8080"]
|
hosts = ["2.2.2.2:8080"]
|
||||||
|
tls {
|
||||||
|
sds {
|
||||||
|
cluster_name = "foo"
|
||||||
|
cert_resource = "bar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request_headers {
|
||||||
|
add {
|
||||||
|
test = "testvalue"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response_headers {
|
||||||
|
remove = ["test2"]
|
||||||
|
}
|
||||||
|
max_connections = 5120
|
||||||
|
max_pending_requests = 512
|
||||||
|
max_concurrent_requests = 2048
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"maps"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -587,9 +588,21 @@ func convertIngressCE(namespace, service string, entry *structs.ConsulIngressCon
|
|||||||
for _, listener := range entry.Listeners {
|
for _, listener := range entry.Listeners {
|
||||||
var services []api.IngressService = nil
|
var services []api.IngressService = nil
|
||||||
for _, s := range listener.Services {
|
for _, s := range listener.Services {
|
||||||
|
var sds *api.GatewayTLSSDSConfig = nil
|
||||||
|
if s.TLS != nil {
|
||||||
|
sds = convertGatewayTLSSDSConfig(s.TLS.SDS)
|
||||||
|
}
|
||||||
services = append(services, api.IngressService{
|
services = append(services, api.IngressService{
|
||||||
Name: s.Name,
|
Name: s.Name,
|
||||||
Hosts: slices.Clone(s.Hosts),
|
Hosts: slices.Clone(s.Hosts),
|
||||||
|
RequestHeaders: convertHTTPHeaderModifiers(s.RequestHeaders),
|
||||||
|
ResponseHeaders: convertHTTPHeaderModifiers(s.ResponseHeaders),
|
||||||
|
MaxConnections: s.MaxConnections,
|
||||||
|
MaxPendingRequests: s.MaxPendingRequests,
|
||||||
|
MaxConcurrentRequests: s.MaxConcurrentRequests,
|
||||||
|
TLS: &api.GatewayServiceTLSConfig{
|
||||||
|
SDS: sds,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
listeners = append(listeners, api.IngressListener{
|
listeners = append(listeners, api.IngressListener{
|
||||||
@@ -611,11 +624,48 @@ func convertIngressCE(namespace, service string, entry *structs.ConsulIngressCon
|
|||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Kind: api.IngressGateway,
|
Kind: api.IngressGateway,
|
||||||
Name: service,
|
Name: service,
|
||||||
TLS: tls,
|
TLS: *convertGatewayTLSConfig(entry.TLS),
|
||||||
Listeners: listeners,
|
Listeners: listeners,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertHTTPHeaderModifiers(in *structs.ConsulHTTPHeaderModifiers) *api.HTTPHeaderModifiers {
|
||||||
|
if in != nil {
|
||||||
|
return &api.HTTPHeaderModifiers{
|
||||||
|
Add: maps.Clone(in.Add),
|
||||||
|
Set: maps.Clone(in.Set),
|
||||||
|
Remove: slices.Clone(in.Remove),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.HTTPHeaderModifiers{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertGatewayTLSConfig(in *structs.ConsulGatewayTLSConfig) *api.GatewayTLSConfig {
|
||||||
|
if in != nil {
|
||||||
|
return &api.GatewayTLSConfig{
|
||||||
|
Enabled: in.Enabled,
|
||||||
|
TLSMinVersion: in.TLSMinVersion,
|
||||||
|
TLSMaxVersion: in.TLSMaxVersion,
|
||||||
|
CipherSuites: slices.Clone(in.CipherSuites),
|
||||||
|
SDS: convertGatewayTLSSDSConfig(in.SDS),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.GatewayTLSConfig{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertGatewayTLSSDSConfig(in *structs.ConsulGatewayTLSSDSConfig) *api.GatewayTLSSDSConfig {
|
||||||
|
if in != nil {
|
||||||
|
return &api.GatewayTLSSDSConfig{
|
||||||
|
ClusterName: in.ClusterName,
|
||||||
|
CertResource: in.CertResource,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.GatewayTLSSDSConfig{}
|
||||||
|
}
|
||||||
|
|
||||||
func convertTerminatingCE(namespace, service string, entry *structs.ConsulTerminatingConfigEntry) api.ConfigEntry {
|
func convertTerminatingCE(namespace, service string, entry *structs.ConsulTerminatingConfigEntry) api.ConfigEntry {
|
||||||
var linked []api.LinkedService = nil
|
var linked []api.LinkedService = nil
|
||||||
for _, s := range entry.Services {
|
for _, s := range entry.Services {
|
||||||
|
|||||||
@@ -1314,6 +1314,11 @@ func connectGatewayTLSConfigDiff(prev, next *ConsulGatewayTLSConfig, contextual
|
|||||||
// Diff the primitive field.
|
// Diff the primitive field.
|
||||||
diff.Fields = fieldDiffs(oldPrimitiveFlat, newPrimitiveFlat, contextual)
|
diff.Fields = fieldDiffs(oldPrimitiveFlat, newPrimitiveFlat, contextual)
|
||||||
|
|
||||||
|
// Diff SDS object
|
||||||
|
if sdsDiff := primitiveObjectDiff(prev.SDS, next.SDS, nil, "SDS", contextual); sdsDiff != nil {
|
||||||
|
diff.Objects = append(diff.Objects, sdsDiff)
|
||||||
|
}
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1443,6 +1448,38 @@ func connectGatewayIngressServiceDiff(prev, next *ConsulIngressService, contextu
|
|||||||
newPrimitiveFlat = flatmap.Flatten(next, nil, true)
|
newPrimitiveFlat = flatmap.Flatten(next, nil, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Diff pointer types.
|
||||||
|
if prev != nil {
|
||||||
|
if prev.MaxConnections != nil {
|
||||||
|
oldPrimitiveFlat["MaxConnections"] = fmt.Sprintf("%v", *prev.MaxConnections)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if next != nil {
|
||||||
|
if next.MaxConnections != nil {
|
||||||
|
newPrimitiveFlat["MaxConnections"] = fmt.Sprintf("%v", *next.MaxConnections)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if prev != nil {
|
||||||
|
if prev.MaxPendingRequests != nil {
|
||||||
|
oldPrimitiveFlat["MaxPendingRequests"] = fmt.Sprintf("%v", *prev.MaxPendingRequests)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if next != nil {
|
||||||
|
if next.MaxPendingRequests != nil {
|
||||||
|
newPrimitiveFlat["MaxPendingRequests"] = fmt.Sprintf("%v", *next.MaxPendingRequests)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if prev != nil {
|
||||||
|
if prev.MaxConcurrentRequests != nil {
|
||||||
|
oldPrimitiveFlat["MaxConcurrentRequests"] = fmt.Sprintf("%v", *prev.MaxConcurrentRequests)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if next != nil {
|
||||||
|
if next.MaxConcurrentRequests != nil {
|
||||||
|
newPrimitiveFlat["MaxConcurrentRequests"] = fmt.Sprintf("%v", *next.MaxConcurrentRequests)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Diff the primitive fields.
|
// Diff the primitive fields.
|
||||||
diff.Fields = fieldDiffs(oldPrimitiveFlat, newPrimitiveFlat, contextual)
|
diff.Fields = fieldDiffs(oldPrimitiveFlat, newPrimitiveFlat, contextual)
|
||||||
|
|
||||||
@@ -1451,6 +1488,55 @@ func connectGatewayIngressServiceDiff(prev, next *ConsulIngressService, contextu
|
|||||||
diff.Objects = append(diff.Objects, hDiffs)
|
diff.Objects = append(diff.Objects, hDiffs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Diff the ConsulGatewayTLSConfig objects.
|
||||||
|
tlsConfigDiff := connectGatewayTLSConfigDiff(prev.TLS, next.TLS, contextual)
|
||||||
|
if tlsConfigDiff != nil {
|
||||||
|
diff.Objects = append(diff.Objects, tlsConfigDiff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff the ConsulHTTPHeaderModifiers objects (RequestHeaders).
|
||||||
|
reqModifiersDiff := connectGatewayHTTPHeaderModifiersDiff(prev.RequestHeaders, next.RequestHeaders, "RequestHeaders", contextual)
|
||||||
|
if reqModifiersDiff != nil {
|
||||||
|
diff.Objects = append(diff.Objects, reqModifiersDiff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff the ConsulHTTPHeaderModifiers objects (ResponseHeaders).
|
||||||
|
respModifiersDiff := connectGatewayHTTPHeaderModifiersDiff(prev.ResponseHeaders, next.ResponseHeaders, "ResponseHeaders", contextual)
|
||||||
|
if respModifiersDiff != nil {
|
||||||
|
diff.Objects = append(diff.Objects, respModifiersDiff)
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff
|
||||||
|
}
|
||||||
|
|
||||||
|
func connectGatewayHTTPHeaderModifiersDiff(prev, next *ConsulHTTPHeaderModifiers, name string, contextual bool) *ObjectDiff {
|
||||||
|
diff := &ObjectDiff{Type: DiffTypeNone, Name: name}
|
||||||
|
var oldPrimitiveFlat, newPrimitiveFlat map[string]string
|
||||||
|
|
||||||
|
if reflect.DeepEqual(prev, next) {
|
||||||
|
return nil
|
||||||
|
} else if prev == nil {
|
||||||
|
prev = new(ConsulHTTPHeaderModifiers)
|
||||||
|
diff.Type = DiffTypeAdded
|
||||||
|
newPrimitiveFlat = flatmap.Flatten(next, nil, true)
|
||||||
|
} else if next == nil {
|
||||||
|
next = new(ConsulHTTPHeaderModifiers)
|
||||||
|
diff.Type = DiffTypeDeleted
|
||||||
|
oldPrimitiveFlat = flatmap.Flatten(prev, nil, true)
|
||||||
|
} else {
|
||||||
|
diff.Type = DiffTypeEdited
|
||||||
|
oldPrimitiveFlat = flatmap.Flatten(prev, nil, true)
|
||||||
|
newPrimitiveFlat = flatmap.Flatten(next, nil, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff the primitive fields.
|
||||||
|
diff.Fields = fieldDiffs(oldPrimitiveFlat, newPrimitiveFlat, contextual)
|
||||||
|
|
||||||
|
// Diff the Remove Headers.
|
||||||
|
if rDiffs := stringSetDiff(prev.Remove, next.Remove, "Remove", contextual); rDiffs != nil {
|
||||||
|
diff.Objects = append(diff.Objects, rDiffs)
|
||||||
|
}
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1994,12 +1994,61 @@ func (p *ConsulGatewayProxy) Validate() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConsulGatewayTLSConfig is used to configure TLS for a gateway.
|
// ConsulGatewayTLSSDSConfig is used to configure the gateway's TLS listener to
|
||||||
|
// load certificates from an external Secret Discovery Service (SDS)
|
||||||
|
type ConsulGatewayTLSSDSConfig struct {
|
||||||
|
|
||||||
|
// ClusterName specifies the name of the SDS cluster where Consul should
|
||||||
|
// retrieve certificates.
|
||||||
|
ClusterName string
|
||||||
|
|
||||||
|
// CertResource specifies an SDS resource name
|
||||||
|
CertResource string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConsulGatewayTLSSDSConfig) Copy() *ConsulGatewayTLSSDSConfig {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ConsulGatewayTLSSDSConfig{
|
||||||
|
ClusterName: c.ClusterName,
|
||||||
|
CertResource: c.CertResource,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConsulGatewayTLSSDSConfig) Equal(o *ConsulGatewayTLSSDSConfig) bool {
|
||||||
|
if c == nil || o == nil {
|
||||||
|
return c == o
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.ClusterName == o.ClusterName &&
|
||||||
|
c.CertResource == o.CertResource
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsulGatewayTLSConfig is used to configure TLS for a gateway. Both
|
||||||
|
// ConsulIngressConfigEntry and ConsulIngressService use this struct. For more
|
||||||
|
// details, consult the Consul documentation:
|
||||||
|
// https://developer.hashicorp.com/consul/docs/connect/config-entries/ingress-gateway#listeners-services-tls
|
||||||
type ConsulGatewayTLSConfig struct {
|
type ConsulGatewayTLSConfig struct {
|
||||||
Enabled bool
|
// Enabled indicates whether TLS is enabled for the configuration entry
|
||||||
|
Enabled bool
|
||||||
|
|
||||||
|
// TLSMinVersion specifies the minimum TLS version supported for gateway
|
||||||
|
// listeners.
|
||||||
TLSMinVersion string
|
TLSMinVersion string
|
||||||
|
|
||||||
|
// TLSMaxVersion specifies the maxmimum TLS version supported for gateway
|
||||||
|
// listeners.
|
||||||
TLSMaxVersion string
|
TLSMaxVersion string
|
||||||
CipherSuites []string
|
|
||||||
|
// CipherSuites specifies a list of cipher suites that gateway listeners
|
||||||
|
// support when negotiating connections using TLS 1.2 or older.
|
||||||
|
CipherSuites []string
|
||||||
|
|
||||||
|
// SDS specifies parameters that configure the listener to load TLS
|
||||||
|
// certificates from an external Secrets Discovery Service (SDS).
|
||||||
|
SDS *ConsulGatewayTLSSDSConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConsulGatewayTLSConfig) Copy() *ConsulGatewayTLSConfig {
|
func (c *ConsulGatewayTLSConfig) Copy() *ConsulGatewayTLSConfig {
|
||||||
@@ -2012,6 +2061,7 @@ func (c *ConsulGatewayTLSConfig) Copy() *ConsulGatewayTLSConfig {
|
|||||||
TLSMinVersion: c.TLSMinVersion,
|
TLSMinVersion: c.TLSMinVersion,
|
||||||
TLSMaxVersion: c.TLSMaxVersion,
|
TLSMaxVersion: c.TLSMaxVersion,
|
||||||
CipherSuites: slices.Clone(c.CipherSuites),
|
CipherSuites: slices.Clone(c.CipherSuites),
|
||||||
|
SDS: c.SDS.Copy(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2023,13 +2073,95 @@ func (c *ConsulGatewayTLSConfig) Equal(o *ConsulGatewayTLSConfig) bool {
|
|||||||
return c.Enabled == o.Enabled &&
|
return c.Enabled == o.Enabled &&
|
||||||
c.TLSMinVersion == o.TLSMinVersion &&
|
c.TLSMinVersion == o.TLSMinVersion &&
|
||||||
c.TLSMaxVersion == o.TLSMaxVersion &&
|
c.TLSMaxVersion == o.TLSMaxVersion &&
|
||||||
helper.SliceSetEq(c.CipherSuites, o.CipherSuites)
|
helper.SliceSetEq(c.CipherSuites, o.CipherSuites) &&
|
||||||
|
c.SDS.Equal(o.SDS)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsulHTTPHeaderModifiers is a set of rules for HTTP header modification that
|
||||||
|
// should be performed by proxies as the request passes through them. It can
|
||||||
|
// operate on either request or response headers depending on the context in
|
||||||
|
// which it is used.
|
||||||
|
type ConsulHTTPHeaderModifiers struct {
|
||||||
|
// Add is a set of name -> value pairs that should be appended to the request
|
||||||
|
// or response (i.e. allowing duplicates if the same header already exists).
|
||||||
|
Add map[string]string
|
||||||
|
|
||||||
|
// Set is a set of name -> value pairs that should be added to the request or
|
||||||
|
// response, overwriting any existing header values of the same name.
|
||||||
|
Set map[string]string
|
||||||
|
|
||||||
|
// Remove is the set of header names that should be stripped from the request
|
||||||
|
// or response.
|
||||||
|
Remove []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ConsulHTTPHeaderModifiers) Copy() *ConsulHTTPHeaderModifiers {
|
||||||
|
if h == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ConsulHTTPHeaderModifiers{
|
||||||
|
Add: maps.Clone(h.Add),
|
||||||
|
Set: maps.Clone(h.Set),
|
||||||
|
Remove: slices.Clone(h.Remove),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ConsulHTTPHeaderModifiers) Equal(o *ConsulHTTPHeaderModifiers) bool {
|
||||||
|
if h == nil || o == nil {
|
||||||
|
return h == o
|
||||||
|
}
|
||||||
|
|
||||||
|
if !maps.Equal(h.Add, o.Add) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !maps.Equal(h.Set, o.Set) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !helper.SliceSetEq(h.Remove, o.Remove) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConsulIngressService is used to configure a service fronted by the ingress gateway.
|
// ConsulIngressService is used to configure a service fronted by the ingress gateway.
|
||||||
|
// For more details, consult the Consul documentation:
|
||||||
|
// https://developer.hashicorp.com/consul/docs/connect/config-entries/ingress-gateway
|
||||||
type ConsulIngressService struct {
|
type ConsulIngressService struct {
|
||||||
Name string
|
|
||||||
|
// Name of the service exposed through this listener.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Hosts specifies one or more hosts that the listening services can receive
|
||||||
|
// requests on.
|
||||||
Hosts []string
|
Hosts []string
|
||||||
|
|
||||||
|
// TLS specifies a TLS configuration override for a specific service. If
|
||||||
|
// unset this will fallback to the ConsulIngressConfigEntry's own TLS field.
|
||||||
|
TLS *ConsulGatewayTLSConfig
|
||||||
|
|
||||||
|
// RequestHeaders specifies a set of HTTP-specific header modification rules
|
||||||
|
// applied to requests routed through the gateway
|
||||||
|
RequestHeaders *ConsulHTTPHeaderModifiers
|
||||||
|
|
||||||
|
// ResponseHeader specifies a set of HTTP-specific header modification rules
|
||||||
|
// applied to responses routed through the gateway
|
||||||
|
ResponseHeaders *ConsulHTTPHeaderModifiers
|
||||||
|
|
||||||
|
// MaxConnections specifies the maximum number of HTTP/1.1 connections a
|
||||||
|
// service instance is allowed to establish against the upstream
|
||||||
|
MaxConnections *uint32
|
||||||
|
|
||||||
|
// MaxPendingRequests specifies the maximum number of requests that are
|
||||||
|
// allowed to queue while waiting to establish a connection
|
||||||
|
MaxPendingRequests *uint32
|
||||||
|
|
||||||
|
// MaxConcurrentRequests specifies the maximum number of concurrent HTTP/2
|
||||||
|
// traffic requests that are allowed at a single point in time
|
||||||
|
MaxConcurrentRequests *uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConsulIngressService) Copy() *ConsulIngressService {
|
func (s *ConsulIngressService) Copy() *ConsulIngressService {
|
||||||
@@ -2037,16 +2169,19 @@ func (s *ConsulIngressService) Copy() *ConsulIngressService {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var hosts []string = nil
|
ns := new(ConsulIngressService)
|
||||||
if n := len(s.Hosts); n > 0 {
|
*ns = *s
|
||||||
hosts = make([]string, n)
|
|
||||||
copy(hosts, s.Hosts)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ConsulIngressService{
|
ns.Hosts = slices.Clone(s.Hosts)
|
||||||
Name: s.Name,
|
ns.RequestHeaders = s.RequestHeaders.Copy()
|
||||||
Hosts: hosts,
|
ns.ResponseHeaders = s.ResponseHeaders.Copy()
|
||||||
}
|
ns.TLS = s.TLS.Copy()
|
||||||
|
|
||||||
|
ns.MaxConnections = pointer.Copy(s.MaxConnections)
|
||||||
|
ns.MaxPendingRequests = pointer.Copy(s.MaxPendingRequests)
|
||||||
|
ns.MaxConcurrentRequests = pointer.Copy(s.MaxConcurrentRequests)
|
||||||
|
|
||||||
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConsulIngressService) Equal(o *ConsulIngressService) bool {
|
func (s *ConsulIngressService) Equal(o *ConsulIngressService) bool {
|
||||||
@@ -2058,7 +2193,35 @@ func (s *ConsulIngressService) Equal(o *ConsulIngressService) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return helper.SliceSetEq(s.Hosts, o.Hosts)
|
if !helper.SliceSetEq(s.Hosts, o.Hosts) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.TLS.Equal(o.TLS) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.RequestHeaders.Equal(o.RequestHeaders) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.ResponseHeaders.Equal(o.ResponseHeaders) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !pointer.Eq(s.MaxConnections, o.MaxConnections) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !pointer.Eq(s.MaxPendingRequests, o.MaxPendingRequests) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !pointer.Eq(s.MaxConcurrentRequests, o.MaxConcurrentRequests) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConsulIngressService) Validate(protocol string) error {
|
func (s *ConsulIngressService) Validate(protocol string) error {
|
||||||
@@ -2171,7 +2334,12 @@ func ingressServicesEqual(a, b []*ConsulIngressService) bool {
|
|||||||
//
|
//
|
||||||
// https://www.consul.io/docs/agent/config-entries/ingress-gateway#available-fields
|
// https://www.consul.io/docs/agent/config-entries/ingress-gateway#available-fields
|
||||||
type ConsulIngressConfigEntry struct {
|
type ConsulIngressConfigEntry struct {
|
||||||
TLS *ConsulGatewayTLSConfig
|
|
||||||
|
// TLS specifies a TLS configuration for the gateway.
|
||||||
|
TLS *ConsulGatewayTLSConfig
|
||||||
|
|
||||||
|
// Listeners specifies a list of listeners in the mesh for the
|
||||||
|
// gateway. Listeners are uniquely identified by their port number.
|
||||||
Listeners []*ConsulIngressListener
|
Listeners []*ConsulIngressListener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ description: |-
|
|||||||
|
|
||||||
<Placement groups={['job', 'group', 'service', 'connect', 'gateway']} />
|
<Placement groups={['job', 'group', 'service', 'connect', 'gateway']} />
|
||||||
|
|
||||||
The `gateway` block allows configuration of [Consul Connect Gateways](/consul/docs/connect/gateways). Nomad will
|
The `gateway` block allows configuration of [Consul Connect
|
||||||
automatically create the necessary Gateway [Configuration Entry](/consul/docs/agent/config-entries)
|
Gateways](/consul/docs/connect/gateways). Nomad will automatically create the
|
||||||
as well as inject an Envoy proxy task into the Nomad job to serve as the Gateway.
|
necessary Gateway [Configuration Entry](/consul/docs/agent/config-entries) as
|
||||||
|
well as inject an Envoy proxy task into the Nomad job to serve as the Gateway.
|
||||||
|
|
||||||
The `gateway` configuration is valid within the context of a `connect` block.
|
The `gateway` configuration is valid within the context of a `connect` block.
|
||||||
Additional information about Gateway configurations can be found in Consul's
|
Additional information about Gateway configurations can be found in Consul's
|
||||||
@@ -48,19 +49,23 @@ Exactly one of `ingress`, `terminating`, or `mesh` must be configured.
|
|||||||
|
|
||||||
### `proxy` Parameters
|
### `proxy` Parameters
|
||||||
|
|
||||||
- `connect_timeout` `(string: "5s")` - The amount of time to allow when making upstream
|
- `connect_timeout` `(string: "5s")` - The amount of time to allow when making
|
||||||
connections before timing out. Defaults to 5 seconds. If the upstream service has
|
upstream connections before timing out. Defaults to 5 seconds. If the upstream
|
||||||
the configuration option <code>[connect_timeout_ms]</code> set for the `service-resolver`, that
|
service has the configuration option <code>[connect_timeout_ms]</code> set for
|
||||||
timeout value will take precedence over this gateway proxy option.
|
the `service-resolver`, that timeout value will take precedence over this
|
||||||
- `envoy_gateway_bind_tagged_addresses` `(bool: false)` - Indicates that the gateway
|
gateway proxy option.
|
||||||
services tagged addresses should be bound to listeners in addition to the default
|
|
||||||
listener address.
|
- `envoy_gateway_bind_tagged_addresses` `(bool: false)` - Indicates that the
|
||||||
- `envoy_gateway_bind_addresses` <code>(map<string|[address]>: nil)</code> - A map of additional addresses to be bound.
|
gateway services tagged addresses should be bound to listeners in addition to
|
||||||
The keys to this map are the same of the listeners to be created and the values are
|
the default listener address.
|
||||||
a map with two keys - address and port, that combined make the address to bind the
|
|
||||||
listener to. These are bound in addition to the default address.
|
- `envoy_gateway_bind_addresses` <code>(map<string|[address]>: nil)</code> - A
|
||||||
If `bridge` networking is in use, this map is automatically populated with additional
|
map of additional addresses to be bound. The keys to this map are the same of
|
||||||
listeners enabling the Envoy proxy to work from inside the network namespace.
|
the listeners to be created and the values are a map with two keys - address
|
||||||
|
and port, that combined make the address to bind the listener to. These are
|
||||||
|
bound in addition to the default address. If `bridge` networking is in use,
|
||||||
|
this map is automatically populated with additional listeners enabling the
|
||||||
|
Envoy proxy to work from inside the network namespace.
|
||||||
|
|
||||||
```
|
```
|
||||||
envoy_gateway_bind_addresses "<service>" {
|
envoy_gateway_bind_addresses "<service>" {
|
||||||
@@ -76,9 +81,9 @@ envoy_gateway_bind_addresses "<service>" {
|
|||||||
service address from inside the network namespace.
|
service address from inside the network namespace.
|
||||||
- `envoy_dns_discovery_type` `(string: optional)` - Determintes how Envoy will
|
- `envoy_dns_discovery_type` `(string: optional)` - Determintes how Envoy will
|
||||||
resolve hostnames. Defaults to `LOGICAL_DNS`. Must be one of `STRICT_DNS` or
|
resolve hostnames. Defaults to `LOGICAL_DNS`. Must be one of `STRICT_DNS` or
|
||||||
`LOGICAL_DNS`. Details for each type are available in the [Envoy Documentation](https://www.envoyproxy.io/docs/envoy/v1.16.1/intro/arch_overview/upstream/service_discovery).
|
`LOGICAL_DNS`. Details for each type are available in the [Envoy
|
||||||
This option applies to terminating gateways that route to services addressed by a
|
Documentation][envoy_sd_docs]. This option applies to terminating gateways
|
||||||
hostname.
|
that route to services addressed by a hostname.
|
||||||
- `config` `(map: nil)` - Escape hatch for [Advanced Configuration] of Envoy.
|
- `config` `(map: nil)` - Escape hatch for [Advanced Configuration] of Envoy.
|
||||||
Keys and values support [runtime variable interpolation][interpolation].
|
Keys and values support [runtime variable interpolation][interpolation].
|
||||||
|
|
||||||
@@ -89,51 +94,39 @@ envoy_gateway_bind_addresses "<service>" {
|
|||||||
|
|
||||||
### `ingress` Parameters
|
### `ingress` Parameters
|
||||||
|
|
||||||
|
- `listener` <code>(array<[listener]> : required)</code> - One or more listeners
|
||||||
|
that the ingress gateway should setup, uniquely identified by their port
|
||||||
|
number.
|
||||||
|
|
||||||
- `tls` <code>([tls]: nil)</code> - TLS configuration for this gateway.
|
- `tls` <code>([tls]: nil)</code> - TLS configuration for this gateway.
|
||||||
- `listener` <code>(array<[listener]> : required)</code> - One or more listeners that the
|
|
||||||
ingress gateway should setup, uniquely identified by their port number.
|
|
||||||
|
|
||||||
#### `tls` Parameters
|
|
||||||
|
|
||||||
- `enabled` `(bool: false)` - Set this configuration to enable TLS for every listener
|
|
||||||
on the gateway. If TLS is enabled, then each host defined in the `host` field will
|
|
||||||
be added as a DNSSAN to the gateway's x509 certificate.
|
|
||||||
|
|
||||||
- `tls_min_version` `(string: optional)` - Set the default minimum TLS version
|
|
||||||
supported by the gateway. Refer to
|
|
||||||
[`TLSMinVersion`](/consul/docs/connect/config-entries/ingress-gateway#tlsminversion)
|
|
||||||
in the Consul documentation for supported versions.
|
|
||||||
|
|
||||||
- `tls_max_version` `(string: optional)` - Set the default maximum TLS version
|
|
||||||
supported by the gateway. Refer to
|
|
||||||
[`TLSMaxVersion`](/consul/docs/connect/config-entries/ingress-gateway#tlsmaxversion)
|
|
||||||
in the Consul documentation for supported versions.
|
|
||||||
|
|
||||||
- `cipher_suites` `(array<string>: optional)` - Set the default list of TLS
|
|
||||||
cipher suites for the gateway's listeners. Refer to
|
|
||||||
[`CipherSuites`](/consul/docs/connect/config-entries/ingress-gateway#ciphersuites)
|
|
||||||
in the Consul documentation for the supported cipher suites.
|
|
||||||
|
|
||||||
#### `listener` Parameters
|
#### `listener` Parameters
|
||||||
|
|
||||||
- `port` `(int: required)` - The port that the listener should receive traffic on.
|
- `port` `(int: required)` - The port that the listener should receive traffic on.
|
||||||
|
|
||||||
- `protocol` `(string: "tcp")` - The protocol associated with the listener. One
|
- `protocol` `(string: "tcp")` - The protocol associated with the listener. One
|
||||||
of `tcp`, `http`, `http2`, or `grpc`.
|
of `tcp`, `http`, `http2`, or `grpc`.
|
||||||
|
|
||||||
~> **Note:** If using any protocol other than `tcp` (for example: `http` or `grpc`), preconfiguring a [service-default] in Consul to
|
~> **Note:** If using any protocol other than `tcp` (for example: `http` or
|
||||||
set the [Protocol](/consul/docs/connect/config-entries/service-defaults#protocol)
|
`grpc`), preconfiguring a [service-default][] in Consul to set the
|
||||||
of the service to the desired protocol is mandatory due to an [open issue](https://github.com/hashicorp/nomad/issues/8647).
|
[Protocol][service-default-protocol] of the service to the desired protocol is
|
||||||
|
mandatory due to an [open issue](https://github.com/hashicorp/nomad/issues/8647).
|
||||||
|
|
||||||
- `service` <code>(array<[service]>: required)</code> - One or more services to be
|
- `service` <code>(array<[listener-service]>: required)</code> - One or more services to be
|
||||||
exposed via this listener. For `tcp` listeners, only a single service is allowed.
|
exposed via this listener. For `tcp` listeners, only a single service is allowed.
|
||||||
|
|
||||||
#### `service` Parameters
|
#### Listener `service` Parameters
|
||||||
|
|
||||||
|
The `service` blocks for a listener under an `ingress` gateway accept the
|
||||||
|
following parameters. Note these are different than the `service` blocks under a
|
||||||
|
`terminating` gateway.
|
||||||
|
|
||||||
- `name` `(string: required)` - The name of the service that should be exposed through
|
- `name` `(string: required)` - The name of the service that should be exposed through
|
||||||
this listener. This can be either a service registered in the catalog, or a
|
this listener. This can be either a service registered in the catalog, or a
|
||||||
service defined by other config entries, or a service that is going to be configured
|
service defined by other config entries, or a service that is going to be configured
|
||||||
by Nomad. If the wildcard specifier `*` is provided, then ALL services will be
|
by Nomad. If the wildcard specifier `*` is provided, then ALL services will be
|
||||||
exposed through this listener. This is not supported for a listener with protocol `tcp`.
|
exposed through this listener. This is not supported for a listener with protocol `tcp`.
|
||||||
|
|
||||||
- `hosts` `(array<string>: nil)` - A list of hosts that specify what requests will
|
- `hosts` `(array<string>: nil)` - A list of hosts that specify what requests will
|
||||||
match this service. This cannot be used with a `tcp` listener, and cannot be
|
match this service. This cannot be used with a `tcp` listener, and cannot be
|
||||||
specified alongside a wildcard (`*`) service name. If not specified, the default
|
specified alongside a wildcard (`*`) service name. If not specified, the default
|
||||||
@@ -148,6 +141,79 @@ envoy_gateway_bind_addresses "<service>" {
|
|||||||
hosts are valid DNS records. For example, `*.example.com` is valid while `example.*`
|
hosts are valid DNS records. For example, `*.example.com` is valid while `example.*`
|
||||||
and `*-suffix.example.com` are not.
|
and `*-suffix.example.com` are not.
|
||||||
|
|
||||||
|
- `request_headers` `([header modifiers]: <optional>)` - A set of HTTP-specific
|
||||||
|
header modification rules that will be applied to requests routed to this
|
||||||
|
service. This cannot be used with a tcp listener.
|
||||||
|
|
||||||
|
- `response_headers` `([header modifiers]: <optional>)` - A set of HTTP-specific
|
||||||
|
header modification rules that will be applied to responses from this
|
||||||
|
service. This cannot be used with a tcp listener.
|
||||||
|
|
||||||
|
- `max_concurrent_requests` `(int: <optional>)` - Specifies the maximum number
|
||||||
|
of concurrent HTTP/2 traffic requests that are allowed at a single point in
|
||||||
|
time. If unset, will default to the Envoy proxy's default.
|
||||||
|
|
||||||
|
- `max_connections` `(int: <optional>)` - Specifies the maximum number of
|
||||||
|
HTTP/1.1 connections a service instance is allowed to establish against the
|
||||||
|
upstream. If unset, will default to the Envoy proxy's default.
|
||||||
|
|
||||||
|
- `max_pending_requests` `(int: <optional>)` - Specifies the maximum number of
|
||||||
|
requests that are allowed to queue while waiting to establish a connection.
|
||||||
|
If unset, will default to the Envoy proxy's default.
|
||||||
|
|
||||||
|
- `tls` <code>([tls]: nil)</code> - TLS configuration for this service.
|
||||||
|
|
||||||
|
#### Header modifier parameters
|
||||||
|
|
||||||
|
The `request_headers` and `response_headers` blocks of an `ingress.service`
|
||||||
|
block accept the following parameters. For more details, see the [Consul
|
||||||
|
documentation][response-headers].
|
||||||
|
|
||||||
|
- `add` `(map<string|string>: optional)` - A set of key-value pairs to add to the
|
||||||
|
headers, where header names are keys and header values are the values. Header
|
||||||
|
names are not case-sensitive. If header values with the same name already
|
||||||
|
exist, the value is appended and Consul applies both headers.
|
||||||
|
|
||||||
|
- `set` `(map<string|string>: optional)` - A set of key-value pairs to add to the
|
||||||
|
response header or to replace existing header values with. Use header names as
|
||||||
|
the keys. Header names are not case-sensitive. If header values with the same
|
||||||
|
names already exist, Consul replaces the header values.
|
||||||
|
|
||||||
|
- `remove` `array(string): optional` - Defines a list of headers to remove. Consul
|
||||||
|
removes only headers containing exact matches. Header names are not
|
||||||
|
case-sensitive.
|
||||||
|
|
||||||
|
#### `tls` Parameters
|
||||||
|
|
||||||
|
- `enabled` `(bool: false)` - Set this configuration to enable TLS for every
|
||||||
|
listener on the gateway. If TLS is enabled, then each host defined in the
|
||||||
|
`host` field will be added as a DNSSAN to the gateway's x509 certificate.
|
||||||
|
|
||||||
|
- `cipher_suites` `(array<string>: optional)` - Set the default list of TLS
|
||||||
|
cipher suites for the gateway's listeners. Refer to
|
||||||
|
[`CipherSuites`](/consul/docs/connect/config-entries/ingress-gateway#ciphersuites)
|
||||||
|
in the Consul documentation for the supported cipher suites.
|
||||||
|
|
||||||
|
- `sds` `(block: optional)` - Defines a set of parameters that configures the
|
||||||
|
listener to load TLS certificates from an external Secret Discovery Service
|
||||||
|
([SDS][]).
|
||||||
|
|
||||||
|
- `cluster_name` `(string)` - The SDS cluster name to connect to to retrieve
|
||||||
|
certificates.
|
||||||
|
|
||||||
|
- `cert_resource` `(string)` - The SDS resource name to request when fetching
|
||||||
|
the certificate from the SDS service.
|
||||||
|
|
||||||
|
- `tls_max_version` `(string: optional)` - Set the default maximum TLS version
|
||||||
|
supported by the gateway. Refer to
|
||||||
|
[`TLSMaxVersion`](/consul/docs/connect/config-entries/ingress-gateway#tlsmaxversion)
|
||||||
|
in the Consul documentation for supported versions.
|
||||||
|
|
||||||
|
- `tls_min_version` `(string: optional)` - Set the default minimum TLS version
|
||||||
|
supported by the gateway. Refer to
|
||||||
|
[`TLSMinVersion`](/consul/docs/connect/config-entries/ingress-gateway#tlsminversion)
|
||||||
|
in the Consul documentation for supported versions.
|
||||||
|
|
||||||
### `terminating` Parameters
|
### `terminating` Parameters
|
||||||
|
|
||||||
- `service` <code>(array<[linked-service]>: required)</code> - One or more services to be
|
- `service` <code>(array<[linked-service]>: required)</code> - One or more services to be
|
||||||
@@ -156,26 +222,35 @@ envoy_gateway_bind_addresses "<service>" {
|
|||||||
addresses. They must also be registered in the same Consul datacenter as the
|
addresses. They must also be registered in the same Consul datacenter as the
|
||||||
terminating gateway.
|
terminating gateway.
|
||||||
|
|
||||||
#### `service` Parameters
|
#### linked `service` Parameters
|
||||||
|
|
||||||
- `name` `(string: required)` - The name of the service to link with the gateway.
|
The `service` blocks for a `terminating` gateway accept the following
|
||||||
If the wildcard specifier `*` is provided, then ALL services within the Consul
|
parameters. Note these are different than the `service` blocks for listeners
|
||||||
namespace wil lbe linked with the gateway.
|
under an `ingress` gateway.
|
||||||
|
|
||||||
|
- `name` `(string: required)` - The name of the service to link with the
|
||||||
|
gateway. If the wildcard specifier `*` is provided, then ALL services within
|
||||||
|
the Consul namespace wil lbe linked with the gateway.
|
||||||
|
|
||||||
- `ca_file` `(string: <optional>)` - A file path to a PEM-encoded certificate
|
- `ca_file` `(string: <optional>)` - A file path to a PEM-encoded certificate
|
||||||
authority. The file must be accessible by the gateway task. The certificate authority
|
authority. The file must be accessible by the gateway task. The certificate
|
||||||
is used to verify the authenticity of the service linked with the gateway. It
|
authority is used to verify the authenticity of the service linked with the
|
||||||
can be provided along with a `cert_file` and `key_file` for mutual TLS
|
gateway. It can be provided along with a `cert_file` and `key_file` for mutual
|
||||||
authentication, or on its own for one-way TLS authentication. If none is provided
|
TLS authentication, or on its own for one-way TLS authentication. If none is
|
||||||
the gateway **will not** encrypt traffic to the destination.
|
provided the gateway **will not** encrypt traffic to the destination.
|
||||||
|
|
||||||
- `cert_file` `(string: <optional>)` - A file path to a PEM-encoded certificate.
|
- `cert_file` `(string: <optional>)` - A file path to a PEM-encoded certificate.
|
||||||
The file must be accessible by the gateway task. The certificate is provided to servers
|
The file must be accessible by the gateway task. The certificate is provided
|
||||||
to verify the gateway's authenticity. It must be provided if a `key_file` is provided.
|
to servers to verify the gateway's authenticity. It must be provided if a
|
||||||
|
`key_file` is provided.
|
||||||
|
|
||||||
- `key_file` `(string: <optional>)` - A file path to a PEM-encoded private key.
|
- `key_file` `(string: <optional>)` - A file path to a PEM-encoded private key.
|
||||||
The file must be accessible by the gateway task. The key is used with the certificate
|
The file must be accessible by the gateway task. The key is used with the
|
||||||
to verify the gateway's authenticity. It must be provided if a `cert_file` is provided.
|
certificate to verify the gateway's authenticity. It must be provided if a
|
||||||
- `sni` `(string: <optional>)` - An optional hostname or domain name to specify during
|
`cert_file` is provided.
|
||||||
the TLS handshake.
|
|
||||||
|
- `sni` `(string: <optional>)` - An optional hostname or domain name to specify
|
||||||
|
during the TLS handshake.
|
||||||
|
|
||||||
### `mesh` Parameters
|
### `mesh` Parameters
|
||||||
|
|
||||||
@@ -654,13 +729,18 @@ job "countdash-mesh-two" {
|
|||||||
[envoy docker]: https://hub.docker.com/r/envoyproxy/envoy/tags
|
[envoy docker]: https://hub.docker.com/r/envoyproxy/envoy/tags
|
||||||
[ingress]: /nomad/docs/job-specification/gateway#ingress-parameters
|
[ingress]: /nomad/docs/job-specification/gateway#ingress-parameters
|
||||||
[proxy]: /nomad/docs/job-specification/gateway#proxy-parameters
|
[proxy]: /nomad/docs/job-specification/gateway#proxy-parameters
|
||||||
[linked-service]: /nomad/docs/job-specification/gateway#service-parameters-1
|
[linked-service]: /nomad/docs/job-specification/gateway#linked-service-parameters
|
||||||
[listener]: /nomad/docs/job-specification/gateway#listener-parameters
|
[listener]: /nomad/docs/job-specification/gateway#listener-parameters
|
||||||
[interpolation]: /nomad/docs/runtime/interpolation
|
[interpolation]: /nomad/docs/runtime/interpolation
|
||||||
[service]: /nomad/docs/job-specification/gateway#service-parameters
|
[listener-service]: /nomad/docs/job-specification/gateway#listener-service-parameters
|
||||||
[service-default]: /consul/docs/connect/config-entries/service-defaults
|
[service-default]: /consul/docs/connect/config-entries/service-defaults
|
||||||
[sidecar_task]: /nomad/docs/job-specification/sidecar_task
|
[sidecar_task]: /nomad/docs/job-specification/sidecar_task
|
||||||
[terminating]: /nomad/docs/job-specification/gateway#terminating-parameters
|
[terminating]: /nomad/docs/job-specification/gateway#terminating-parameters
|
||||||
[tls]: /nomad/docs/job-specification/gateway#tls-parameters
|
[tls]: /nomad/docs/job-specification/gateway#tls-parameters
|
||||||
[mesh]: /nomad/docs/job-specification/gateway#mesh-parameters
|
[mesh]: /nomad/docs/job-specification/gateway#mesh-parameters
|
||||||
[meta]: /nomad/docs/job-specification/service#meta
|
[meta]: /nomad/docs/job-specification/service#meta
|
||||||
|
[envoy_sd_docs]: https://www.envoyproxy.io/docs/envoy/v1.16.1/intro/arch_overview/upstream/service_discovery
|
||||||
|
[SDS]: https://developer.hashicorp.com/consul/docs/connect/config-entries/ingress-gateway#listeners-services-tls-sds
|
||||||
|
[service-default-protocol]: /consul/docs/connect/config-entries/service-defaults#protocol
|
||||||
|
[response-headers]: /consul/docs/connect/config-entries/ingress-gateway#listeners-services-responseheaders
|
||||||
|
[header modifiers]: /nomad/docs/job-specification/gateway#header-modifier-parameters
|
||||||
|
|||||||
Reference in New Issue
Block a user