mirror of https://github.com/status-im/consul.git
Merge pull request #10903 from hashicorp/feature/ingress-sds
Add Support to for providing TLS certificates for Ingress listeners from an SDS source
This commit is contained in:
commit
1ecec84fd7
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
connect: Add low-level feature to allow an Ingress to retrieve TLS certificates from SDS.
|
||||
```
|
|
@ -80,13 +80,13 @@ func (s *handlerIngressGateway) handleUpdate(ctx context.Context, u cache.Update
|
|||
return fmt.Errorf("invalid type for config entry: %T", resp.Entry)
|
||||
}
|
||||
|
||||
snap.IngressGateway.TLSEnabled = gatewayConf.TLS.Enabled
|
||||
snap.IngressGateway.TLSSet = true
|
||||
snap.IngressGateway.GatewayConfigLoaded = true
|
||||
snap.IngressGateway.TLSConfig = gatewayConf.TLS
|
||||
|
||||
// Load each listener's config from the config entry so we don't have to
|
||||
// pass listener config through "upstreams" types as that grows.
|
||||
for _, l := range gatewayConf.Listeners {
|
||||
key := IngressListenerKey{Protocol: l.Protocol, Port: l.Port}
|
||||
key := IngressListenerKeyFromListener(l)
|
||||
snap.IngressGateway.Listeners[key] = l
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ func (s *handlerIngressGateway) handleUpdate(ctx context.Context, u cache.Update
|
|||
|
||||
hosts = append(hosts, service.Hosts...)
|
||||
|
||||
id := IngressListenerKey{Protocol: service.Protocol, Port: service.Port}
|
||||
id := IngressListenerKeyFromGWService(*service)
|
||||
upstreamsMap[id] = append(upstreamsMap[id], u)
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,9 @@ func makeUpstream(g *structs.GatewayService) structs.Upstream {
|
|||
}
|
||||
|
||||
func (s *handlerIngressGateway) watchIngressLeafCert(ctx context.Context, snap *ConfigSnapshot) error {
|
||||
if !snap.IngressGateway.TLSSet || !snap.IngressGateway.HostsSet {
|
||||
// Note that we DON'T test for TLS.Enabled because we need a leaf cert for the
|
||||
// gateway even without TLS to use as a client cert.
|
||||
if !snap.IngressGateway.GatewayConfigLoaded || !snap.IngressGateway.HostsSet {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -197,7 +199,7 @@ func (s *handlerIngressGateway) watchIngressLeafCert(ctx context.Context, snap *
|
|||
func (s *handlerIngressGateway) generateIngressDNSSANs(snap *ConfigSnapshot) []string {
|
||||
// Update our leaf cert watch with wildcard entries for our DNS domains as well as any
|
||||
// configured custom hostnames from the service.
|
||||
if !snap.IngressGateway.TLSEnabled {
|
||||
if !snap.IngressGateway.TLSConfig.Enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@ package proxycfg
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/hashicorp/consul/agent/connect"
|
||||
"sort"
|
||||
|
||||
"github.com/mitchellh/copystructure"
|
||||
|
||||
"github.com/hashicorp/consul/agent/connect"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
|
@ -305,9 +305,13 @@ func (c *configSnapshotMeshGateway) IsEmpty() bool {
|
|||
type configSnapshotIngressGateway struct {
|
||||
ConfigSnapshotUpstreams
|
||||
|
||||
// TLSEnabled is whether this gateway's listeners should have TLS configured.
|
||||
TLSEnabled bool
|
||||
TLSSet bool
|
||||
// TLSConfig is the gateway-level TLS configuration. Listener/service level
|
||||
// config is preserved in the Listeners map below.
|
||||
TLSConfig structs.GatewayTLSConfig
|
||||
|
||||
// GatewayConfigLoaded is used to determine if we have received the initial
|
||||
// ingress-gateway config entry yet.
|
||||
GatewayConfigLoaded bool
|
||||
|
||||
// Hosts is the list of extra host entries to add to our leaf cert's DNS SANs.
|
||||
Hosts []string
|
||||
|
@ -346,6 +350,14 @@ func (k *IngressListenerKey) RouteName() string {
|
|||
return fmt.Sprintf("%d", k.Port)
|
||||
}
|
||||
|
||||
func IngressListenerKeyFromGWService(s structs.GatewayService) IngressListenerKey {
|
||||
return IngressListenerKey{Protocol: s.Protocol, Port: s.Port}
|
||||
}
|
||||
|
||||
func IngressListenerKeyFromListener(l structs.IngressListener) IngressListenerKey {
|
||||
return IngressListenerKey{Protocol: l.Protocol, Port: l.Port}
|
||||
}
|
||||
|
||||
// ConfigSnapshot captures all the resulting config needed for a proxy instance.
|
||||
// It is meant to be point-in-time coherent and is used to deliver the current
|
||||
// config state to observers who need it to be pushed in (e.g. XDS server).
|
||||
|
@ -403,7 +415,7 @@ func (s *ConfigSnapshot) Valid() bool {
|
|||
case structs.ServiceKindIngressGateway:
|
||||
return s.Roots != nil &&
|
||||
s.IngressGateway.Leaf != nil &&
|
||||
s.IngressGateway.TLSSet &&
|
||||
s.IngressGateway.GatewayConfigLoaded &&
|
||||
s.IngressGateway.HostsSet
|
||||
default:
|
||||
return false
|
||||
|
|
|
@ -942,8 +942,8 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
},
|
||||
verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) {
|
||||
require.False(t, snap.Valid(), "gateway without hosts set is not valid")
|
||||
require.True(t, snap.IngressGateway.TLSSet)
|
||||
require.False(t, snap.IngressGateway.TLSEnabled)
|
||||
require.True(t, snap.IngressGateway.GatewayConfigLoaded)
|
||||
require.False(t, snap.IngressGateway.TLSConfig.Enabled)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -1111,8 +1111,8 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
},
|
||||
verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) {
|
||||
require.True(t, snap.Valid())
|
||||
require.True(t, snap.IngressGateway.TLSSet)
|
||||
require.True(t, snap.IngressGateway.TLSEnabled)
|
||||
require.True(t, snap.IngressGateway.GatewayConfigLoaded)
|
||||
require.True(t, snap.IngressGateway.TLSConfig.Enabled)
|
||||
require.True(t, snap.IngressGateway.HostsSet)
|
||||
require.Len(t, snap.IngressGateway.Hosts, 1)
|
||||
require.Len(t, snap.IngressGateway.Upstreams, 1)
|
||||
|
|
|
@ -1622,7 +1622,16 @@ func TestConfigSnapshotIngress(t testing.T) *ConfigSnapshot {
|
|||
|
||||
func TestConfigSnapshotIngressWithTLSListener(t testing.T) *ConfigSnapshot {
|
||||
snap := testConfigSnapshotIngressGateway(t, true, "tcp", "default")
|
||||
snap.IngressGateway.TLSEnabled = true
|
||||
snap.IngressGateway.TLSConfig.Enabled = true
|
||||
return snap
|
||||
}
|
||||
|
||||
func TestConfigSnapshotIngressWithGatewaySDS(t testing.T) *ConfigSnapshot {
|
||||
snap := testConfigSnapshotIngressGateway(t, true, "tcp", "default")
|
||||
snap.IngressGateway.TLSConfig.SDS = &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "sds-cluster",
|
||||
CertResource: "cert-resource",
|
||||
}
|
||||
return snap
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ type IngressGatewayConfigEntry struct {
|
|||
// service. This should match the name provided in the service definition.
|
||||
Name string
|
||||
|
||||
// TLS holds the TLS configuration for this gateway.
|
||||
// TLS holds the TLS configuration for this gateway. It would be nicer if it
|
||||
// were a pointer so it could be omitempty when read back in JSON but that
|
||||
// would be a breaking API change now as we currently always return it.
|
||||
TLS GatewayTLSConfig
|
||||
|
||||
// Listeners declares what ports the ingress gateway should listen on, and
|
||||
|
@ -43,6 +45,9 @@ type IngressListener struct {
|
|||
// current supported values are: (tcp | http | http2 | grpc).
|
||||
Protocol string
|
||||
|
||||
// TLS config for this listener.
|
||||
TLS *GatewayTLSConfig `json:",omitempty"`
|
||||
|
||||
// Services declares the set of services to which the listener forwards
|
||||
// traffic.
|
||||
//
|
||||
|
@ -75,6 +80,11 @@ type IngressService struct {
|
|||
// using a "tcp" listener.
|
||||
Hosts []string
|
||||
|
||||
// TLS configuration overrides for this service. At least one entry must exist
|
||||
// in Hosts to use set and the Listener must also have a default Cert loaded
|
||||
// from SDS.
|
||||
TLS *GatewayServiceTLSConfig `json:",omitempty"`
|
||||
|
||||
// Allow HTTP header manipulation to be configured.
|
||||
RequestHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"request_headers"`
|
||||
ResponseHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"response_headers"`
|
||||
|
@ -84,8 +94,24 @@ type IngressService struct {
|
|||
}
|
||||
|
||||
type GatewayTLSConfig struct {
|
||||
// Indicates that TLS should be enabled for this gateway service
|
||||
// Indicates that TLS should be enabled for this gateway or listener
|
||||
Enabled bool
|
||||
|
||||
// SDS allows configuring TLS certificate from an SDS service.
|
||||
SDS *GatewayTLSSDSConfig `json:",omitempty"`
|
||||
}
|
||||
|
||||
type GatewayServiceTLSConfig struct {
|
||||
// Note no Enabled field here since it doesn't make sense to disable TLS on
|
||||
// one host on a TLS-configured listener.
|
||||
|
||||
// SDS allows configuring TLS certificate from an SDS service.
|
||||
SDS *GatewayTLSSDSConfig `json:",omitempty"`
|
||||
}
|
||||
|
||||
type GatewayTLSSDSConfig struct {
|
||||
ClusterName string `json:",omitempty" alias:"cluster_name"`
|
||||
CertResource string `json:",omitempty" alias:"cert_resource"`
|
||||
}
|
||||
|
||||
func (e *IngressGatewayConfigEntry) GetKind() string {
|
||||
|
@ -134,6 +160,77 @@ func (e *IngressGatewayConfigEntry) Normalize() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// validateServiceSDS validates the SDS config for a specific service on a
|
||||
// specific listener. It checks inherited config properties from listener and
|
||||
// gateway level and ensures they are valid all the way down. If called on
|
||||
// several services some of these checks will be duplicated but that isn't a big
|
||||
// deal and it's significantly easier to reason about and read if this is in one
|
||||
// place rather than threaded through the multi-level loop in Validate with
|
||||
// other checks.
|
||||
func (e *IngressGatewayConfigEntry) validateServiceSDS(lis IngressListener, svc IngressService) error {
|
||||
// First work out if there is valid gateway-level SDS config
|
||||
gwSDSClusterSet := false
|
||||
gwSDSCertSet := false
|
||||
if e.TLS.SDS != nil {
|
||||
// Gateway level SDS config must set ClusterName if it specifies a default
|
||||
// certificate. Just a clustername is OK though if certs are specified
|
||||
// per-listener.
|
||||
if e.TLS.SDS.ClusterName == "" && e.TLS.SDS.CertResource != "" {
|
||||
return fmt.Errorf("TLS.SDS.ClusterName is required if CertResource is set")
|
||||
}
|
||||
// Note we rely on the fact that ClusterName must be non-empty if any SDS
|
||||
// properties are defined at this level (as validated above) in validation
|
||||
// below that uses this variable. If that changes we will need to change the
|
||||
// code below too.
|
||||
gwSDSClusterSet = (e.TLS.SDS.ClusterName != "")
|
||||
gwSDSCertSet = (e.TLS.SDS.CertResource != "")
|
||||
}
|
||||
|
||||
// Validate listener-level SDS config.
|
||||
lisSDSCertSet := false
|
||||
lisSDSClusterSet := false
|
||||
if lis.TLS != nil && lis.TLS.SDS != nil {
|
||||
lisSDSCertSet = (lis.TLS.SDS.CertResource != "")
|
||||
lisSDSClusterSet = (lis.TLS.SDS.ClusterName != "")
|
||||
}
|
||||
|
||||
// If SDS was setup at gw level but without a default CertResource, the
|
||||
// listener MUST set a CertResource.
|
||||
if gwSDSClusterSet && !gwSDSCertSet && !lisSDSCertSet {
|
||||
return fmt.Errorf("TLS.SDS.CertResource is required if ClusterName is set for gateway (listener on port %d)", lis.Port)
|
||||
}
|
||||
|
||||
// If listener set a cluster name then it requires a cert resource too.
|
||||
if lisSDSClusterSet && !lisSDSCertSet {
|
||||
return fmt.Errorf("TLS.SDS.CertResource is required if ClusterName is set for listener (listener on port %d)", lis.Port)
|
||||
}
|
||||
|
||||
// If a listener-level cert is given, we need a cluster from at least one
|
||||
// level.
|
||||
if lisSDSCertSet && !lisSDSClusterSet && !gwSDSClusterSet {
|
||||
return fmt.Errorf("TLS.SDS.ClusterName is required if CertResource is set (listener on port %d)", lis.Port)
|
||||
}
|
||||
|
||||
// Validate service-level SDS config
|
||||
svcSDSSet := (svc.TLS != nil && svc.TLS.SDS != nil && svc.TLS.SDS.CertResource != "")
|
||||
|
||||
// Service SDS is only supported with Host names because we need to bind
|
||||
// specific service certs to one or more SNI hostnames.
|
||||
if svcSDSSet && len(svc.Hosts) < 1 {
|
||||
sid := NewServiceID(svc.Name, &svc.EnterpriseMeta)
|
||||
return fmt.Errorf("A service specifying TLS.SDS.CertResource must have at least one item in Hosts (service %q on listener on port %d)",
|
||||
sid.String(), lis.Port)
|
||||
}
|
||||
// If this service specified a certificate, there must be an SDS cluster set
|
||||
// at one of the three levels.
|
||||
if svcSDSSet && svc.TLS.SDS.ClusterName == "" && !lisSDSClusterSet && !gwSDSClusterSet {
|
||||
sid := NewServiceID(svc.Name, &svc.EnterpriseMeta)
|
||||
return fmt.Errorf("TLS.SDS.ClusterName is required if CertResource is set (service %q on listener on port %d)",
|
||||
sid.String(), lis.Port)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *IngressGatewayConfigEntry) Validate() error {
|
||||
if err := validateConfigEntryMeta(e.Meta); err != nil {
|
||||
return err
|
||||
|
@ -204,6 +301,11 @@ func (e *IngressGatewayConfigEntry) Validate() error {
|
|||
}
|
||||
serviceNames[sid] = struct{}{}
|
||||
|
||||
// Validate SDS configuration for this service
|
||||
if err := e.validateServiceSDS(listener, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, h := range s.Hosts {
|
||||
if declaredHosts[h] {
|
||||
return fmt.Errorf("Hosts must be unique within a specific listener (listener on port %d)", listener.Port)
|
||||
|
|
|
@ -437,6 +437,7 @@ func TestIngressGatewayConfigEntry(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
expectUnchanged: true,
|
||||
},
|
||||
"request header manip not allowed for non-http protocol": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
|
@ -503,6 +504,377 @@ func TestIngressGatewayConfigEntry(t *testing.T) {
|
|||
// differs between Ent and OSS default/default/web vs web
|
||||
validateErr: "cannot be added multiple times (listener on port 1111)",
|
||||
},
|
||||
"TLS.SDS kitchen sink": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
TLS: GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "secret-service1",
|
||||
CertResource: "some-ns/ingress-default",
|
||||
},
|
||||
},
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "http",
|
||||
TLS: &GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "secret-service2",
|
||||
CertResource: "some-ns/ingress-1111",
|
||||
},
|
||||
},
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "web",
|
||||
Hosts: []string{"*"},
|
||||
TLS: &GatewayServiceTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "secret-service3",
|
||||
CertResource: "some-ns/web",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"TLS.SDS gateway-level": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
TLS: GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "secret-service1",
|
||||
CertResource: "some-ns/ingress-default",
|
||||
},
|
||||
},
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "tcp",
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectUnchanged: true,
|
||||
},
|
||||
"TLS.SDS listener-level": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "tcp",
|
||||
TLS: &GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "secret-service1",
|
||||
CertResource: "some-ns/db1",
|
||||
},
|
||||
},
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Port: 2222,
|
||||
Protocol: "tcp",
|
||||
TLS: &GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "secret-service2",
|
||||
CertResource: "some-ns/db2",
|
||||
},
|
||||
},
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectUnchanged: true,
|
||||
},
|
||||
"TLS.SDS gateway-level cluster only": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
TLS: GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "secret-service",
|
||||
},
|
||||
},
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "tcp",
|
||||
TLS: &GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
CertResource: "some-ns/db1",
|
||||
},
|
||||
},
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Port: 2222,
|
||||
Protocol: "tcp",
|
||||
TLS: &GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
CertResource: "some-ns/db2",
|
||||
},
|
||||
},
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectUnchanged: true,
|
||||
},
|
||||
"TLS.SDS mixed TLS and non-TLS listeners": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
// No Gateway level TLS.Enabled or SDS config
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "tcp",
|
||||
TLS: &GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "sds-cluster",
|
||||
CertResource: "some-ns/db1",
|
||||
},
|
||||
},
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Port: 2222,
|
||||
Protocol: "tcp",
|
||||
// No TLS config
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectUnchanged: true,
|
||||
},
|
||||
"TLS.SDS only service-level mixed": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
// No Gateway level TLS.Enabled or SDS config
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "http",
|
||||
// No TLS config
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "web",
|
||||
Hosts: []string{"www.example.com"},
|
||||
TLS: &GatewayServiceTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "sds-cluster",
|
||||
CertResource: "web-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "api",
|
||||
Hosts: []string{"api.example.com"},
|
||||
TLS: &GatewayServiceTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "sds-cluster",
|
||||
CertResource: "api-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Port: 2222,
|
||||
Protocol: "http",
|
||||
// No TLS config
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectUnchanged: true,
|
||||
},
|
||||
"TLS.SDS requires cluster if gateway-level cert specified": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
TLS: GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
CertResource: "foo",
|
||||
},
|
||||
},
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "tcp",
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: "TLS.SDS.ClusterName is required if CertResource is set",
|
||||
},
|
||||
"TLS.SDS listener requires cluster if there is no gateway-level one": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "tcp",
|
||||
TLS: &GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
CertResource: "foo",
|
||||
},
|
||||
},
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: "TLS.SDS.ClusterName is required if CertResource is set",
|
||||
},
|
||||
"TLS.SDS listener requires a cert resource if gw ClusterName set": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
TLS: GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "foo",
|
||||
},
|
||||
},
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "tcp",
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: "TLS.SDS.CertResource is required if ClusterName is set for gateway (listener on port 1111)",
|
||||
},
|
||||
"TLS.SDS listener requires a cert resource if listener ClusterName set": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "tcp",
|
||||
TLS: &GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "foo",
|
||||
},
|
||||
},
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "db",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
validateErr: "TLS.SDS.CertResource is required if ClusterName is set for listener (listener on port 1111)",
|
||||
},
|
||||
"TLS.SDS at service level is not supported without Hosts set": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "http",
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "*",
|
||||
TLS: &GatewayServiceTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
CertResource: "foo",
|
||||
ClusterName: "sds-cluster",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Note we don't assert the last part `(service \"*\" on listener on port 1111)`
|
||||
// since the service name is normalized differently on OSS and Ent
|
||||
validateErr: "A service specifying TLS.SDS.CertResource must have at least one item in Hosts",
|
||||
},
|
||||
"TLS.SDS at service level needs a cluster from somewhere": {
|
||||
entry: &IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress-web",
|
||||
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 1111,
|
||||
Protocol: "http",
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "foo",
|
||||
Hosts: []string{"foo.example.com"},
|
||||
TLS: &GatewayServiceTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
CertResource: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Note we don't assert the last part `(service \"foo\" on listener on port 1111)`
|
||||
// since the service name is normalized differently on OSS and Ent
|
||||
validateErr: "TLS.SDS.ClusterName is required if CertResource is set",
|
||||
},
|
||||
}
|
||||
|
||||
testConfigEntryNormalizeAndValidate(t, cases)
|
||||
|
|
|
@ -6,8 +6,10 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/go-msgpack/codec"
|
||||
"github.com/hashicorp/hcl"
|
||||
"github.com/mitchellh/copystructure"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
@ -2519,8 +2521,9 @@ type configEntryTestcase struct {
|
|||
normalizeErr string
|
||||
validateErr string
|
||||
|
||||
// Only one of either expected or check can be set.
|
||||
expected ConfigEntry
|
||||
// Only one of expected, expectUnchanged or check can be set.
|
||||
expected ConfigEntry
|
||||
expectUnchanged bool
|
||||
// check is called between normalize and validate
|
||||
check func(t *testing.T, entry ConfigEntry)
|
||||
}
|
||||
|
@ -2531,21 +2534,50 @@ func testConfigEntryNormalizeAndValidate(t *testing.T, cases map[string]configEn
|
|||
for name, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := tc.entry.Normalize()
|
||||
beforeNormalize, err := copystructure.Copy(tc.entry)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = tc.entry.Normalize()
|
||||
if tc.normalizeErr != "" {
|
||||
testutil.RequireErrorContains(t, err, tc.normalizeErr)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
if tc.expected != nil && tc.check != nil {
|
||||
t.Fatal("cannot set both 'expected' and 'check' test case fields")
|
||||
checkMethods := 0
|
||||
if tc.expected != nil {
|
||||
checkMethods++
|
||||
}
|
||||
if tc.expectUnchanged {
|
||||
checkMethods++
|
||||
}
|
||||
if tc.check != nil {
|
||||
checkMethods++
|
||||
}
|
||||
|
||||
if checkMethods > 1 {
|
||||
t.Fatal("cannot set more than one of 'expected', 'expectUnchanged' and 'check' test case fields")
|
||||
}
|
||||
|
||||
if tc.expected != nil {
|
||||
require.Equal(t, tc.expected, tc.entry)
|
||||
}
|
||||
|
||||
if tc.expectUnchanged {
|
||||
// EnterpriseMeta.Normalize behaves differently in Ent and OSS which
|
||||
// causes an exact comparison to fail. It's still useful to assert that
|
||||
// nothing else changes though during Normalize. So we ignore
|
||||
// EnterpriseMeta Defaults.
|
||||
opts := cmp.Options{
|
||||
cmp.Comparer(func(a, b EnterpriseMeta) bool {
|
||||
return a.IsSame(&b)
|
||||
}),
|
||||
}
|
||||
if diff := cmp.Diff(beforeNormalize, tc.entry, opts); diff != "" {
|
||||
t.Fatalf("expect unchanged after Normalize, got diff:\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
if tc.check != nil {
|
||||
tc.check(t, tc.entry)
|
||||
}
|
||||
|
|
|
@ -79,6 +79,10 @@ func (m *EnterpriseMeta) NamespaceOrEmpty() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (m *EnterpriseMeta) InDefaultNamespace() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *EnterpriseMeta) PartitionOrDefault() string {
|
||||
return "default"
|
||||
}
|
||||
|
@ -91,6 +95,10 @@ func (m *EnterpriseMeta) PartitionOrEmpty() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (m *EnterpriseMeta) InDefaultPartition() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ReplicationEnterpriseMeta stub
|
||||
func ReplicationEnterpriseMeta() *EnterpriseMeta {
|
||||
return &emptyEnterpriseMeta
|
||||
|
|
|
@ -511,75 +511,47 @@ func (s *ResourceGenerator) listenersFromSnapshotGateway(cfgSnap *proxycfg.Confi
|
|||
return resources, err
|
||||
}
|
||||
|
||||
func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
var resources []proto.Message
|
||||
func resolveListenerSDSConfig(cfgSnap *proxycfg.ConfigSnapshot, listenerKey proxycfg.IngressListenerKey) (*structs.GatewayTLSSDSConfig, error) {
|
||||
var mergedCfg structs.GatewayTLSSDSConfig
|
||||
|
||||
for listenerKey, upstreams := range cfgSnap.IngressGateway.Upstreams {
|
||||
var tlsContext *envoy_tls_v3.DownstreamTlsContext
|
||||
if cfgSnap.IngressGateway.TLSEnabled {
|
||||
tlsContext = &envoy_tls_v3.DownstreamTlsContext{
|
||||
CommonTlsContext: makeCommonTLSContextFromLeaf(cfgSnap, cfgSnap.Leaf()),
|
||||
RequireClientCertificate: &wrappers.BoolValue{Value: false},
|
||||
}
|
||||
gwSDS := cfgSnap.IngressGateway.TLSConfig.SDS
|
||||
if gwSDS != nil {
|
||||
mergedCfg.ClusterName = gwSDS.ClusterName
|
||||
mergedCfg.CertResource = gwSDS.CertResource
|
||||
}
|
||||
|
||||
listenerCfg, ok := cfgSnap.IngressGateway.Listeners[listenerKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no listener config found for listener on port %d", listenerKey.Port)
|
||||
}
|
||||
|
||||
if listenerCfg.TLS != nil && listenerCfg.TLS.SDS != nil {
|
||||
if listenerCfg.TLS.SDS.ClusterName != "" {
|
||||
mergedCfg.ClusterName = listenerCfg.TLS.SDS.ClusterName
|
||||
}
|
||||
|
||||
if listenerKey.Protocol == "tcp" {
|
||||
// We rely on the invariant of upstreams slice always having at least 1
|
||||
// member, because this key/value pair is created only when a
|
||||
// GatewayService is returned in the RPC
|
||||
u := upstreams[0]
|
||||
id := u.Identifier()
|
||||
|
||||
chain := cfgSnap.IngressGateway.DiscoveryChain[id]
|
||||
|
||||
var upstreamListener proto.Message
|
||||
upstreamListener, err := s.makeUpstreamListenerForDiscoveryChain(
|
||||
&u,
|
||||
address,
|
||||
chain,
|
||||
cfgSnap,
|
||||
tlsContext,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resources = append(resources, upstreamListener)
|
||||
} else {
|
||||
// If multiple upstreams share this port, make a special listener for the protocol.
|
||||
listener := makePortListener(listenerKey.Protocol, address, listenerKey.Port, envoy_core_v3.TrafficDirection_OUTBOUND)
|
||||
opts := listenerFilterOpts{
|
||||
useRDS: true,
|
||||
protocol: listenerKey.Protocol,
|
||||
filterName: listenerKey.RouteName(),
|
||||
routeName: listenerKey.RouteName(),
|
||||
cluster: "",
|
||||
statPrefix: "ingress_upstream_",
|
||||
routePath: "",
|
||||
httpAuthzFilter: nil,
|
||||
}
|
||||
filter, err := makeListenerFilter(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transportSocket, err := makeDownstreamTLSTransportSocket(tlsContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener.FilterChains = []*envoy_listener_v3.FilterChain{
|
||||
{
|
||||
Filters: []*envoy_listener_v3.Filter{
|
||||
filter,
|
||||
},
|
||||
TransportSocket: transportSocket,
|
||||
},
|
||||
}
|
||||
resources = append(resources, listener)
|
||||
if listenerCfg.TLS.SDS.CertResource != "" {
|
||||
mergedCfg.CertResource = listenerCfg.TLS.SDS.CertResource
|
||||
}
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
// Validate. Either merged should have both fields empty or both set. Other
|
||||
// cases shouldn't be possible as we validate them at input but be robust to
|
||||
// bugs later.
|
||||
switch {
|
||||
case mergedCfg.ClusterName == "" && mergedCfg.CertResource == "":
|
||||
return nil, nil
|
||||
|
||||
case mergedCfg.ClusterName != "" && mergedCfg.CertResource != "":
|
||||
return &mergedCfg, nil
|
||||
|
||||
case mergedCfg.ClusterName == "" && mergedCfg.CertResource != "":
|
||||
return nil, fmt.Errorf("missing SDS cluster name for listener on port %d", listenerKey.Port)
|
||||
|
||||
case mergedCfg.ClusterName != "" && mergedCfg.CertResource == "":
|
||||
return nil, fmt.Errorf("missing SDS cert resource for listener on port %d", listenerKey.Port)
|
||||
}
|
||||
|
||||
return &mergedCfg, nil
|
||||
}
|
||||
|
||||
// makeListener returns a listener with name and bind details set. Filters must
|
||||
|
@ -1584,9 +1556,9 @@ func makeTLSInspectorListenerFilter() (*envoy_listener_v3.ListenerFilter, error)
|
|||
return &envoy_listener_v3.ListenerFilter{Name: "envoy.filters.listener.tls_inspector"}, nil
|
||||
}
|
||||
|
||||
func makeSNIFilterChainMatch(sniMatch string) *envoy_listener_v3.FilterChainMatch {
|
||||
func makeSNIFilterChainMatch(sniMatches ...string) *envoy_listener_v3.FilterChainMatch {
|
||||
return &envoy_listener_v3.FilterChainMatch{
|
||||
ServerNames: []string{sniMatch},
|
||||
ServerNames: sniMatches,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1763,7 +1735,6 @@ func makeCommonTLSContextFromLeaf(cfgSnap *proxycfg.ConfigSnapshot, leaf *struct
|
|||
return nil
|
||||
}
|
||||
|
||||
// TODO(banks): verify this actually works with Envoy (docs are not clear).
|
||||
rootPEMS := ""
|
||||
for _, root := range cfgSnap.Roots.Roots {
|
||||
rootPEMS += ca.EnsureTrailingNewline(root.RootCert)
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
package xds
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||
envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
||||
envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes/duration"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
var resources []proto.Message
|
||||
|
||||
for listenerKey, upstreams := range cfgSnap.IngressGateway.Upstreams {
|
||||
var tlsContext *envoy_tls_v3.DownstreamTlsContext
|
||||
|
||||
sdsCfg, err := resolveListenerSDSConfig(cfgSnap, listenerKey)
|
||||
if err != nil {
|
||||
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 cfgSnap.IngressGateway.TLSConfig.Enabled {
|
||||
tlsContext = &envoy_tls_v3.DownstreamTlsContext{
|
||||
CommonTlsContext: makeCommonTLSContextFromLeaf(cfgSnap, cfgSnap.Leaf()),
|
||||
RequireClientCertificate: &wrappers.BoolValue{Value: false},
|
||||
}
|
||||
}
|
||||
|
||||
if listenerKey.Protocol == "tcp" {
|
||||
// We rely on the invariant of upstreams slice always having at least 1
|
||||
// member, because this key/value pair is created only when a
|
||||
// GatewayService is returned in the RPC
|
||||
u := upstreams[0]
|
||||
id := u.Identifier()
|
||||
|
||||
chain := cfgSnap.IngressGateway.DiscoveryChain[id]
|
||||
|
||||
var upstreamListener proto.Message
|
||||
upstreamListener, err := s.makeUpstreamListenerForDiscoveryChain(
|
||||
&u,
|
||||
address,
|
||||
chain,
|
||||
cfgSnap,
|
||||
tlsContext,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resources = append(resources, upstreamListener)
|
||||
} else {
|
||||
// If multiple upstreams share this port, make a special listener for the protocol.
|
||||
listener := makePortListener(listenerKey.Protocol, address, listenerKey.Port, envoy_core_v3.TrafficDirection_OUTBOUND)
|
||||
opts := listenerFilterOpts{
|
||||
useRDS: true,
|
||||
protocol: listenerKey.Protocol,
|
||||
filterName: listenerKey.RouteName(),
|
||||
routeName: listenerKey.RouteName(),
|
||||
cluster: "",
|
||||
statPrefix: "ingress_upstream_",
|
||||
routePath: "",
|
||||
httpAuthzFilter: nil,
|
||||
}
|
||||
|
||||
// Generate any filter chains needed for services with custom TLS certs
|
||||
// via SDS.
|
||||
sniFilterChains, err := makeSDSOverrideFilterChains(cfgSnap, listenerKey, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If there are any sni filter chains, we need a TLS inspector filter!
|
||||
if len(sniFilterChains) > 0 {
|
||||
tlsInspector, err := makeTLSInspectorListenerFilter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listener.ListenerFilters = []*envoy_listener_v3.ListenerFilter{tlsInspector}
|
||||
}
|
||||
|
||||
listener.FilterChains = sniFilterChains
|
||||
|
||||
// See if there are other services that didn't have specific SNI-matching
|
||||
// filter chains. If so add a default filterchain to serve them.
|
||||
if len(sniFilterChains) < len(upstreams) {
|
||||
defaultFilter, err := makeListenerFilter(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transportSocket, err := makeDownstreamTLSTransportSocket(tlsContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listener.FilterChains = append(listener.FilterChains,
|
||||
&envoy_listener_v3.FilterChain{
|
||||
Filters: []*envoy_listener_v3.Filter{
|
||||
defaultFilter,
|
||||
},
|
||||
TransportSocket: transportSocket,
|
||||
})
|
||||
}
|
||||
|
||||
resources = append(resources, listener)
|
||||
}
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func routeNameForUpstream(l structs.IngressListener, s structs.IngressService) string {
|
||||
key := proxycfg.IngressListenerKeyFromListener(l)
|
||||
|
||||
// If the upstream service doesn't have any TLS overrides then it can just use
|
||||
// the combined filterchain with all the merged routes.
|
||||
if !ingressServiceHasSDSOverrides(s) {
|
||||
return key.RouteName()
|
||||
}
|
||||
|
||||
// Return a specific route for this service as it needs a custom FilterChain
|
||||
// to serve its custom cert so we should attach its routes to a separate Route
|
||||
// too. We need this to be consistent between OSS and Enterprise to avoid xDS
|
||||
// config golden files in tests conflicting so we can't use ServiceID.String()
|
||||
// which normalizes to included all identifiers in Enterprise.
|
||||
sn := s.ToServiceName()
|
||||
svcIdentifier := sn.Name
|
||||
if !sn.InDefaultPartition() || !sn.InDefaultNamespace() {
|
||||
// Non-default partition/namespace, use a full identifier
|
||||
svcIdentifier = sn.String()
|
||||
}
|
||||
return fmt.Sprintf("%s_%s", key.RouteName(), svcIdentifier)
|
||||
}
|
||||
|
||||
func ingressServiceHasSDSOverrides(s structs.IngressService) bool {
|
||||
return s.TLS != nil &&
|
||||
s.TLS.SDS != nil &&
|
||||
s.TLS.SDS.CertResource != ""
|
||||
}
|
||||
|
||||
// ingress services that specify custom TLS certs via SDS overrides need to get
|
||||
// their own filter chain and routes. This will generate all the extra filter
|
||||
// chains an ingress listener needs. It may be empty and expects the default
|
||||
// catch-all chain and route to contain all the other services that share the
|
||||
// default TLS config.
|
||||
func makeSDSOverrideFilterChains(cfgSnap *proxycfg.ConfigSnapshot,
|
||||
listenerKey proxycfg.IngressListenerKey,
|
||||
filterOpts listenerFilterOpts) ([]*envoy_listener_v3.FilterChain, error) {
|
||||
|
||||
listenerCfg, ok := cfgSnap.IngressGateway.Listeners[listenerKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no listener config found for listener on port %d", listenerKey.Port)
|
||||
}
|
||||
|
||||
var chains []*envoy_listener_v3.FilterChain
|
||||
|
||||
for _, svc := range listenerCfg.Services {
|
||||
if !ingressServiceHasSDSOverrides(svc) {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(svc.Hosts) < 1 {
|
||||
// Shouldn't be possible with validation but be careful
|
||||
return nil, fmt.Errorf("no hosts specified with SDS certificate (service %q on listener on port %d)",
|
||||
svc.ToServiceName().ToServiceID().String(), listenerKey.Port)
|
||||
}
|
||||
|
||||
// Service has a certificate resource override. Return a new filter chain
|
||||
// with the right TLS cert and a filter that will load only the routes for
|
||||
// this service.
|
||||
routeName := routeNameForUpstream(listenerCfg, svc)
|
||||
filterOpts.filterName = routeName
|
||||
filterOpts.routeName = routeName
|
||||
filter, err := makeListenerFilter(filterOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tlsContext := &envoy_tls_v3.DownstreamTlsContext{
|
||||
CommonTlsContext: makeCommonTLSContextFromSDS(*svc.TLS.SDS),
|
||||
RequireClientCertificate: &wrappers.BoolValue{Value: false},
|
||||
}
|
||||
|
||||
transportSocket, err := makeDownstreamTLSTransportSocket(tlsContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chain := &envoy_listener_v3.FilterChain{
|
||||
// Only match traffic for this service's hosts.
|
||||
FilterChainMatch: makeSNIFilterChainMatch(svc.Hosts...),
|
||||
Filters: []*envoy_listener_v3.Filter{
|
||||
filter,
|
||||
},
|
||||
TransportSocket: transportSocket,
|
||||
}
|
||||
|
||||
chains = append(chains, chain)
|
||||
}
|
||||
|
||||
return chains, nil
|
||||
}
|
||||
|
||||
func makeCommonTLSContextFromSDS(sdsCfg structs.GatewayTLSSDSConfig) *envoy_tls_v3.CommonTlsContext {
|
||||
return &envoy_tls_v3.CommonTlsContext{
|
||||
TlsParams: &envoy_tls_v3.TlsParameters{},
|
||||
TlsCertificateSdsSecretConfigs: []*envoy_tls_v3.SdsSecretConfig{
|
||||
{
|
||||
Name: sdsCfg.CertResource,
|
||||
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},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ResourceApiVersion: envoy_core_v3.ApiVersion_V3,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
|
@ -485,6 +485,10 @@ func TestListenersFromSnapshot(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||
{Protocol: "http", Port: 8080}: {},
|
||||
{Protocol: "http", Port: 443}: {},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -499,6 +503,251 @@ func TestListenersFromSnapshot(t *testing.T) {
|
|||
create: proxycfg.TestConfigSnapshotIngressWithTLSListener,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-listener-gw-level",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithGatewaySDS,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-listener-listener-level",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithGatewaySDS,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||
{Protocol: "tcp", Port: 8080}: {
|
||||
{
|
||||
DestinationName: "foo",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
},
|
||||
}
|
||||
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||
{Protocol: "tcp", Port: 8080}: {
|
||||
Port: 8080,
|
||||
TLS: &structs.GatewayTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
// Override the cert, fall back to the cluster at gw level. We
|
||||
// don't test every possible valid combination here since we
|
||||
// already did that in TestResolveListenerSDSConfig. This is
|
||||
// just an extra check to make sure that data is plumbed through
|
||||
// correctly.
|
||||
CertResource: "listener-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-listener-gw-level-http",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithGatewaySDS,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
{
|
||||
DestinationName: "foo",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
},
|
||||
}
|
||||
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
Port: 8080,
|
||||
TLS: &structs.GatewayTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
// Override the cert, fall back to the cluster at gw level. We
|
||||
// don't test every possible valid combination here since we
|
||||
// already did that in TestResolveListenerSDSConfig. This is
|
||||
// just an extra check to make sure that data is plumbed through
|
||||
// correctly.
|
||||
CertResource: "listener-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-listener-gw-level-mixed-tls",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithGatewaySDS,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
// Disable GW-level defaults so we can mix TLS and non-TLS listeners
|
||||
snap.IngressGateway.TLSConfig.SDS = nil
|
||||
|
||||
// Setup two TCP listeners, one with and one without SDS config
|
||||
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||
{Protocol: "tcp", Port: 8080}: {
|
||||
{
|
||||
DestinationName: "secure",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
},
|
||||
{Protocol: "tcp", Port: 9090}: {
|
||||
{
|
||||
DestinationName: "insecure",
|
||||
LocalBindPort: 9090,
|
||||
},
|
||||
},
|
||||
}
|
||||
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||
{Protocol: "tcp", Port: 8080}: {
|
||||
Port: 8080,
|
||||
TLS: &structs.GatewayTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "listener-sds-cluster",
|
||||
CertResource: "listener-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
{Protocol: "tcp", Port: 9090}: {
|
||||
Port: 9090,
|
||||
TLS: nil,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-service-level",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithGatewaySDS,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
// Disable GW-level defaults so we can test only service-level
|
||||
snap.IngressGateway.TLSConfig.SDS = nil
|
||||
|
||||
// Setup http listeners, one multiple services with SDS
|
||||
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
{
|
||||
DestinationName: "s1",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
{
|
||||
DestinationName: "s2",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
},
|
||||
}
|
||||
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
Port: 8080,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "s1",
|
||||
Hosts: []string{"s1.example.com"},
|
||||
TLS: &structs.GatewayServiceTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "sds-cluster-1",
|
||||
CertResource: "s1.example.com-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "s2",
|
||||
Hosts: []string{"s2.example.com"},
|
||||
TLS: &structs.GatewayServiceTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "sds-cluster-2",
|
||||
CertResource: "s2.example.com-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TLS: nil, // no listener-level SDS config
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-listener+service-level",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithGatewaySDS,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
// Disable GW-level defaults so we can test only service-level
|
||||
snap.IngressGateway.TLSConfig.SDS = nil
|
||||
|
||||
// Setup http listeners, one multiple services with SDS
|
||||
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
{
|
||||
DestinationName: "s1",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
{
|
||||
DestinationName: "s2",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
},
|
||||
}
|
||||
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
Port: 8080,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "s1",
|
||||
Hosts: []string{"s1.example.com"},
|
||||
TLS: &structs.GatewayServiceTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "sds-cluster-1",
|
||||
CertResource: "s1.example.com-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "s2",
|
||||
// s2 uses the default listener cert
|
||||
},
|
||||
},
|
||||
TLS: &structs.GatewayTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "sds-cluster-2",
|
||||
CertResource: "*.example.com-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-service-level-mixed-no-tls",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithGatewaySDS,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
// Disable GW-level defaults so we can test only service-level
|
||||
snap.IngressGateway.TLSConfig.SDS = nil
|
||||
|
||||
// Setup http listeners, one multiple services with SDS
|
||||
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
{
|
||||
DestinationName: "s1",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
{
|
||||
DestinationName: "s2",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
},
|
||||
}
|
||||
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
Port: 8080,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "s1",
|
||||
Hosts: []string{"s1.example.com"},
|
||||
TLS: &structs.GatewayServiceTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "sds-cluster-1",
|
||||
CertResource: "s1.example.com-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "s2",
|
||||
// s2 has no SDS config so should be non-TLS
|
||||
},
|
||||
},
|
||||
TLS: nil, // No listener level TLS setup either
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "transparent-proxy",
|
||||
create: proxycfg.TestConfigSnapshot,
|
||||
|
@ -706,6 +955,17 @@ func TestListenersFromSnapshot(t *testing.T) {
|
|||
|
||||
gName += ".v2compat"
|
||||
|
||||
// It's easy to miss a new type that encodes a version from just
|
||||
// looking at the golden files so lets make it an error here. If
|
||||
// there are ever false positives we can maybe include an allow list
|
||||
// here as it seems safer to assume something was missed than to
|
||||
// assume we'll notice the golden file being wrong. Note the first
|
||||
// one matches both resourceApiVersion and transportApiVersion. I
|
||||
// left it as a suffix in case there are other field names that
|
||||
// follow that convention now or in the future.
|
||||
require.NotContains(t, gotJSON, `ApiVersion": "V3"`)
|
||||
require.NotContains(t, gotJSON, `type.googleapis.com/envoy.api.v3`)
|
||||
|
||||
require.JSONEq(t, goldenEnvoy(t, filepath.Join("listeners", gName), envoyVersion, latestEnvoyVersion_v2, gotJSON), gotJSON)
|
||||
})
|
||||
})
|
||||
|
@ -844,3 +1104,158 @@ var _ ConfigFetcher = (configFetcherFunc)(nil)
|
|||
func (f configFetcherFunc) AdvertiseAddrLAN() string {
|
||||
return f()
|
||||
}
|
||||
|
||||
func TestResolveListenerSDSConfig(t *testing.T) {
|
||||
type testCase struct {
|
||||
name string
|
||||
gwSDS *structs.GatewayTLSSDSConfig
|
||||
lisSDS *structs.GatewayTLSSDSConfig
|
||||
want *structs.GatewayTLSSDSConfig
|
||||
wantErr string
|
||||
}
|
||||
|
||||
run := func(tc testCase) {
|
||||
// fake a snapshot with just the data we care about
|
||||
snap := proxycfg.TestConfigSnapshotIngressWithGatewaySDS(t)
|
||||
// Override TLS configs
|
||||
snap.IngressGateway.TLSConfig.SDS = tc.gwSDS
|
||||
var key proxycfg.IngressListenerKey
|
||||
for k, lisCfg := range snap.IngressGateway.Listeners {
|
||||
if tc.lisSDS == nil {
|
||||
lisCfg.TLS = nil
|
||||
} else {
|
||||
lisCfg.TLS = &structs.GatewayTLSConfig{
|
||||
SDS: tc.lisSDS,
|
||||
}
|
||||
}
|
||||
// Override listener cfg in map
|
||||
snap.IngressGateway.Listeners[k] = lisCfg
|
||||
// Save the last key doesn't matter which as we set same listener config
|
||||
// for all.
|
||||
key = k
|
||||
}
|
||||
|
||||
got, err := resolveListenerSDSConfig(snap, key)
|
||||
if tc.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.wantErr)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.want, got)
|
||||
}
|
||||
}
|
||||
|
||||
cases := []testCase{
|
||||
{
|
||||
name: "no SDS config",
|
||||
gwSDS: nil,
|
||||
lisSDS: nil,
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "all cluster-level SDS config",
|
||||
gwSDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
CertResource: "cert",
|
||||
},
|
||||
lisSDS: nil,
|
||||
want: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
CertResource: "cert",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all listener-level SDS config",
|
||||
gwSDS: nil,
|
||||
lisSDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
CertResource: "cert",
|
||||
},
|
||||
want: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
CertResource: "cert",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mixed level SDS config",
|
||||
gwSDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
},
|
||||
lisSDS: &structs.GatewayTLSSDSConfig{
|
||||
CertResource: "cert",
|
||||
},
|
||||
want: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
CertResource: "cert",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "override cert",
|
||||
gwSDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
CertResource: "gw-cert",
|
||||
},
|
||||
lisSDS: &structs.GatewayTLSSDSConfig{
|
||||
CertResource: "lis-cert",
|
||||
},
|
||||
want: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
CertResource: "lis-cert",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "override both",
|
||||
gwSDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "gw-cluster",
|
||||
CertResource: "gw-cert",
|
||||
},
|
||||
lisSDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "lis-cluster",
|
||||
CertResource: "lis-cert",
|
||||
},
|
||||
want: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "lis-cluster",
|
||||
CertResource: "lis-cert",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing cluster listener",
|
||||
gwSDS: nil,
|
||||
lisSDS: &structs.GatewayTLSSDSConfig{
|
||||
CertResource: "lis-cert",
|
||||
},
|
||||
wantErr: "missing SDS cluster name",
|
||||
},
|
||||
{
|
||||
name: "missing cert listener",
|
||||
gwSDS: nil,
|
||||
lisSDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
},
|
||||
wantErr: "missing SDS cert resource",
|
||||
},
|
||||
{
|
||||
name: "missing cluster gw",
|
||||
gwSDS: &structs.GatewayTLSSDSConfig{
|
||||
CertResource: "lis-cert",
|
||||
},
|
||||
lisSDS: nil,
|
||||
wantErr: "missing SDS cluster name",
|
||||
},
|
||||
{
|
||||
name: "missing cert gw",
|
||||
gwSDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "cluster",
|
||||
},
|
||||
lisSDS: nil,
|
||||
wantErr: "missing SDS cert resource",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
run(tc)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -177,13 +177,17 @@ func (s *ResourceGenerator) routesForIngressGateway(
|
|||
continue
|
||||
}
|
||||
|
||||
upstreamRoute := &envoy_route_v3.RouteConfiguration{
|
||||
// Depending on their TLS config, upstreams are either attached to the
|
||||
// default route or have their own routes. We'll add any upstreams that
|
||||
// don't have custom filter chains and routes to this.
|
||||
defaultRoute := &envoy_route_v3.RouteConfiguration{
|
||||
Name: listenerKey.RouteName(),
|
||||
// ValidateClusters defaults to true when defined statically and false
|
||||
// when done via RDS. Re-set the reasonable value of true to prevent
|
||||
// null-routing traffic.
|
||||
ValidateClusters: makeBoolValue(true),
|
||||
}
|
||||
|
||||
for _, u := range upstreams {
|
||||
upstreamID := u.Identifier()
|
||||
chain := chains[upstreamID]
|
||||
|
@ -197,45 +201,42 @@ func (s *ResourceGenerator) routesForIngressGateway(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// See if we need to configure any special settings on this route config
|
||||
if lCfg, ok := listeners[listenerKey]; ok {
|
||||
if is := findIngressServiceMatchingUpstream(lCfg, u); is != nil {
|
||||
// Set up any header manipulation we need
|
||||
if is.RequestHeaders != nil {
|
||||
virtualHost.RequestHeadersToAdd = append(
|
||||
virtualHost.RequestHeadersToAdd,
|
||||
makeHeadersValueOptions(is.RequestHeaders.Add, true)...,
|
||||
)
|
||||
virtualHost.RequestHeadersToAdd = append(
|
||||
virtualHost.RequestHeadersToAdd,
|
||||
makeHeadersValueOptions(is.RequestHeaders.Set, false)...,
|
||||
)
|
||||
virtualHost.RequestHeadersToRemove = append(
|
||||
virtualHost.RequestHeadersToRemove,
|
||||
is.RequestHeaders.Remove...,
|
||||
)
|
||||
}
|
||||
if is.ResponseHeaders != nil {
|
||||
virtualHost.ResponseHeadersToAdd = append(
|
||||
virtualHost.ResponseHeadersToAdd,
|
||||
makeHeadersValueOptions(is.ResponseHeaders.Add, true)...,
|
||||
)
|
||||
virtualHost.ResponseHeadersToAdd = append(
|
||||
virtualHost.ResponseHeadersToAdd,
|
||||
makeHeadersValueOptions(is.ResponseHeaders.Set, false)...,
|
||||
)
|
||||
virtualHost.ResponseHeadersToRemove = append(
|
||||
virtualHost.ResponseHeadersToRemove,
|
||||
is.ResponseHeaders.Remove...,
|
||||
)
|
||||
}
|
||||
}
|
||||
// Lookup listener and service config details from ingress gateway
|
||||
// definition.
|
||||
lCfg, ok := listeners[listenerKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("missing ingress listener config (listener on port %d)", listenerKey.Port)
|
||||
}
|
||||
svc := findIngressServiceMatchingUpstream(lCfg, u)
|
||||
if svc == nil {
|
||||
return nil, fmt.Errorf("missing service in listener config (service %q listener on port %d)",
|
||||
u.DestinationID(), listenerKey.Port)
|
||||
}
|
||||
|
||||
upstreamRoute.VirtualHosts = append(upstreamRoute.VirtualHosts, virtualHost)
|
||||
if err := injectHeaderManipToVirtualHost(svc, virtualHost); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// See if this upstream has its own route/filter chain
|
||||
svcRouteName := routeNameForUpstream(lCfg, *svc)
|
||||
|
||||
// If the routeName is the same as the default one, merge the virtual host
|
||||
// to the default route
|
||||
if svcRouteName == defaultRoute.Name {
|
||||
defaultRoute.VirtualHosts = append(defaultRoute.VirtualHosts, virtualHost)
|
||||
} else {
|
||||
svcRoute := &envoy_route_v3.RouteConfiguration{
|
||||
Name: svcRouteName,
|
||||
ValidateClusters: makeBoolValue(true),
|
||||
VirtualHosts: []*envoy_route_v3.VirtualHost{virtualHost},
|
||||
}
|
||||
result = append(result, svcRoute)
|
||||
}
|
||||
}
|
||||
|
||||
result = append(result, upstreamRoute)
|
||||
if len(defaultRoute.VirtualHosts) > 0 {
|
||||
result = append(result, defaultRoute)
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
@ -262,13 +263,23 @@ func findIngressServiceMatchingUpstream(l structs.IngressListener, u structs.Ups
|
|||
// wasn't checked as it didn't matter. Assume there is only one now
|
||||
// though!
|
||||
wantSID := u.DestinationID()
|
||||
var foundSameNSWildcard *structs.IngressService
|
||||
for _, s := range l.Services {
|
||||
sid := structs.NewServiceID(s.Name, &s.EnterpriseMeta)
|
||||
if wantSID.Matches(sid) {
|
||||
return &s
|
||||
}
|
||||
if s.Name == structs.WildcardSpecifier &&
|
||||
s.NamespaceOrDefault() == wantSID.NamespaceOrDefault() &&
|
||||
s.PartitionOrDefault() == wantSID.PartitionOrDefault() {
|
||||
// Make a copy so we don't take a reference to the loop variable
|
||||
found := s
|
||||
foundSameNSWildcard = &found
|
||||
}
|
||||
}
|
||||
return nil
|
||||
// Didn't find an exact match. Return the wildcard from same service if we
|
||||
// found one.
|
||||
return foundSameNSWildcard
|
||||
}
|
||||
|
||||
func generateUpstreamIngressDomains(listenerKey proxycfg.IngressListenerKey, u structs.Upstream) []string {
|
||||
|
@ -753,6 +764,38 @@ func injectHeaderManipToRoute(dest *structs.ServiceRouteDestination, r *envoy_ro
|
|||
return nil
|
||||
}
|
||||
|
||||
func injectHeaderManipToVirtualHost(dest *structs.IngressService, vh *envoy_route_v3.VirtualHost) error {
|
||||
if !dest.RequestHeaders.IsZero() {
|
||||
vh.RequestHeadersToAdd = append(
|
||||
vh.RequestHeadersToAdd,
|
||||
makeHeadersValueOptions(dest.RequestHeaders.Add, true)...,
|
||||
)
|
||||
vh.RequestHeadersToAdd = append(
|
||||
vh.RequestHeadersToAdd,
|
||||
makeHeadersValueOptions(dest.RequestHeaders.Set, false)...,
|
||||
)
|
||||
vh.RequestHeadersToRemove = append(
|
||||
vh.RequestHeadersToRemove,
|
||||
dest.RequestHeaders.Remove...,
|
||||
)
|
||||
}
|
||||
if !dest.ResponseHeaders.IsZero() {
|
||||
vh.ResponseHeadersToAdd = append(
|
||||
vh.ResponseHeadersToAdd,
|
||||
makeHeadersValueOptions(dest.ResponseHeaders.Add, true)...,
|
||||
)
|
||||
vh.ResponseHeadersToAdd = append(
|
||||
vh.ResponseHeadersToAdd,
|
||||
makeHeadersValueOptions(dest.ResponseHeaders.Set, false)...,
|
||||
)
|
||||
vh.ResponseHeadersToRemove = append(
|
||||
vh.ResponseHeadersToRemove,
|
||||
dest.ResponseHeaders.Remove...,
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func injectHeaderManipToWeightedCluster(split *structs.ServiceSplit, c *envoy_route_v3.WeightedCluster_ClusterWeight) error {
|
||||
if !split.RequestHeaders.IsZero() {
|
||||
c.RequestHeadersToAdd = append(
|
||||
|
|
|
@ -155,6 +155,30 @@ func TestRoutesFromSnapshot(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
Port: 8080,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
{Protocol: "http", Port: 443}: {
|
||||
Port: 443,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "baz",
|
||||
},
|
||||
{
|
||||
Name: "qux",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// We do not add baz/qux here so that we test the chain.IsDefault() case
|
||||
entries := []structs.ConfigEntry{
|
||||
|
@ -216,6 +240,45 @@ func TestRoutesFromSnapshot(t *testing.T) {
|
|||
snap.IngressGateway.Listeners[k] = l
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-listener-level",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||
setup: setupIngressWithTwoHTTPServices(t, ingressSDSOpts{
|
||||
// Listener-level SDS means all services share the default route.
|
||||
listenerSDS: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-listener-level-wildcard",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||
setup: setupIngressWithTwoHTTPServices(t, ingressSDSOpts{
|
||||
// Listener-level SDS means all services share the default route.
|
||||
listenerSDS: true,
|
||||
wildcard: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-service-level",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||
setup: setupIngressWithTwoHTTPServices(t, ingressSDSOpts{
|
||||
listenerSDS: false,
|
||||
// Services should get separate routes and no default since they all
|
||||
// have custom certs.
|
||||
webSDS: true,
|
||||
fooSDS: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-service-level-mixed-tls",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||
setup: setupIngressWithTwoHTTPServices(t, ingressSDSOpts{
|
||||
listenerSDS: false,
|
||||
// Web needs a separate route as it has custom filter chain but foo
|
||||
// should use default route for listener.
|
||||
webSDS: true,
|
||||
fooSDS: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-lb-config",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
|
@ -324,6 +387,17 @@ func TestRoutesFromSnapshot(t *testing.T) {
|
|||
|
||||
gName += ".v2compat"
|
||||
|
||||
// It's easy to miss a new type that encodes a version from just
|
||||
// looking at the golden files so lets make it an error here. If
|
||||
// there are ever false positives we can maybe include an allow list
|
||||
// here as it seems safer to assume something was missed than to
|
||||
// assume we'll notice the golden file being wrong. Note the first
|
||||
// one matches both resourceApiVersion and transportApiVersion. I
|
||||
// left it as a suffix in case there are other field names that
|
||||
// follow that convention now or in the future.
|
||||
require.NotContains(t, gotJSON, `ApiVersion": "V3"`)
|
||||
require.NotContains(t, gotJSON, `type.googleapis.com/envoy.api.v3`)
|
||||
|
||||
require.JSONEq(t, goldenEnvoy(t, filepath.Join("routes", gName), envoyVersion, latestEnvoyVersion_v2, gotJSON), gotJSON)
|
||||
})
|
||||
})
|
||||
|
@ -585,3 +659,155 @@ func TestEnvoyLBConfig_InjectToRouteAction(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
type ingressSDSOpts struct {
|
||||
listenerSDS, webSDS, fooSDS, wildcard bool
|
||||
entMetas map[string]*structs.EnterpriseMeta
|
||||
}
|
||||
|
||||
// setupIngressWithTwoHTTPServices can be used with
|
||||
// proxycfg.TestConfigSnapshotIngressWithRouter to generate a setup func for an
|
||||
// ingress listener with multiple HTTP services and varying SDS configurations
|
||||
// since those affect how we generate routes.
|
||||
func setupIngressWithTwoHTTPServices(t *testing.T, o ingressSDSOpts) func(snap *proxycfg.ConfigSnapshot) {
|
||||
return func(snap *proxycfg.ConfigSnapshot) {
|
||||
|
||||
snap.IngressGateway.TLSConfig.SDS = nil
|
||||
|
||||
webUpstream := structs.Upstream{
|
||||
DestinationName: "web",
|
||||
// We use empty not default here because of the way upstream identifiers
|
||||
// vary between OSS and Enterprise currently causing test conflicts. In
|
||||
// real life `proxycfg` always sets ingress upstream namespaces to
|
||||
// `NamespaceOrDefault` which shouldn't matter because we should be
|
||||
// consistent within a single binary it's just inconvenient if OSS and
|
||||
// enterprise tests generate different output.
|
||||
DestinationNamespace: o.entMetas["web"].NamespaceOrEmpty(),
|
||||
DestinationPartition: o.entMetas["web"].PartitionOrEmpty(),
|
||||
LocalBindPort: 9191,
|
||||
IngressHosts: []string{
|
||||
"www.example.com",
|
||||
},
|
||||
}
|
||||
fooUpstream := structs.Upstream{
|
||||
DestinationName: "foo",
|
||||
DestinationNamespace: o.entMetas["foo"].NamespaceOrEmpty(),
|
||||
DestinationPartition: o.entMetas["foo"].PartitionOrEmpty(),
|
||||
LocalBindPort: 9191,
|
||||
IngressHosts: []string{
|
||||
"foo.example.com",
|
||||
},
|
||||
}
|
||||
|
||||
// Setup additional HTTP service on same listener with default router
|
||||
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||
{Protocol: "http", Port: 9191}: {webUpstream, fooUpstream},
|
||||
}
|
||||
il := structs.IngressListener{
|
||||
Port: 9191,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "web",
|
||||
Hosts: []string{"www.example.com"},
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
Hosts: []string{"foo.example.com"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for i, svc := range il.Services {
|
||||
if em, ok := o.entMetas[svc.Name]; ok && em != nil {
|
||||
il.Services[i].EnterpriseMeta = *em
|
||||
}
|
||||
}
|
||||
|
||||
// Now set the appropriate SDS configs
|
||||
if o.listenerSDS {
|
||||
il.TLS = &structs.GatewayTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "listener-cluster",
|
||||
CertResource: "listener-cert",
|
||||
},
|
||||
}
|
||||
}
|
||||
if o.webSDS {
|
||||
il.Services[0].TLS = &structs.GatewayServiceTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "web-cluster",
|
||||
CertResource: "www-cert",
|
||||
},
|
||||
}
|
||||
}
|
||||
if o.fooSDS {
|
||||
il.Services[1].TLS = &structs.GatewayServiceTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "foo-cluster",
|
||||
CertResource: "foo-cert",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if o.wildcard {
|
||||
// undo all that and set just a single wildcard config with no TLS to test
|
||||
// the lookup path where we have to compare an actual resolved upstream to
|
||||
// a wildcard config.
|
||||
il.Services = []structs.IngressService{
|
||||
{
|
||||
Name: "*",
|
||||
},
|
||||
}
|
||||
// We also don't support user-specified hosts with wildcard so remove
|
||||
// those from the upstreams.
|
||||
ups := snap.IngressGateway.Upstreams[proxycfg.IngressListenerKey{Protocol: "http", Port: 9191}]
|
||||
for i := range ups {
|
||||
ups[i].IngressHosts = nil
|
||||
}
|
||||
snap.IngressGateway.Upstreams[proxycfg.IngressListenerKey{Protocol: "http", Port: 9191}] = ups
|
||||
}
|
||||
|
||||
snap.IngressGateway.Listeners[proxycfg.IngressListenerKey{Protocol: "http", Port: 9191}] = il
|
||||
|
||||
entries := []structs.ConfigEntry{
|
||||
&structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
ConnectTimeout: 22 * time.Second,
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "foo",
|
||||
ConnectTimeout: 22 * time.Second,
|
||||
},
|
||||
}
|
||||
for i, e := range entries {
|
||||
switch v := e.(type) {
|
||||
// Add other Service types here if we ever need them above
|
||||
case *structs.ServiceResolverConfigEntry:
|
||||
if em, ok := o.entMetas[v.Name]; ok && em != nil {
|
||||
v.EnterpriseMeta = *em
|
||||
entries[i] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
webChain := discoverychain.TestCompileConfigEntries(t, "web",
|
||||
o.entMetas["web"].NamespaceOrDefault(),
|
||||
o.entMetas["web"].PartitionOrDefault(), "dc1",
|
||||
connect.TestClusterID+".consul", "dc1", nil, entries...)
|
||||
fooChain := discoverychain.TestCompileConfigEntries(t, "foo",
|
||||
o.entMetas["foo"].NamespaceOrDefault(),
|
||||
o.entMetas["web"].PartitionOrDefault(), "dc1",
|
||||
connect.TestClusterID+".consul", "dc1", nil, entries...)
|
||||
|
||||
snap.IngressGateway.DiscoveryChain[webUpstream.Identifier()] = webChain
|
||||
snap.IngressGateway.DiscoveryChain[fooUpstream.Identifier()] = fooChain
|
||||
}
|
||||
}
|
||||
|
|
154
agent/xds/testdata/listeners/ingress-with-sds-listener+service-level.envoy-1-18-x.golden
vendored
Normal file
154
agent/xds/testdata/listeners/ingress-with-sds-listener+service-level.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,154 @@
|
|||
{
|
||||
"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": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"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_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-1"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "*.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-2"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
154
agent/xds/testdata/listeners/ingress-with-sds-listener+service-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
154
agent/xds/testdata/listeners/ingress-with-sds-listener+service-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,154 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "http:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-1"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "*.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-2"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
82
agent/xds/testdata/listeners/ingress-with-sds-listener-gw-level-http.envoy-1-18-x.golden
vendored
Normal file
82
agent/xds/testdata/listeners/ingress-with-sds-listener-gw-level-http.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "listener-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.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.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "listener-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
89
agent/xds/testdata/listeners/ingress-with-sds-listener-gw-level-mixed-tls.envoy-1-18-x.golden
vendored
Normal file
89
agent/xds/testdata/listeners/ingress-with-sds-listener-gw-level-mixed-tls.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "insecure:1.2.3.4:9090",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9090
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||
"statPrefix": "upstream.insecure.default.default.dc1",
|
||||
"cluster": "insecure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "secure:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||
"statPrefix": "upstream.secure.default.default.dc1",
|
||||
"cluster": "secure.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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "listener-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "listener-sds-cluster"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "insecure:1.2.3.4:9090",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9090
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.tcp_proxy.v2.TcpProxy",
|
||||
"statPrefix": "upstream.insecure.default.default.dc1",
|
||||
"cluster": "insecure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "secure:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.tcp_proxy.v2.TcpProxy",
|
||||
"statPrefix": "upstream.secure.default.default.dc1",
|
||||
"cluster": "secure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "listener-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "listener-sds-cluster"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
64
agent/xds/testdata/listeners/ingress-with-sds-listener-gw-level.envoy-1-18-x.golden
vendored
Normal file
64
agent/xds/testdata/listeners/ingress-with-sds-listener-gw-level.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "cert-resource",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
64
agent/xds/testdata/listeners/ingress-with-sds-listener-gw-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
64
agent/xds/testdata/listeners/ingress-with-sds-listener-gw-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.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.config.filter.network.tcp_proxy.v2.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.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "cert-resource",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
142
agent/xds/testdata/listeners/ingress-with-sds-listener-listener+service-level.envoy-1-18-x.golden
vendored
Normal file
142
agent/xds/testdata/listeners/ingress-with-sds-listener-listener+service-level.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,142 @@
|
|||
{
|
||||
"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": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"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_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"clusterNames": [
|
||||
"sds-cluster-1"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "*.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"clusterNames": [
|
||||
"sds-cluster-2"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "http:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"clusterNames": [
|
||||
"sds-cluster-1"
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "*.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"clusterNames": [
|
||||
"sds-cluster-2"
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
64
agent/xds/testdata/listeners/ingress-with-sds-listener-listener-level.envoy-1-18-x.golden
vendored
Normal file
64
agent/xds/testdata/listeners/ingress-with-sds-listener-listener-level.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "foo:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||
"statPrefix": "upstream.foo.default.default.dc1",
|
||||
"cluster": "foo.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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "listener-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "foo:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.tcp_proxy.v2.TcpProxy",
|
||||
"statPrefix": "upstream.foo.default.default.dc1",
|
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "listener-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
147
agent/xds/testdata/listeners/ingress-with-sds-listener-service-level.envoy-1-18-x.golden
vendored
Normal file
147
agent/xds/testdata/listeners/ingress-with-sds-listener-service-level.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
{
|
||||
"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": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"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_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"clusterNames": [
|
||||
"sds-cluster-1"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s2.example.com"
|
||||
]
|
||||
},
|
||||
"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_s2",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
},
|
||||
"routeConfigName": "8080_s2"
|
||||
},
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s2.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"clusterNames": [
|
||||
"sds-cluster-2"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
149
agent/xds/testdata/listeners/ingress-with-sds-listener-service-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
149
agent/xds/testdata/listeners/ingress-with-sds-listener-service-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "http:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"clusterNames": [
|
||||
"sds-cluster-1"
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s2.example.com"
|
||||
]
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080_s2",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080_s2"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s2.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"clusterNames": [
|
||||
"sds-cluster-2"
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"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.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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "cert-resource",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"clusterNames": [
|
||||
"sds-cluster"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
58
agent/xds/testdata/listeners/ingress-with-sds-listener.v2compat.envoy-1-16-x.golden
vendored
Normal file
58
agent/xds/testdata/listeners/ingress-with-sds-listener.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.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.config.filter.network.tcp_proxy.v2.TcpProxy",
|
||||
"statPrefix": "upstream.db.default.dc1",
|
||||
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "cert-resource",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"clusterNames": [
|
||||
"sds-cluster"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
122
agent/xds/testdata/listeners/ingress-with-sds-service-level-mixed-no-tls.envoy-1-18-x.golden
vendored
Normal file
122
agent/xds/testdata/listeners/ingress-with-sds-service-level-mixed-no-tls.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"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": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"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_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-1"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"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": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "http:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-1"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
159
agent/xds/testdata/listeners/ingress-with-sds-service-level.envoy-1-18-x.golden
vendored
Normal file
159
agent/xds/testdata/listeners/ingress-with-sds-service-level.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
{
|
||||
"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": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"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_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-1"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s2.example.com"
|
||||
]
|
||||
},
|
||||
"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_s2",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
},
|
||||
"routeConfigName": "8080_s2"
|
||||
},
|
||||
"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": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s2.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V3",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-2"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
159
agent/xds/testdata/listeners/ingress-with-sds-service-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
159
agent/xds/testdata/listeners/ingress-with-sds-service-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "http:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s1.example.com"
|
||||
]
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080_s1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080_s1"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s1.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-1"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"s2.example.com"
|
||||
]
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_8080_s2",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
},
|
||||
"routeConfigName": "8080_s2"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificateSdsSecretConfigs": [
|
||||
{
|
||||
"name": "s2.example.com-cert",
|
||||
"sdsConfig": {
|
||||
"apiConfigSource": {
|
||||
"apiType": "GRPC",
|
||||
"transportApiVersion": "V2",
|
||||
"grpcServices": [
|
||||
{
|
||||
"envoyGrpc": {
|
||||
"clusterName": "sds-cluster-2"
|
||||
},
|
||||
"timeout": "5s"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resourceApiVersion": "V2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"requireClientCertificate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector"
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
48
agent/xds/testdata/routes/ingress-with-sds-listener-level-wildcard.envoy-1-18-x.golden
vendored
Normal file
48
agent/xds/testdata/routes/ingress-with-sds-listener-level-wildcard.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web",
|
||||
"domains": [
|
||||
"web.ingress.*",
|
||||
"web.ingress.*:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "foo",
|
||||
"domains": [
|
||||
"foo.ingress.*",
|
||||
"foo.ingress.*:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
48
agent/xds/testdata/routes/ingress-with-sds-listener-level-wildcard.v2compat.envoy-1-16-x.golden
vendored
Normal file
48
agent/xds/testdata/routes/ingress-with-sds-listener-level-wildcard.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web",
|
||||
"domains": [
|
||||
"web.ingress.*",
|
||||
"web.ingress.*:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "foo",
|
||||
"domains": [
|
||||
"foo.ingress.*",
|
||||
"foo.ingress.*:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
48
agent/xds/testdata/routes/ingress-with-sds-listener-level.envoy-1-18-x.golden
vendored
Normal file
48
agent/xds/testdata/routes/ingress-with-sds-listener-level.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web",
|
||||
"domains": [
|
||||
"www.example.com",
|
||||
"www.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "foo",
|
||||
"domains": [
|
||||
"foo.example.com",
|
||||
"foo.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
48
agent/xds/testdata/routes/ingress-with-sds-listener-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
48
agent/xds/testdata/routes/ingress-with-sds-listener-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web",
|
||||
"domains": [
|
||||
"www.example.com",
|
||||
"www.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "foo",
|
||||
"domains": [
|
||||
"foo.example.com",
|
||||
"foo.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
55
agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-tls.envoy-1-18-x.golden
vendored
Normal file
55
agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-tls.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "foo",
|
||||
"domains": [
|
||||
"foo.example.com",
|
||||
"foo.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191_web",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web",
|
||||
"domains": [
|
||||
"www.example.com",
|
||||
"www.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
55
agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-tls.v2compat.envoy-1-16-x.golden
vendored
Normal file
55
agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-tls.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "foo",
|
||||
"domains": [
|
||||
"foo.example.com",
|
||||
"foo.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "9191_web",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web",
|
||||
"domains": [
|
||||
"www.example.com",
|
||||
"www.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
55
agent/xds/testdata/routes/ingress-with-sds-service-level.envoy-1-18-x.golden
vendored
Normal file
55
agent/xds/testdata/routes/ingress-with-sds-service-level.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191_foo",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "foo",
|
||||
"domains": [
|
||||
"foo.example.com",
|
||||
"foo.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191_web",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web",
|
||||
"domains": [
|
||||
"www.example.com",
|
||||
"www.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
55
agent/xds/testdata/routes/ingress-with-sds-service-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
55
agent/xds/testdata/routes/ingress-with-sds-service-level.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "9191_foo",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "foo",
|
||||
"domains": [
|
||||
"foo.example.com",
|
||||
"foo.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "9191_web",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "web",
|
||||
"domains": [
|
||||
"www.example.com",
|
||||
"www.example.com:9191"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -440,7 +440,14 @@ func convertTypedConfigsToV2(pb proto.Message) error {
|
|||
return nil
|
||||
case *envoy_core_v2.ConfigSource:
|
||||
if x.ConfigSourceSpecifier != nil {
|
||||
if _, ok := x.ConfigSourceSpecifier.(*envoy_core_v2.ConfigSource_Ads); !ok {
|
||||
switch spec := x.ConfigSourceSpecifier.(type) {
|
||||
case *envoy_core_v2.ConfigSource_Ads:
|
||||
// Nothing else to do
|
||||
break
|
||||
case *envoy_core_v2.ConfigSource_ApiConfigSource:
|
||||
spec.ApiConfigSource.TransportApiVersion = envoy_core_v2.ApiVersion_V2
|
||||
break
|
||||
default:
|
||||
return fmt.Errorf("%T: ConfigSourceSpecifier type %T not handled", x, x.ConfigSourceSpecifier)
|
||||
}
|
||||
}
|
||||
|
@ -491,8 +498,30 @@ func convertTypedConfigsToV2(pb proto.Message) error {
|
|||
case *envoy_http_rbac_v2.RBAC:
|
||||
return nil
|
||||
case *envoy_tls_v2.UpstreamTlsContext:
|
||||
if x.CommonTlsContext != nil {
|
||||
if err := convertTypedConfigsToV2(x.CommonTlsContext); err != nil {
|
||||
return fmt.Errorf("%T: %w", x, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case *envoy_tls_v2.DownstreamTlsContext:
|
||||
if x.CommonTlsContext != nil {
|
||||
if err := convertTypedConfigsToV2(x.CommonTlsContext); err != nil {
|
||||
return fmt.Errorf("%T: %w", x, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case *envoy_tls_v2.CommonTlsContext:
|
||||
for _, sds := range x.TlsCertificateSdsSecretConfigs {
|
||||
if err := convertTypedConfigsToV2(sds); err != nil {
|
||||
return fmt.Errorf("%T: %w", x, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case *envoy_tls_v2.SdsSecretConfig:
|
||||
if err := convertTypedConfigsToV2(x.SdsConfig); err != nil {
|
||||
return fmt.Errorf("%T: %w", x, err)
|
||||
}
|
||||
return nil
|
||||
case *envoy_grpc_stats_v2.FilterConfig:
|
||||
return nil
|
||||
|
|
|
@ -40,6 +40,19 @@ type IngressGatewayConfigEntry struct {
|
|||
type GatewayTLSConfig struct {
|
||||
// Indicates that TLS should be enabled for this gateway service.
|
||||
Enabled bool
|
||||
|
||||
// SDS allows configuring TLS certificate from an SDS service.
|
||||
SDS *GatewayTLSSDSConfig `json:",omitempty"`
|
||||
}
|
||||
|
||||
type GatewayServiceTLSConfig struct {
|
||||
// SDS allows configuring TLS certificate from an SDS service.
|
||||
SDS *GatewayTLSSDSConfig `json:",omitempty"`
|
||||
}
|
||||
|
||||
type GatewayTLSSDSConfig struct {
|
||||
ClusterName string `json:",omitempty" alias:"cluster_name"`
|
||||
CertResource string `json:",omitempty" alias:"cert_resource"`
|
||||
}
|
||||
|
||||
// IngressListener manages the configuration for a listener on a specific port.
|
||||
|
@ -59,6 +72,9 @@ type IngressListener struct {
|
|||
// For "tcp" protocol listeners, only a single service is allowed.
|
||||
// For "http" listeners, multiple services can be declared.
|
||||
Services []IngressService
|
||||
|
||||
// TLS allows specifying some TLS configuration per listener.
|
||||
TLS *GatewayTLSConfig `json:",omitempty"`
|
||||
}
|
||||
|
||||
// IngressService manages configuration for services that are exposed to
|
||||
|
@ -93,6 +109,9 @@ type IngressService struct {
|
|||
// Namespacing is a Consul Enterprise feature.
|
||||
Namespace string `json:",omitempty"`
|
||||
|
||||
// TLS allows specifying some TLS configuration per listener.
|
||||
TLS *GatewayServiceTLSConfig `json:",omitempty"`
|
||||
|
||||
// Allow HTTP header manipulation to be configured.
|
||||
RequestHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"request_headers"`
|
||||
ResponseHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"response_headers"`
|
||||
|
|
|
@ -86,8 +86,26 @@ func TestAPI_ConfigEntries_IngressGateway(t *testing.T) {
|
|||
ResponseHeaders: &HTTPHeaderModifiers{
|
||||
Remove: []string{"x-foo"},
|
||||
},
|
||||
TLS: &GatewayServiceTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "foo",
|
||||
CertResource: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TLS: &GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "baz",
|
||||
CertResource: "qux",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ingress1.TLS = GatewayTLSConfig{
|
||||
SDS: &GatewayTLSSDSConfig{
|
||||
ClusterName: "qux",
|
||||
CertResource: "bug",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
FROM golang:latest
|
||||
|
||||
WORKDIR /go/src
|
||||
COPY ./test-sds-server .
|
||||
|
||||
RUN go build -v -o test-sds-server sds.go
|
||||
|
||||
CMD ["/go/src/test-sds-server"]
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
snapshot_envoy_admin localhost:20000 ingress-gateway primary || true
|
|
@ -0,0 +1,60 @@
|
|||
config_entries {
|
||||
bootstrap = [
|
||||
{
|
||||
kind = "proxy-defaults"
|
||||
name = "global"
|
||||
config {
|
||||
protocol = "http"
|
||||
}
|
||||
},
|
||||
{
|
||||
kind = "ingress-gateway"
|
||||
name = "ingress-gateway"
|
||||
|
||||
listeners = [
|
||||
{
|
||||
port = 9999
|
||||
protocol = "http"
|
||||
services = [
|
||||
{
|
||||
name = "*"
|
||||
}
|
||||
]
|
||||
tls {
|
||||
sds {
|
||||
cluster_name = "sds-cluster"
|
||||
cert_resource = "wildcard.ingress.consul"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
port = 9998
|
||||
protocol = "http"
|
||||
services = [
|
||||
{
|
||||
name = "s1"
|
||||
hosts = ["foo.example.com"]
|
||||
tls {
|
||||
sds {
|
||||
cluster_name = "sds-cluster"
|
||||
cert_resource = "foo.example.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
# Route to s2 on a differet domain with different cert
|
||||
name = "s2"
|
||||
hosts = ["www.example.com"]
|
||||
tls {
|
||||
sds {
|
||||
cluster_name = "sds-cluster"
|
||||
cert_resource = "www.example.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
services {
|
||||
name = "ingress-gateway"
|
||||
kind = "ingress-gateway"
|
||||
|
||||
proxy {
|
||||
config {
|
||||
# Note that http2_protocol_options is a deprecated field and Envoy 1.17
|
||||
# and up would prefer:
|
||||
# typed_extension_protocol_options:
|
||||
# envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
|
||||
# "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
|
||||
# explicit_http_config:
|
||||
# http2_protocol_options:
|
||||
#
|
||||
# But that breaks 1.15 and 1.16. For now use this which is supported by
|
||||
# all our supported versions to avoid needing to setup different
|
||||
# bootstrap based on the envoy version.
|
||||
envoy_extra_static_clusters_json = <<EOF
|
||||
{
|
||||
"name": "sds-cluster",
|
||||
"connect_timeout": "5s",
|
||||
"http2_protocol_options": {},
|
||||
"load_assignment": {
|
||||
"cluster_name": "sds-cluster",
|
||||
"endpoints": [
|
||||
{
|
||||
"lb_endpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socket_address": {
|
||||
"address": "127.0.0.1",
|
||||
"port_value": 1234
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# wait for bootstrap to apply config entries
|
||||
wait_for_config_entry ingress-gateway ingress-gateway
|
||||
wait_for_config_entry proxy-defaults global
|
||||
|
||||
register_services primary
|
||||
|
||||
gen_envoy_bootstrap ingress-gateway 20000 primary true
|
||||
gen_envoy_bootstrap s1 19000
|
||||
gen_envoy_bootstrap s2 19001
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
export REQUIRED_SERVICES="$DEFAULT_REQUIRED_SERVICES ingress-gateway-primary test-sds-server"
|
||||
|
||||
if is_set $TEST_V2_XDS; then
|
||||
export SKIP_CASE="test SDS server doesn't support V2"
|
||||
fi
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
@test "ingress proxy admin is up on :20000" {
|
||||
retry_default curl -f -s localhost:20000/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s1 proxy admin is up on :19000" {
|
||||
retry_default curl -f -s localhost:19000/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s2 proxy admin is up on :19001" {
|
||||
retry_default curl -f -s localhost:19001/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s1 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21000 s1
|
||||
}
|
||||
|
||||
@test "s2 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21001 s2
|
||||
}
|
||||
|
||||
@test "ingress-gateway should have healthy endpoints for s1" {
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s1 HEALTHY 1
|
||||
}
|
||||
|
||||
@test "ingress-gateway should have healthy endpoints for s2" {
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s2 HEALTHY 1
|
||||
}
|
||||
|
||||
@test "ingress should be able to connect to s1 using Host header" {
|
||||
assert_expected_fortio_name s1 https://s1.ingress.consul 9999
|
||||
}
|
||||
|
||||
@test "ingress should be able to connect to s2 using Host header" {
|
||||
assert_expected_fortio_name s2 https://s2.ingress.consul 9999
|
||||
}
|
||||
|
||||
@test "ingress should be able to connect to s1 using a user-specified Host" {
|
||||
assert_expected_fortio_name s1 https://foo.example.com 9998
|
||||
}
|
||||
|
||||
@test "ingress should serve SDS-supplied cert for wildcard service" {
|
||||
# Make sure the Cert was the one SDS served and didn't just happen to have the
|
||||
# right domain from Connect.
|
||||
assert_cert_signed_by_ca /workdir/test-sds-server/certs/ca-root.crt \
|
||||
localhost:9999 '*.ingress.consul'
|
||||
}
|
||||
|
||||
@test "ingress should serve SDS-supplied cert for specific service" {
|
||||
# Make sure the Cert was the one SDS served and didn't just happen to have the
|
||||
# right domain from Connect.
|
||||
assert_cert_signed_by_ca /workdir/test-sds-server/certs/ca-root.crt \
|
||||
localhost:9998 foo.example.com
|
||||
}
|
||||
|
||||
@test "ingress should serve SDS-supplied cert for second specific service on same http listener" {
|
||||
# Make sure the Cert was the one SDS served and didn't just happen to have the
|
||||
# right domain from Connect. This also ensures that listeners work when we've
|
||||
# had to split their routing tables due to different certs for different
|
||||
# hostnames.
|
||||
assert_cert_signed_by_ca /workdir/test-sds-server/certs/ca-root.crt \
|
||||
localhost:9998 www.example.com
|
||||
}
|
|
@ -100,7 +100,13 @@ function is_set {
|
|||
|
||||
function get_cert {
|
||||
local HOSTPORT=$1
|
||||
CERT=$(openssl s_client -connect $HOSTPORT -showcerts </dev/null)
|
||||
local SERVER_NAME=$2
|
||||
local CA_FILE=$3
|
||||
local SNI_FLAG=""
|
||||
if [ -n "$SERVER_NAME" ]; then
|
||||
SNI_FLAG="-servername $SERVER_NAME"
|
||||
fi
|
||||
CERT=$(openssl s_client -connect $HOSTPORT $SNI_FLAG -showcerts </dev/null)
|
||||
openssl x509 -noout -text <<< "$CERT"
|
||||
}
|
||||
|
||||
|
@ -122,16 +128,34 @@ function assert_proxy_presents_cert_uri {
|
|||
function assert_dnssan_in_cert {
|
||||
local HOSTPORT=$1
|
||||
local DNSSAN=$2
|
||||
local SERVER_NAME=${3:-$DNSSAN}
|
||||
|
||||
CERT=$(retry_default get_cert $HOSTPORT)
|
||||
CERT=$(retry_default get_cert $HOSTPORT $SERVER_NAME)
|
||||
|
||||
echo "WANT DNSSAN: ${DNSSAN}"
|
||||
echo "WANT DNSSAN: ${DNSSAN} (SNI: ${SERVER_NAME})"
|
||||
echo "GOT CERT:"
|
||||
echo "$CERT"
|
||||
|
||||
echo "$CERT" | grep -Eo "DNS:${DNSSAN}"
|
||||
}
|
||||
|
||||
function assert_cert_signed_by_ca {
|
||||
local CA_FILE=$1
|
||||
local HOSTPORT=$2
|
||||
local DNSSAN=$3
|
||||
local SERVER_NAME=${4:-$DNSSAN}
|
||||
local SNI_FLAG=""
|
||||
if [ -n "$SERVER_NAME" ]; then
|
||||
SNI_FLAG="-servername $SERVER_NAME"
|
||||
fi
|
||||
CERT=$(openssl s_client -connect $HOSTPORT $SNI_FLAG -CAfile $CA_FILE -showcerts </dev/null)
|
||||
|
||||
echo "GOT CERT:"
|
||||
echo "$CERT"
|
||||
|
||||
echo "$CERT" | grep 'Verify return code: 0 (ok)'
|
||||
}
|
||||
|
||||
function assert_envoy_version {
|
||||
local ADMINPORT=$1
|
||||
run retry_default curl -f -s localhost:$ADMINPORT/server_info
|
||||
|
@ -823,8 +847,25 @@ function get_upstream_fortio_name {
|
|||
if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then
|
||||
extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}"
|
||||
fi
|
||||
run retry_default curl -v -s -f -H"Host: ${HOST}" $extra_args \
|
||||
"localhost:${PORT}${PREFIX}/debug?env=dump"
|
||||
# split proto if https:// is at the front of the host since the --resolve
|
||||
# string needs just a bare host.
|
||||
local PROTO=""
|
||||
local CA_FILE=""
|
||||
if [ "${HOST:0:8}" = "https://" ]; then
|
||||
HOST="${HOST:8}"
|
||||
PROTO="https://"
|
||||
extra_args="${extra_args} --cacert /workdir/test-sds-server/certs/ca-root.crt"
|
||||
fi
|
||||
# We use --resolve instead of setting a Host header since we need the right
|
||||
# name to be sent for SNI in some cases too.
|
||||
run retry_default curl -v -s -f --resolve "${HOST}:${PORT}:127.0.0.1" $extra_args \
|
||||
"${PROTO}${HOST}:${PORT}${PREFIX}/debug?env=dump"
|
||||
|
||||
# Useful Debugging but breaks the expectation that the value output is just
|
||||
# the grep output when things don't fail
|
||||
if [ "$status" != 0 ]; then
|
||||
echo "GOT FORTIO OUTPUT: $output"
|
||||
fi
|
||||
[ "$status" == 0 ]
|
||||
echo "$output" | grep -E "^FORTIO_NAME="
|
||||
}
|
||||
|
@ -836,12 +877,12 @@ function assert_expected_fortio_name {
|
|||
local URL_PREFIX=${4:-""}
|
||||
local DEBUG_HEADER_VALUE="${5:-""}"
|
||||
|
||||
GOT=$(get_upstream_fortio_name ${HOST} ${PORT} "${URL_PREFIX}" "${DEBUG_HEADER_VALUE}")
|
||||
run get_upstream_fortio_name ${HOST} ${PORT} "${URL_PREFIX}" "${DEBUG_HEADER_VALUE}"
|
||||
|
||||
if [ "$GOT" != "FORTIO_NAME=${EXPECT_NAME}" ]; then
|
||||
echo "expected name: $EXPECT_NAME, actual name: $GOT" 1>&2
|
||||
return 1
|
||||
fi
|
||||
echo "GOT: $output"
|
||||
|
||||
[ "$status" == 0 ]
|
||||
[ "$output" == "FORTIO_NAME=${EXPECT_NAME}" ]
|
||||
}
|
||||
|
||||
function assert_expected_fortio_name_pattern {
|
||||
|
@ -889,4 +930,4 @@ function assert_expected_fortio_host_header {
|
|||
echo "expected Host header: $EXPECT_HOST, actual Host header: $GOT" 1>&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
}
|
|
@ -89,6 +89,10 @@ function init_workdir {
|
|||
# move all of the registration files OUT of the consul config dir now
|
||||
find workdir/${DC}/consul -type f -name 'service_*.hcl' -exec mv -f {} workdir/${DC}/register \;
|
||||
|
||||
# copy the ca-certs for SDS so we can verify the right ones are served
|
||||
mkdir -p workdir/test-sds-server/certs
|
||||
cp test-sds-server/certs/ca-root.crt workdir/test-sds-server/certs/ca-root.crt
|
||||
|
||||
if test -d "${CASE_DIR}/data"
|
||||
then
|
||||
cp -r ${CASE_DIR}/data/* workdir/${DC}/data
|
||||
|
@ -283,6 +287,7 @@ function run_tests {
|
|||
CASE_DIR="${CASE_DIR?CASE_DIR must be set to the path of the test case}"
|
||||
CASE_NAME=$( basename $CASE_DIR | cut -c6- )
|
||||
export CASE_NAME
|
||||
export SKIP_CASE=""
|
||||
|
||||
init_vars
|
||||
|
||||
|
@ -296,6 +301,12 @@ function run_tests {
|
|||
|
||||
global_setup
|
||||
|
||||
# Allow vars.sh to set a reason to skip this test case based on the ENV
|
||||
if [ "$SKIP_CASE" != "" ] ; then
|
||||
echoyellow "SKIPPING CASE: $SKIP_CASE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Wipe state
|
||||
wipe_volumes
|
||||
|
||||
|
@ -366,6 +377,10 @@ function suite_setup {
|
|||
docker build -t consul-dev-envoy:${ENVOY_VERSION} \
|
||||
--build-arg ENVOY_VERSION=${ENVOY_VERSION} \
|
||||
-f Dockerfile-consul-envoy .
|
||||
|
||||
# pre-build the test-sds-server container
|
||||
echo "Rebuilding 'test-sds-server' image..."
|
||||
docker build -t test-sds-server -f Dockerfile-test-sds-server .
|
||||
}
|
||||
|
||||
function suite_teardown {
|
||||
|
@ -576,6 +591,13 @@ function run_container_jaeger {
|
|||
--collector.zipkin.http-port=9411
|
||||
}
|
||||
|
||||
function run_container_test-sds-server {
|
||||
docker run -d --name $(container_name) \
|
||||
$WORKDIR_SNIPPET \
|
||||
$(network_snippet primary) \
|
||||
"test-sds-server"
|
||||
}
|
||||
|
||||
function container_name {
|
||||
echo "envoy_${FUNCNAME[1]/#run_container_/}_1"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIE5jCCAs4CCQCSUow3YnwtFTANBgkqhkiG9w0BAQsFADA1MQswCQYDVQQGEwJV
|
||||
UzELMAkGA1UECAwCQ0ExGTAXBgNVBAMMEFNEUyBUZXN0IENBIENlcnQwHhcNMjEw
|
||||
ODI0MTIzMjM4WhcNMzEwODIyMTIzMjM4WjA1MQswCQYDVQQGEwJVUzELMAkGA1UE
|
||||
CAwCQ0ExGTAXBgNVBAMMEFNEUyBUZXN0IENBIENlcnQwggIiMA0GCSqGSIb3DQEB
|
||||
AQUAA4ICDwAwggIKAoICAQDFGKACcPEVX4qMV6+ycjsTC5BAeGvB/9k1g6vULdEM
|
||||
atyZMJ74i/vMuI6NSNKbB+XKyZVfbLDkoU2vlnDIWljX13WiFOHA7yueuIFyYTWl
|
||||
7OG3SIoABqefh14dd86DyBrBYsNIp//QyzFNX9D98Ss3dnBnINTvFfFZKQ/hR90r
|
||||
wtOtgh51vUTHU8dhHP2i7t/YoHn5yIUrtkLYKOe76loveqRE9G34QHPo00EHEg/X
|
||||
0cCSOwzos+wK9ebLzgXdquvuIf8e8xkwJEpo/1MZ/0Tq9zsGWkNSM6G0jQ0qrHoa
|
||||
X+LMGY5JnyZTMjuwLI5UtU9b4aSxbUbVoHftVxnkfVPSOD1770QLLpYIUBEvbonh
|
||||
Y3r4zejQY2ES1sbMIOX+9lYaZKGGwd8/777bjeYTI+oIHlWgDMqiLhwzCOuQQ2Jo
|
||||
c7ilfWItyhAmucJdpHY80aFGGUhbqUWftrFnuSRJlxUy2+sEqIQiv1D1/q3pLcOP
|
||||
rPB/GozfeCW346LO5NpJmBdWItO37EARmH1cZW3PbX6FeXHWgm2MjWNR0E3K4Biv
|
||||
r0QeYagzjIjTiXqfZAMPscjHZI3YpMDtXuHUD2ppoCpAu0Qw5CKmvw834P2xezM9
|
||||
Y28CfciGxknYtkf3hd1Vgr0aRnBd5PRJq3iNdfO/a/YpDpdhFhDi29MPPnAJxBpj
|
||||
CwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQAIFjEsrFR2AwhPuBCY9rB8NXiuWU6A
|
||||
O9hXxF36VUolJpD5F/E3J5LGSRlI4H5fAX09aoPNfwqTN4jBWOg0pAZP2oZ1BBQ8
|
||||
VQZwzGki9uJTKDnr09mnnMFbdVceYN+nh2HlknEyVj6oSGpD/D1WvhOpeAct30f4
|
||||
Z/kKnfM7awUJ/0VsbtVwcBMJTuoFflig9NXyqU1QRA2wEvnFSPG7bqprWE4FtODL
|
||||
71Fj9gB4M/PFs8+dB9UeSeI20834hRw8zI/QwpMyAs/5EU6wxjaVQtEba396oVQU
|
||||
BC+UxxQOmK/m31OKJYBLrzeeRD/im4H9fsbWiw4C0xi72OFDWjsRay5mxZlF9N2G
|
||||
LPIwS9f34JU5HBa/jutShfHE8xnUOeLiXz7AZJ4cNbN+OMPBF40gr67mGCTLpidd
|
||||
Kldl57UBQacrkecficpmL2KuCAZ80m1QxTJzTIzwSgqPfElsilNFNzeKaM+Qct/S
|
||||
XSOEsd7St7PxzceiyNkOOV6W+b4GVmxgiClQsWqxMmH7P9X6B+M0SSHFwIxaf126
|
||||
VpMOKRXH838s8aFl38PfnEY3v6mS5irvSk9iUsYRpcBHETVzltHzF5Qyn7lp9ncf
|
||||
iNlIeFEPABODkkU8KQ5MxAwHn5XoXIfJBRrmBfKvxEMCxdUrmUl3ZcsQMvj0c6xJ
|
||||
MUv9D4WRXMb3XA==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIJKAIBAAKCAgEAxRigAnDxFV+KjFevsnI7EwuQQHhrwf/ZNYOr1C3RDGrcmTCe
|
||||
+Iv7zLiOjUjSmwflysmVX2yw5KFNr5ZwyFpY19d1ohThwO8rnriBcmE1pezht0iK
|
||||
AAann4deHXfOg8gawWLDSKf/0MsxTV/Q/fErN3ZwZyDU7xXxWSkP4UfdK8LTrYIe
|
||||
db1Ex1PHYRz9ou7f2KB5+ciFK7ZC2Cjnu+paL3qkRPRt+EBz6NNBBxIP19HAkjsM
|
||||
6LPsCvXmy84F3arr7iH/HvMZMCRKaP9TGf9E6vc7BlpDUjOhtI0NKqx6Gl/izBmO
|
||||
SZ8mUzI7sCyOVLVPW+GksW1G1aB37VcZ5H1T0jg9e+9ECy6WCFARL26J4WN6+M3o
|
||||
0GNhEtbGzCDl/vZWGmShhsHfP+++243mEyPqCB5VoAzKoi4cMwjrkENiaHO4pX1i
|
||||
LcoQJrnCXaR2PNGhRhlIW6lFn7axZ7kkSZcVMtvrBKiEIr9Q9f6t6S3Dj6zwfxqM
|
||||
33glt+OizuTaSZgXViLTt+xAEZh9XGVtz21+hXlx1oJtjI1jUdBNyuAYr69EHmGo
|
||||
M4yI04l6n2QDD7HIx2SN2KTA7V7h1A9qaaAqQLtEMOQipr8PN+D9sXszPWNvAn3I
|
||||
hsZJ2LZH94XdVYK9GkZwXeT0Sat4jXXzv2v2KQ6XYRYQ4tvTDz5wCcQaYwsCAwEA
|
||||
AQKCAgBn+Zan0wcLfGxtnvB8FdDeOjJuIFjQbfUbSwwBke3/O/yF/+VNPyOlmxLw
|
||||
q6MWz/LEqNVZEtC6u/FsmNOEjkziCLLwv01c548+Wx1GxstzbeShOO48F0akXNgk
|
||||
eYiDcrPSoxRcJuxILHkk1VA+NtTSnHOto99RBWVd4NCUysF9jXj3xnXlLOS0tpiu
|
||||
vYl8Q8Ho2LegMs02Ax9+Qw4Ezxumgm9YRQ4icXX0NEXQwhGDjA6n1ej4dbonChQo
|
||||
HdZwWvO9m0en/xyhjfOHMnKXe1fTEHud3U44di5vPh3dDkIX2c+eVjj+06t3Jj/g
|
||||
r5CiVUe5M+8a/ofouI+rsFBjfk4R4d7uC9FEvuv8SLzBBkCvZK3VLpX+8YCdlaVE
|
||||
y+2iTp0C42FB4RvSj8aV3qu6mxbyA1fa/Q17GiexYYuBqnc+yQANs5uBra+Lidn7
|
||||
W66D0cMEJS3IZJ5atpasFBiXh7a/xXAQBq6H3daEGyvgDZt144qqqVZBrGq5ZIYm
|
||||
4fbFMIbEC1xPovnPLlYPGeYwydXYGbKaPZ3S5Q30QAj+j7L1vvczvf0CmeYTc4dI
|
||||
qrQiLe8ksZ/wD7X5xOUPRFGKmiUqDLPDxGKX4kRKNmEZ7zo9lp+/LAAty5ekFS3f
|
||||
I5Vi0MjLCTCOt1xtgtArUuEK7QsV1p+CXfExhA/aALjnw/tWSQKCAQEA7fMmb8sp
|
||||
JYrkoJZHLz/jsvYAkY4B+j3L9Fdbd5b8kh+hvw9J5Av6IETJfWCxI+gPuyX6/0KK
|
||||
UzOv+bU/tT1Z/4Cb5S5TobTO83Yfs8XA1ML8ZMl8b9w7vpyUBoR93DCREpd1uF0Y
|
||||
89o1eKOPpjCvJMqDN+A3SQ3rqmkeEiFA1iNhhexjoon3u+v6xKfmG6txKcsS+vtq
|
||||
v8dKEvMsy25AkC6CnHpFR9WpuaCu48nRFif9ru5eZCKN3Vu+WFG/KuVCKtxZAFtE
|
||||
GVPvZ7ZkRY5V2uEDjeLXIz8ygv4ZcoRI79k2+SkoIbs1mrSWQqFVUDtaiekgyt3K
|
||||
vXG/jElg1NmTpwKCAQEA1Awe9vsADWCQo54cTToHe6+N/6DKddjvEFKly6QDPbxq
|
||||
zBbJNgQ8CCxF19lZY8nOMZsRi8qwb/ytnK2lYBp8+x/5g6NsQ6QkuWUmSPBJR2O/
|
||||
370284V1fwj/L9LxO3FS2Ci6AVlsMxEHG1Uifq80F80kSt2Qfdh3qTGrIrH9xFhQ
|
||||
RDGRaTURIWZEtpmJrmwLZFeWLJVOwAfRKuz+vEuOK2f1GwfK5avcGnRxXvp0SJU1
|
||||
uO+Aamj5i5aBz//gMhx/QAAOgVEhrED2bPKPj1erDa/yksB6t73fg3Gki7LdPf/E
|
||||
g3nBMTXMkI6MNA1h9IeRTnJXJgJpr6Qqy18wybux/QKCAQEA2OJSu30rAPwrTbAM
|
||||
LCYIzjrp48HTTZr8BreFOGjXx/yq+jHeQM0l7DmmifATJc5EYGnK8NVerV2kXW92
|
||||
JSVJndhEwE1Mj0z1gPW/CaYLECK12MvJ70+G6UNgrNwguA1QfeittSCuOL5BFLfI
|
||||
nEstqNQpbEmjOqRElOwBK7dBmK1hG6eOXT1yH8iEprD+zWOj3tspbriw4SKuAr3B
|
||||
q57PnFu4UxYjhclbTUYHgrqWKKLE2KiOQqk4M3aG9Yt1Oo0ClXyIZwnI9WkLArY9
|
||||
iSSmXr3P9oi3XXoh+UHQQhAPRwbu04ZO/QfdYSiO+SaCU4H2EVP7vs0QGULPu/e6
|
||||
GehDawKCAQBo35nM8zUCaLkAgyliNIoQ7TGgtUiM4n7SJt4jCnoj5XU4fSiE07FR
|
||||
JXxhlfi09tFJDXWvGs8KhADllahOEKuxlA3WwlPAXIVhQBqgRl8ntLjoEnAEHwSO
|
||||
kMeNQpnWmWSsze+4zR5LX2eRaBjIaSSthOMnN8/HvfDouEz4uulUW41PPOi7DOjt
|
||||
COSBHwzOPFeiCAOZBztMlFEqFs6iGAg3hZHfDYqW7tnMJ70OiXZLk6hfT+zGNCb/
|
||||
l6+aTOX4QsnYwG5sHNE3nWWDWrAP5/8MpPGnDRVknL7YBrOn+A2eJUpu8B/Rk9cZ
|
||||
w7ap49iHlSkTkE9z2AunN92GegzqKS+NAoIBABIyp3GOvAHfMKPDWoP9YvSeyxfd
|
||||
nnnA+OqS5CrpXcifLaY1kDdpPvI8Kixi+6+gtU4N5yoi2nfiG7X7JsWA//OPBymp
|
||||
OSqIlrC9adAM6UdoYuQHb4v2Wdk98Hdk5Su+xIERP09fC1PXWh6c2W5YzrBqsNKg
|
||||
RIq/oz1arcgESAbhFNqYMHoMKcFVnkS8XO8JvL9mQbnGYCwUsbcWb6rfKQtrspMF
|
||||
Owy2EOn0F9a1pj1VndHSRR6Tu5NgpcZtWlaOXTUuvtn594zRjotYeGu/nmyhTO2x
|
||||
ZE3IsZpHujFlUPctmFeRle5AL0Ev6ikfsgafF44kqA2D8iM236BeKCLHpSg=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1 @@
|
|||
E3EC7A5D1F03189F
|
|
@ -0,0 +1,24 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIECjCCAfKgAwIBAgIJAOPsel0fAxibMA0GCSqGSIb3DQEBCwUAMDUxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJDQTEZMBcGA1UEAwwQU0RTIFRlc3QgQ0EgQ2VydDAe
|
||||
Fw0yMTA4MjQxMjMyMzhaFw0zMTA4MjIxMjMyMzhaMDQxCzAJBgNVBAYTAlVTMQsw
|
||||
CQYDVQQIDAJDQTEYMBYGA1UEAwwPZm9vLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG
|
||||
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoNqz7MhSbI3pn+vNfO/3FrEkC64jmxrSK9bQ
|
||||
W4WXhbstaM1SbrIqlzacOhslyj5RjzNb1d1TAhdGzrrLiSkCGsstAnMOQIFzP1j9
|
||||
2Jiesm5ypiqiOACnwEmSOcfH91N3l/9rLB14uon3q3bLuKv2TjIKeQ21WlIIUSF4
|
||||
RwTZGb1sagj8qT9+k/byt94cURVK8DljAuY7v74XLoomRyr4hqaUnamE+K9/rPHi
|
||||
3IlcTdECHX57SLmfJvSD5YU1O+6l8+u2F79E1/Po2ckNuTFopwnAO487US8qRVjs
|
||||
3bn/iu9WcMNdTwwEdLEVPPAGNNEvl5gKzrIr+0aoE/XCJuDKFQIDAQABox4wHDAa
|
||||
BgNVHREEEzARgg9mb28uZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggIBADYg
|
||||
UcWXPZdH1QPgWNgbs3q9ldNi1bl7BmPxuZio3a/yP1+xHWFVKvHJEQZI2OgdESCV
|
||||
zkLhpVOzpK9MO+pCSzE3ZOtM7+nKtHwmOGsjK7pOJblwXb3kXi6stEellKXOU4h3
|
||||
zYR5L0uZu7OBTnigvYSwT3cvTMQFRttVVJ5UYr+s84QUrKesiYlitUqiHmiBRitx
|
||||
/3Pxft/V5KvIuovJD7YXJij+hst17Wmoe/lpN6vzGBFaNJE25TZe+momCfU1Cn/F
|
||||
v0n63wwoR6LsSUuI5T7gFdUb/JXrJWV37P1fs/rk/8H2c6IYxVRjGSNGRIQ+QhdU
|
||||
2hVXEWexdieRcGsL75E0p9Ok5OjICPkdlkhhMRkJv/oVA9YNaqLk8t0ZtJmWX7Jr
|
||||
3rILNispG1UnfaBYFtXSSPUbQqyujeqMcXIg1JOAK1tjcMGPrd8BcaU8tT0Ycvg3
|
||||
kOcTayd9ZwuJhHTpNW090d3K55FJhEmR+1S4/JoHI1MLEUDRACdxnCKhJ+X9qPlk
|
||||
DBqyudDRaoe54eoUXtxBujB3rgTrWpryBvxJ5cXEeN8W0Yv8dTEywlHF3X+sp3U/
|
||||
5hlMrzsAn7+O+ZnxnSPGrIP/UxSqEoSz1Jz7mNhIXYTV1V1L8mRyDAEIBLMmTyEj
|
||||
hg2RBdjqu5KFPFogazXpe9mAK+hxb5TfsroWn/Zk
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAoNqz7MhSbI3pn+vNfO/3FrEkC64jmxrSK9bQW4WXhbstaM1S
|
||||
brIqlzacOhslyj5RjzNb1d1TAhdGzrrLiSkCGsstAnMOQIFzP1j92Jiesm5ypiqi
|
||||
OACnwEmSOcfH91N3l/9rLB14uon3q3bLuKv2TjIKeQ21WlIIUSF4RwTZGb1sagj8
|
||||
qT9+k/byt94cURVK8DljAuY7v74XLoomRyr4hqaUnamE+K9/rPHi3IlcTdECHX57
|
||||
SLmfJvSD5YU1O+6l8+u2F79E1/Po2ckNuTFopwnAO487US8qRVjs3bn/iu9WcMNd
|
||||
TwwEdLEVPPAGNNEvl5gKzrIr+0aoE/XCJuDKFQIDAQABAoIBAHbCQcj19XTUKcK6
|
||||
k9JEUQdd7aD6BqvDV5yqUtbfgQlpMpOH0+6KeEuANEPqOzJgZFL3tjvl1h1bFhoX
|
||||
a6JutnEVxLtkOweBC5efmntJ4xEV3mu0WmRCh5e+OcmTKJ3/7/I2z+eYMsR2jHb5
|
||||
lFtaCtWcuIK7jkOLATz1GxpECA2p0zQZOlg2KyO2oyypig52p+kzR79L8EWcK3gX
|
||||
fJHdgycPkqbWb0mal3MPyHmMuYSvIeh40uTnTu0MAQh+N32247vuxXZu0zSeiOXe
|
||||
vJdgPRi8FpNe97DVmcx/JUKjmfuBySL8w6Jg1hrXGZTpEgEZVYWITEP1SmnGYGGW
|
||||
mzsyzMECgYEAzHw/ZqaEnXl+XmhuigFr5yOlfIy7NHrvCnXt08Ba791QGqEHPA+K
|
||||
8MXb5Yw8Vwb9VOnNTRN3nzDwBL1et9+oanH3ngAu8tSC7DfZhkPDS7EhE4sLU3k0
|
||||
C616Qn/+q+QEQctMZQKuk4yy+BZf5yLNOASZxgY5HemGIuy1oOV/U20CgYEAyWCV
|
||||
q6G8kLHUvXnwL86rJPdtQwwcUoGTkKEwRTqf94mW2IKHA/NNP9bIpAI799HtxIEw
|
||||
C9yX/0grAKwzpztqos+pcb5Ly8dOwg0DNVsOdAVHE5EBeLeQD/gP1t+VkYRBGEhF
|
||||
+VRJwbrgg9WMCDPj/zLskRiWm3nRT/BTsN6aAEkCgYEAp/H8GJD3JmcclOlssEgO
|
||||
mV47kpn7P1UgcxT8agf4KD06h0RuLrQNR0caHeQZwthoxI7qIT2157dHynzGCHrX
|
||||
VeWYm9pGtQY5KU2NiKqrAcXPBsASY1KOnnCyk1+QiRjTLj6M1gFn5KOQchXeWnXI
|
||||
2xNcQLnnu1uK4bBMVINpGdkCgYA14uuKFuh/i6aS4Utdb58qcC9Drrzxcw0KuadS
|
||||
DyL5OU8tNphsfTGhsJbWFGb5pKpMWAmEUw41WJlxP6M+z850LL952WMs73Nqx9Kg
|
||||
93HBqBvh536OUAhzzXxnkkLSwqIsnkJjOqPV/GzRulYTZ9dN1dGp7ft3NTzGeFfc
|
||||
z2RESQKBgG4RDl1uHt0t6+dPH+apexI+uwJ9cfM0z+e7BjRjkkuQiSBUDUQJzYdK
|
||||
iIm0ftmO5esvgYWCJVndNGWbacOoq1/9W9WMjjpFMDgBTcZayt9yi9qc38AVhqGW
|
||||
x/FiQOZ8Eg2LE2lMEQVrIyXnKopZgU+wHlJPWoLvccK+cLXZuevg
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -eEuo pipefail
|
||||
unset CDPATH
|
||||
|
||||
# force the script to first switch to the directory containing the script before
|
||||
# messing with the filesystem
|
||||
cd "$(dirname "$0")"
|
||||
rm -rf *.crt *.key
|
||||
|
||||
openssl genrsa -out ca-root.key 4096
|
||||
openssl req -x509 -new -nodes -key ca-root.key -out ca-root.crt \
|
||||
-subj "/C=US/ST=CA/O=/CN=SDS Test CA Cert" \
|
||||
-sha256 -days 3650
|
||||
|
||||
function gen_cert {
|
||||
local FILE_NAME=$1
|
||||
local DNS_NAME=$2
|
||||
|
||||
openssl genrsa -out "$FILE_NAME.key" 2048
|
||||
openssl req -new -key "$FILE_NAME.key" -out "$FILE_NAME.csr" \
|
||||
-reqexts SAN \
|
||||
-config <(cat /etc/ssl/openssl.cnf \
|
||||
<(printf "\n[SAN]\nsubjectAltName=DNS:$DNS_NAME")) \
|
||||
-subj "/C=US/ST=CA/O=/CN=$DNS_NAME"
|
||||
|
||||
openssl x509 -req -in "$FILE_NAME.csr" \
|
||||
-CA ca-root.crt -CAkey ca-root.key -CAcreateserial \
|
||||
-out "$FILE_NAME.crt" -days 3650 -sha256 \
|
||||
-extfile <(printf "subjectAltName=DNS:$DNS_NAME")
|
||||
|
||||
rm "$FILE_NAME.csr"
|
||||
}
|
||||
|
||||
DOMAINS="www.example.com foo.example.com *.ingress.consul"
|
||||
|
||||
for domain in $DOMAINS
|
||||
do
|
||||
# * in file names is interpreted as a global and all sorts of things go
|
||||
# strange!
|
||||
FILE_NAME="$domain"
|
||||
if [ ${domain:0:2} == "*." ]; then
|
||||
FILE_NAME="wildcard.${domain:2}"
|
||||
fi
|
||||
gen_cert $FILE_NAME $domain
|
||||
done
|
|
@ -0,0 +1,24 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEDDCCAfSgAwIBAgIJAOPsel0fAxicMA0GCSqGSIb3DQEBCwUAMDUxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJDQTEZMBcGA1UEAwwQU0RTIFRlc3QgQ0EgQ2VydDAe
|
||||
Fw0yMTA4MjQxMjMyMzhaFw0zMTA4MjIxMjMyMzhaMDUxCzAJBgNVBAYTAlVTMQsw
|
||||
CQYDVQQIDAJDQTEZMBcGA1UEAwwQKi5pbmdyZXNzLmNvbnN1bDCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBALdsZUrmtIPO914Gcsgr7llxD6Dq/+c4zj5M
|
||||
GYaFegfCK8mj27Lunxibz7ANkeb/TY7ujBSUjC12PzKNwZTtqs9ZuMlBvxcZeesB
|
||||
FawiWZ1P1TUJ/J8E+j0Egx6nIa5zd8/tZRR6wnBr/bCSUpr6ZQtkPSPA8vh7/cea
|
||||
al0SDsgq+ssbgpWf4EvnUDK6TH5x2iymJKkycppi2d4RkIha5uu9eznPkWKMNcFN
|
||||
nLCPOdljpJ2bC96hurdQAIElJAg+iJr+Oten1GtxlzhHi2U0IBFJ+aRObsTQYR2f
|
||||
AUGIEqS+E5vVPKsTZnitVL9DdEagl8NLMGTr3k2Ok4AOU+42uVkCAwEAAaMfMB0w
|
||||
GwYDVR0RBBQwEoIQKi5pbmdyZXNzLmNvbnN1bDANBgkqhkiG9w0BAQsFAAOCAgEA
|
||||
sNL1izKiFrY41+dK1RYtNAhtlexn+Jyizh8t6aDQfTEyYM8v7+FK5CmLECkGO+5Z
|
||||
0+HsHB4KwG1OhiTPbFdxyI3na2hluoxPM3ykR1erC10XoKSuerK8vO4JFEJSFVp1
|
||||
iqW926YgDnM38565JofXTj4keRvPyFGVW5y1HckgviDeYEpAuunolz3w2w7yuvfc
|
||||
EQydhl2WZHD1+6uRMKGmJz8f+7JwanfpW5XdwuVR6LH9uHcuDDR5xa+7jmDhQzto
|
||||
V3hejsVrCV85dyIELseLb1R+T36HXrAWUM3IBYd9DclwwhKo48TXfh3br8XFLkUV
|
||||
N7IobJthBVqtQqW7V/yI/zYZn+SPhX7BudUVf/dJwDq1hgxwmUo/vcx2HnlSoEDw
|
||||
M/r1RwY1QY0omZNn3G87VGZjC2tqL8FrT7Yu94EOZ21hneoaH+5Igt4groQ4aZl2
|
||||
MGVNdC9Slv8K7n+RyQbbo+JdfKDSDoi8FD5XYlaRSgA+TAn9ginl4/516cwcIZrU
|
||||
rxnx0QVjFzLeaFa51x6IC0FEE1Sp8dJQxJCMFndgCkIc8TC03SrCCSAvbIOj9CrD
|
||||
dT3/uAP+xQGZVGwRVY9qMH+gxE+KbjEukY1RmxrDFtSVUEwFPVhpgJmoHDy/N+lh
|
||||
BV6NlYN2M59mFI/rJh01yRCv0W0Qe0idJ76fVYOv1jk=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAt2xlSua0g873XgZyyCvuWXEPoOr/5zjOPkwZhoV6B8IryaPb
|
||||
su6fGJvPsA2R5v9Nju6MFJSMLXY/Mo3BlO2qz1m4yUG/Fxl56wEVrCJZnU/VNQn8
|
||||
nwT6PQSDHqchrnN3z+1lFHrCcGv9sJJSmvplC2Q9I8Dy+Hv9x5pqXRIOyCr6yxuC
|
||||
lZ/gS+dQMrpMfnHaLKYkqTJymmLZ3hGQiFrm6717Oc+RYow1wU2csI852WOknZsL
|
||||
3qG6t1AAgSUkCD6Imv4616fUa3GXOEeLZTQgEUn5pE5uxNBhHZ8BQYgSpL4Tm9U8
|
||||
qxNmeK1Uv0N0RqCXw0swZOveTY6TgA5T7ja5WQIDAQABAoIBAQCIgTX9ASbUdUGp
|
||||
Cvl/ORqAG+E6q8lYxfDPcgkJEOrZPUsjHDwTtPxX7xUoe2Da3aNVvPgpFMghyT+N
|
||||
Guw3Lo0RFT+tH63bvgz6tOrxGPtCVLhiaZVErwqgQGxoco9hafN/nbe8/wMXcXby
|
||||
YmLxjWmHicjqg90Oyg/67VM9AoRXuEo1vKaJQGOHz8kC1HUUzj7NJDDqZP9WAoqO
|
||||
EKcc/Q20SKuvI+IEdkuJ3Z+mxDU8jj8JtKOHp7q+5GpTqPonVxUC5nvH0wGelrAl
|
||||
uMws3IvqEgqzRuMWB6LY/1vMBxDjtMvR0c7N5HoK6UvWdefcvmAQgXy5LmUgEEWH
|
||||
nb0cpAABAoGBANjoe5/76d57jAHV5XZkme5TM/Eo2W3E658p45saL2L1kBycy8uS
|
||||
8KRdB4A7kwgllZQjUQSYpIOtSgiYP8c62OjXe7ysRZ6Da5fKD8bcSsC3kjoVA5Ei
|
||||
cy8mz+iwQnhpVsr08T9GgGBs7RRtn44ThYrM1j+avA2ABV+Kh/4LSVlZAoGBANh7
|
||||
BjxFg+iLiwzYA14R48kgY5U8fds+BciuS2X4zPGw/vm+JxipW6Xh1xdI7BHene4A
|
||||
+FBTIXoVidE3FJ+s+qbNbWj6efQu1AUg60GkUoSI9mYz0CxLE+7YI50CMK5gzt8Y
|
||||
XykHG3t/E3I1x+oyIM3o0UgYTIO2FQs1O7xTTGABAoGBAJbRDyQuBG6teKvODb5E
|
||||
NMOBFpyXypaIVUxV0+wESO6Fz64VV540jR27kXuX8KO5fkeCRtLrT3g/BTr0oWPl
|
||||
huxe56pIHiAZQLZJyK58fX2CJio8cj53tZ8TXXxtEcqnc7GqnhNg8eIZ2r5ZepdO
|
||||
+4uG4XFYJWk9mn7T07rQHjABAoGAM7U/Cgp4tYUPU6QNOd0AEbyAzNbEISgxbXvk
|
||||
WpkRKvHiFXlMEWHymC7Xl6I9cQ9BneXxag5RQr3+S1DixjklLc6HwbmCg8bjsc3p
|
||||
I6bCZxHn+QWLRekw+63447nwMtbA0x0ZLc2azObPmEosVE5g844W3yeerx9A64pt
|
||||
mFA1QAECgYEAlFKaFgtaWWR0b4RtSvlpDJNuBaBKueG6otpyOOXbndegfugaI8jV
|
||||
VWdnsRPForAuBUbg9fgO/Pfq5+x+V9u2GdchVPA16oolmDZF6CpNhxAa3hARdxD6
|
||||
MhYm0HJ2KySUhuAiChDM9UG6Fn02wz7KHRATuDzf3J9pdt1fA2XXj+I=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,24 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIECjCCAfKgAwIBAgIJAOPsel0fAxiaMA0GCSqGSIb3DQEBCwUAMDUxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJDQTEZMBcGA1UEAwwQU0RTIFRlc3QgQ0EgQ2VydDAe
|
||||
Fw0yMTA4MjQxMjMyMzhaFw0zMTA4MjIxMjMyMzhaMDQxCzAJBgNVBAYTAlVTMQsw
|
||||
CQYDVQQIDAJDQTEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMIIBIjANBgkqhkiG
|
||||
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtAihQ1cJlIQEx6r7nmATL8OVh0wsOlKRwBBp
|
||||
0imcTfrhB4UAA8UnoPktozQe2PqAaeDEYvjmn6hxkhs+6Al5hpDPDLz+HO7FAXy+
|
||||
K29ywUtd+XQutzMS5ss5gPpGx4l1u6L+25avfG0AkUKF612RCrablLddTCGfMmiJ
|
||||
pnKPP6P/7I7aM0WSUFSRC632q91bDAF75/3hVs05/catN2FhCv+xyHsgAnoI5wmI
|
||||
bpbVik55aPkACI6oqWHiyYJpSCgUslLHAvgd9BdrTrerKrH7MNP/0nlMeC95DrpN
|
||||
wklUKhT3Dj90LFAnUewFsppUJf1tY3yqFSvCQ3926RsN9zF5lQIDAQABox4wHDAa
|
||||
BgNVHREEEzARgg93d3cuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggIBALos
|
||||
qLaJEInX1V7qp0U7B4x0U+FLZLvqif+K0o6dIoMyN+pdSbLvXnWPx5qKVdJxQ3V/
|
||||
DA7AVBbeOkdqSiVO0aDmH8/XSA+cVjMpd1fSm2tZcT0Ur1fLsTnv4ZP8Oaak6TY9
|
||||
SVLNE9EiNhRG8ykYO3zshDZAhgKxeTvP//gjMGrSyEgT7fvccE/gxZcXhzEonuMc
|
||||
837E85anz23/Ygo31AOIMyTqOzyR2DFof9LVuh85PP1Cl86q4Co2+ApFzipzgr4t
|
||||
yvrADAPcyiDAR9fLpemorTIH9UyJPsqri0tSLOkjjk3vO43O8DIijTYcERc3FZId
|
||||
/Ju8ZKa+89wfL2OzmpogEBieaWiif4adcGRJngq9C6qSk4/p5/iqvMhbdFJNIknD
|
||||
88OSet0eDFIL1jy/h+ibFTzat6BAflxwCu7tn9lmP7+c8rTvRd8hXsu7n8bUZ9V4
|
||||
LVHlGdKFfrcyJ5q/yr77GPDapkyQt/MP7Y+DVNtnO/ryupf8v4JjfK42cfHbbClJ
|
||||
gLTJI4PgRYtXMzWLbbrzMbeydVYiV1NLxQeB4fVHkm9AXcfb+aNG/85X3TUuIrqs
|
||||
AlalaWIcNsiN8ghHRzH4Zlg7JjBnqQyPnw7xzZVVcoE0t83paYVB6TvcpqWbfb41
|
||||
PnjvHQb39zDf7iU9cVC2hQpBmyA1ctq1hubxArXP
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAtAihQ1cJlIQEx6r7nmATL8OVh0wsOlKRwBBp0imcTfrhB4UA
|
||||
A8UnoPktozQe2PqAaeDEYvjmn6hxkhs+6Al5hpDPDLz+HO7FAXy+K29ywUtd+XQu
|
||||
tzMS5ss5gPpGx4l1u6L+25avfG0AkUKF612RCrablLddTCGfMmiJpnKPP6P/7I7a
|
||||
M0WSUFSRC632q91bDAF75/3hVs05/catN2FhCv+xyHsgAnoI5wmIbpbVik55aPkA
|
||||
CI6oqWHiyYJpSCgUslLHAvgd9BdrTrerKrH7MNP/0nlMeC95DrpNwklUKhT3Dj90
|
||||
LFAnUewFsppUJf1tY3yqFSvCQ3926RsN9zF5lQIDAQABAoIBACWVG50EIWLYgGry
|
||||
HZ69LaQt7xwUYbM3I2f1xTFzMEbzFWDNeehPkus+uTE1oy7mdEImArkqfnJb5oF6
|
||||
oJIt0CmwNxjQpzeA/K1HzichF9KUGiUGBO6Hge2eBP4QwQ/MeUBXUV6jwTR3SMQK
|
||||
IAy3Np0G68mK0bYf2qzaN8oAZjkBeJerROyfQ02tuXKbcnK4C/ksVOT/efEb6WHK
|
||||
H6CasvodiyUdzpeL9uM//cgsMoHkA/Bw56okDkrAYVacQKqHHzZR1A7kbMa/Fbk4
|
||||
Gj8xF6CR+Ui/csyNX6pbPEynbosyTAhwZsHCKNareKbj0gpAQWzG0Cg0Rbxvyz9c
|
||||
kYQzgo0CgYEA4zYJL6kuBecU2iDWxI2TvfESUUyC5c3jRPemdPzXY/n1Tv0D4dER
|
||||
O7HaNOYX+Q07IZ+eRigHKkRdFxEQEXZxGC3n8XawtG7XSwe+YV1xfmj3axA4hoEf
|
||||
Uky/2Ci5M8mXHiTAM2vge9BX60XbZUEywlB1WIC6iLgaynG/+qR7U9cCgYEAythR
|
||||
mRoPKrdooq7x+MM+d5CNfPP7Stzz3Yby902GknLWwSD2UnhkgiZK1Rx9Y5aSAhhq
|
||||
dgHqtz7aKwCqCzKEMB3uNGLSmU7WnlqDMAebyXzjybgdtyBbgDmppfj/6KP9MoxD
|
||||
7pV+WQbItzAXVJLm7fgsG50ncbR01ACAA/IxsHMCgYB639Qj9EgxZQC/3haHgVEu
|
||||
3VpcoRYBFVEdERjyF3KcXKcvKmGZE6lQMSSiivTX+THLQzkjE66cSxBU0yNvbjBH
|
||||
NTxENz3ktjS0HOH2YcRo6nczbThEdTvtFBiD27IcsZ6J7LIMnQBvtQJ29/ZoUdQT
|
||||
hdOQIz29hmLmrJF4CM+xTQKBgH/xa55vImvmHZinUjZ/KBKQWb4bwkAZF7R93xh/
|
||||
jMcoqi5M1TF1gKfa8U50Vt6O5W9u6Q+f6+VDPqbrF1ZSubAD4PCn+H/8i0B8hMyx
|
||||
r+Cp5p+ggxWz0iMRu+DVKs0ZSqYsdNiy8GvE7KsnKUAOHJyy8VdFi9CbaykhW52h
|
||||
kRfjAoGBAJm+ZylqeopxFigMzqe+ibqQ03y08aHqSnvH99QXBQPTlSOmgqMOz52v
|
||||
jYc4GlnB+G77oaXbJ+74qVS159k6b0fQSNzN+IILq7/QNKsmXpPmbwhiRgQJOdSB
|
||||
9VbSPXeEKlr70QJ7iCfGvymVo/QPj0eQfrN9JdWoRDn49QoeptV0
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,9 @@
|
|||
module test-sds-server
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/envoyproxy/go-control-plane v0.9.9
|
||||
github.com/hashicorp/go-hclog v0.16.2
|
||||
google.golang.org/grpc v1.40.0
|
||||
)
|
|
@ -0,0 +1,134 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9 h1:vQLjymTobffN2R0F8eTqw6q7iozfRO5Z0m+/4Vw+/uA=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
|
||||
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
@ -0,0 +1,162 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||
tls "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
||||
discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
|
||||
secretservice "github.com/envoyproxy/go-control-plane/envoy/service/secret/v3"
|
||||
"github.com/envoyproxy/go-control-plane/pkg/cache/types"
|
||||
cache "github.com/envoyproxy/go-control-plane/pkg/cache/v3"
|
||||
xds "github.com/envoyproxy/go-control-plane/pkg/server/v3"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
const (
|
||||
sdsTypeURI = "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log := hclog.Default()
|
||||
log.SetLevel(hclog.Trace)
|
||||
|
||||
if err := run(log); err != nil {
|
||||
log.Error("failed to run SDS server", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run(log hclog.Logger) error {
|
||||
cache := cache.NewLinearCache(sdsTypeURI)
|
||||
|
||||
addr := "0.0.0.0:1234"
|
||||
if a := os.Getenv("SDS_BIND_ADDR"); a != "" {
|
||||
addr = a
|
||||
}
|
||||
certPath := "certs"
|
||||
if p := os.Getenv("SDS_CERT_PATH"); p != "" {
|
||||
certPath = p
|
||||
}
|
||||
|
||||
if err := loadCertsFromPath(cache, log, certPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer l.Close()
|
||||
log.Info("==> SDS listening", "addr", addr)
|
||||
|
||||
callbacks := makeLoggerCallbacks(log)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
xdsServer := xds.NewServer(ctx, cache, callbacks)
|
||||
grpcServer := grpc.NewServer()
|
||||
grpclog.SetLogger(log.StandardLogger(nil))
|
||||
|
||||
secretservice.RegisterSecretDiscoveryServiceServer(grpcServer, xdsServer)
|
||||
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
<-sigs
|
||||
grpcServer.Stop()
|
||||
cancel()
|
||||
}()
|
||||
|
||||
if err := grpcServer.Serve(l); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadCertsFromPath(cache *cache.LinearCache, log hclog.Logger, dir string) error {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
if !strings.HasSuffix(entry.Name(), ".crt") {
|
||||
continue
|
||||
}
|
||||
|
||||
certName := strings.TrimSuffix(entry.Name(), ".crt")
|
||||
cert, err := ioutil.ReadFile(filepath.Join(dir, entry.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyFile := certName + ".key"
|
||||
key, err := ioutil.ReadFile(filepath.Join(dir, keyFile))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var res tls.Secret
|
||||
res.Name = certName
|
||||
res.Type = &tls.Secret_TlsCertificate{
|
||||
TlsCertificate: &tls.TlsCertificate{
|
||||
CertificateChain: &core.DataSource{
|
||||
Specifier: &core.DataSource_InlineBytes{
|
||||
InlineBytes: cert,
|
||||
},
|
||||
},
|
||||
PrivateKey: &core.DataSource{
|
||||
Specifier: &core.DataSource_InlineBytes{
|
||||
InlineBytes: key,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := cache.UpdateResource(certName, types.Resource(&res)); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info("Loaded cert from file", "name", certName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeLoggerCallbacks(log hclog.Logger) *xds.CallbackFuncs {
|
||||
return &xds.CallbackFuncs{
|
||||
|
||||
StreamOpenFunc: func(_ context.Context, id int64, addr string) error {
|
||||
log.Trace("gRPC stream opened", "id", id, "addr", addr)
|
||||
return nil
|
||||
},
|
||||
StreamClosedFunc: func(id int64) {
|
||||
log.Trace("gRPC stream closed", "id", id)
|
||||
},
|
||||
StreamRequestFunc: func(id int64, req *discovery.DiscoveryRequest) error {
|
||||
log.Trace("gRPC stream request", "id", id,
|
||||
"node.id", req.Node.Id,
|
||||
"req.typeURL", req.TypeUrl,
|
||||
"req.version", req.VersionInfo,
|
||||
)
|
||||
return nil
|
||||
},
|
||||
StreamResponseFunc: func(id int64, req *discovery.DiscoveryRequest, resp *discovery.DiscoveryResponse) {
|
||||
log.Trace("gRPC stream response", "id", id,
|
||||
"resp.typeURL", resp.TypeUrl,
|
||||
"resp.version", resp.VersionInfo,
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue