mirror of https://github.com/hashicorp/consul
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1603 lines
43 KiB
1603 lines
43 KiB
package proxycfg |
|
|
|
import ( |
|
"time" |
|
|
|
"github.com/mitchellh/go-testing-interface" |
|
"github.com/stretchr/testify/require" |
|
|
|
"github.com/hashicorp/consul/acl" |
|
"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 []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 := []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, []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"}, |
|
}, |
|
}, |
|
} |
|
}, []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", |
|
}, |
|
}, |
|
}, |
|
} |
|
}, []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", |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
} |
|
}, []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 |
|
}, |
|
}, |
|
}, |
|
} |
|
}, []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 |
|
}, |
|
}, |
|
}, |
|
} |
|
}, []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"}, |
|
}, |
|
}, |
|
} |
|
}, []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.Default) |
|
require.False(t, barChain.Default) |
|
require.True(t, bazChain.Default) |
|
require.True(t, quxChain.Default) |
|
|
|
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"}, |
|
}, |
|
}, |
|
} |
|
}, []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_GRPCMultipleServices(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...) |
|
) |
|
|
|
require.False(t, fooChain.Default) |
|
require.False(t, barChain.Default) |
|
|
|
return TestConfigSnapshotIngressGateway(t, false, "http", "default", nil, func(entry *structs.IngressGatewayConfigEntry) { |
|
entry.Listeners = []structs.IngressListener{ |
|
{ |
|
Port: 8080, |
|
Protocol: "grpc", |
|
Services: []structs.IngressService{ |
|
{ |
|
Name: "foo", |
|
Hosts: []string{ |
|
"test1.example.com", |
|
"test2.example.com", |
|
"test2.example.com:8080", |
|
}, |
|
}, |
|
{Name: "bar"}, |
|
}, |
|
}, |
|
} |
|
}, []UpdateEvent{ |
|
{ |
|
CorrelationID: gatewayServicesWatchID, |
|
Result: &structs.IndexedGatewayServices{ |
|
Services: []*structs.GatewayService{ |
|
{ |
|
Service: foo, |
|
Port: 8080, |
|
Protocol: "grpc", |
|
Hosts: []string{ |
|
"test1.example.com", |
|
"test2.example.com", |
|
"test2.example.com:8080", |
|
}, |
|
}, |
|
{ |
|
Service: bar, |
|
Port: 8080, |
|
Protocol: "grpc", |
|
}, |
|
}, |
|
}, |
|
}, |
|
{ |
|
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"), |
|
}, |
|
}, |
|
}) |
|
} |
|
|
|
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"}, |
|
}, |
|
}, |
|
} |
|
}, []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 *acl.EnterpriseMeta, |
|
) *ConfigSnapshot { |
|
if webEntMeta == nil { |
|
webEntMeta = &acl.EnterpriseMeta{} |
|
} |
|
if fooEntMeta == nil { |
|
fooEntMeta = &acl.EnterpriseMeta{} |
|
} |
|
|
|
var ( |
|
updates []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 = []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, |
|
}, |
|
}, |
|
} |
|
}, []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, |
|
}, |
|
}, |
|
} |
|
}, []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, |
|
}, |
|
}, |
|
} |
|
}, []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"), |
|
}, |
|
}, |
|
}) |
|
}
|
|
|