ingress: allow setting TLS min version and cipher suites in ingress gateway config entries (#11576)
* xds: refactor ingress listener SDS configuration * xds: update resolveListenerSDS call args in listeners_test * ingress: add TLS min, max and cipher suites to GatewayTLSConfig * xds: implement envoyTLSVersions and envoyTLSCipherSuites * xds: merge TLS config * xds: configure TLS parameters with ingress TLS context from leaf * xds: nil check in resolveListenerTLSConfig validation * xds: nil check in makeTLSParameters* functions * changelog: add entry for TLS params on ingress config entries * xds: remove indirection for TLS params in TLSConfig structs * xds: return tlsContext, nil instead of ambiguous err Co-authored-by: Chris S. Kim <ckim@hashicorp.com> * xds: switch zero checks to types.TLSVersionUnspecified * ingress: add validation for ingress config entry TLS params * ingress: validate listener TLS config * xds: add basic ingress with TLS params tests * xds: add ingress listeners mixed TLS min version defaults precedence test * xds: add more explicit tests for ingress listeners inheriting gateway defaults * xds: add test for single TLS listener on gateway without TLS defaults * xds: regen golden files for TLSVersionInvalid zero value, add TLSVersionAuto listener test * types/tls: change TLSVersion to string * types/tls: update TLSCipherSuite to string type * types/tls: implement validation functions for TLSVersion and TLSCipherSuites, make some maps private * api: add TLS params to GatewayTLSConfig, add tests * api: add TLSMinVersion to ingress gateway config entry test JSON * xds: switch to Envoy TLS cipher suite encoding from types package * xds: fixup validation for TLSv1_3 min version with cipher suites * add some kitchen sink tests and add a missing struct tag * xds: check if mergedCfg.TLSVersion is in TLSVersionsWithConfigurableCipherSuites * xds: update connectTLSEnabled comment * xds: remove unsued resolveGatewayServiceTLSConfig function * xds: add makeCommonTLSContextFromLeafWithoutParams * types/tls: add LessThan comparator function for concrete values * types/tls: change tlsVersions validation map from string to TLSVersion keys * types/tls: remove unused envoyTLSCipherSuites * types/tls: enable chacha20 cipher suites for Consul agent * types/tls: remove insecure cipher suites from allowed config TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 and TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 are both explicitly listed as insecure and disabled in the Go source. Refs https://cs.opensource.google/go/go/+/refs/tags/go1.17.3:src/crypto/tls/cipher_suites.go;l=329-330 * types/tls: add ValidateConsulAgentCipherSuites function, make direct lookup map private * types/tls: return all unmatched cipher suites in validation errors * xds: check that Envoy API value matching TLS version is found when building TlsParameters * types/tls: check that value is found in map before appending to slice in MarshalEnvoyTLSCipherSuiteStrings * types/tls: cast to string rather than fmt.Printf in TLSCihperSuite.String() * xds: add TLSVersionUnspecified to list of configurable cipher suites * structs: update note about config entry warning * xds: remove TLS min version cipher suite unconfigurable test placeholder * types/tls: update tests to remove assumption about private map values Co-authored-by: R.B. Boyer <rb@hashicorp.com>
This commit is contained in:
parent
889aa2dd1a
commit
277c41d336
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:feature
|
||||||
|
ingress: allow setting TLS min version and cipher suites in ingress gateway config entries
|
||||||
|
```
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
"github.com/hashicorp/consul/acl"
|
||||||
"github.com/hashicorp/consul/lib/stringslice"
|
"github.com/hashicorp/consul/lib/stringslice"
|
||||||
|
"github.com/hashicorp/consul/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IngressGatewayConfigEntry manages the configuration for an ingress service
|
// IngressGatewayConfigEntry manages the configuration for an ingress service
|
||||||
|
@ -99,6 +100,13 @@ type GatewayTLSConfig struct {
|
||||||
|
|
||||||
// SDS allows configuring TLS certificate from an SDS service.
|
// SDS allows configuring TLS certificate from an SDS service.
|
||||||
SDS *GatewayTLSSDSConfig `json:",omitempty"`
|
SDS *GatewayTLSSDSConfig `json:",omitempty"`
|
||||||
|
|
||||||
|
TLSMinVersion types.TLSVersion `json:",omitempty" alias:"tls_min_version"`
|
||||||
|
TLSMaxVersion types.TLSVersion `json:",omitempty" alias:"tls_max_version"`
|
||||||
|
|
||||||
|
// Define a subset of cipher suites to restrict
|
||||||
|
// Only applicable to connections negotiated via TLS 1.2 or earlier
|
||||||
|
CipherSuites []types.TLSCipherSuite `json:",omitempty" alias:"cipher_suites"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GatewayServiceTLSConfig struct {
|
type GatewayServiceTLSConfig struct {
|
||||||
|
@ -231,11 +239,49 @@ func (e *IngressGatewayConfigEntry) validateServiceSDS(lis IngressListener, svc
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateGatewayTLSConfig(tlsCfg GatewayTLSConfig) error {
|
||||||
|
if tlsCfg.TLSMinVersion != types.TLSVersionUnspecified {
|
||||||
|
if err := types.ValidateTLSVersion(tlsCfg.TLSMinVersion); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tlsCfg.TLSMaxVersion != types.TLSVersionUnspecified {
|
||||||
|
if err := types.ValidateTLSVersion(tlsCfg.TLSMaxVersion); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if tlsCfg.TLSMinVersion != types.TLSVersionUnspecified {
|
||||||
|
if err, maxLessThanMin := tlsCfg.TLSMaxVersion.LessThan(tlsCfg.TLSMinVersion); err == nil && maxLessThanMin {
|
||||||
|
return fmt.Errorf("configuring max version %s less than the configured min version %s is invalid", tlsCfg.TLSMaxVersion, tlsCfg.TLSMinVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tlsCfg.CipherSuites) != 0 {
|
||||||
|
if _, ok := types.TLSVersionsWithConfigurableCipherSuites[tlsCfg.TLSMinVersion]; !ok {
|
||||||
|
return fmt.Errorf("configuring CipherSuites is only applicable to conncetions negotiated with TLS 1.2 or earlier, TLSMinVersion is set to %s", tlsCfg.TLSMinVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: it would be nice to emit a warning but not return an error from
|
||||||
|
// here if TLSMaxVersion is unspecified, TLS_AUTO or TLSv1_3
|
||||||
|
if err := types.ValidateEnvoyCipherSuites(tlsCfg.CipherSuites); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (e *IngressGatewayConfigEntry) Validate() error {
|
func (e *IngressGatewayConfigEntry) Validate() error {
|
||||||
if err := validateConfigEntryMeta(e.Meta); err != nil {
|
if err := validateConfigEntryMeta(e.Meta); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := validateGatewayTLSConfig(e.TLS); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
validProtocols := map[string]bool{
|
validProtocols := map[string]bool{
|
||||||
"tcp": true,
|
"tcp": true,
|
||||||
"http": true,
|
"http": true,
|
||||||
|
@ -264,6 +310,12 @@ func (e *IngressGatewayConfigEntry) Validate() error {
|
||||||
listener.Port)
|
listener.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if listener.TLS != nil {
|
||||||
|
if err := validateGatewayTLSConfig(*listener.TLS); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
declaredHosts := make(map[string]bool)
|
declaredHosts := make(map[string]bool)
|
||||||
serviceNames := make(map[ServiceID]struct{})
|
serviceNames := make(map[ServiceID]struct{})
|
||||||
for _, s := range listener.Services {
|
for _, s := range listener.Services {
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/hashicorp/consul/acl"
|
"github.com/hashicorp/consul/acl"
|
||||||
"github.com/hashicorp/consul/agent/cache"
|
"github.com/hashicorp/consul/agent/cache"
|
||||||
"github.com/hashicorp/consul/sdk/testutil"
|
"github.com/hashicorp/consul/sdk/testutil"
|
||||||
|
"github.com/hashicorp/consul/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConfigEntries_ACLs(t *testing.T) {
|
func TestConfigEntries_ACLs(t *testing.T) {
|
||||||
|
@ -1107,6 +1108,7 @@ func TestDecodeConfigEntry(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// TODO(rb): test SDS stuff here in both places (global/service)
|
||||||
name: "ingress-gateway: kitchen sink",
|
name: "ingress-gateway: kitchen sink",
|
||||||
snake: `
|
snake: `
|
||||||
kind = "ingress-gateway"
|
kind = "ingress-gateway"
|
||||||
|
@ -1118,6 +1120,12 @@ func TestDecodeConfigEntry(t *testing.T) {
|
||||||
|
|
||||||
tls {
|
tls {
|
||||||
enabled = true
|
enabled = true
|
||||||
|
tls_min_version = "TLSv1_1"
|
||||||
|
tls_max_version = "TLSv1_2"
|
||||||
|
cipher_suites = [
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
listeners = [
|
listeners = [
|
||||||
|
@ -1181,6 +1189,12 @@ func TestDecodeConfigEntry(t *testing.T) {
|
||||||
}
|
}
|
||||||
TLS {
|
TLS {
|
||||||
Enabled = true
|
Enabled = true
|
||||||
|
TLSMinVersion = "TLSv1_1"
|
||||||
|
TLSMaxVersion = "TLSv1_2"
|
||||||
|
CipherSuites = [
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
Listeners = [
|
Listeners = [
|
||||||
{
|
{
|
||||||
|
@ -1242,7 +1256,13 @@ func TestDecodeConfigEntry(t *testing.T) {
|
||||||
"gir": "zim",
|
"gir": "zim",
|
||||||
},
|
},
|
||||||
TLS: GatewayTLSConfig{
|
TLS: GatewayTLSConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
|
TLSMinVersion: types.TLSv1_1,
|
||||||
|
TLSMaxVersion: types.TLSv1_2,
|
||||||
|
CipherSuites: []types.TLSCipherSuite{
|
||||||
|
types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
types.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Listeners: []IngressListener{
|
Listeners: []IngressListener{
|
||||||
{
|
{
|
||||||
|
|
|
@ -186,7 +186,7 @@ func makePassthroughClusters(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message,
|
||||||
ConnectTimeout: ptypes.DurationProto(5 * time.Second),
|
ConnectTimeout: ptypes.DurationProto(5 * time.Second),
|
||||||
}
|
}
|
||||||
|
|
||||||
commonTLSContext := makeCommonTLSContextFromLeaf(cfgSnap, cfgSnap.Leaf())
|
commonTLSContext := makeCommonTLSContextFromLeafWithoutParams(cfgSnap, cfgSnap.Leaf())
|
||||||
err := injectSANMatcher(commonTLSContext, passthrough.SpiffeID)
|
err := injectSANMatcher(commonTLSContext, passthrough.SpiffeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", passthrough.SNI, err)
|
return nil, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", passthrough.SNI, err)
|
||||||
|
@ -550,7 +550,7 @@ func (s *ResourceGenerator) makeUpstreamClusterForPreparedQuery(upstream structs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable TLS upstream with the configured client certificate.
|
// Enable TLS upstream with the configured client certificate.
|
||||||
commonTLSContext := makeCommonTLSContextFromLeaf(cfgSnap, cfgSnap.Leaf())
|
commonTLSContext := makeCommonTLSContextFromLeafWithoutParams(cfgSnap, cfgSnap.Leaf())
|
||||||
err = injectSANMatcher(commonTLSContext, spiffeIDs...)
|
err = injectSANMatcher(commonTLSContext, spiffeIDs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", sni, err)
|
return nil, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", sni, err)
|
||||||
|
@ -728,7 +728,7 @@ func (s *ResourceGenerator) makeUpstreamClustersForDiscoveryChain(
|
||||||
c.Http2ProtocolOptions = &envoy_core_v3.Http2ProtocolOptions{}
|
c.Http2ProtocolOptions = &envoy_core_v3.Http2ProtocolOptions{}
|
||||||
}
|
}
|
||||||
|
|
||||||
commonTLSContext := makeCommonTLSContextFromLeaf(cfgSnap, cfgSnap.Leaf())
|
commonTLSContext := makeCommonTLSContextFromLeafWithoutParams(cfgSnap, cfgSnap.Leaf())
|
||||||
err = injectSANMatcher(commonTLSContext, spiffeIDs...)
|
err = injectSANMatcher(commonTLSContext, spiffeIDs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", sni, err)
|
return nil, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", sni, err)
|
||||||
|
|
|
@ -740,7 +740,7 @@ func injectHTTPFilterOnFilterChains(
|
||||||
func (s *ResourceGenerator) injectConnectTLSOnFilterChains(cfgSnap *proxycfg.ConfigSnapshot, listener *envoy_listener_v3.Listener) error {
|
func (s *ResourceGenerator) injectConnectTLSOnFilterChains(cfgSnap *proxycfg.ConfigSnapshot, listener *envoy_listener_v3.Listener) error {
|
||||||
for idx := range listener.FilterChains {
|
for idx := range listener.FilterChains {
|
||||||
tlsContext := &envoy_tls_v3.DownstreamTlsContext{
|
tlsContext := &envoy_tls_v3.DownstreamTlsContext{
|
||||||
CommonTlsContext: makeCommonTLSContextFromLeaf(cfgSnap, cfgSnap.Leaf()),
|
CommonTlsContext: makeCommonTLSContextFromLeafWithoutParams(cfgSnap, cfgSnap.Leaf()),
|
||||||
RequireClientCertificate: &wrappers.BoolValue{Value: true},
|
RequireClientCertificate: &wrappers.BoolValue{Value: true},
|
||||||
}
|
}
|
||||||
transportSocket, err := makeDownstreamTLSTransportSocket(tlsContext)
|
transportSocket, err := makeDownstreamTLSTransportSocket(tlsContext)
|
||||||
|
@ -1062,7 +1062,7 @@ func (s *ResourceGenerator) makeFilterChainTerminatingGateway(
|
||||||
protocol string,
|
protocol string,
|
||||||
) (*envoy_listener_v3.FilterChain, error) {
|
) (*envoy_listener_v3.FilterChain, error) {
|
||||||
tlsContext := &envoy_tls_v3.DownstreamTlsContext{
|
tlsContext := &envoy_tls_v3.DownstreamTlsContext{
|
||||||
CommonTlsContext: makeCommonTLSContextFromLeaf(cfgSnap, cfgSnap.TerminatingGateway.ServiceLeaves[service]),
|
CommonTlsContext: makeCommonTLSContextFromLeafWithoutParams(cfgSnap, cfgSnap.TerminatingGateway.ServiceLeaves[service]),
|
||||||
RequireClientCertificate: &wrappers.BoolValue{Value: true},
|
RequireClientCertificate: &wrappers.BoolValue{Value: true},
|
||||||
}
|
}
|
||||||
transportSocket, err := makeDownstreamTLSTransportSocket(tlsContext)
|
transportSocket, err := makeDownstreamTLSTransportSocket(tlsContext)
|
||||||
|
@ -1536,7 +1536,11 @@ func makeEnvoyHTTPFilter(name string, cfg proto.Message) (*envoy_http_v3.HttpFil
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCommonTLSContextFromLeaf(cfgSnap *proxycfg.ConfigSnapshot, leaf *structs.IssuedCert) *envoy_tls_v3.CommonTlsContext {
|
func makeCommonTLSContextFromLeafWithoutParams(cfgSnap *proxycfg.ConfigSnapshot, leaf *structs.IssuedCert) *envoy_tls_v3.CommonTlsContext {
|
||||||
|
return makeCommonTLSContextFromLeaf(cfgSnap, leaf, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCommonTLSContextFromLeaf(cfgSnap *proxycfg.ConfigSnapshot, leaf *structs.IssuedCert, tlsParams *envoy_tls_v3.TlsParameters) *envoy_tls_v3.CommonTlsContext {
|
||||||
// Concatenate all the root PEMs into one.
|
// Concatenate all the root PEMs into one.
|
||||||
if cfgSnap.Roots == nil {
|
if cfgSnap.Roots == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -1547,8 +1551,12 @@ func makeCommonTLSContextFromLeaf(cfgSnap *proxycfg.ConfigSnapshot, leaf *struct
|
||||||
rootPEMS += ca.EnsureTrailingNewline(root.RootCert)
|
rootPEMS += ca.EnsureTrailingNewline(root.RootCert)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tlsParams == nil {
|
||||||
|
tlsParams = &envoy_tls_v3.TlsParameters{}
|
||||||
|
}
|
||||||
|
|
||||||
return &envoy_tls_v3.CommonTlsContext{
|
return &envoy_tls_v3.CommonTlsContext{
|
||||||
TlsParams: &envoy_tls_v3.TlsParameters{},
|
TlsParams: tlsParams,
|
||||||
TlsCertificates: []*envoy_tls_v3.TlsCertificate{
|
TlsCertificates: []*envoy_tls_v3.TlsCertificate{
|
||||||
{
|
{
|
||||||
CertificateChain: &envoy_core_v3.DataSource{
|
CertificateChain: &envoy_core_v3.DataSource{
|
||||||
|
|
|
@ -8,43 +8,26 @@ import (
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/golang/protobuf/ptypes/duration"
|
"github.com/golang/protobuf/ptypes/duration"
|
||||||
"github.com/golang/protobuf/ptypes/wrappers"
|
"github.com/golang/protobuf/ptypes/wrappers"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent/proxycfg"
|
"github.com/hashicorp/consul/agent/proxycfg"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
"github.com/hashicorp/consul/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||||
var resources []proto.Message
|
var resources []proto.Message
|
||||||
|
|
||||||
for listenerKey, upstreams := range cfgSnap.IngressGateway.Upstreams {
|
for listenerKey, upstreams := range cfgSnap.IngressGateway.Upstreams {
|
||||||
var tlsContext *envoy_tls_v3.DownstreamTlsContext
|
|
||||||
|
|
||||||
listenerCfg, ok := cfgSnap.IngressGateway.Listeners[listenerKey]
|
listenerCfg, ok := cfgSnap.IngressGateway.Listeners[listenerKey]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("no listener config found for listener on port %d", listenerKey.Port)
|
return nil, fmt.Errorf("no listener config found for listener on port %d", listenerKey.Port)
|
||||||
}
|
}
|
||||||
// Enable connect TLS if it is enabled at the Gateway or specific listener
|
|
||||||
// level.
|
|
||||||
connectTLSEnabled := cfgSnap.IngressGateway.TLSConfig.Enabled ||
|
|
||||||
(listenerCfg.TLS != nil && listenerCfg.TLS.Enabled)
|
|
||||||
|
|
||||||
sdsCfg, err := resolveListenerSDSConfig(cfgSnap, listenerCfg)
|
tlsContext, err := makeDownstreamTLSContextFromSnapshotListenerConfig(cfgSnap, listenerCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if sdsCfg != nil {
|
|
||||||
// Set up listener TLS from SDS
|
|
||||||
tlsContext = &envoy_tls_v3.DownstreamTlsContext{
|
|
||||||
CommonTlsContext: makeCommonTLSContextFromSDS(*sdsCfg),
|
|
||||||
RequireClientCertificate: &wrappers.BoolValue{Value: false},
|
|
||||||
}
|
|
||||||
} else if connectTLSEnabled {
|
|
||||||
tlsContext = &envoy_tls_v3.DownstreamTlsContext{
|
|
||||||
CommonTlsContext: makeCommonTLSContextFromLeaf(cfgSnap, cfgSnap.Leaf()),
|
|
||||||
RequireClientCertificate: &wrappers.BoolValue{Value: false},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if listenerKey.Protocol == "tcp" {
|
if listenerKey.Protocol == "tcp" {
|
||||||
// We rely on the invariant of upstreams slice always having at least 1
|
// We rely on the invariant of upstreams slice always having at least 1
|
||||||
// member, because this key/value pair is created only when a
|
// member, because this key/value pair is created only when a
|
||||||
|
@ -154,21 +137,116 @@ func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap
|
||||||
return resources, nil
|
return resources, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveListenerSDSConfig(cfgSnap *proxycfg.ConfigSnapshot, listenerCfg structs.IngressListener) (*structs.GatewayTLSSDSConfig, error) {
|
func makeDownstreamTLSContextFromSnapshotListenerConfig(cfgSnap *proxycfg.ConfigSnapshot, listenerCfg structs.IngressListener) (*envoy_tls_v3.DownstreamTlsContext, error) {
|
||||||
var mergedCfg structs.GatewayTLSSDSConfig
|
var downstreamContext *envoy_tls_v3.DownstreamTlsContext
|
||||||
|
|
||||||
gwSDS := cfgSnap.IngressGateway.TLSConfig.SDS
|
tlsContext, err := makeCommonTLSContextFromSnapshotListenerConfig(cfgSnap, listenerCfg)
|
||||||
if gwSDS != nil {
|
if err != nil {
|
||||||
mergedCfg.ClusterName = gwSDS.ClusterName
|
return nil, err
|
||||||
mergedCfg.CertResource = gwSDS.CertResource
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if listenerCfg.TLS != nil && listenerCfg.TLS.SDS != nil {
|
if tlsContext != nil {
|
||||||
if listenerCfg.TLS.SDS.ClusterName != "" {
|
downstreamContext = &envoy_tls_v3.DownstreamTlsContext{
|
||||||
mergedCfg.ClusterName = listenerCfg.TLS.SDS.ClusterName
|
CommonTlsContext: tlsContext,
|
||||||
|
RequireClientCertificate: &wrappers.BoolValue{Value: false},
|
||||||
}
|
}
|
||||||
if listenerCfg.TLS.SDS.CertResource != "" {
|
}
|
||||||
mergedCfg.CertResource = listenerCfg.TLS.SDS.CertResource
|
|
||||||
|
return downstreamContext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCommonTLSContextFromSnapshotListenerConfig(cfgSnap *proxycfg.ConfigSnapshot, listenerCfg structs.IngressListener) (*envoy_tls_v3.CommonTlsContext, error) {
|
||||||
|
var tlsContext *envoy_tls_v3.CommonTlsContext
|
||||||
|
|
||||||
|
// Enable connect TLS if it is enabled at the Gateway or specific listener
|
||||||
|
// level.
|
||||||
|
gatewayTLSCfg := cfgSnap.IngressGateway.TLSConfig
|
||||||
|
|
||||||
|
// It is not possible to explicitly _disable_ TLS on a listener if it's
|
||||||
|
// enabled on the gateway, because false is the zero-value of the struct field
|
||||||
|
// and therefore indistinguishable from it being unspecified.
|
||||||
|
connectTLSEnabled := gatewayTLSCfg.Enabled ||
|
||||||
|
(listenerCfg.TLS != nil && listenerCfg.TLS.Enabled)
|
||||||
|
|
||||||
|
tlsCfg, err := resolveListenerTLSConfig(&gatewayTLSCfg, listenerCfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if tlsCfg.SDS != nil {
|
||||||
|
// Set up listener TLS from SDS
|
||||||
|
tlsContext = makeCommonTLSContextFromGatewayTLSConfig(*tlsCfg)
|
||||||
|
} else if connectTLSEnabled {
|
||||||
|
tlsContext = makeCommonTLSContextFromLeaf(cfgSnap, cfgSnap.Leaf(), makeTLSParametersFromGatewayTLSConfig(*tlsCfg))
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlsContext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveListenerTLSConfig(gatewayTLSCfg *structs.GatewayTLSConfig, listenerCfg structs.IngressListener) (*structs.GatewayTLSConfig, error) {
|
||||||
|
var mergedCfg structs.GatewayTLSConfig
|
||||||
|
|
||||||
|
resolvedSDSCfg, err := resolveListenerSDSConfig(gatewayTLSCfg.SDS, listenerCfg.TLS, listenerCfg.Port)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mergedCfg.SDS = resolvedSDSCfg
|
||||||
|
|
||||||
|
if gatewayTLSCfg != nil {
|
||||||
|
mergedCfg.TLSMinVersion = gatewayTLSCfg.TLSMinVersion
|
||||||
|
mergedCfg.TLSMaxVersion = gatewayTLSCfg.TLSMaxVersion
|
||||||
|
mergedCfg.CipherSuites = gatewayTLSCfg.CipherSuites
|
||||||
|
}
|
||||||
|
|
||||||
|
if listenerCfg.TLS != nil {
|
||||||
|
if listenerCfg.TLS.TLSMinVersion != types.TLSVersionUnspecified {
|
||||||
|
mergedCfg.TLSMinVersion = listenerCfg.TLS.TLSMinVersion
|
||||||
|
}
|
||||||
|
if listenerCfg.TLS.TLSMaxVersion != types.TLSVersionUnspecified {
|
||||||
|
mergedCfg.TLSMaxVersion = listenerCfg.TLS.TLSMaxVersion
|
||||||
|
}
|
||||||
|
if len(listenerCfg.TLS.CipherSuites) != 0 {
|
||||||
|
mergedCfg.CipherSuites = listenerCfg.TLS.CipherSuites
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var TLSVersionsWithConfigurableCipherSuites = map[types.TLSVersion]struct{}{
|
||||||
|
// Remove these two if Envoy ever sets TLS 1.3 as default minimum
|
||||||
|
types.TLSVersionUnspecified: {},
|
||||||
|
types.TLSVersionAuto: {},
|
||||||
|
|
||||||
|
types.TLSv1_0: {},
|
||||||
|
types.TLSv1_1: {},
|
||||||
|
types.TLSv1_2: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate. Configuring cipher suites is only applicable to connections negotiated
|
||||||
|
// via TLS 1.2 or earlier. Other cases shouldn't be possible as we validate them at
|
||||||
|
// input but be resilient to bugs later.
|
||||||
|
if len(mergedCfg.CipherSuites) != 0 {
|
||||||
|
if _, ok := TLSVersionsWithConfigurableCipherSuites[mergedCfg.TLSMinVersion]; !ok {
|
||||||
|
return nil, fmt.Errorf("configuring CipherSuites is only applicable to connections negotiated with TLS 1.2 or earlier, TLSMinVersion is set to %s in listener or gateway config", mergedCfg.TLSMinVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &mergedCfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveListenerSDSConfig(gatewaySDSCfg *structs.GatewayTLSSDSConfig, listenerTLSCfg *structs.GatewayTLSConfig, listenerPort int) (*structs.GatewayTLSSDSConfig, error) {
|
||||||
|
var mergedCfg structs.GatewayTLSSDSConfig
|
||||||
|
|
||||||
|
if gatewaySDSCfg != nil {
|
||||||
|
mergedCfg.ClusterName = gatewaySDSCfg.ClusterName
|
||||||
|
mergedCfg.CertResource = gatewaySDSCfg.CertResource
|
||||||
|
}
|
||||||
|
|
||||||
|
if listenerTLSCfg != nil && listenerTLSCfg.SDS != nil {
|
||||||
|
if listenerTLSCfg.SDS.ClusterName != "" {
|
||||||
|
mergedCfg.ClusterName = listenerTLSCfg.SDS.ClusterName
|
||||||
|
}
|
||||||
|
if listenerTLSCfg.SDS.CertResource != "" {
|
||||||
|
mergedCfg.CertResource = listenerTLSCfg.SDS.CertResource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,10 +261,10 @@ func resolveListenerSDSConfig(cfgSnap *proxycfg.ConfigSnapshot, listenerCfg stru
|
||||||
return &mergedCfg, nil
|
return &mergedCfg, nil
|
||||||
|
|
||||||
case mergedCfg.ClusterName == "" && mergedCfg.CertResource != "":
|
case mergedCfg.ClusterName == "" && mergedCfg.CertResource != "":
|
||||||
return nil, fmt.Errorf("missing SDS cluster name for listener on port %d", listenerCfg.Port)
|
return nil, fmt.Errorf("missing SDS cluster name for listener on port %d", listenerPort)
|
||||||
|
|
||||||
case mergedCfg.ClusterName != "" && mergedCfg.CertResource == "":
|
case mergedCfg.ClusterName != "" && mergedCfg.CertResource == "":
|
||||||
return nil, fmt.Errorf("missing SDS cert resource for listener on port %d", listenerCfg.Port)
|
return nil, fmt.Errorf("missing SDS cert resource for listener on port %d", listenerPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &mergedCfg, nil
|
return &mergedCfg, nil
|
||||||
|
@ -260,7 +338,7 @@ func makeSDSOverrideFilterChains(cfgSnap *proxycfg.ConfigSnapshot,
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsContext := &envoy_tls_v3.DownstreamTlsContext{
|
tlsContext := &envoy_tls_v3.DownstreamTlsContext{
|
||||||
CommonTlsContext: makeCommonTLSContextFromSDS(*svc.TLS.SDS),
|
CommonTlsContext: makeCommonTLSContextFromGatewayServiceTLSConfig(*svc.TLS),
|
||||||
RequireClientCertificate: &wrappers.BoolValue{Value: false},
|
RequireClientCertificate: &wrappers.BoolValue{Value: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,33 +362,71 @@ func makeSDSOverrideFilterChains(cfgSnap *proxycfg.ConfigSnapshot,
|
||||||
return chains, nil
|
return chains, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCommonTLSContextFromSDS(sdsCfg structs.GatewayTLSSDSConfig) *envoy_tls_v3.CommonTlsContext {
|
var envoyTLSVersions = map[types.TLSVersion]envoy_tls_v3.TlsParameters_TlsProtocol{
|
||||||
|
types.TLSVersionAuto: envoy_tls_v3.TlsParameters_TLS_AUTO,
|
||||||
|
types.TLSv1_0: envoy_tls_v3.TlsParameters_TLSv1_0,
|
||||||
|
types.TLSv1_1: envoy_tls_v3.TlsParameters_TLSv1_1,
|
||||||
|
types.TLSv1_2: envoy_tls_v3.TlsParameters_TLSv1_2,
|
||||||
|
types.TLSv1_3: envoy_tls_v3.TlsParameters_TLSv1_3,
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTLSParametersFromGatewayTLSConfig(tlsCfg structs.GatewayTLSConfig) *envoy_tls_v3.TlsParameters {
|
||||||
|
tlsParams := envoy_tls_v3.TlsParameters{}
|
||||||
|
|
||||||
|
if tlsCfg.TLSMinVersion != types.TLSVersionUnspecified {
|
||||||
|
if minVersion, ok := envoyTLSVersions[tlsCfg.TLSMinVersion]; ok {
|
||||||
|
tlsParams.TlsMinimumProtocolVersion = minVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tlsCfg.TLSMaxVersion != types.TLSVersionUnspecified {
|
||||||
|
if maxVersion, ok := envoyTLSVersions[tlsCfg.TLSMaxVersion]; ok {
|
||||||
|
tlsParams.TlsMaximumProtocolVersion = maxVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(tlsCfg.CipherSuites) != 0 {
|
||||||
|
tlsParams.CipherSuites = types.MarshalEnvoyTLSCipherSuiteStrings(tlsCfg.CipherSuites)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tlsParams
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCommonTLSContextFromGatewayTLSConfig(tlsCfg structs.GatewayTLSConfig) *envoy_tls_v3.CommonTlsContext {
|
||||||
return &envoy_tls_v3.CommonTlsContext{
|
return &envoy_tls_v3.CommonTlsContext{
|
||||||
TlsParams: &envoy_tls_v3.TlsParameters{},
|
TlsParams: makeTLSParametersFromGatewayTLSConfig(tlsCfg),
|
||||||
TlsCertificateSdsSecretConfigs: []*envoy_tls_v3.SdsSecretConfig{
|
TlsCertificateSdsSecretConfigs: makeTLSCertificateSdsSecretConfigsFromSDS(*tlsCfg.SDS),
|
||||||
{
|
}
|
||||||
Name: sdsCfg.CertResource,
|
}
|
||||||
SdsConfig: &envoy_core_v3.ConfigSource{
|
|
||||||
ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_ApiConfigSource{
|
func makeCommonTLSContextFromGatewayServiceTLSConfig(tlsCfg structs.GatewayServiceTLSConfig) *envoy_tls_v3.CommonTlsContext {
|
||||||
ApiConfigSource: &envoy_core_v3.ApiConfigSource{
|
return &envoy_tls_v3.CommonTlsContext{
|
||||||
ApiType: envoy_core_v3.ApiConfigSource_GRPC,
|
TlsParams: &envoy_tls_v3.TlsParameters{},
|
||||||
TransportApiVersion: envoy_core_v3.ApiVersion_V3,
|
TlsCertificateSdsSecretConfigs: makeTLSCertificateSdsSecretConfigsFromSDS(*tlsCfg.SDS),
|
||||||
// Note ClusterNames can't be set here - that's only for REST type
|
}
|
||||||
// we need a full GRPC config instead.
|
}
|
||||||
GrpcServices: []*envoy_core_v3.GrpcService{
|
func makeTLSCertificateSdsSecretConfigsFromSDS(sdsCfg structs.GatewayTLSSDSConfig) []*envoy_tls_v3.SdsSecretConfig {
|
||||||
{
|
return []*envoy_tls_v3.SdsSecretConfig{
|
||||||
TargetSpecifier: &envoy_core_v3.GrpcService_EnvoyGrpc_{
|
{
|
||||||
EnvoyGrpc: &envoy_core_v3.GrpcService_EnvoyGrpc{
|
Name: sdsCfg.CertResource,
|
||||||
ClusterName: sdsCfg.ClusterName,
|
SdsConfig: &envoy_core_v3.ConfigSource{
|
||||||
},
|
ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_ApiConfigSource{
|
||||||
|
ApiConfigSource: &envoy_core_v3.ApiConfigSource{
|
||||||
|
ApiType: envoy_core_v3.ApiConfigSource_GRPC,
|
||||||
|
TransportApiVersion: envoy_core_v3.ApiVersion_V3,
|
||||||
|
// Note ClusterNames can't be set here - that's only for REST type
|
||||||
|
// we need a full GRPC config instead.
|
||||||
|
GrpcServices: []*envoy_core_v3.GrpcService{
|
||||||
|
{
|
||||||
|
TargetSpecifier: &envoy_core_v3.GrpcService_EnvoyGrpc_{
|
||||||
|
EnvoyGrpc: &envoy_core_v3.GrpcService_EnvoyGrpc{
|
||||||
|
ClusterName: sdsCfg.ClusterName,
|
||||||
},
|
},
|
||||||
Timeout: &duration.Duration{Seconds: 5},
|
|
||||||
},
|
},
|
||||||
|
Timeout: &duration.Duration{Seconds: 5},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ResourceApiVersion: envoy_core_v3.ApiVersion_V3,
|
|
||||||
},
|
},
|
||||||
|
ResourceApiVersion: envoy_core_v3.ApiVersion_V3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -519,6 +519,30 @@ func TestListenersFromSnapshot(t *testing.T) {
|
||||||
create: proxycfg.TestConfigSnapshotIngressWithTLSListener,
|
create: proxycfg.TestConfigSnapshotIngressWithTLSListener,
|
||||||
setup: nil,
|
setup: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ingress-with-tls-listener-min-version",
|
||||||
|
create: proxycfg.TestConfigSnapshotIngressWithTLSListener,
|
||||||
|
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||||
|
snap.IngressGateway.TLSConfig.TLSMinVersion = types.TLSv1_3
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ingress-with-tls-listener-max-version",
|
||||||
|
create: proxycfg.TestConfigSnapshotIngressWithTLSListener,
|
||||||
|
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||||
|
snap.IngressGateway.TLSConfig.TLSMaxVersion = types.TLSv1_2
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ingress-with-tls-listener-cipher-suites",
|
||||||
|
create: proxycfg.TestConfigSnapshotIngressWithTLSListener,
|
||||||
|
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||||
|
snap.IngressGateway.TLSConfig.CipherSuites = []types.TLSCipherSuite{
|
||||||
|
types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ingress-with-tls-mixed-listeners",
|
name: "ingress-with-tls-mixed-listeners",
|
||||||
// Use SDS helper even though we aren't testing SDS since it already sets
|
// Use SDS helper even though we aren't testing SDS since it already sets
|
||||||
|
@ -572,6 +596,215 @@ func TestListenersFromSnapshot(t *testing.T) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ingress-with-tls-min-version-listeners-gateway-defaults",
|
||||||
|
create: proxycfg.TestConfigSnapshotIngressWithTLSListener,
|
||||||
|
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||||
|
snap.IngressGateway.TLSConfig.TLSMinVersion = types.TLSv1_2
|
||||||
|
|
||||||
|
// One listener disables TLS, one inherits TLS minimum version from the gateway
|
||||||
|
// config, two others set different versions
|
||||||
|
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||||
|
{Protocol: "http", Port: 8080}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s1",
|
||||||
|
LocalBindPort: 8080,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8081}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s2",
|
||||||
|
LocalBindPort: 8081,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8082}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s3",
|
||||||
|
LocalBindPort: 8082,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8083}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s4",
|
||||||
|
LocalBindPort: 8083,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8084}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s4",
|
||||||
|
LocalBindPort: 8084,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||||
|
// Omits listener TLS config, should default to gateway TLS config
|
||||||
|
{Protocol: "http", Port: 8080}: {
|
||||||
|
Port: 8080,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Explicitly sets listener TLS config to nil, should default to gateway TLS config
|
||||||
|
{Protocol: "http", Port: 8081}: {
|
||||||
|
Port: 8081,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: nil,
|
||||||
|
},
|
||||||
|
// Explicitly enables TLS config, but with no listener default TLS params,
|
||||||
|
// should default to gateway TLS config
|
||||||
|
{Protocol: "http", Port: 8082}: {
|
||||||
|
Port: 8082,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &structs.GatewayTLSConfig{
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Explicitly unset gateway default TLS min version in favor of proxy default
|
||||||
|
{Protocol: "http", Port: 8083}: {
|
||||||
|
Port: 8083,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &structs.GatewayTLSConfig{
|
||||||
|
Enabled: true,
|
||||||
|
TLSMinVersion: types.TLSVersionAuto,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Disables listener TLS
|
||||||
|
{Protocol: "http", Port: 8084}: {
|
||||||
|
Port: 8084,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &structs.GatewayTLSConfig{
|
||||||
|
Enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ingress-with-single-tls-listener",
|
||||||
|
create: proxycfg.TestConfigSnapshotIngress,
|
||||||
|
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||||
|
// One listener should inherit non-TLS gateway config, another
|
||||||
|
// listener configures TLS with an explicit minimum version
|
||||||
|
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||||
|
{Protocol: "http", Port: 8080}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s1",
|
||||||
|
LocalBindPort: 8080,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8081}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s2",
|
||||||
|
LocalBindPort: 8081,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||||
|
{Protocol: "http", Port: 8080}: {
|
||||||
|
Port: 8080,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8081}: {
|
||||||
|
Port: 8081,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &structs.GatewayTLSConfig{
|
||||||
|
Enabled: true,
|
||||||
|
TLSMinVersion: types.TLSv1_2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ingress-with-tls-mixed-min-version-listeners",
|
||||||
|
create: proxycfg.TestConfigSnapshotIngressWithTLSListener,
|
||||||
|
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||||
|
snap.IngressGateway.TLSConfig.TLSMinVersion = types.TLSv1_2
|
||||||
|
|
||||||
|
// One listener should inherit TLS minimum version from the gateway config,
|
||||||
|
// two others each set explicit TLS minimum versions
|
||||||
|
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||||
|
{Protocol: "http", Port: 8080}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s1",
|
||||||
|
LocalBindPort: 8080,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8081}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s2",
|
||||||
|
LocalBindPort: 8081,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8082}: {
|
||||||
|
{
|
||||||
|
DestinationName: "s3",
|
||||||
|
LocalBindPort: 8082,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||||
|
{Protocol: "http", Port: 8080}: {
|
||||||
|
Port: 8080,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8081}: {
|
||||||
|
Port: 8081,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &structs.GatewayTLSConfig{
|
||||||
|
Enabled: true,
|
||||||
|
TLSMinVersion: types.TLSv1_0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Protocol: "http", Port: 8082}: {
|
||||||
|
Port: 8082,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{
|
||||||
|
Name: "s3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &structs.GatewayTLSConfig{
|
||||||
|
Enabled: true,
|
||||||
|
TLSMinVersion: types.TLSv1_3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ingress-with-sds-listener-gw-level",
|
name: "ingress-with-sds-listener-gw-level",
|
||||||
create: proxycfg.TestConfigSnapshotIngressWithGatewaySDS,
|
create: proxycfg.TestConfigSnapshotIngressWithGatewaySDS,
|
||||||
|
@ -1208,7 +1441,7 @@ func TestResolveListenerSDSConfig(t *testing.T) {
|
||||||
listenerCfg = lisCfg
|
listenerCfg = lisCfg
|
||||||
}
|
}
|
||||||
|
|
||||||
got, err := resolveListenerSDSConfig(snap, listenerCfg)
|
got, err := resolveListenerSDSConfig(snap.IngressGateway.TLSConfig.SDS, listenerCfg.TLS, listenerCfg.Port)
|
||||||
if tc.wantErr != "" {
|
if tc.wantErr != "" {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Contains(t, err.Error(), tc.wantErr)
|
require.Contains(t, err.Error(), tc.wantErr)
|
||||||
|
|
120
agent/xds/testdata/listeners/ingress-with-single-tls-listener.envoy-1-20-x.golden
vendored
Normal file
120
agent/xds/testdata/listeners/ingress-with-single-tls-listener.envoy-1-20-x.golden
vendored
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8080",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8080
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8080",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8080"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8081",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8081
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8081",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8081"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMinimumProtocolVersion": "TLSv1_2"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
62
agent/xds/testdata/listeners/ingress-with-tls-listener-cipher-suites.envoy-1-20-x.golden
vendored
Normal file
62
agent/xds/testdata/listeners/ingress-with-tls-listener-cipher-suites.envoy-1-20-x.golden
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "db:1.2.3.4:9191",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 9191
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.tcp_proxy",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||||
|
"statPrefix": "upstream.db.default.default.dc1",
|
||||||
|
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"cipherSuites": [
|
||||||
|
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
||||||
|
"ECDHE-ECDSA-CHACHA20-POLY1305"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
59
agent/xds/testdata/listeners/ingress-with-tls-listener-max-version.envoy-1-20-x.golden
vendored
Normal file
59
agent/xds/testdata/listeners/ingress-with-tls-listener-max-version.envoy-1-20-x.golden
vendored
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "db:1.2.3.4:9191",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 9191
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.tcp_proxy",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||||
|
"statPrefix": "upstream.db.default.default.dc1",
|
||||||
|
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMaximumProtocolVersion": "TLSv1_2"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
59
agent/xds/testdata/listeners/ingress-with-tls-listener-min-version.envoy-1-20-x.golden
vendored
Normal file
59
agent/xds/testdata/listeners/ingress-with-tls-listener-min-version.envoy-1-20-x.golden
vendored
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "db:1.2.3.4:9191",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 9191
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.tcp_proxy",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||||
|
"statPrefix": "upstream.db.default.default.dc1",
|
||||||
|
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMinimumProtocolVersion": "TLSv1_3"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
|
@ -0,0 +1,357 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8080",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8080
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8080",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8080"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMinimumProtocolVersion": "TLSv1_2"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8081",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8081
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8081",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8081"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMinimumProtocolVersion": "TLSv1_2"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8082",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8082
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8082",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8082"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMinimumProtocolVersion": "TLSv1_2"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8083",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8083
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8083",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8083"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8084",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8084
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8084",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8084"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMinimumProtocolVersion": "TLSv1_2"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
217
agent/xds/testdata/listeners/ingress-with-tls-mixed-min-version-listeners.envoy-1-20-x.golden
vendored
Normal file
217
agent/xds/testdata/listeners/ingress-with-tls-mixed-min-version-listeners.envoy-1-20-x.golden
vendored
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8080",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8080
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8080",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8080"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMinimumProtocolVersion": "TLSv1_2"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8081",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8081
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8081",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8081"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMinimumProtocolVersion": "TLSv1_0"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"name": "http:1.2.3.4:8082",
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "1.2.3.4",
|
||||||
|
"portValue": 8082
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filterChains": [
|
||||||
|
{
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.network.http_connection_manager",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||||
|
"statPrefix": "ingress_upstream_8082",
|
||||||
|
"rds": {
|
||||||
|
"configSource": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"resourceApiVersion": "V3"
|
||||||
|
},
|
||||||
|
"routeConfigName": "8082"
|
||||||
|
},
|
||||||
|
"httpFilters": [
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.http.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tracing": {
|
||||||
|
"randomSampling": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transportSocket": {
|
||||||
|
"name": "tls",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||||
|
"commonTlsContext": {
|
||||||
|
"tlsParams": {
|
||||||
|
"tlsMinimumProtocolVersion": "TLSv1_3"
|
||||||
|
},
|
||||||
|
"tlsCertificates": [
|
||||||
|
{
|
||||||
|
"certificateChain": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||||
|
},
|
||||||
|
"privateKey": {
|
||||||
|
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validationContext": {
|
||||||
|
"trustedCa": {
|
||||||
|
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requireClientCertificate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trafficDirection": "OUTBOUND"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
|
@ -43,6 +43,13 @@ type GatewayTLSConfig struct {
|
||||||
|
|
||||||
// SDS allows configuring TLS certificate from an SDS service.
|
// SDS allows configuring TLS certificate from an SDS service.
|
||||||
SDS *GatewayTLSSDSConfig `json:",omitempty"`
|
SDS *GatewayTLSSDSConfig `json:",omitempty"`
|
||||||
|
|
||||||
|
TLSMinVersion string `json:",omitempty" alias:"tls_min_version"`
|
||||||
|
TLSMaxVersion string `json:",omitempty" alias:"tls_max_version"`
|
||||||
|
|
||||||
|
// Define a subset of cipher suites to restrict
|
||||||
|
// Only applicable to connections negotiated via TLS 1.2 or earlier
|
||||||
|
CipherSuites []string `json:",omitempty" alias:"cipher_suites"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GatewayServiceTLSConfig struct {
|
type GatewayServiceTLSConfig struct {
|
||||||
|
|
|
@ -26,7 +26,8 @@ func TestAPI_ConfigEntries_IngressGateway(t *testing.T) {
|
||||||
Kind: IngressGateway,
|
Kind: IngressGateway,
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
TLS: GatewayTLSConfig{
|
TLS: GatewayTLSConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
|
TLSMinVersion: "TLSv1_2",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -945,6 +945,7 @@ func TestDecodeConfigEntry(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// TODO(rb): test SDS stuff here in both places (global/service)
|
||||||
name: "ingress-gateway",
|
name: "ingress-gateway",
|
||||||
body: `
|
body: `
|
||||||
{
|
{
|
||||||
|
@ -955,7 +956,13 @@ func TestDecodeConfigEntry(t *testing.T) {
|
||||||
"gir": "zim"
|
"gir": "zim"
|
||||||
},
|
},
|
||||||
"Tls": {
|
"Tls": {
|
||||||
"Enabled": true
|
"Enabled": true,
|
||||||
|
"TLSMinVersion": "TLSv1_1",
|
||||||
|
"TLSMaxVersion": "TLSv1_2",
|
||||||
|
"CipherSuites": [
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"Listeners": [
|
"Listeners": [
|
||||||
{
|
{
|
||||||
|
@ -992,7 +999,13 @@ func TestDecodeConfigEntry(t *testing.T) {
|
||||||
"gir": "zim",
|
"gir": "zim",
|
||||||
},
|
},
|
||||||
TLS: GatewayTLSConfig{
|
TLS: GatewayTLSConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
|
TLSMinVersion: "TLSv1_1",
|
||||||
|
TLSMaxVersion: "TLSv1_2",
|
||||||
|
CipherSuites: []string{
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Listeners: []IngressListener{
|
Listeners: []IngressListener{
|
||||||
{
|
{
|
||||||
|
|
|
@ -2096,6 +2096,7 @@ func TestParseConfigEntry(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// TODO(rb): test SDS stuff here in both places (global/service)
|
||||||
name: "ingress-gateway: kitchen sink",
|
name: "ingress-gateway: kitchen sink",
|
||||||
snake: `
|
snake: `
|
||||||
kind = "ingress-gateway"
|
kind = "ingress-gateway"
|
||||||
|
@ -2106,6 +2107,12 @@ func TestParseConfigEntry(t *testing.T) {
|
||||||
}
|
}
|
||||||
tls {
|
tls {
|
||||||
enabled = true
|
enabled = true
|
||||||
|
tls_min_version = "TLSv1_1"
|
||||||
|
tls_max_version = "TLSv1_2"
|
||||||
|
cipher_suites = [
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
listeners = [
|
listeners = [
|
||||||
{
|
{
|
||||||
|
@ -2133,6 +2140,12 @@ func TestParseConfigEntry(t *testing.T) {
|
||||||
}
|
}
|
||||||
Tls {
|
Tls {
|
||||||
Enabled = true
|
Enabled = true
|
||||||
|
TLSMinVersion = "TLSv1_1"
|
||||||
|
TLSMaxVersion = "TLSv1_2"
|
||||||
|
CipherSuites = [
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
Listeners = [
|
Listeners = [
|
||||||
{
|
{
|
||||||
|
@ -2160,7 +2173,13 @@ func TestParseConfigEntry(t *testing.T) {
|
||||||
"gir": "zim"
|
"gir": "zim"
|
||||||
},
|
},
|
||||||
"tls": {
|
"tls": {
|
||||||
"enabled": true
|
"enabled": true,
|
||||||
|
"tls_min_version": "TLSv1_1",
|
||||||
|
"tls_max_version": "TLSv1_2",
|
||||||
|
"cipher_suites": [
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"listeners": [
|
"listeners": [
|
||||||
{
|
{
|
||||||
|
@ -2188,8 +2207,14 @@ func TestParseConfigEntry(t *testing.T) {
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
"gir": "zim"
|
"gir": "zim"
|
||||||
},
|
},
|
||||||
"Tls": {
|
"TLS": {
|
||||||
"Enabled": true
|
"Enabled": true,
|
||||||
|
"TLSMinVersion": "TLSv1_1",
|
||||||
|
"TLSMaxVersion": "TLSv1_2",
|
||||||
|
"CipherSuites": [
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"Listeners": [
|
"Listeners": [
|
||||||
{
|
{
|
||||||
|
@ -2217,7 +2242,13 @@ func TestParseConfigEntry(t *testing.T) {
|
||||||
"gir": "zim",
|
"gir": "zim",
|
||||||
},
|
},
|
||||||
TLS: api.GatewayTLSConfig{
|
TLS: api.GatewayTLSConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
|
TLSMinVersion: "TLSv1_1",
|
||||||
|
TLSMaxVersion: "TLSv1_2",
|
||||||
|
CipherSuites: []string{
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Listeners: []api.IngressListener{
|
Listeners: []api.IngressListener{
|
||||||
{
|
{
|
||||||
|
|
240
types/tls.go
240
types/tls.go
|
@ -1,43 +1,42 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TLSVersion is a strongly-typed int used for relative comparison
|
// TLSVersion is a strongly-typed string for TLS versions
|
||||||
// (minimum, maximum, greater than, less than) of TLS versions
|
type TLSVersion string
|
||||||
type TLSVersion int
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Error value, excluded from lookup maps
|
// Error value, excluded from lookup maps
|
||||||
TLSVersionInvalid TLSVersion = iota - 1
|
TLSVersionInvalid TLSVersion = "TLS_INVALID"
|
||||||
|
|
||||||
// Explicit unspecified zero-value to avoid overwriting parent defaults
|
// Explicit unspecified zero-value to avoid overwriting parent defaults
|
||||||
TLSVersionUnspecified
|
TLSVersionUnspecified TLSVersion = ""
|
||||||
|
|
||||||
// Explictly allow implementation to select TLS version
|
// Explictly allow implementation to select TLS version
|
||||||
// May be useful to supercede defaults specified at a higher layer
|
// May be useful to supercede defaults specified at a higher layer
|
||||||
TLSVersionAuto
|
TLSVersionAuto TLSVersion = "TLS_AUTO"
|
||||||
|
|
||||||
_ // Placeholder for SSLv3, hopefully we won't have to add this
|
_ // Placeholder for SSLv3, hopefully we won't have to add this
|
||||||
|
|
||||||
// TLS versions
|
// TLS versions
|
||||||
TLSv1_0
|
TLSv1_0 TLSVersion = "TLSv1_0"
|
||||||
TLSv1_1
|
TLSv1_1 TLSVersion = "TLSv1_1"
|
||||||
TLSv1_2
|
TLSv1_2 TLSVersion = "TLSv1_2"
|
||||||
TLSv1_3
|
TLSv1_3 TLSVersion = "TLSv1_3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
TLSVersions = map[string]TLSVersion{
|
tlsVersions = map[TLSVersion]struct{}{
|
||||||
"TLS_AUTO": TLSVersionAuto,
|
TLSVersionAuto: {},
|
||||||
"TLSv1_0": TLSv1_0,
|
TLSv1_0: {},
|
||||||
"TLSv1_1": TLSv1_1,
|
TLSv1_1: {},
|
||||||
"TLSv1_2": TLSv1_2,
|
TLSv1_2: {},
|
||||||
"TLSv1_3": TLSv1_3,
|
TLSv1_3: {},
|
||||||
}
|
}
|
||||||
// NOTE: This interface is deprecated in favor of TLSVersions
|
// NOTE: This interface is deprecated in favor of tlsVersions
|
||||||
// and should be eventually removed in a future release.
|
// and should be eventually removed in a future release.
|
||||||
DeprecatedConsulAgentTLSVersions = map[string]TLSVersion{
|
DeprecatedConsulAgentTLSVersions = map[string]TLSVersion{
|
||||||
"": TLSVersionAuto,
|
"": TLSVersionAuto,
|
||||||
|
@ -46,24 +45,10 @@ var (
|
||||||
"tls12": TLSv1_2,
|
"tls12": TLSv1_2,
|
||||||
"tls13": TLSv1_3,
|
"tls13": TLSv1_3,
|
||||||
}
|
}
|
||||||
HumanTLSVersionStrings = map[TLSVersion]string{
|
|
||||||
TLSVersionAuto: "Allow implementation to select TLS version",
|
|
||||||
TLSv1_0: "TLS 1.0",
|
|
||||||
TLSv1_1: "TLS 1.1",
|
|
||||||
TLSv1_2: "TLS 1.2",
|
|
||||||
TLSv1_3: "TLS 1.3",
|
|
||||||
}
|
|
||||||
ConsulConfigTLSVersionStrings = func() map[TLSVersion]string {
|
|
||||||
inverted := make(map[TLSVersion]string, len(TLSVersions))
|
|
||||||
for k, v := range TLSVersions {
|
|
||||||
inverted[v] = k
|
|
||||||
}
|
|
||||||
return inverted
|
|
||||||
}()
|
|
||||||
// NOTE: these currently map to the deprecated config strings to support the
|
// NOTE: these currently map to the deprecated config strings to support the
|
||||||
// deployment pattern of upgrading servers first. This map should eventually
|
// deployment pattern of upgrading servers first. This map should eventually
|
||||||
// be removed and any lookups updated to use ConsulConfigTLSVersionStrings
|
// be removed and any lookups updated to instead use the TLSVersion string
|
||||||
// with newer config strings instead in a future release.
|
// values directly in a future release.
|
||||||
ConsulAutoConfigTLSVersionStrings = map[TLSVersion]string{
|
ConsulAutoConfigTLSVersionStrings = map[TLSVersion]string{
|
||||||
TLSVersionAuto: "",
|
TLSVersionAuto: "",
|
||||||
TLSv1_0: "tls10",
|
TLSv1_0: "tls10",
|
||||||
|
@ -71,33 +56,51 @@ var (
|
||||||
TLSv1_2: "tls12",
|
TLSv1_2: "tls12",
|
||||||
TLSv1_3: "tls13",
|
TLSv1_3: "tls13",
|
||||||
}
|
}
|
||||||
|
TLSVersionsWithConfigurableCipherSuites = map[TLSVersion]struct{}{
|
||||||
|
// NOTE: these two are implementation-dependent, but it is not expected that
|
||||||
|
// either Go or Envoy would default to TLS 1.3 as a minimum version in the
|
||||||
|
// near future
|
||||||
|
TLSVersionUnspecified: {},
|
||||||
|
TLSVersionAuto: {},
|
||||||
|
|
||||||
|
TLSv1_0: {},
|
||||||
|
TLSv1_1: {},
|
||||||
|
TLSv1_2: {},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (v TLSVersion) String() string {
|
func (v *TLSVersion) String() string {
|
||||||
return ConsulConfigTLSVersionStrings[v]
|
return string(*v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v TLSVersion) MarshalJSON() ([]byte, error) {
|
var tlsVersionComparison = map[TLSVersion]uint{
|
||||||
return json.Marshal(v.String())
|
TLSv1_0: 1,
|
||||||
|
TLSv1_1: 2,
|
||||||
|
TLSv1_2: 3,
|
||||||
|
TLSv1_3: 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *TLSVersion) UnmarshalJSON(bytes []byte) error {
|
// Will only return true for concrete versions and won't catch
|
||||||
versionStr := string(bytes)
|
// implementation-dependent conflicts with TLSVersionAuto or unspecified values
|
||||||
|
func (a TLSVersion) LessThan(b TLSVersion) (error, bool) {
|
||||||
if n := len(versionStr); n > 1 && versionStr[0] == '"' && versionStr[n-1] == '"' {
|
for _, v := range []TLSVersion{a, b} {
|
||||||
versionStr = versionStr[1 : n-1] // trim surrounding quotes
|
if _, ok := tlsVersionComparison[v]; !ok {
|
||||||
|
return fmt.Errorf("can't compare implementation-dependent values"), false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if version, ok := TLSVersions[versionStr]; ok {
|
return nil, tlsVersionComparison[a] < tlsVersionComparison[b]
|
||||||
*v = version
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
*v = TLSVersionInvalid
|
|
||||||
return fmt.Errorf("no matching TLS Version found for %s", versionStr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IANA cipher suite constants and values as defined at
|
func ValidateTLSVersion(v TLSVersion) error {
|
||||||
|
if _, ok := tlsVersions[v]; !ok {
|
||||||
|
return fmt.Errorf("no matching TLS version found for %s", v.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IANA cipher suite string constants as defined at
|
||||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
|
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
|
||||||
// This is the total list of TLS 1.2-style cipher suites
|
// This is the total list of TLS 1.2-style cipher suites
|
||||||
// which are currently supported by either Envoy 1.21 or the Consul agent
|
// which are currently supported by either Envoy 1.21 or the Consul agent
|
||||||
|
@ -106,67 +109,49 @@ func (v *TLSVersion) UnmarshalJSON(bytes []byte) error {
|
||||||
// and as supported cipher suites in the Go runtime change.
|
// and as supported cipher suites in the Go runtime change.
|
||||||
//
|
//
|
||||||
// The naming convention for cipher suites changed in TLS 1.3
|
// The naming convention for cipher suites changed in TLS 1.3
|
||||||
// but constant values should still be globally unqiue
|
// but constant values should still be globally unqiue.
|
||||||
// Handling validation on a subset of TLSCipherSuite constants
|
//
|
||||||
// would be a future exercise if cipher suites for TLS 1.3 ever
|
// Handling validation on distinct sets of TLS 1.3 and TLS 1.2 TLSCipherSuite
|
||||||
// become configurable in BoringSSL, Envoy, or other implementation
|
// constants would be a future exercise if cipher suites for TLS 1.3 ever
|
||||||
type TLSCipherSuite uint16
|
// become configurable in BoringSSL, Envoy, or other implementation.
|
||||||
|
type TLSCipherSuite string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Envoy cipher suites also used by Consul agent
|
// Cipher suites used by both Envoy and Consul agent
|
||||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLSCipherSuite = 0xc02b
|
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xcca9 // Not used by Consul agent yet
|
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
|
||||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xcca8 // Not used by Consul agent yet
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xc009
|
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"
|
||||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xc013
|
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
|
||||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xc02c
|
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
|
||||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xc030
|
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
|
||||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xc00a
|
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"
|
||||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xc014
|
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"
|
||||||
|
|
||||||
// Older cipher suites not supported for Consul agent TLS, will eventually be removed from Envoy defaults
|
// Older cipher suites not supported for Consul agent TLS,
|
||||||
TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009c
|
// will eventually be removed from Envoy defaults
|
||||||
TLS_RSA_WITH_AES_128_CBC_SHA = 0x002f
|
TLS_RSA_WITH_AES_128_GCM_SHA256 = "TLS_RSA_WITH_AES_128_GCM_SHA256"
|
||||||
TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009d
|
TLS_RSA_WITH_AES_128_CBC_SHA = "TLS_RSA_WITH_AES_128_CBC_SHA"
|
||||||
TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035
|
TLS_RSA_WITH_AES_256_GCM_SHA384 = "TLS_RSA_WITH_AES_256_GCM_SHA384"
|
||||||
|
TLS_RSA_WITH_AES_256_CBC_SHA = "TLS_RSA_WITH_AES_256_CBC_SHA"
|
||||||
// Additional cipher suites used by Consul agent but not Envoy
|
|
||||||
// TODO: these are both explicitly listed as insecure and disabled in the Go source, should they be removed?
|
|
||||||
// https://cs.opensource.google/go/go/+/refs/tags/go1.17.3:src/crypto/tls/cipher_suites.go;l=329-330
|
|
||||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0x0023
|
|
||||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xc027
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
TLSCipherSuites = map[string]TLSCipherSuite{
|
consulAgentTLSCipherSuites = map[TLSCipherSuite]struct{}{
|
||||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: {},
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: {},
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: {},
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: {},
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: {},
|
||||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
|
|
||||||
"TLS_RSA_WITH_AES_128_GCM_SHA256": TLS_RSA_WITH_AES_128_GCM_SHA256,
|
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: {},
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA": TLS_RSA_WITH_AES_128_CBC_SHA,
|
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: {},
|
||||||
"TLS_RSA_WITH_AES_256_GCM_SHA384": TLS_RSA_WITH_AES_256_GCM_SHA384,
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: {},
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA": TLS_RSA_WITH_AES_256_CBC_SHA,
|
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: {},
|
||||||
|
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: {},
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
|
||||||
}
|
}
|
||||||
HumanTLSCipherSuiteStrings = func() map[TLSCipherSuite]string {
|
envoyTLSCipherSuiteStrings = map[TLSCipherSuite]string{
|
||||||
inverted := make(map[TLSCipherSuite]string, len(TLSCipherSuites))
|
|
||||||
for k, v := range TLSCipherSuites {
|
|
||||||
inverted[v] = k
|
|
||||||
}
|
|
||||||
return inverted
|
|
||||||
}()
|
|
||||||
EnvoyTLSCipherSuiteStrings = map[TLSCipherSuite]string{
|
|
||||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "ECDHE-ECDSA-AES128-GCM-SHA256",
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "ECDHE-ECDSA-AES128-GCM-SHA256",
|
||||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: "ECDHE-ECDSA-CHACHA20-POLY1305",
|
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: "ECDHE-ECDSA-CHACHA20-POLY1305",
|
||||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "ECDHE-RSA-AES128-GCM-SHA256",
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "ECDHE-RSA-AES128-GCM-SHA256",
|
||||||
|
@ -183,3 +168,50 @@ var (
|
||||||
TLS_RSA_WITH_AES_256_CBC_SHA: "AES256-SHA",
|
TLS_RSA_WITH_AES_256_CBC_SHA: "AES256-SHA",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (c *TLSCipherSuite) String() string {
|
||||||
|
return string(*c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateConsulAgentCipherSuites(cipherSuites []TLSCipherSuite) error {
|
||||||
|
var unmatched []string
|
||||||
|
|
||||||
|
for _, c := range cipherSuites {
|
||||||
|
if _, ok := consulAgentTLSCipherSuites[c]; !ok {
|
||||||
|
unmatched = append(unmatched, c.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(unmatched) > 0 {
|
||||||
|
return fmt.Errorf("no matching Consul Agent TLS cipher suite found for %s", strings.Join(unmatched, ","))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateEnvoyCipherSuites(cipherSuites []TLSCipherSuite) error {
|
||||||
|
var unmatched []string
|
||||||
|
|
||||||
|
for _, c := range cipherSuites {
|
||||||
|
if _, ok := envoyTLSCipherSuiteStrings[c]; !ok {
|
||||||
|
unmatched = append(unmatched, c.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(unmatched) > 0 {
|
||||||
|
return fmt.Errorf("no matching Envoy TLS cipher suite found for %s", strings.Join(unmatched, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalEnvoyTLSCipherSuiteStrings(cipherSuites []TLSCipherSuite) []string {
|
||||||
|
cipherSuiteStrings := []string{}
|
||||||
|
|
||||||
|
for _, c := range cipherSuites {
|
||||||
|
if s, ok := envoyTLSCipherSuiteStrings[c]; ok {
|
||||||
|
cipherSuiteStrings = append(cipherSuiteStrings, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cipherSuiteStrings
|
||||||
|
}
|
||||||
|
|
|
@ -7,14 +7,12 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTLSVersion_PartialEq(t *testing.T) {
|
func TestTLSVersion_Valid(t *testing.T) {
|
||||||
require.Greater(t, TLSv1_3, TLSv1_2)
|
require.NoError(t, ValidateTLSVersion("TLS_AUTO"))
|
||||||
require.Greater(t, TLSv1_2, TLSv1_1)
|
require.NoError(t, ValidateTLSVersion("TLSv1_0"))
|
||||||
require.Greater(t, TLSv1_1, TLSv1_0)
|
require.NoError(t, ValidateTLSVersion("TLSv1_1"))
|
||||||
|
require.NoError(t, ValidateTLSVersion("TLSv1_2"))
|
||||||
require.Less(t, TLSv1_2, TLSv1_3)
|
require.NoError(t, ValidateTLSVersion("TLSv1_3"))
|
||||||
require.Less(t, TLSv1_1, TLSv1_2)
|
|
||||||
require.Less(t, TLSv1_0, TLSv1_1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTLSVersion_Invalid(t *testing.T) {
|
func TestTLSVersion_Invalid(t *testing.T) {
|
||||||
|
@ -33,16 +31,19 @@ func TestTLSVersion_Zero(t *testing.T) {
|
||||||
|
|
||||||
func TestTLSVersion_ToJSON(t *testing.T) {
|
func TestTLSVersion_ToJSON(t *testing.T) {
|
||||||
var tlsVersion TLSVersion
|
var tlsVersion TLSVersion
|
||||||
err := tlsVersion.UnmarshalJSON([]byte(`"foo"`))
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Equal(t, tlsVersion, TLSVersionInvalid)
|
|
||||||
|
|
||||||
for str, version := range TLSVersions {
|
// Unmarshalling won't catch invalid version strings,
|
||||||
|
// must be checked in config or config entry validation
|
||||||
|
err := json.Unmarshal([]byte(`"foo"`), &tlsVersion)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
for version := range tlsVersions {
|
||||||
|
str := version.String()
|
||||||
versionJSON, err := json.Marshal(version)
|
versionJSON, err := json.Marshal(version)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, versionJSON, []byte(`"`+str+`"`))
|
require.Equal(t, versionJSON, []byte(`"`+str+`"`))
|
||||||
|
|
||||||
err = tlsVersion.UnmarshalJSON([]byte(`"` + str + `"`))
|
err = json.Unmarshal([]byte(`"`+str+`"`), &tlsVersion)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, tlsVersion, version)
|
require.Equal(t, tlsVersion, version)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue