mirror of https://github.com/status-im/consul.git
Add subset support
This commit is contained in:
parent
9f233dece2
commit
913b13f31f
|
@ -81,6 +81,16 @@ type configSnapshotTerminatingGateway struct {
|
|||
// on the service that the caller is trying to reach.
|
||||
ServiceLeaves map[structs.ServiceID]*structs.IssuedCert
|
||||
|
||||
// WatchedResolvers is a map of ServiceID to a cancel function.
|
||||
// This cancel function is tied to the watch of resolvers for linked services.
|
||||
// As with WatchedServices, resolver watches will be cancelled when services
|
||||
// are no longer linked to the gateway.
|
||||
WatchedResolvers map[structs.ServiceID]context.CancelFunc
|
||||
|
||||
// ServiceResolvers is a map of service id to an associated
|
||||
// service-resolver config entry for that service.
|
||||
ServiceResolvers map[structs.ServiceID]*structs.ServiceResolverConfigEntry
|
||||
|
||||
// ServiceGroups is a map of service id to the service instances of that
|
||||
// service in the local datacenter.
|
||||
ServiceGroups map[structs.ServiceID]structs.CheckServiceNodes
|
||||
|
@ -94,7 +104,8 @@ func (c *configSnapshotTerminatingGateway) IsEmpty() bool {
|
|||
len(c.WatchedLeaves) == 0 &&
|
||||
len(c.WatchedIntentions) == 0 &&
|
||||
len(c.ServiceGroups) == 0 &&
|
||||
len(c.WatchedServices) == 0
|
||||
len(c.WatchedServices) == 0 &&
|
||||
len(c.ServiceResolvers) == 0
|
||||
}
|
||||
|
||||
type configSnapshotMeshGateway struct {
|
||||
|
|
|
@ -536,8 +536,10 @@ func (s *state) initialConfigSnapshot() ConfigSnapshot {
|
|||
snap.TerminatingGateway.WatchedServices = make(map[structs.ServiceID]context.CancelFunc)
|
||||
snap.TerminatingGateway.WatchedLeaves = make(map[structs.ServiceID]context.CancelFunc)
|
||||
snap.TerminatingGateway.WatchedIntentions = make(map[structs.ServiceID]context.CancelFunc)
|
||||
snap.TerminatingGateway.WatchedResolvers = make(map[structs.ServiceID]context.CancelFunc)
|
||||
snap.TerminatingGateway.ServiceLeaves = make(map[structs.ServiceID]*structs.IssuedCert)
|
||||
snap.TerminatingGateway.ServiceGroups = make(map[structs.ServiceID]structs.CheckServiceNodes)
|
||||
snap.TerminatingGateway.ServiceResolvers = make(map[structs.ServiceID]*structs.ServiceResolverConfigEntry)
|
||||
case structs.ServiceKindMeshGateway:
|
||||
snap.MeshGateway.WatchedServices = make(map[structs.ServiceID]context.CancelFunc)
|
||||
snap.MeshGateway.WatchedDatacenters = make(map[string]context.CancelFunc)
|
||||
|
@ -983,6 +985,29 @@ func (s *state) handleUpdateTerminatingGateway(u cache.UpdateEvent, snap *Config
|
|||
}
|
||||
snap.TerminatingGateway.WatchedLeaves[svc.Service] = cancel
|
||||
}
|
||||
|
||||
// Watch service resolvers for the service
|
||||
// These are used to create clusters and endpoints for the service subsets
|
||||
if _, ok := snap.TerminatingGateway.WatchedResolvers[svc.Service]; !ok {
|
||||
ctx, cancel := context.WithCancel(s.ctx)
|
||||
err := s.cache.Notify(ctx, cachetype.ConfigEntriesName, &structs.ConfigEntryQuery{
|
||||
Datacenter: s.source.Datacenter,
|
||||
QueryOptions: structs.QueryOptions{Token: s.token},
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: svc.Service.ID,
|
||||
EnterpriseMeta: svc.Service.EnterpriseMeta,
|
||||
}, fmt.Sprintf("service-resolver:%s", svc.Service.String()), s.ch)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("failed to register watch for a service-resolver",
|
||||
"service", svc.Service.String(),
|
||||
"error", err,
|
||||
)
|
||||
cancel()
|
||||
return err
|
||||
}
|
||||
snap.TerminatingGateway.WatchedResolvers[svc.Service] = cancel
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel service instance watches for services that were not in the update
|
||||
|
@ -1005,6 +1030,16 @@ func (s *state) handleUpdateTerminatingGateway(u cache.UpdateEvent, snap *Config
|
|||
}
|
||||
}
|
||||
|
||||
// Cancel service-resolver watches for services that were not in the update
|
||||
for sid, cancelFn := range snap.TerminatingGateway.WatchedResolvers {
|
||||
if _, ok := svcMap[sid]; !ok {
|
||||
logger.Debug("canceling watch for service-resolver", "service", sid.String())
|
||||
delete(snap.TerminatingGateway.WatchedResolvers, sid)
|
||||
delete(snap.TerminatingGateway.ServiceResolvers, sid)
|
||||
cancelFn()
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel intention watches for services that were not in the update
|
||||
for sid, cancelFn := range snap.TerminatingGateway.WatchedIntentions {
|
||||
if _, ok := svcMap[sid]; !ok {
|
||||
|
@ -1044,6 +1079,18 @@ func (s *state) handleUpdateTerminatingGateway(u cache.UpdateEvent, snap *Config
|
|||
sid := structs.ServiceIDFromString(strings.TrimPrefix(u.CorrelationID, "service-leaf:"))
|
||||
snap.TerminatingGateway.ServiceLeaves[sid] = leaf
|
||||
|
||||
case strings.HasPrefix(u.CorrelationID, "service-resolver:"):
|
||||
configEntries, ok := u.Result.(*structs.IndexedConfigEntries)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid type for response: %T", u.Result)
|
||||
}
|
||||
// There should only ever be one entry for a service resolver within a namespace
|
||||
if len(configEntries.Entries) == 1 {
|
||||
if resolver, ok := configEntries.Entries[0].(*structs.ServiceResolverConfigEntry); ok {
|
||||
snap.TerminatingGateway.ServiceResolvers[structs.NewServiceID(resolver.Name, &resolver.EnterpriseMeta)] = resolver
|
||||
}
|
||||
}
|
||||
|
||||
case strings.HasPrefix(u.CorrelationID, "service-intentions:"):
|
||||
// no-op: Intentions don't get stored in the snapshot, calls to ConnectAuthorize will fetch them from the cache
|
||||
|
||||
|
|
|
@ -206,6 +206,18 @@ func genVerifyLeafWatch(expectedService string, expectedDatacenter string) verif
|
|||
}
|
||||
}
|
||||
|
||||
func genVerifyResolverWatch(expectedService, expectedDatacenter, expectedKind string) verifyWatchRequest {
|
||||
return func(t testing.TB, cacheType string, request cache.Request) {
|
||||
require.Equal(t, cachetype.ConfigEntriesName, cacheType)
|
||||
|
||||
reqReal, ok := request.(*structs.ConfigEntryQuery)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, expectedDatacenter, reqReal.Datacenter)
|
||||
require.Equal(t, expectedService, reqReal.Name)
|
||||
require.Equal(t, expectedKind, reqReal.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
func genVerifyIntentionWatch(expectedService string, expectedDatacenter string) verifyWatchRequest {
|
||||
return func(t testing.TB, cacheType string, request cache.Request) {
|
||||
require.Equal(t, cachetype.IntentionMatchName, cacheType)
|
||||
|
@ -827,8 +839,11 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
require.True(t, snap.ConnectProxy.IsEmpty())
|
||||
require.Equal(t, indexedRoots, snap.Roots)
|
||||
require.Empty(t, snap.TerminatingGateway.WatchedServices)
|
||||
require.Empty(t, snap.TerminatingGateway.WatchedLeaves)
|
||||
require.Empty(t, snap.TerminatingGateway.ServiceGroups)
|
||||
require.Empty(t, snap.TerminatingGateway.WatchedLeaves)
|
||||
require.Empty(t, snap.TerminatingGateway.ServiceLeaves)
|
||||
require.Empty(t, snap.TerminatingGateway.WatchedResolvers)
|
||||
require.Empty(t, snap.TerminatingGateway.ServiceResolvers)
|
||||
require.Empty(t, snap.TerminatingGateway.WatchedIntentions)
|
||||
},
|
||||
},
|
||||
|
@ -904,6 +919,10 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
require.Len(t, snap.TerminatingGateway.WatchedLeaves, 2)
|
||||
require.Contains(t, snap.TerminatingGateway.WatchedLeaves, db)
|
||||
require.Contains(t, snap.TerminatingGateway.WatchedLeaves, billing)
|
||||
|
||||
require.Len(t, snap.TerminatingGateway.WatchedResolvers, 2)
|
||||
require.Contains(t, snap.TerminatingGateway.WatchedResolvers, db)
|
||||
require.Contains(t, snap.TerminatingGateway.WatchedResolvers, billing)
|
||||
},
|
||||
},
|
||||
verificationStage{
|
||||
|
@ -963,6 +982,41 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
require.Equal(t, snap.TerminatingGateway.ServiceLeaves[structs.NewServiceID("db", nil)], issuedCert)
|
||||
},
|
||||
},
|
||||
verificationStage{
|
||||
requiredWatches: map[string]verifyWatchRequest{
|
||||
"service-resolver:db": genVerifyResolverWatch("db", "dc1", structs.ServiceResolver),
|
||||
},
|
||||
events: []cache.UpdateEvent{
|
||||
cache.UpdateEvent{
|
||||
CorrelationID: "service-resolver:db",
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Name: "db",
|
||||
Kind: structs.ServiceResolver,
|
||||
Redirect: &structs.ServiceResolverRedirect{
|
||||
Service: "db",
|
||||
Datacenter: "dc2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Err: nil,
|
||||
},
|
||||
},
|
||||
verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) {
|
||||
want := &structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
Redirect: &structs.ServiceResolverRedirect{
|
||||
Service: "db",
|
||||
Datacenter: "dc2",
|
||||
},
|
||||
}
|
||||
require.Equal(t, want, snap.TerminatingGateway.ServiceResolvers[structs.NewServiceID("db", nil)])
|
||||
},
|
||||
},
|
||||
verificationStage{
|
||||
events: []cache.UpdateEvent{
|
||||
cache.UpdateEvent{
|
||||
|
@ -993,9 +1047,13 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
require.Len(t, snap.TerminatingGateway.WatchedLeaves, 1)
|
||||
require.Contains(t, snap.TerminatingGateway.WatchedLeaves, billing)
|
||||
|
||||
require.Len(t, snap.TerminatingGateway.WatchedResolvers, 1)
|
||||
require.Contains(t, snap.TerminatingGateway.WatchedResolvers, billing)
|
||||
|
||||
// There was no update event for billing's leaf/endpoints, so length is 0
|
||||
require.Len(t, snap.TerminatingGateway.ServiceGroups, 0)
|
||||
require.Len(t, snap.TerminatingGateway.ServiceLeaves, 0)
|
||||
require.Len(t, snap.TerminatingGateway.ServiceResolvers, 0)
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1475,6 +1475,12 @@ func testConfigSnapshotTerminatingGateway(t testing.T, populateServices bool) *C
|
|||
if populateServices {
|
||||
web := structs.NewServiceID("web", nil)
|
||||
webNodes := TestUpstreamNodes(t)
|
||||
webNodes[0].Service.Meta = map[string]string{
|
||||
"version": "1",
|
||||
}
|
||||
webNodes[1].Service.Meta = map[string]string{
|
||||
"version": "2",
|
||||
}
|
||||
|
||||
api := structs.NewServiceID("api", nil)
|
||||
apiNodes := TestUpstreamNodes(t)
|
||||
|
|
|
@ -120,22 +120,9 @@ func makeExposeClusterName(destinationPort int) string {
|
|||
}
|
||||
|
||||
// clustersFromSnapshotTerminatingGateway returns the xDS API representation of the "clusters"
|
||||
// for a terminating gateway. This will include 1 cluster per service.
|
||||
// for a terminating gateway. This will include 1 cluster per service and service subset.
|
||||
func (s *Server) clustersFromSnapshotTerminatingGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
clusters := make([]proto.Message, 0, len(cfgSnap.TerminatingGateway.ServiceGroups))
|
||||
|
||||
// Generate the per-service clusters
|
||||
for svc, _ := range cfgSnap.TerminatingGateway.ServiceGroups {
|
||||
clusterName := connect.ServiceSNI(svc.ID, "", svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
||||
|
||||
cluster, err := s.makeGatewayCluster(clusterName, cfgSnap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to make cluster %q for terminating-gateway: %v", cluster, err)
|
||||
}
|
||||
clusters = append(clusters, cluster)
|
||||
}
|
||||
|
||||
return clusters, nil
|
||||
return s.clustersFromServicesAndResolvers(cfgSnap, cfgSnap.TerminatingGateway.ServiceGroups, cfgSnap.TerminatingGateway.ServiceResolvers)
|
||||
}
|
||||
|
||||
// clustersFromSnapshotMeshGateway returns the xDS API representation of the "clusters"
|
||||
|
@ -185,10 +172,26 @@ func (s *Server) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapsho
|
|||
}
|
||||
}
|
||||
|
||||
// generate the per-service clusters
|
||||
for svc, _ := range cfgSnap.MeshGateway.ServiceGroups {
|
||||
// generate the per-service/subset clusters
|
||||
c, err := s.clustersFromServicesAndResolvers(cfgSnap, cfgSnap.MeshGateway.ServiceGroups, cfgSnap.MeshGateway.ServiceResolvers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clusters = append(clusters, c...)
|
||||
|
||||
return clusters, nil
|
||||
}
|
||||
|
||||
func (s *Server) clustersFromServicesAndResolvers(
|
||||
cfgSnap *proxycfg.ConfigSnapshot,
|
||||
services map[structs.ServiceID]structs.CheckServiceNodes,
|
||||
resolvers map[structs.ServiceID]*structs.ServiceResolverConfigEntry) ([]proto.Message, error) {
|
||||
|
||||
clusters := make([]proto.Message, 0, len(services))
|
||||
|
||||
for svc, _ := range services {
|
||||
clusterName := connect.ServiceSNI(svc.ID, "", svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
||||
resolver, hasResolver := cfgSnap.MeshGateway.ServiceResolvers[svc]
|
||||
resolver, hasResolver := resolvers[svc]
|
||||
|
||||
// Create the cluster for default/unnamed services
|
||||
var cluster *envoy.Cluster
|
||||
|
@ -199,7 +202,7 @@ func (s *Server) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapsho
|
|||
cluster, err = s.makeGatewayCluster(clusterName, cfgSnap)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to make %s cluster: %v", cfgSnap.Kind, err)
|
||||
}
|
||||
clusters = append(clusters, cluster)
|
||||
|
||||
|
@ -211,7 +214,7 @@ func (s *Server) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapsho
|
|||
|
||||
cluster, err := s.makeGatewayClusterWithConnectTimeout(clusterName, cfgSnap, resolver.ConnectTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to make %s cluster: %v", cfgSnap.Kind, err)
|
||||
}
|
||||
clusters = append(clusters, cluster)
|
||||
}
|
||||
|
@ -529,9 +532,9 @@ func (s *Server) makeGatewayCluster(clusterName string, cfgSnap *proxycfg.Config
|
|||
return s.makeGatewayClusterWithConnectTimeout(clusterName, cfgSnap, 0)
|
||||
}
|
||||
|
||||
// makeGatewayClusterWithConnectTimeout initializes a mesh gateway cluster
|
||||
// makeGatewayClusterWithConnectTimeout initializes a gateway cluster
|
||||
// with the specified connect timeout. If the timeout is 0, the connect timeout
|
||||
// defaults to use the mesh gateway timeout.
|
||||
// defaults to use the configured gateway timeout.
|
||||
func (s *Server) makeGatewayClusterWithConnectTimeout(clusterName string, cfgSnap *proxycfg.ConfigSnapshot,
|
||||
connectTimeout time.Duration) (*envoy.Cluster, error) {
|
||||
cfg, err := ParseGatewayConfig(cfgSnap.Proxy.Config)
|
||||
|
|
|
@ -428,6 +428,63 @@ func TestClustersFromSnapshot(t *testing.T) {
|
|||
create: proxycfg.TestConfigSnapshotTerminatingGatewayNoServices,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-service-subsets",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.TerminatingGateway.ServiceResolvers = map[structs.ServiceID]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceID("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-ignore-extra-resolvers",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.TerminatingGateway.ServiceResolvers = map[structs.ServiceID]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceID("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.NewServiceID("notfound", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "notfound",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
@ -108,19 +108,7 @@ func (s *Server) filterSubsetEndpoints(subset *structs.ServiceResolverSubset, en
|
|||
}
|
||||
|
||||
func (s *Server) endpointsFromSnapshotTerminatingGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
resources := make([]proto.Message, 0, len(cfgSnap.TerminatingGateway.ServiceGroups))
|
||||
|
||||
// generate the endpoints for the linked service groups
|
||||
for svc, endpoints := range cfgSnap.TerminatingGateway.ServiceGroups {
|
||||
clusterName := connect.ServiceSNI(svc.ID, "", svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
||||
|
||||
group := []loadAssignmentEndpointGroup{{Endpoints: endpoints, OnlyPassing: false}}
|
||||
|
||||
la := makeLoadAssignment(clusterName, group, cfgSnap.Datacenter)
|
||||
resources = append(resources, la)
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
return s.endpointsFromServicesAndResolvers(cfgSnap, cfgSnap.TerminatingGateway.ServiceGroups, cfgSnap.TerminatingGateway.ServiceResolvers)
|
||||
}
|
||||
|
||||
func (s *Server) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
|
@ -209,38 +197,53 @@ func (s *Server) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapsh
|
|||
}
|
||||
|
||||
// Generate the endpoints for each service and its subsets
|
||||
for svc, endpoints := range cfgSnap.MeshGateway.ServiceGroups {
|
||||
clusterEndpoints := make(map[string]loadAssignmentEndpointGroup)
|
||||
clusterEndpoints[UnnamedSubset] = loadAssignmentEndpointGroup{Endpoints: endpoints, OnlyPassing: false}
|
||||
e, err := s.endpointsFromServicesAndResolvers(cfgSnap, cfgSnap.MeshGateway.ServiceGroups, cfgSnap.MeshGateway.ServiceResolvers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resources = append(resources, e...)
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func (s *Server) endpointsFromServicesAndResolvers(
|
||||
cfgSnap *proxycfg.ConfigSnapshot,
|
||||
services map[structs.ServiceID]structs.CheckServiceNodes,
|
||||
resolvers map[structs.ServiceID]*structs.ServiceResolverConfigEntry) ([]proto.Message, error) {
|
||||
|
||||
resources := make([]proto.Message, 0, len(services))
|
||||
|
||||
// generate the endpoints for the linked service groups
|
||||
for svc, endpoints := range services {
|
||||
clusterEndpoints := make(map[string][]loadAssignmentEndpointGroup)
|
||||
clusterEndpoints[UnnamedSubset] = []loadAssignmentEndpointGroup{{Endpoints: endpoints, OnlyPassing: false}}
|
||||
|
||||
// Collect all of the loadAssignmentEndpointGroups for the various subsets. We do this before generating
|
||||
// the endpoints for the default/unnamed subset so that we can take into account the DefaultSubset on the
|
||||
// service-resolver which may prevent the default/unnamed cluster from creating endpoints for all service
|
||||
// instances.
|
||||
if resolver, hasResolver := cfgSnap.MeshGateway.ServiceResolvers[svc]; hasResolver {
|
||||
if resolver, hasResolver := resolvers[svc]; hasResolver {
|
||||
for subsetName, subset := range resolver.Subsets {
|
||||
subsetEndpoints, err := s.filterSubsetEndpoints(&subset, endpoints)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
group := loadAssignmentEndpointGroup{Endpoints: subsetEndpoints, OnlyPassing: subset.OnlyPassing}
|
||||
clusterEndpoints[subsetName] = group
|
||||
groups := []loadAssignmentEndpointGroup{{Endpoints: subsetEndpoints, OnlyPassing: subset.OnlyPassing}}
|
||||
clusterEndpoints[subsetName] = groups
|
||||
|
||||
// if this subset is the default then override the unnamed subset with this configuration
|
||||
if subsetName == resolver.DefaultSubset {
|
||||
clusterEndpoints[UnnamedSubset] = group
|
||||
clusterEndpoints[UnnamedSubset] = groups
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now generate the load assignment for all subsets
|
||||
for subsetName, group := range clusterEndpoints {
|
||||
for subsetName, groups := range clusterEndpoints {
|
||||
clusterName := connect.ServiceSNI(svc.ID, subsetName, svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
||||
la := makeLoadAssignment(
|
||||
clusterName,
|
||||
[]loadAssignmentEndpointGroup{
|
||||
group,
|
||||
},
|
||||
groups,
|
||||
cfgSnap.Datacenter,
|
||||
)
|
||||
resources = append(resources, la)
|
||||
|
|
|
@ -466,6 +466,76 @@ func Test_endpointsFromSnapshot(t *testing.T) {
|
|||
create: proxycfg.TestConfigSnapshotTerminatingGatewayNoServices,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-service-subsets",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.TerminatingGateway.ServiceResolvers = map[structs.ServiceID]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceID("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.NewServiceID("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-default-service-subset",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.TerminatingGateway.ServiceResolvers = map[structs.ServiceID]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceID("web", nil): &structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.NewServiceID("web", nil): &structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
@ -562,35 +562,31 @@ func (s *Server) makeTerminatingGatewayListener(name, addr string, port int, cfg
|
|||
}
|
||||
l.ListenerFilters = []envoylistener.ListenerFilter{tlsInspector}
|
||||
|
||||
sniCluster, err := makeSNIClusterFilter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Make a FilterChain for each linked service
|
||||
// Match on the cluster name,
|
||||
for svc, _ := range cfgSnap.TerminatingGateway.ServiceGroups {
|
||||
clusterName := connect.ServiceSNI(svc.ID, "", svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
||||
resolver, hasResolver := cfgSnap.TerminatingGateway.ServiceResolvers[svc]
|
||||
|
||||
// The cluster name here doesn't matter as the sni_cluster filter will fill it in for us.
|
||||
tcpProxy, err := makeTCPProxyFilter(name, "", fmt.Sprintf("terminating_gateway_%s_", svc.ID))
|
||||
clusterChain, err := s.sniFilterChainTerminatingGateway(name, clusterName, svc, cfgSnap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterChain := envoylistener.FilterChain{
|
||||
FilterChainMatch: makeSNIFilterChainMatch(clusterName),
|
||||
Filters: []envoylistener.Filter{
|
||||
sniCluster,
|
||||
tcpProxy,
|
||||
},
|
||||
TlsContext: &envoyauth.DownstreamTlsContext{
|
||||
// TODO (gateways) (freddy) Could we get to this point and not have a leaf for the service?
|
||||
CommonTlsContext: makeCommonTLSContext(cfgSnap, cfgSnap.TerminatingGateway.ServiceLeaves[svc]),
|
||||
RequireClientCertificate: &types.BoolValue{Value: true},
|
||||
},
|
||||
return nil, fmt.Errorf("failed to make filter chain for cluster %q: %v", clusterName, err)
|
||||
}
|
||||
l.FilterChains = append(l.FilterChains, clusterChain)
|
||||
|
||||
// if there is a service-resolver for this service then also setup subset filter chains for it
|
||||
if hasResolver {
|
||||
// generate 1 filter chain for each service subset
|
||||
for subsetName := range resolver.Subsets {
|
||||
clusterName := connect.ServiceSNI(svc.ID, subsetName, svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
|
||||
|
||||
clusterChain, err := s.sniFilterChainTerminatingGateway(name, clusterName, svc, cfgSnap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to make filter chain for cluster %q: %v", clusterName, err)
|
||||
}
|
||||
l.FilterChains = append(l.FilterChains, clusterChain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = injectConnectFilters(cfgSnap, token, l, false)
|
||||
|
@ -598,6 +594,31 @@ func (s *Server) makeTerminatingGatewayListener(name, addr string, port int, cfg
|
|||
return l, nil
|
||||
}
|
||||
|
||||
func (s *Server) sniFilterChainTerminatingGateway(listener, cluster string, service structs.ServiceID, cfgSnap *proxycfg.ConfigSnapshot) (envoylistener.FilterChain, error) {
|
||||
sniCluster, err := makeSNIClusterFilter()
|
||||
if err != nil {
|
||||
return envoylistener.FilterChain{}, err
|
||||
}
|
||||
|
||||
// The cluster name here doesn't matter as the sni_cluster filter will fill it in for us.
|
||||
tcpProxy, err := makeTCPProxyFilter(listener, "", fmt.Sprintf("terminating_gateway_%s_", service.String()))
|
||||
if err != nil {
|
||||
return envoylistener.FilterChain{}, err
|
||||
}
|
||||
|
||||
return envoylistener.FilterChain{
|
||||
FilterChainMatch: makeSNIFilterChainMatch(cluster),
|
||||
Filters: []envoylistener.Filter{
|
||||
sniCluster,
|
||||
tcpProxy,
|
||||
},
|
||||
TlsContext: &envoyauth.DownstreamTlsContext{
|
||||
CommonTlsContext: makeCommonTLSContext(cfgSnap, cfgSnap.TerminatingGateway.ServiceLeaves[service]),
|
||||
RequireClientCertificate: &types.BoolValue{Value: true},
|
||||
},
|
||||
}, err
|
||||
}
|
||||
|
||||
func (s *Server) makeMeshGatewayListener(name, addr string, port int, cfgSnap *proxycfg.ConfigSnapshot) (*envoy.Listener, error) {
|
||||
tlsInspector, err := makeTLSInspectorListenerFilter()
|
||||
if err != nil {
|
||||
|
|
|
@ -329,6 +329,40 @@ func TestListenersFromSnapshot(t *testing.T) {
|
|||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-service-subsets",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.TerminatingGateway.ServiceResolvers = map[structs.ServiceID]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceID("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.NewServiceID("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
71
agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.golden
vendored
Normal file
71
agent/xds/testdata/clusters/terminating-gateway-ignore-extra-resolvers.golden
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
107
agent/xds/testdata/endpoints/terminating-gateway-default-service-subset.golden
vendored
Normal file
107
agent/xds/testdata/endpoints/terminating-gateway-default-service-subset.golden
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,260 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "default:1.2.3.4:8443",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8443
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
]
|
||||
},
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\\nMIICKDCCAc+gAwIBAgIIT/zLIOrnlRQwCgYIKoZIzj0EAwIwFTETMBEGA1UEAxMK\\nVGVzdCBDQSA4NTAeFw0yMDA0MTEwMDMxMjJaFw0zMDA0MTEwMDMxMjJaMCoxKDAm\\nBgNVBAMTH3dlYi5zdmMuZGVmYXVsdC4xMTExMTExMS5jb25zdWwwWTATBgcqhkjO\\nPQIBBggqhkjOPQMBBwNCAAR3uNYYt8amLQMfae6GpMyFaMBBkGL2ZPANmCy7nsL7\\n5kczishLb0GG1/PoNBQJW5A1Wl7uI/SE77KTThRxk3Wco4HzMIHwMA4GA1UdDwEB\\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\\nBAIwADApBgNVHQ4EIgQgYbec+6bte/VdH3M63TFVmDU0jH5461iZTsiJ1x+18iow\\nKwYDVR0jBCQwIoAgqo5xDZXH+SCNmEyBYOSyc8RlSBX3sJJrSLCtuZp5WxgwWQYD\\nVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1NTU1\\nNTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqGSM49\\nBAMCA0cAMEQCIC/xdLblMMnwXGqBn9XkdGOnUEtJW0LU+tKyen5PxRO7AiBjTefh\\n5uZU8QVs2FQTQHN0Omr4ngToHBHNwKl1Flvyqw==\\n-----END CERTIFICATE-----\\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\\nMHcCAQEEIP6roctlkGz+7od7hFwaldpvbnkXmnjvpPBxyKU4NcM9oAoGCCqGSM49\\nAwEHoUQDQgAEd7jWGLfGpi0DH2nuhqTMhWjAQZBi9mTwDZgsu57C++ZHM4rIS29B\\nhtfz6DQUCVuQNVpe7iP0hO+yk04UcZN1nA==\\n-----END EC PRIVATE KEY-----\\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requireClientCertificate": true
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.ext_authz",
|
||||
"config": {
|
||||
"grpc_service": {
|
||||
"envoy_grpc": {
|
||||
"cluster_name": "local_agent"
|
||||
},
|
||||
"initial_metadata": [
|
||||
{
|
||||
"key": "x-consul-token",
|
||||
"value": "my-token"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stat_prefix": "connect_authz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.network.sni_cluster"
|
||||
},
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "",
|
||||
"stat_prefix": "terminating_gateway_web_default_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
]
|
||||
},
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\\nMIICKDCCAc+gAwIBAgIIT/zLIOrnlRQwCgYIKoZIzj0EAwIwFTETMBEGA1UEAxMK\\nVGVzdCBDQSA4NTAeFw0yMDA0MTEwMDMxMjJaFw0zMDA0MTEwMDMxMjJaMCoxKDAm\\nBgNVBAMTH3dlYi5zdmMuZGVmYXVsdC4xMTExMTExMS5jb25zdWwwWTATBgcqhkjO\\nPQIBBggqhkjOPQMBBwNCAAR3uNYYt8amLQMfae6GpMyFaMBBkGL2ZPANmCy7nsL7\\n5kczishLb0GG1/PoNBQJW5A1Wl7uI/SE77KTThRxk3Wco4HzMIHwMA4GA1UdDwEB\\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\\nBAIwADApBgNVHQ4EIgQgYbec+6bte/VdH3M63TFVmDU0jH5461iZTsiJ1x+18iow\\nKwYDVR0jBCQwIoAgqo5xDZXH+SCNmEyBYOSyc8RlSBX3sJJrSLCtuZp5WxgwWQYD\\nVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1NTU1\\nNTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqGSM49\\nBAMCA0cAMEQCIC/xdLblMMnwXGqBn9XkdGOnUEtJW0LU+tKyen5PxRO7AiBjTefh\\n5uZU8QVs2FQTQHN0Omr4ngToHBHNwKl1Flvyqw==\\n-----END CERTIFICATE-----\\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\\nMHcCAQEEIP6roctlkGz+7od7hFwaldpvbnkXmnjvpPBxyKU4NcM9oAoGCCqGSM49\\nAwEHoUQDQgAEd7jWGLfGpi0DH2nuhqTMhWjAQZBi9mTwDZgsu57C++ZHM4rIS29B\\nhtfz6DQUCVuQNVpe7iP0hO+yk04UcZN1nA==\\n-----END EC PRIVATE KEY-----\\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requireClientCertificate": true
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.ext_authz",
|
||||
"config": {
|
||||
"grpc_service": {
|
||||
"envoy_grpc": {
|
||||
"cluster_name": "local_agent"
|
||||
},
|
||||
"initial_metadata": [
|
||||
{
|
||||
"key": "x-consul-token",
|
||||
"value": "my-token"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stat_prefix": "connect_authz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.network.sni_cluster"
|
||||
},
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "",
|
||||
"stat_prefix": "terminating_gateway_web_default_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
]
|
||||
},
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\\nMIICKDCCAc+gAwIBAgIIT/zLIOrnlRQwCgYIKoZIzj0EAwIwFTETMBEGA1UEAxMK\\nVGVzdCBDQSA4NTAeFw0yMDA0MTEwMDMxMjJaFw0zMDA0MTEwMDMxMjJaMCoxKDAm\\nBgNVBAMTH3dlYi5zdmMuZGVmYXVsdC4xMTExMTExMS5jb25zdWwwWTATBgcqhkjO\\nPQIBBggqhkjOPQMBBwNCAAR3uNYYt8amLQMfae6GpMyFaMBBkGL2ZPANmCy7nsL7\\n5kczishLb0GG1/PoNBQJW5A1Wl7uI/SE77KTThRxk3Wco4HzMIHwMA4GA1UdDwEB\\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\\nBAIwADApBgNVHQ4EIgQgYbec+6bte/VdH3M63TFVmDU0jH5461iZTsiJ1x+18iow\\nKwYDVR0jBCQwIoAgqo5xDZXH+SCNmEyBYOSyc8RlSBX3sJJrSLCtuZp5WxgwWQYD\\nVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1NTU1\\nNTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqGSM49\\nBAMCA0cAMEQCIC/xdLblMMnwXGqBn9XkdGOnUEtJW0LU+tKyen5PxRO7AiBjTefh\\n5uZU8QVs2FQTQHN0Omr4ngToHBHNwKl1Flvyqw==\\n-----END CERTIFICATE-----\\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\\nMHcCAQEEIP6roctlkGz+7od7hFwaldpvbnkXmnjvpPBxyKU4NcM9oAoGCCqGSM49\\nAwEHoUQDQgAEd7jWGLfGpi0DH2nuhqTMhWjAQZBi9mTwDZgsu57C++ZHM4rIS29B\\nhtfz6DQUCVuQNVpe7iP0hO+yk04UcZN1nA==\\n-----END EC PRIVATE KEY-----\\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requireClientCertificate": true
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.ext_authz",
|
||||
"config": {
|
||||
"grpc_service": {
|
||||
"envoy_grpc": {
|
||||
"cluster_name": "local_agent"
|
||||
},
|
||||
"initial_metadata": [
|
||||
{
|
||||
"key": "x-consul-token",
|
||||
"value": "my-token"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stat_prefix": "connect_authz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.network.sni_cluster"
|
||||
},
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "",
|
||||
"stat_prefix": "terminating_gateway_web_default_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
]
|
||||
},
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\\nMIICKjCCAc+gAwIBAgIICeaPMbQdJsswCgYIKoZIzj0EAwIwFTETMBEGA1UEAxMK\\nVGVzdCBDQSA4NTAeFw0yMDA0MTEwMDE3NTZaFw0zMDA0MTEwMDE3NTZaMCoxKDAm\\nBgNVBAMTH2FwaS5zdmMuZGVmYXVsdC4xMTExMTExMS5jb25zdWwwWTATBgcqhkjO\\nPQIBBggqhkjOPQMBBwNCAASvkFCbA1rP8NxyKAOGoLmVjwSB+dO/ncs5KqourUPw\\nbZfQEETsTaTdO5aWgkJilagD7Z1RZltWk+MGhPleo8/bo4HzMIHwMA4GA1UdDwEB\\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\\nBAIwADApBgNVHQ4EIgQgyNkAhsJy93ueCk9Bjo9DdiZB+eJq7zs4qr9tmrT5zBAw\\nKwYDVR0jBCQwIoAgJDQM9fdkMlYIa/hmjVbXie/3qNMaAS8R9dKPQ2XE05gwWQYD\\nVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1NTU1\\nNTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvYXBpMAoGCCqGSM49\\nBAMCA0kAMEYCIQDN/60bmqjeFQpHw52r63Lftuuexl6AHVDI+o7MPYzfKwIhANMJ\\n0s1qRbOUItdIC8y0Ph2woXcj2yXluiPzFT3Ij94k\\n-----END CERTIFICATE-----\\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\\nMHcCAQEEIBdbcIKnjbzUBLHVQANB2P6bQf6SNOtEd6san+82wY21oAoGCCqGSM49\\nAwEHoUQDQgAEr5BQmwNaz/DccigDhqC5lY8EgfnTv53LOSqqLq1D8G2X0BBE7E2k\\n3TuWloJCYpWoA+2dUWZbVpPjBoT5XqPP2w==\\n-----END EC PRIVATE KEY-----\\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requireClientCertificate": true
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.ext_authz",
|
||||
"config": {
|
||||
"grpc_service": {
|
||||
"envoy_grpc": {
|
||||
"cluster_name": "local_agent"
|
||||
},
|
||||
"initial_metadata": [
|
||||
{
|
||||
"key": "x-consul-token",
|
||||
"value": "my-token"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stat_prefix": "connect_authz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.network.sni_cluster"
|
||||
},
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "",
|
||||
"stat_prefix": "terminating_gateway_api_default_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.listener.tls_inspector"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
Loading…
Reference in New Issue