Simple API Gateway e2e test for tcp routes (#16222)

* Simple API Gateway e2e test for tcp routes

* Drop DNSSans since we don't front the Gateway with a leaf cert
This commit is contained in:
Andrew Stucki 2023-02-09 16:20:12 -05:00 committed by GitHub
parent db2bd404bf
commit 3b9c569561
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 57 additions and 12 deletions

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
cachetype "github.com/hashicorp/consul/agent/cache-types"
"github.com/hashicorp/consul/agent/proxycfg/internal/watch"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/proto/pbpeering"
@ -225,7 +226,7 @@ func (h *handlerAPIGateway) handleGatewayConfigUpdate(ctx context.Context, u Upd
return fmt.Errorf("invalid type for config entry: %T", resp.Entry)
}
return nil
return h.watchIngressLeafCert(ctx, snap)
}
// handleInlineCertConfigUpdate stores the certificate for the gateway
@ -416,7 +417,7 @@ func (h *handlerAPIGateway) handleRouteConfigUpdate(ctx context.Context, u Updat
//
// TODO This would probably be more generally useful as a helper in the structs pkg
func (h *handlerAPIGateway) referenceIsForListener(ref structs.ResourceReference, listener structs.APIGatewayListener, snap *ConfigSnapshot) bool {
if ref.Kind != snap.APIGateway.GatewayConfig.Kind {
if ref.Kind != structs.APIGateway && ref.Kind != "" {
return false
}
if ref.Name != snap.APIGateway.GatewayConfig.Name {
@ -424,3 +425,30 @@ func (h *handlerAPIGateway) referenceIsForListener(ref structs.ResourceReference
}
return ref.SectionName == "" || ref.SectionName == listener.Name
}
func (h *handlerAPIGateway) watchIngressLeafCert(ctx context.Context, snap *ConfigSnapshot) error {
// Note that we DON'T test for TLS.enabled because we need a leaf cert for the
// gateway even without TLS to use as a client cert.
if !snap.APIGateway.GatewayConfigLoaded {
return nil
}
// Watch the leaf cert
if snap.APIGateway.LeafCertWatchCancel != nil {
snap.APIGateway.LeafCertWatchCancel()
}
ctx, cancel := context.WithCancel(ctx)
err := h.dataSources.LeafCertificate.Notify(ctx, &cachetype.ConnectCALeafRequest{
Datacenter: h.source.Datacenter,
Token: h.token,
Service: h.service,
EnterpriseMeta: h.proxyID.EnterpriseMeta,
}, leafWatchID, h.ch)
if err != nil {
cancel()
return err
}
snap.APIGateway.LeafCertWatchCancel = cancel
return nil
}

View File

@ -678,6 +678,10 @@ type configSnapshotAPIGateway struct {
TCPRoutes watch.Map[structs.ResourceReference, *structs.TCPRouteConfigEntry]
Certificates watch.Map[structs.ResourceReference, *structs.InlineCertificateConfigEntry]
// LeafCertWatchCancel is a CancelFunc to use when refreshing this gateway's
// leaf cert watch with different parameters.
LeafCertWatchCancel context.CancelFunc
// Listeners is the original listener config from the api-gateway config
// entry to save us trying to pass fields through Upstreams
Listeners map[string]structs.APIGatewayListener
@ -733,6 +737,7 @@ func (c *configSnapshotAPIGateway) ToIngress(datacenter string) (configSnapshotI
upstreams.DiscoveryChain = synthesizedChains
return configSnapshotIngressGateway{
Upstreams: c.Upstreams,
ConfigSnapshotUpstreams: upstreams,
GatewayConfigLoaded: true,
Listeners: ingressListeners,
@ -928,6 +933,7 @@ func (s *ConfigSnapshot) Valid() bool {
case structs.ServiceKindAPIGateway:
// TODO Is this the proper set of things to validate?
return s.Roots != nil &&
s.APIGateway.Leaf != nil &&
s.APIGateway.GatewayConfigLoaded &&
s.APIGateway.BoundGatewayConfigLoaded &&
s.APIGateway.AreHostsSet &&

View File

@ -1,7 +0,0 @@
#!/usr/bin/env bats
load helpers
@test "api gateway proxy admin is up on :20000" {
retry_default curl -f -s localhost:20000/stats -o /dev/null
}

View File

@ -23,6 +23,7 @@ services = [
]
parents = [
{
kind = "api-gateway"
name = "api-gateway"
}
]

View File

@ -0,0 +1,17 @@
#!/usr/bin/env bats
load helpers
@test "api gateway proxy admin is up on :20000" {
retry_default curl -f -s localhost:20000/stats -o /dev/null
}
@test "api gateway should have healthy endpoints for s1" {
assert_upstream_has_endpoints_in_status 127.0.0.1:20000 s1 HEALTHY 1
}
@test "api gateway should be able to connect to s1 via configured port" {
run retry_default curl -s -f -d hello localhost:9999
[ "$status" -eq 0 ]
[[ "$output" == *"hello"* ]]
}