mirror of
https://github.com/status-im/consul.git
synced 2025-01-09 21:35:52 +00:00
2a56e0055b
Prior to this PR for the envoy xDS golden tests in the agent/xds package we were hand-creating a proxycfg.ConfigSnapshot structure in the proper format for input to the xDS generator. Over time this intermediate structure has gotten trickier to build correctly for the various tests. This PR proposes to switch to using the existing mechanism for turning a structs.NodeService and a sequence of cache.UpdateEvent copies into a proxycfg.ConfigSnapshot, as that is less error prone to construct and aligns more with how the data arrives. NOTE: almost all of this is in test-related code. I tried super hard to craft correct event inputs to get the golden files to be the same, or similar enough after construction to feel ok that i recreated the spirit of the original test cases.
1501 lines
40 KiB
Go
1501 lines
40 KiB
Go
package proxycfg
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/mitchellh/go-testing-interface"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/hashicorp/consul/agent/cache"
|
|
"github.com/hashicorp/consul/agent/connect"
|
|
"github.com/hashicorp/consul/agent/consul/discoverychain"
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
"github.com/hashicorp/consul/types"
|
|
)
|
|
|
|
func TestConfigSnapshotIngressGateway(
|
|
t testing.T,
|
|
populateServices bool,
|
|
protocol string,
|
|
variation string,
|
|
nsFn func(ns *structs.NodeService),
|
|
configFn func(entry *structs.IngressGatewayConfigEntry),
|
|
extraUpdates []cache.UpdateEvent,
|
|
additionalEntries ...structs.ConfigEntry,
|
|
) *ConfigSnapshot {
|
|
roots, placeholderLeaf := TestCerts(t)
|
|
|
|
entry := &structs.IngressGatewayConfigEntry{
|
|
Kind: structs.IngressGateway,
|
|
Name: "ingress-gateway",
|
|
}
|
|
|
|
if populateServices {
|
|
entry.Listeners = []structs.IngressListener{
|
|
{
|
|
Port: 8080,
|
|
Protocol: protocol,
|
|
Services: []structs.IngressService{
|
|
{Name: "db"},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
if configFn != nil {
|
|
configFn(entry)
|
|
}
|
|
|
|
baseEvents := []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: rootsWatchID,
|
|
Result: roots,
|
|
},
|
|
{
|
|
CorrelationID: gatewayConfigWatchID,
|
|
Result: &structs.ConfigEntryResponse{
|
|
Entry: entry,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: leafWatchID,
|
|
Result: placeholderLeaf, // TODO(rb): should this be generated differently?
|
|
},
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: nil,
|
|
},
|
|
},
|
|
}
|
|
|
|
if populateServices {
|
|
baseEvents = testSpliceEvents(baseEvents, []cache.UpdateEvent{{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: structs.NewServiceName("db", nil),
|
|
Port: 8080,
|
|
Hosts: nil,
|
|
Protocol: protocol,
|
|
},
|
|
},
|
|
},
|
|
}})
|
|
|
|
upstreams := structs.TestUpstreams(t)
|
|
upstreams = structs.Upstreams{upstreams[0]} // just keep 'db'
|
|
|
|
baseEvents = testSpliceEvents(baseEvents, setupTestVariationConfigEntriesAndSnapshot(
|
|
t, variation, upstreams, additionalEntries...,
|
|
))
|
|
}
|
|
|
|
return testConfigSnapshotFixture(t, &structs.NodeService{
|
|
Kind: structs.ServiceKindIngressGateway,
|
|
Service: "ingress-gateway",
|
|
Port: 9999,
|
|
Address: "1.2.3.4",
|
|
Meta: nil,
|
|
TaggedAddresses: nil,
|
|
}, nsFn, nil, testSpliceEvents(baseEvents, extraUpdates))
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGatewaySDS_GatewayLevel_MixedTLS(t testing.T) *ConfigSnapshot {
|
|
secureUID := UpstreamIDFromString("secure")
|
|
secureChain := discoverychain.TestCompileConfigEntries(
|
|
t,
|
|
"secure",
|
|
"default",
|
|
"default",
|
|
"dc1",
|
|
connect.TestClusterID+".consul",
|
|
nil,
|
|
)
|
|
|
|
insecureUID := UpstreamIDFromString("insecure")
|
|
insecureChain := discoverychain.TestCompileConfigEntries(
|
|
t,
|
|
"insecure",
|
|
"default",
|
|
"default",
|
|
"dc1",
|
|
connect.TestClusterID+".consul",
|
|
nil,
|
|
)
|
|
|
|
return TestConfigSnapshotIngressGateway(t, false, "tcp", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
// Disable GW-level defaults so we can mix TLS and non-TLS listeners
|
|
entry.TLS = structs.GatewayTLSConfig{
|
|
SDS: nil,
|
|
}
|
|
entry.Listeners = []structs.IngressListener{
|
|
// Setup two TCP listeners, one with and one without SDS config
|
|
{
|
|
Port: 8080,
|
|
Protocol: "tcp",
|
|
TLS: &structs.GatewayTLSConfig{
|
|
SDS: &structs.GatewayTLSSDSConfig{
|
|
ClusterName: "listener-sds-cluster",
|
|
CertResource: "listener-cert",
|
|
},
|
|
},
|
|
Services: []structs.IngressService{
|
|
{Name: "secure"},
|
|
},
|
|
},
|
|
{
|
|
Port: 9090,
|
|
Protocol: "tcp",
|
|
TLS: nil,
|
|
Services: []structs.IngressService{
|
|
{Name: "insecure"},
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: structs.NewServiceName("secure", nil),
|
|
Port: 8080,
|
|
Protocol: "tcp",
|
|
},
|
|
{
|
|
Service: structs.NewServiceName("insecure", nil),
|
|
Port: 9090,
|
|
Protocol: "tcp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + secureUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: secureChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + secureChain.ID() + ":" + secureUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "secure"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + insecureUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: insecureChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + insecureChain.ID() + ":" + insecureUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "insecure"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGatewaySDS_GatewayLevel(t testing.T) *ConfigSnapshot {
|
|
return TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.TLS = structs.GatewayTLSConfig{
|
|
SDS: &structs.GatewayTLSSDSConfig{
|
|
ClusterName: "sds-cluster",
|
|
CertResource: "cert-resource",
|
|
},
|
|
}
|
|
}, nil)
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGatewaySDS_GatewayAndListenerLevel(t testing.T) *ConfigSnapshot {
|
|
return TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.TLS = structs.GatewayTLSConfig{
|
|
SDS: &structs.GatewayTLSSDSConfig{
|
|
ClusterName: "sds-cluster",
|
|
CertResource: "cert-resource",
|
|
},
|
|
}
|
|
entry.Listeners[0].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",
|
|
},
|
|
}
|
|
}, nil)
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGatewaySDS_GatewayAndListenerLevel_HTTP(t testing.T) *ConfigSnapshot {
|
|
var (
|
|
http = structs.NewServiceName("http", nil)
|
|
httpUID = NewUpstreamIDFromServiceName(http)
|
|
httpChain = discoverychain.TestCompileConfigEntries(t, "http", "default", "default", "dc1", connect.TestClusterID+".consul", nil,
|
|
&structs.ServiceConfigEntry{
|
|
Kind: structs.ServiceDefaults,
|
|
Name: "http",
|
|
Protocol: "http",
|
|
})
|
|
)
|
|
|
|
return TestConfigSnapshotIngressGateway(t, false, "http", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.TLS = structs.GatewayTLSConfig{
|
|
SDS: &structs.GatewayTLSSDSConfig{
|
|
ClusterName: "sds-cluster",
|
|
CertResource: "cert-resource",
|
|
},
|
|
}
|
|
entry.Listeners = []structs.IngressListener{
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "http"},
|
|
},
|
|
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",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: http,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + httpUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: httpChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + httpChain.ID() + ":" + httpUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "http"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGatewaySDS_ServiceLevel(t testing.T) *ConfigSnapshot {
|
|
var (
|
|
s1 = structs.NewServiceName("s1", nil)
|
|
s1UID = NewUpstreamIDFromServiceName(s1)
|
|
s1Chain = discoverychain.TestCompileConfigEntries(t, "s1", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s2 = structs.NewServiceName("s2", nil)
|
|
s2UID = NewUpstreamIDFromServiceName(s2)
|
|
s2Chain = discoverychain.TestCompileConfigEntries(t, "s2", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
)
|
|
|
|
return TestConfigSnapshotIngressGateway(t, false, "tcp", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
// Disable GW-level defaults so we can test only service-level
|
|
entry.TLS = structs.GatewayTLSConfig{
|
|
SDS: nil,
|
|
}
|
|
entry.Listeners = []structs.IngressListener{
|
|
// Setup http listeners, one multiple services with SDS
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
TLS: nil, // no listener-level SDS config
|
|
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",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: s1,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s2,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s1UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s1Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s1Chain.ID() + ":" + s1UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s1"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s2UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s2Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s2Chain.ID() + ":" + s2UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s2"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGatewaySDS_ListenerAndServiceLevel(t testing.T) *ConfigSnapshot {
|
|
var (
|
|
s1 = structs.NewServiceName("s1", nil)
|
|
s1UID = NewUpstreamIDFromServiceName(s1)
|
|
s1Chain = discoverychain.TestCompileConfigEntries(t, "s1", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s2 = structs.NewServiceName("s2", nil)
|
|
s2UID = NewUpstreamIDFromServiceName(s2)
|
|
s2Chain = discoverychain.TestCompileConfigEntries(t, "s2", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
)
|
|
|
|
return TestConfigSnapshotIngressGateway(t, false, "tcp", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
// Disable GW-level defaults so we can test only service-level
|
|
entry.TLS = structs.GatewayTLSConfig{
|
|
SDS: nil,
|
|
}
|
|
entry.Listeners = []structs.IngressListener{
|
|
// Setup http listeners, one multiple services with SDS
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
TLS: &structs.GatewayTLSConfig{
|
|
SDS: &structs.GatewayTLSSDSConfig{
|
|
ClusterName: "sds-cluster-2",
|
|
CertResource: "*.example.com-cert",
|
|
},
|
|
},
|
|
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
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: s1,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s2,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s1UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s1Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s1Chain.ID() + ":" + s1UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s1"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s2UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s2Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s2Chain.ID() + ":" + s2UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s2"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGatewaySDS_MixedNoTLS(t testing.T) *ConfigSnapshot {
|
|
var (
|
|
s1 = structs.NewServiceName("s1", nil)
|
|
s1UID = NewUpstreamIDFromServiceName(s1)
|
|
s1Chain = discoverychain.TestCompileConfigEntries(t, "s1", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s2 = structs.NewServiceName("s2", nil)
|
|
s2UID = NewUpstreamIDFromServiceName(s2)
|
|
s2Chain = discoverychain.TestCompileConfigEntries(t, "s2", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
)
|
|
|
|
return TestConfigSnapshotIngressGateway(t, false, "tcp", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
// Disable GW-level defaults so we can test only service-level
|
|
entry.TLS = structs.GatewayTLSConfig{
|
|
SDS: nil,
|
|
}
|
|
entry.Listeners = []structs.IngressListener{
|
|
// Setup http listeners, one multiple services with SDS
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
TLS: nil, // No listener level TLS setup either
|
|
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
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: s1,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s2,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s1UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s1Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s1Chain.ID() + ":" + s1UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s1"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s2UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s2Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s2Chain.ID() + ":" + s2UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s2"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGateway_MixedListeners(t testing.T) *ConfigSnapshot {
|
|
var (
|
|
s1 = structs.NewServiceName("s1", nil)
|
|
s1UID = NewUpstreamIDFromServiceName(s1)
|
|
s1Chain = discoverychain.TestCompileConfigEntries(t, "s1", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s2 = structs.NewServiceName("s2", nil)
|
|
s2UID = NewUpstreamIDFromServiceName(s2)
|
|
s2Chain = discoverychain.TestCompileConfigEntries(t, "s2", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
)
|
|
|
|
return TestConfigSnapshotIngressGateway(t, false, "tcp", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.TLS = structs.GatewayTLSConfig{
|
|
Enabled: false, // No Gateway-level built-in TLS
|
|
SDS: nil, // Undo gateway-level SDS
|
|
}
|
|
entry.Listeners = []structs.IngressListener{
|
|
// One listener has built-in TLS, one doesn't
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
TLS: &structs.GatewayTLSConfig{
|
|
Enabled: true, // built-in TLS enabled
|
|
},
|
|
Services: []structs.IngressService{
|
|
{Name: "s1"},
|
|
},
|
|
},
|
|
{
|
|
Port: 9090,
|
|
Protocol: "http",
|
|
TLS: nil, // No TLS enabled
|
|
Services: []structs.IngressService{
|
|
{Name: "s2"},
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: s1,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s2,
|
|
Port: 9090,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s1UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s1Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s1Chain.ID() + ":" + s1UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s1"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s2UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s2Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s2Chain.ID() + ":" + s2UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s2"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngress_HTTPMultipleServices(t testing.T) *ConfigSnapshot {
|
|
// We do not add baz/qux here so that we test the chain.IsDefault() case
|
|
entries := []structs.ConfigEntry{
|
|
&structs.ProxyConfigEntry{
|
|
Kind: structs.ProxyDefaults,
|
|
Name: structs.ProxyConfigGlobal,
|
|
Config: map[string]interface{}{
|
|
"protocol": "http",
|
|
},
|
|
},
|
|
&structs.ServiceResolverConfigEntry{
|
|
Kind: structs.ServiceResolver,
|
|
Name: "foo",
|
|
ConnectTimeout: 22 * time.Second,
|
|
},
|
|
&structs.ServiceResolverConfigEntry{
|
|
Kind: structs.ServiceResolver,
|
|
Name: "bar",
|
|
ConnectTimeout: 22 * time.Second,
|
|
},
|
|
}
|
|
|
|
var (
|
|
foo = structs.NewServiceName("foo", nil)
|
|
fooUID = NewUpstreamIDFromServiceName(foo)
|
|
fooChain = discoverychain.TestCompileConfigEntries(t, "foo", "default", "default", "dc1", connect.TestClusterID+".consul", nil, entries...)
|
|
|
|
bar = structs.NewServiceName("bar", nil)
|
|
barUID = NewUpstreamIDFromServiceName(bar)
|
|
barChain = discoverychain.TestCompileConfigEntries(t, "bar", "default", "default", "dc1", connect.TestClusterID+".consul", nil, entries...)
|
|
|
|
baz = structs.NewServiceName("baz", nil)
|
|
bazUID = NewUpstreamIDFromServiceName(baz)
|
|
bazChain = discoverychain.TestCompileConfigEntries(t, "baz", "default", "default", "dc1", connect.TestClusterID+".consul", nil, entries...)
|
|
|
|
qux = structs.NewServiceName("qux", nil)
|
|
quxUID = NewUpstreamIDFromServiceName(qux)
|
|
quxChain = discoverychain.TestCompileConfigEntries(t, "qux", "default", "default", "dc1", connect.TestClusterID+".consul", nil, entries...)
|
|
)
|
|
|
|
require.False(t, fooChain.IsDefault())
|
|
require.False(t, barChain.IsDefault())
|
|
require.True(t, bazChain.IsDefault())
|
|
require.True(t, quxChain.IsDefault())
|
|
|
|
return TestConfigSnapshotIngressGateway(t, false, "http", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.Listeners = []structs.IngressListener{
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{
|
|
Name: "foo",
|
|
Hosts: []string{
|
|
"test1.example.com",
|
|
"test2.example.com",
|
|
"test2.example.com:8080",
|
|
},
|
|
},
|
|
{Name: "bar"},
|
|
},
|
|
},
|
|
{
|
|
Port: 443,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "baz"},
|
|
{Name: "qux"},
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: foo,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
Hosts: []string{
|
|
"test1.example.com",
|
|
"test2.example.com",
|
|
"test2.example.com:8080",
|
|
},
|
|
},
|
|
{
|
|
Service: bar,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: baz,
|
|
Port: 443,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: qux,
|
|
Port: 443,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + fooUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: fooChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + fooChain.ID() + ":" + fooUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "foo"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + barUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: barChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + barChain.ID() + ":" + barUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "bar"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + bazUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: bazChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + bazChain.ID() + ":" + bazUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "baz"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + quxUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: quxChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + quxChain.ID() + ":" + quxUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "qux"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngress_MultipleListenersDuplicateService(t testing.T) *ConfigSnapshot {
|
|
var (
|
|
foo = structs.NewServiceName("foo", nil)
|
|
fooUID = NewUpstreamIDFromServiceName(foo)
|
|
fooChain = discoverychain.TestCompileConfigEntries(t, "foo", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
bar = structs.NewServiceName("bar", nil)
|
|
barUID = NewUpstreamIDFromServiceName(bar)
|
|
barChain = discoverychain.TestCompileConfigEntries(t, "bar", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
)
|
|
|
|
return TestConfigSnapshotIngressGateway(t, false, "http", "default", nil, func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.Listeners = []structs.IngressListener{
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "foo"},
|
|
{Name: "bar"},
|
|
},
|
|
},
|
|
{
|
|
Port: 443,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "foo"},
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: foo,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: bar,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: foo,
|
|
Port: 443,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + fooUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: fooChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + fooChain.ID() + ":" + fooUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "foo"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + barUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: barChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + barChain.ID() + ":" + barUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodesAlternate(t),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGatewayWithChain(
|
|
t testing.T,
|
|
variant string,
|
|
webEntMeta, fooEntMeta *structs.EnterpriseMeta,
|
|
) *ConfigSnapshot {
|
|
if webEntMeta == nil {
|
|
webEntMeta = &structs.EnterpriseMeta{}
|
|
}
|
|
if fooEntMeta == nil {
|
|
fooEntMeta = &structs.EnterpriseMeta{}
|
|
}
|
|
|
|
var (
|
|
updates []cache.UpdateEvent
|
|
configFn func(entry *structs.IngressGatewayConfigEntry)
|
|
|
|
populateServices bool
|
|
useSDS bool
|
|
listenerSDS, webSDS, fooSDS, wildcard bool
|
|
)
|
|
switch variant {
|
|
case "router-header-manip":
|
|
configFn = func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.Listeners = []structs.IngressListener{
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{
|
|
Name: "db",
|
|
RequestHeaders: &structs.HTTPHeaderModifiers{
|
|
Add: map[string]string{
|
|
"foo": "bar",
|
|
},
|
|
Set: map[string]string{
|
|
"bar": "baz",
|
|
},
|
|
Remove: []string{"qux"},
|
|
},
|
|
ResponseHeaders: &structs.HTTPHeaderModifiers{
|
|
Add: map[string]string{
|
|
"foo": "bar",
|
|
},
|
|
Set: map[string]string{
|
|
"bar": "baz",
|
|
},
|
|
Remove: []string{"qux"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
populateServices = true
|
|
case "sds-listener-level":
|
|
// Listener-level SDS means all services share the default route.
|
|
useSDS = true
|
|
listenerSDS = true
|
|
case "sds-listener-level-wildcard":
|
|
// Listener-level SDS means all services share the default route.
|
|
useSDS = true
|
|
listenerSDS = true
|
|
wildcard = true
|
|
case "sds-service-level":
|
|
// Services should get separate routes and no default since they all
|
|
// have custom certs.
|
|
useSDS = true
|
|
webSDS = true
|
|
fooSDS = true
|
|
case "sds-service-level-mixed-tls":
|
|
// Web needs a separate route as it has custom filter chain but foo
|
|
// should use default route for listener.
|
|
useSDS = true
|
|
webSDS = true
|
|
default:
|
|
t.Fatalf("unknown variant %q", variant)
|
|
return nil
|
|
}
|
|
|
|
if useSDS {
|
|
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: webEntMeta.NamespaceOrEmpty(),
|
|
DestinationPartition: webEntMeta.PartitionOrEmpty(),
|
|
LocalBindPort: 9191,
|
|
IngressHosts: []string{
|
|
"www.example.com",
|
|
},
|
|
}
|
|
fooUpstream := structs.Upstream{
|
|
DestinationName: "foo",
|
|
DestinationNamespace: fooEntMeta.NamespaceOrEmpty(),
|
|
DestinationPartition: fooEntMeta.PartitionOrEmpty(),
|
|
LocalBindPort: 9191,
|
|
IngressHosts: []string{
|
|
"foo.example.com",
|
|
},
|
|
}
|
|
|
|
var (
|
|
web = structs.NewServiceName("web", webEntMeta)
|
|
webUID = NewUpstreamID(&webUpstream)
|
|
|
|
foo = structs.NewServiceName("foo", fooEntMeta)
|
|
fooUID = NewUpstreamID(&fooUpstream)
|
|
)
|
|
|
|
configFn = func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.TLS.SDS = nil
|
|
il := structs.IngressListener{
|
|
Port: 9191,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{
|
|
Name: "web",
|
|
Hosts: []string{"www.example.com"},
|
|
EnterpriseMeta: *webEntMeta,
|
|
},
|
|
{
|
|
Name: "foo",
|
|
Hosts: []string{"foo.example.com"},
|
|
EnterpriseMeta: *fooEntMeta,
|
|
},
|
|
},
|
|
}
|
|
|
|
// Now set the appropriate SDS configs
|
|
if listenerSDS {
|
|
il.TLS = &structs.GatewayTLSConfig{
|
|
SDS: &structs.GatewayTLSSDSConfig{
|
|
ClusterName: "listener-cluster",
|
|
CertResource: "listener-cert",
|
|
},
|
|
}
|
|
}
|
|
if webSDS {
|
|
il.Services[0].TLS = &structs.GatewayServiceTLSConfig{
|
|
SDS: &structs.GatewayTLSSDSConfig{
|
|
ClusterName: "web-cluster",
|
|
CertResource: "www-cert",
|
|
},
|
|
}
|
|
}
|
|
if fooSDS {
|
|
il.Services[1].TLS = &structs.GatewayServiceTLSConfig{
|
|
SDS: &structs.GatewayTLSSDSConfig{
|
|
ClusterName: "foo-cluster",
|
|
CertResource: "foo-cert",
|
|
},
|
|
}
|
|
}
|
|
if 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: "*",
|
|
},
|
|
}
|
|
}
|
|
entry.Listeners = []structs.IngressListener{il}
|
|
}
|
|
|
|
if wildcard {
|
|
// We also don't support user-specified hosts with wildcard so remove
|
|
// those from the upstreams.
|
|
webUpstream.IngressHosts = nil
|
|
fooUpstream.IngressHosts = nil
|
|
}
|
|
|
|
entries := []structs.ConfigEntry{
|
|
&structs.ProxyConfigEntry{
|
|
Kind: structs.ProxyDefaults,
|
|
Name: structs.ProxyConfigGlobal,
|
|
Config: map[string]interface{}{
|
|
"protocol": "http",
|
|
},
|
|
},
|
|
&structs.ServiceResolverConfigEntry{
|
|
Kind: structs.ServiceResolver,
|
|
Name: "web",
|
|
EnterpriseMeta: *webEntMeta,
|
|
ConnectTimeout: 22 * time.Second,
|
|
},
|
|
&structs.ServiceResolverConfigEntry{
|
|
Kind: structs.ServiceResolver,
|
|
Name: "foo",
|
|
EnterpriseMeta: *fooEntMeta,
|
|
ConnectTimeout: 22 * time.Second,
|
|
},
|
|
}
|
|
|
|
webChain := discoverychain.TestCompileConfigEntries(t, "web",
|
|
webEntMeta.NamespaceOrDefault(),
|
|
webEntMeta.PartitionOrDefault(), "dc1",
|
|
connect.TestClusterID+".consul", nil, entries...)
|
|
fooChain := discoverychain.TestCompileConfigEntries(t, "foo",
|
|
fooEntMeta.NamespaceOrDefault(),
|
|
fooEntMeta.PartitionOrDefault(), "dc1",
|
|
connect.TestClusterID+".consul", nil, entries...)
|
|
|
|
updates = []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: web,
|
|
Port: 9191,
|
|
Protocol: "http",
|
|
Hosts: webUpstream.IngressHosts,
|
|
},
|
|
{
|
|
Service: foo,
|
|
Port: 9191,
|
|
Protocol: "http",
|
|
Hosts: fooUpstream.IngressHosts,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + webUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: webChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + fooUID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: fooChain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + webChain.ID() + ":" + webUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "web"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + fooChain.ID() + ":" + fooUID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "foo"),
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
return TestConfigSnapshotIngressGateway(t, populateServices, "http", "chain-and-router", nil, configFn, updates)
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGateway_TLSMinVersionListenersGatewayDefaults(t testing.T) *ConfigSnapshot {
|
|
var (
|
|
s1 = structs.NewServiceName("s1", nil)
|
|
s1UID = NewUpstreamIDFromServiceName(s1)
|
|
s1Chain = discoverychain.TestCompileConfigEntries(t, "s1", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s2 = structs.NewServiceName("s2", nil)
|
|
s2UID = NewUpstreamIDFromServiceName(s2)
|
|
s2Chain = discoverychain.TestCompileConfigEntries(t, "s2", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s3 = structs.NewServiceName("s3", nil)
|
|
s3UID = NewUpstreamIDFromServiceName(s3)
|
|
s3Chain = discoverychain.TestCompileConfigEntries(t, "s3", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s4 = structs.NewServiceName("s4", nil)
|
|
s4UID = NewUpstreamIDFromServiceName(s4)
|
|
s4Chain = discoverychain.TestCompileConfigEntries(t, "s4", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
)
|
|
|
|
return TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil,
|
|
func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.TLS.Enabled = true
|
|
entry.TLS.TLSMinVersion = types.TLSv1_2
|
|
|
|
// One listener disables TLS, one inherits TLS minimum version from the gateway
|
|
// config, two others set different versions
|
|
entry.Listeners = []structs.IngressListener{
|
|
// Omits listener TLS config, should default to gateway TLS config
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s1"},
|
|
},
|
|
},
|
|
// Explicitly sets listener TLS config to nil, should default to gateway TLS config
|
|
{
|
|
Port: 8081,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s2"},
|
|
},
|
|
TLS: nil,
|
|
},
|
|
// Explicitly enables TLS config, but with no listener default TLS params,
|
|
// should default to gateway TLS config
|
|
{
|
|
Port: 8082,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s3"},
|
|
},
|
|
TLS: &structs.GatewayTLSConfig{
|
|
Enabled: true,
|
|
},
|
|
},
|
|
// Explicitly unset gateway default TLS min version in favor of proxy default
|
|
{
|
|
Port: 8083,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s3"},
|
|
},
|
|
TLS: &structs.GatewayTLSConfig{
|
|
Enabled: true,
|
|
TLSMinVersion: types.TLSVersionAuto,
|
|
},
|
|
},
|
|
// Disables listener TLS
|
|
{
|
|
Port: 8084,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s4"},
|
|
},
|
|
TLS: &structs.GatewayTLSConfig{
|
|
Enabled: false,
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
// One listener disables TLS, one inherits TLS minimum version from the gateway
|
|
// config, two others set different versions
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: s1,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s2,
|
|
Port: 8081,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s3,
|
|
Port: 8082,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s4,
|
|
Port: 8083,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s4,
|
|
Port: 8084,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s1UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s1Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s2UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s2Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s3UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s3Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s4UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s4Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s1Chain.ID() + ":" + s1UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s1"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s2Chain.ID() + ":" + s2UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s2"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s3Chain.ID() + ":" + s3UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s3"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s4Chain.ID() + ":" + s4UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s4"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGateway_SingleTLSListener(t testing.T) *ConfigSnapshot {
|
|
var (
|
|
s1 = structs.NewServiceName("s1", nil)
|
|
s1UID = NewUpstreamIDFromServiceName(s1)
|
|
s1Chain = discoverychain.TestCompileConfigEntries(t, "s1", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s2 = structs.NewServiceName("s2", nil)
|
|
s2UID = NewUpstreamIDFromServiceName(s2)
|
|
s2Chain = discoverychain.TestCompileConfigEntries(t, "s2", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
)
|
|
return TestConfigSnapshotIngressGateway(t, true, "tcp", "simple", nil,
|
|
func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.Listeners = []structs.IngressListener{
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s1"},
|
|
},
|
|
},
|
|
{
|
|
Port: 8081,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s2"},
|
|
},
|
|
TLS: &structs.GatewayTLSConfig{
|
|
Enabled: true,
|
|
TLSMinVersion: types.TLSv1_2,
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
// One listener should inherit non-TLS gateway config, another
|
|
// listener configures TLS with an explicit minimum version
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: s1,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s2,
|
|
Port: 8081,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s1UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s1Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s2UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s2Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s1Chain.ID() + ":" + s1UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s1"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s2Chain.ID() + ":" + s2UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s2"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestConfigSnapshotIngressGateway_TLSMixedMinVersionListeners(t testing.T) *ConfigSnapshot {
|
|
var (
|
|
s1 = structs.NewServiceName("s1", nil)
|
|
s1UID = NewUpstreamIDFromServiceName(s1)
|
|
s1Chain = discoverychain.TestCompileConfigEntries(t, "s1", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s2 = structs.NewServiceName("s2", nil)
|
|
s2UID = NewUpstreamIDFromServiceName(s2)
|
|
s2Chain = discoverychain.TestCompileConfigEntries(t, "s2", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
|
|
s3 = structs.NewServiceName("s3", nil)
|
|
s3UID = NewUpstreamIDFromServiceName(s3)
|
|
s3Chain = discoverychain.TestCompileConfigEntries(t, "s3", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
|
)
|
|
|
|
return TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil,
|
|
func(entry *structs.IngressGatewayConfigEntry) {
|
|
entry.TLS.Enabled = true
|
|
entry.TLS.TLSMinVersion = types.TLSv1_2
|
|
|
|
// One listener disables TLS, one inherits TLS minimum version from the gateway
|
|
// config, two others set different versions
|
|
entry.Listeners = []structs.IngressListener{
|
|
{
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s1"},
|
|
},
|
|
},
|
|
{
|
|
Port: 8081,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s2"},
|
|
},
|
|
TLS: &structs.GatewayTLSConfig{
|
|
Enabled: true,
|
|
TLSMinVersion: types.TLSv1_0,
|
|
},
|
|
},
|
|
{
|
|
Port: 8082,
|
|
Protocol: "http",
|
|
Services: []structs.IngressService{
|
|
{Name: "s3"},
|
|
},
|
|
TLS: &structs.GatewayTLSConfig{
|
|
Enabled: true,
|
|
TLSMinVersion: types.TLSv1_3,
|
|
},
|
|
},
|
|
}
|
|
}, []cache.UpdateEvent{
|
|
{
|
|
CorrelationID: gatewayServicesWatchID,
|
|
Result: &structs.IndexedGatewayServices{
|
|
// One listener should inherit TLS minimum version from the gateway config,
|
|
// two others each set explicit TLS minimum versions
|
|
Services: []*structs.GatewayService{
|
|
{
|
|
Service: s1,
|
|
Port: 8080,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s2,
|
|
Port: 8081,
|
|
Protocol: "http",
|
|
},
|
|
{
|
|
Service: s3,
|
|
Port: 8082,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s1UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s1Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s2UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s2Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "discovery-chain:" + s3UID.String(),
|
|
Result: &structs.DiscoveryChainResponse{
|
|
Chain: s3Chain,
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s1Chain.ID() + ":" + s1UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s1"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s2Chain.ID() + ":" + s2UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s2"),
|
|
},
|
|
},
|
|
{
|
|
CorrelationID: "upstream-target:" + s3Chain.ID() + ":" + s3UID.String(),
|
|
Result: &structs.IndexedCheckServiceNodes{
|
|
Nodes: TestUpstreamNodes(t, "s3"),
|
|
},
|
|
},
|
|
})
|
|
}
|