mirror of https://github.com/status-im/consul.git
connect: introduce ExternalSNI field on service-defaults (#6324)
Compiling this will set an optional SNI field on each DiscoveryTarget. When set this value should be used for TLS connections to the instances of the target. If not set the default should be used. Setting ExternalSNI will disable mesh gateway use for that target. It also disables several service-resolver features that do not make sense for an external service.
This commit is contained in:
parent
1351f6d345
commit
ae79cdab1b
|
@ -2783,6 +2783,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
|
|||
"kind": "service-defaults",
|
||||
"name": "web",
|
||||
"protocol": "http",
|
||||
"external_sni": "abc-123",
|
||||
"mesh_gateway": {
|
||||
"mode": "remote"
|
||||
}
|
||||
|
@ -2796,6 +2797,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
|
|||
kind = "service-defaults"
|
||||
name = "web"
|
||||
protocol = "http"
|
||||
external_sni = "abc-123"
|
||||
mesh_gateway {
|
||||
mode = "remote"
|
||||
}
|
||||
|
@ -2805,9 +2807,10 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
|
|||
rt.DataDir = dataDir
|
||||
rt.ConfigEntryBootstrap = []structs.ConfigEntry{
|
||||
&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "web",
|
||||
Protocol: "http",
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "web",
|
||||
Protocol: "http",
|
||||
ExternalSNI: "abc-123",
|
||||
MeshGateway: structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeRemote,
|
||||
},
|
||||
|
@ -2825,6 +2828,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
|
|||
"Kind": "service-defaults",
|
||||
"Name": "web",
|
||||
"Protocol": "http",
|
||||
"ExternalSNI": "abc-123",
|
||||
"MeshGateway": {
|
||||
"Mode": "remote"
|
||||
}
|
||||
|
@ -2838,6 +2842,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
|
|||
Kind = "service-defaults"
|
||||
Name = "web"
|
||||
Protocol = "http"
|
||||
ExternalSNI = "abc-123"
|
||||
MeshGateway {
|
||||
Mode = "remote"
|
||||
}
|
||||
|
@ -2847,9 +2852,10 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
|
|||
rt.DataDir = dataDir
|
||||
rt.ConfigEntryBootstrap = []structs.ConfigEntry{
|
||||
&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "web",
|
||||
Protocol: "http",
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "web",
|
||||
Protocol: "http",
|
||||
ExternalSNI: "abc-123",
|
||||
MeshGateway: structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeRemote,
|
||||
},
|
||||
|
|
|
@ -813,9 +813,48 @@ RESOLVE_AGAIN:
|
|||
|
||||
target.Subset = resolver.Subsets[target.ServiceSubset]
|
||||
|
||||
if serviceDefault := c.entries.GetService(target.Service); serviceDefault != nil && serviceDefault.ExternalSNI != "" {
|
||||
// Explicitly set the SNI value.
|
||||
target.SNI = serviceDefault.ExternalSNI
|
||||
target.External = true
|
||||
}
|
||||
|
||||
// If using external SNI the service is fundamentally external.
|
||||
if target.External {
|
||||
if resolver.Redirect != nil {
|
||||
return nil, &structs.ConfigEntryGraphError{
|
||||
Message: fmt.Sprintf(
|
||||
"service %q has an external SNI set; cannot define redirects for external services",
|
||||
target.Service,
|
||||
),
|
||||
}
|
||||
}
|
||||
if len(resolver.Subsets) > 0 {
|
||||
return nil, &structs.ConfigEntryGraphError{
|
||||
Message: fmt.Sprintf(
|
||||
"service %q has an external SNI set; cannot define subsets for external services",
|
||||
target.Service,
|
||||
),
|
||||
}
|
||||
}
|
||||
if len(resolver.Failover) > 0 {
|
||||
return nil, &structs.ConfigEntryGraphError{
|
||||
Message: fmt.Sprintf(
|
||||
"service %q has an external SNI set; cannot define failover for external services",
|
||||
target.Service,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO (mesh-gateway)- maybe allow using a gateway within a datacenter at some point
|
||||
if target.Datacenter == c.useInDatacenter {
|
||||
target.MeshGateway.Mode = structs.MeshGatewayModeDefault
|
||||
|
||||
} else if target.External {
|
||||
// Bypass mesh gateways if it is an external service.
|
||||
target.MeshGateway.Mode = structs.MeshGatewayModeDefault
|
||||
|
||||
} else {
|
||||
// Default mesh gateway settings
|
||||
if serviceDefault := c.entries.GetService(target.Service); serviceDefault != nil {
|
||||
|
|
|
@ -46,6 +46,7 @@ func TestCompile(t *testing.T) {
|
|||
"datacenter failover with mesh gateways": testcase_DatacenterFailover_WithMeshGateways(),
|
||||
"noop split to resolver with default subset": testcase_NoopSplit_WithDefaultSubset(),
|
||||
"resolver with default subset": testcase_Resolve_WithDefaultSubset(),
|
||||
"default resolver with external sni": testcase_DefaultResolver_ExternalSNI(),
|
||||
"resolver with no entries and inferring defaults": testcase_DefaultResolver(),
|
||||
"default resolver with proxy defaults": testcase_DefaultResolver_WithProxyDefaults(),
|
||||
"service redirect to service with default resolver is not a default chain": testcase_RedirectToDefaultResolverIsNotDefaultChain(),
|
||||
|
@ -54,13 +55,16 @@ func TestCompile(t *testing.T) {
|
|||
"multi dc canary": testcase_MultiDatacenterCanary(),
|
||||
|
||||
// various errors
|
||||
"splitter requires valid protocol": testcase_SplitterRequiresValidProtocol(),
|
||||
"router requires valid protocol": testcase_RouterRequiresValidProtocol(),
|
||||
"split to unsplittable protocol": testcase_SplitToUnsplittableProtocol(),
|
||||
"route to unroutable protocol": testcase_RouteToUnroutableProtocol(),
|
||||
"failover crosses protocols": testcase_FailoverCrossesProtocols(),
|
||||
"redirect crosses protocols": testcase_RedirectCrossesProtocols(),
|
||||
"redirect to missing subset": testcase_RedirectToMissingSubset(),
|
||||
"splitter requires valid protocol": testcase_SplitterRequiresValidProtocol(),
|
||||
"router requires valid protocol": testcase_RouterRequiresValidProtocol(),
|
||||
"split to unsplittable protocol": testcase_SplitToUnsplittableProtocol(),
|
||||
"route to unroutable protocol": testcase_RouteToUnroutableProtocol(),
|
||||
"failover crosses protocols": testcase_FailoverCrossesProtocols(),
|
||||
"redirect crosses protocols": testcase_RedirectCrossesProtocols(),
|
||||
"redirect to missing subset": testcase_RedirectToMissingSubset(),
|
||||
"resolver with failover and external sni": testcase_Resolver_ExternalSNI_FailoverNotAllowed(),
|
||||
"resolver with subsets and external sni": testcase_Resolver_ExternalSNI_SubsetsNotAllowed(),
|
||||
"resolver with redirect and external sni": testcase_Resolver_ExternalSNI_RedirectNotAllowed(),
|
||||
|
||||
// overrides
|
||||
"resolver with protocol from override": testcase_ResolverProtocolOverride(),
|
||||
|
@ -1435,6 +1439,109 @@ func testcase_Resolve_WithDefaultSubset() compileTestCase {
|
|||
return compileTestCase{entries: entries, expect: expect}
|
||||
}
|
||||
|
||||
func testcase_DefaultResolver_ExternalSNI() compileTestCase {
|
||||
entries := newEntries()
|
||||
entries.AddServices(&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "main",
|
||||
ExternalSNI: "main.some.other.service.mesh",
|
||||
})
|
||||
|
||||
expect := &structs.CompiledDiscoveryChain{
|
||||
Protocol: "tcp",
|
||||
StartNode: "resolver:main.default.dc1",
|
||||
Nodes: map[string]*structs.DiscoveryGraphNode{
|
||||
"resolver:main.default.dc1": &structs.DiscoveryGraphNode{
|
||||
Type: structs.DiscoveryGraphNodeTypeResolver,
|
||||
Name: "main.default.dc1",
|
||||
Resolver: &structs.DiscoveryResolver{
|
||||
Default: true,
|
||||
ConnectTimeout: 5 * time.Second,
|
||||
Target: "main.default.dc1",
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: map[string]*structs.DiscoveryTarget{
|
||||
"main.default.dc1": newTarget("main", "", "default", "dc1", func(t *structs.DiscoveryTarget) {
|
||||
t.SNI = "main.some.other.service.mesh"
|
||||
t.External = true
|
||||
}),
|
||||
},
|
||||
}
|
||||
return compileTestCase{entries: entries, expect: expect, expectIsDefault: true}
|
||||
}
|
||||
|
||||
func testcase_Resolver_ExternalSNI_FailoverNotAllowed() compileTestCase {
|
||||
entries := newEntries()
|
||||
entries.AddServices(&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "main",
|
||||
ExternalSNI: "main.some.other.service.mesh",
|
||||
})
|
||||
entries.AddResolvers(&structs.ServiceResolverConfigEntry{
|
||||
Kind: "service-resolver",
|
||||
Name: "main",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Failover: map[string]structs.ServiceResolverFailover{
|
||||
"*": {Service: "backup"},
|
||||
},
|
||||
})
|
||||
|
||||
return compileTestCase{
|
||||
entries: entries,
|
||||
expectErr: `service "main" has an external SNI set; cannot define failover for external services`,
|
||||
expectGraphErr: true,
|
||||
}
|
||||
}
|
||||
|
||||
func testcase_Resolver_ExternalSNI_SubsetsNotAllowed() compileTestCase {
|
||||
entries := newEntries()
|
||||
entries.AddServices(&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "main",
|
||||
ExternalSNI: "main.some.other.service.mesh",
|
||||
})
|
||||
entries.AddResolvers(&structs.ServiceResolverConfigEntry{
|
||||
Kind: "service-resolver",
|
||||
Name: "main",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"canary": {
|
||||
Filter: "Service.Meta.version == canary",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return compileTestCase{
|
||||
entries: entries,
|
||||
expectErr: `service "main" has an external SNI set; cannot define subsets for external services`,
|
||||
expectGraphErr: true,
|
||||
}
|
||||
}
|
||||
|
||||
func testcase_Resolver_ExternalSNI_RedirectNotAllowed() compileTestCase {
|
||||
entries := newEntries()
|
||||
entries.AddServices(&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "main",
|
||||
ExternalSNI: "main.some.other.service.mesh",
|
||||
})
|
||||
entries.AddResolvers(&structs.ServiceResolverConfigEntry{
|
||||
Kind: "service-resolver",
|
||||
Name: "main",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Redirect: &structs.ServiceResolverRedirect{
|
||||
Datacenter: "dc2",
|
||||
},
|
||||
})
|
||||
|
||||
return compileTestCase{
|
||||
entries: entries,
|
||||
expectErr: `service "main" has an external SNI set; cannot define redirects for external services`,
|
||||
expectGraphErr: true,
|
||||
}
|
||||
}
|
||||
|
||||
func testcase_MultiDatacenterCanary() compileTestCase {
|
||||
entries := newEntries()
|
||||
setServiceProtocol(entries, "main", "http")
|
||||
|
|
|
@ -592,6 +592,10 @@ func TestConfigSnapshotDiscoveryChain(t testing.T) *ConfigSnapshot {
|
|||
return testConfigSnapshotDiscoveryChain(t, "simple")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainExternalSNI(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "external-sni")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainWithOverrides(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "simple-with-overrides")
|
||||
}
|
||||
|
@ -664,6 +668,19 @@ func testConfigSnapshotDiscoveryChain(t testing.T, variation string, additionalE
|
|||
ConnectTimeout: 33 * time.Second,
|
||||
},
|
||||
)
|
||||
case "external-sni":
|
||||
entries = append(entries,
|
||||
&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "db",
|
||||
ExternalSNI: "db.some.other.service.mesh",
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
},
|
||||
)
|
||||
case "failover":
|
||||
entries = append(entries,
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
|
@ -858,6 +875,7 @@ func testConfigSnapshotDiscoveryChain(t testing.T, variation string, additionalE
|
|||
switch variation {
|
||||
case "simple-with-overrides":
|
||||
case "simple":
|
||||
case "external-sni":
|
||||
case "failover":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["fail.default.dc1"] =
|
||||
TestUpstreamNodesAlternate(t)
|
||||
|
|
|
@ -52,6 +52,8 @@ type ServiceConfigEntry struct {
|
|||
Protocol string
|
||||
MeshGateway MeshGatewayConfig `json:",omitempty"`
|
||||
|
||||
ExternalSNI string `json:",omitempty"`
|
||||
|
||||
// TODO(banks): enable this once we have upstreams supported too. Enabling
|
||||
// sidecars actually makes no sense and adds complications when you don't
|
||||
// allow upstreams to be specified centrally too.
|
||||
|
@ -302,6 +304,7 @@ func ConfigEntryDecodeRulesForKind(kind string) (skipWhenPatching []string, tran
|
|||
case ServiceDefaults:
|
||||
return nil, map[string]string{
|
||||
"mesh_gateway": "meshgateway",
|
||||
"external_sni": "externalsni",
|
||||
}, nil
|
||||
case ServiceRouter:
|
||||
return []string{
|
||||
|
|
|
@ -93,6 +93,7 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
kind = "service-defaults"
|
||||
name = "main"
|
||||
protocol = "http"
|
||||
external_sni = "abc-123"
|
||||
mesh_gateway {
|
||||
mode = "remote"
|
||||
}
|
||||
|
@ -101,14 +102,16 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
Kind = "service-defaults"
|
||||
Name = "main"
|
||||
Protocol = "http"
|
||||
ExternalSNI = "abc-123"
|
||||
MeshGateway {
|
||||
Mode = "remote"
|
||||
}
|
||||
`,
|
||||
expect: &ServiceConfigEntry{
|
||||
Kind: "service-defaults",
|
||||
Name: "main",
|
||||
Protocol: "http",
|
||||
Kind: "service-defaults",
|
||||
Name: "main",
|
||||
Protocol: "http",
|
||||
ExternalSNI: "abc-123",
|
||||
MeshGateway: MeshGatewayConfig{
|
||||
Mode: MeshGatewayModeRemote,
|
||||
},
|
||||
|
|
|
@ -160,6 +160,11 @@ type DiscoveryTarget struct {
|
|||
|
||||
MeshGateway MeshGatewayConfig `json:",omitempty"`
|
||||
Subset ServiceResolverSubset `json:",omitempty"`
|
||||
|
||||
// SNI if set is the sni field to use when addressing this set of
|
||||
// endpoints. If not configured then the Connect default should be used.
|
||||
SNI string `json:",omitempty"`
|
||||
External bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
func NewDiscoveryTarget(service, serviceSubset, namespace, datacenter string) *DiscoveryTarget {
|
||||
|
|
|
@ -321,10 +321,15 @@ func (s *Server) makeUpstreamClustersForDiscoveryChain(
|
|||
c.Http2ProtocolOptions = &envoycore.Http2ProtocolOptions{}
|
||||
}
|
||||
|
||||
finalSNI := sni
|
||||
if target.SNI != "" {
|
||||
finalSNI = target.SNI
|
||||
}
|
||||
|
||||
// Enable TLS upstream with the configured client certificate.
|
||||
c.TlsContext = &envoyauth.UpstreamTlsContext{
|
||||
CommonTlsContext: makeCommonTLSContext(cfgSnap),
|
||||
Sni: sni,
|
||||
Sni: finalSNI,
|
||||
}
|
||||
|
||||
out = append(out, c)
|
||||
|
|
|
@ -105,6 +105,11 @@ func TestClustersFromSnapshot(t *testing.T) {
|
|||
create: proxycfg.TestConfigSnapshotDiscoveryChain,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-external-sni",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainExternalSNI,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-and-overrides",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithOverrides,
|
||||
|
|
|
@ -243,6 +243,11 @@ func Test_endpointsFromSnapshot(t *testing.T) {
|
|||
create: proxycfg.TestConfigSnapshotDiscoveryChain,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-external-sni",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainExternalSNI,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-and-overrides",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithOverrides,
|
||||
|
|
|
@ -184,6 +184,11 @@ func TestListenersFromSnapshot(t *testing.T) {
|
|||
},
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-external-sni",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainExternalSNI,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-and-overrides",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithOverrides,
|
||||
|
|
|
@ -50,6 +50,11 @@ func TestRoutesFromSnapshot(t *testing.T) {
|
|||
create: proxycfg.TestConfigSnapshotDiscoveryChain,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-external-sni",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainExternalSNI,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-and-overrides",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithOverrides,
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "db.some.other.service.mesh"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "db.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,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "db:127.0.0.1:9191",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 9191
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "",
|
||||
"stat_prefix": "upstream_db_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "prepared_query:geo-cache:127.10.10.10:8181",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.10.10.10",
|
||||
"portValue": 8181
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"stat_prefix": "upstream_prepared_query_geo-cache_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "public_listener:0.0.0.0:9999",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "0.0.0.0",
|
||||
"portValue": 9999
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"tlsContext": {
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requireClientCertificate": 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.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "local_app",
|
||||
"stat_prefix": "public_listener_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"name": "db",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "db",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"validateClusters": true
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -61,6 +61,7 @@ type ServiceConfigEntry struct {
|
|||
Name string
|
||||
Protocol string
|
||||
MeshGateway MeshGatewayConfig
|
||||
ExternalSNI string
|
||||
CreateIndex uint64
|
||||
ModifyIndex uint64
|
||||
}
|
||||
|
|
|
@ -235,15 +235,17 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
"Kind": "service-defaults",
|
||||
"Name": "main",
|
||||
"Protocol": "http",
|
||||
"ExternalSNI": "abc-123",
|
||||
"MeshGateway": {
|
||||
"Mode": "remote"
|
||||
}
|
||||
}
|
||||
`,
|
||||
expect: &ServiceConfigEntry{
|
||||
Kind: "service-defaults",
|
||||
Name: "main",
|
||||
Protocol: "http",
|
||||
Kind: "service-defaults",
|
||||
Name: "main",
|
||||
Protocol: "http",
|
||||
ExternalSNI: "abc-123",
|
||||
MeshGateway: MeshGatewayConfig{
|
||||
Mode: MeshGatewayModeRemote,
|
||||
},
|
||||
|
|
|
@ -187,4 +187,6 @@ type DiscoveryTarget struct {
|
|||
|
||||
MeshGateway MeshGatewayConfig
|
||||
Subset ServiceResolverSubset
|
||||
SNI string
|
||||
External bool
|
||||
}
|
||||
|
|
|
@ -251,6 +251,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
kind = "service-defaults"
|
||||
name = "main"
|
||||
protocol = "http"
|
||||
external_sni = "abc-123"
|
||||
mesh_gateway {
|
||||
mode = "remote"
|
||||
}
|
||||
|
@ -259,6 +260,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
Kind = "service-defaults"
|
||||
Name = "main"
|
||||
Protocol = "http"
|
||||
ExternalSNI = "abc-123"
|
||||
MeshGateway {
|
||||
Mode = "remote"
|
||||
}
|
||||
|
@ -268,6 +270,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"kind": "service-defaults",
|
||||
"name": "main",
|
||||
"protocol": "http",
|
||||
"external_sni": "abc-123",
|
||||
"mesh_gateway": {
|
||||
"mode": "remote"
|
||||
}
|
||||
|
@ -278,15 +281,17 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
"Kind": "service-defaults",
|
||||
"Name": "main",
|
||||
"Protocol": "http",
|
||||
"ExternalSNI": "abc-123",
|
||||
"MeshGateway": {
|
||||
"Mode": "remote"
|
||||
}
|
||||
}
|
||||
`,
|
||||
expect: &api.ServiceConfigEntry{
|
||||
Kind: "service-defaults",
|
||||
Name: "main",
|
||||
Protocol: "http",
|
||||
Kind: "service-defaults",
|
||||
Name: "main",
|
||||
Protocol: "http",
|
||||
ExternalSNI: "abc-123",
|
||||
MeshGateway: api.MeshGatewayConfig{
|
||||
Mode: api.MeshGatewayModeRemote,
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue