Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions internal/xds/translator/globalresources.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"google.golang.org/protobuf/types/known/anypb"

"github.com/envoyproxy/gateway/internal/ir"
"github.com/envoyproxy/gateway/internal/utils/cert"
"github.com/envoyproxy/gateway/internal/xds/types"
)

Expand All @@ -25,15 +26,17 @@ const (
wasmHTTPServiceClusterName = "wasm_cluster"
wasmHTTPServiceHost = "envoy-gateway"
wasmHTTPServicePort = 18002

// SystemTrustStoreSecretName is the shared SDS secret name for the system CA trust store.
SystemTrustStoreSecretName = "system_ca_certificates" //nolint:gosec // not a credential
)

// patchGlobalResources builds and appends the global resources that are shared across listeners and routes.
// for example, the envoy client certificate and the OIDC HMAC secret.
// patchGlobalResources builds and appends global resources shared across listeners and routes.
func (t *Translator) patchGlobalResources(tCtx *types.ResourceVersionTable, irXds *ir.Xds) error {
var errs error

if irXds.GlobalResources != nil && irXds.GlobalResources.EnvoyClientCertificate != nil {
// Create the envoy client TLS secret. It is used for envoy to establish a TLS connection with control plane components.
// Create the envoy client TLS secret for control plane connections (rate limit, wasm).
if err := createEnvoyClientTLSCertSecret(tCtx, irXds.GlobalResources); err != nil {
errs = errors.Join(errs, err)
}
Expand Down Expand Up @@ -66,6 +69,37 @@ func containsGlobalRateLimit(httpListeners []*ir.HTTPListener) bool {
return false
}

// ensureSystemTrustStoreSecret creates the shared system trust store SDS secret if not yet present.
func ensureSystemTrustStoreSecret(tCtx *types.ResourceVersionTable) error {
if findXdsSecret(tCtx, SystemTrustStoreSecretName) != nil {
return nil
}
return tCtx.AddXdsResource(resourcev3.SecretType, &tlsv3.Secret{
Name: SystemTrustStoreSecretName,
Type: &tlsv3.Secret_ValidationContext{
ValidationContext: &tlsv3.CertificateValidationContext{
TrustedCa: &corev3.DataSource{
Specifier: &corev3.DataSource_Filename{Filename: cert.SystemCertPath},
},
},
},
})
}

// validateSystemTrustStoreSecret verifies system_ca_certificates has expected content if present.
// Called once at end of Translate() to catch conflicts from EnvoyPatchPolicy or extensions.
func validateSystemTrustStoreSecret(tCtx *types.ResourceVersionTable) error {
existing := findXdsSecret(tCtx, SystemTrustStoreSecretName)
if existing == nil {
return nil
}
vc := existing.GetValidationContext()
if vc == nil || vc.GetTrustedCa().GetFilename() != cert.SystemCertPath {
Comment on lines +93 to +97

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject missing or mutated shared trust-store secret

When an EnvoyPatchPolicy or post-translation extension renames/removes the generated system_ca_certificates secret, every cluster that used WellKnownCACertificates: System still references that SDS name, but this validation returns success because findXdsSecret no longer finds it. If the patch leaves the filename intact while adding other fields to the validation context, it also passes. In those patch/extension cases translation succeeds with clusters pointing at a missing or globally altered trust-store secret instead of surfacing the reserved-name error.

Useful? React with 👍 / 👎.

return fmt.Errorf("secret name %q is reserved for the system trust store and cannot be used by other resources", SystemTrustStoreSecretName)
}
return nil
}
Comment on lines +91 to +101

func createEnvoyClientTLSCertSecret(tCtx *types.ResourceVersionTable, globalResources *ir.GlobalResources) error {
if err := tCtx.AddXdsResource(
resourcev3.SecretType,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
http:
- address: 0.0.0.0
hostnames:
- '*'
name: envoy-gateway/gateway-btls/http
path:
escapedSlashesAction: UnescapeAndRedirect
mergeSlashes: true
port: 10080
routes:
- destination:
name: httproute/envoy-gateway/httproute-btls-1/rule/0
settings:
- addressType: IP
endpoints:
- host: 10.244.0.11
port: 8080
protocol: HTTP
tls:
CACertificate:
name: policy-btls-1/policies-ca
sni: backend-1.example.com
useSystemTrustStore: true
weight: 1
name: httproute/envoy-gateway/httproute-btls-1/rule/0/backend/0
hostname: '*'
name: httproute/envoy-gateway/httproute-btls-1/rule/0/match/0/*
pathMatch:
distinct: false
exact: /backend-1
name: ""
- destination:
name: httproute/envoy-gateway/httproute-btls-2/rule/0
settings:
- addressType: IP
endpoints:
- host: 10.244.0.12
port: 8080
protocol: HTTP
tls:
CACertificate:
name: policy-btls-2/policies-ca
sni: backend-2.example.com
useSystemTrustStore: true
weight: 1
name: httproute/envoy-gateway/httproute-btls-2/rule/0/backend/0
hostname: '*'
name: httproute/envoy-gateway/httproute-btls-2/rule/0/match/0/*
pathMatch:
distinct: false
exact: /backend-2
name: ""
- destination:
name: httproute/envoy-gateway/httproute-btls-3/rule/0
settings:
- addressType: IP
endpoints:
- host: 10.244.0.13
port: 8080
protocol: HTTP
tls:
CACertificate:
name: policy-btls-3/policies-ca
sni: backend-3.example.com
useSystemTrustStore: true
weight: 1
name: httproute/envoy-gateway/httproute-btls-3/rule/0/backend/0
hostname: '*'
name: httproute/envoy-gateway/httproute-btls-3/rule/0/match/0/*
pathMatch:
distinct: false
exact: /backend-3
name: ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- name: system_ca_certificates
validationContext:
trustedCa:
filename: /etc/ssl/certs/ca-certificates.crt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
exact: subdomain.secondexample.com
sanType: DNS
validationContextSdsSecretConfig:
name: policy-btls-for-backend-1/default-ca
name: system_ca_certificates
sdsConfig:
ads: {}
resourceApiVersion: V3
Expand Down Expand Up @@ -210,7 +210,7 @@
exact: example.com
sanType: DNS
validationContextSdsSecretConfig:
name: policy-btls-for-backend-3/default-ca
name: system_ca_certificates
sdsConfig:
ads: {}
resourceApiVersion: V3
Expand Down Expand Up @@ -289,7 +289,7 @@
exact: example.com
sanType: DNS
validationContextSdsSecretConfig:
name: policy-btls-for-backend-4/default-ca
name: system_ca_certificates
sdsConfig:
ads: {}
resourceApiVersion: V3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,11 @@
inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKRENDQWd5Z0F3SUJBZ0lVU3JTYktMZjBiTEVHb2dXeC9nQ3cyR0N0dnhFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0V6RVJNQThHQTFVRUF3d0lWR1Z6ZENCSmJtTXdIaGNOTWpRd01qSTVNRGt6TURFd1doY05NelF3TWpJMgpNRGt6TURFd1dqQVRNUkV3RHdZRFZRUUREQWhVWlhOMElFbHVZekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBSzFKempQSWlXZzNxb0hTckFkZGtlSmphTVA5aXlNVGkvQlBvOWNKUG9SRThaaTcKV2FwVXJYTC85QTlyK2pITXlHSVpOWk5kY1o1Y1kyWHYwTFA4WnhWeTJsazArM3d0WXpIbnBHWUdWdHlxMnRldApEaEZzaVBsODJZUmpDMG16V2E0UU16NFNYekZITmdJRHBSZGhmcm92bXNldVdHUUU4cFY0VWQ5VUsvU0tpbE1PCnF0QjVKaXJMUDJWczVUMW9XaWNXTFF2ZmJHd3Y3c0ZEZHI5YkcwWHRTUXAxN0hTZ281MFNERTUrQmpTbXB0RncKMVZjS0xscWFoTVhCRERpb3Jnd2hJaEdHS3BFU2VNMFA3YkZoVm1rTTNhc2gyeFNUQnVGVUJEbEU0Sk9haHp3cwpEWHJ1cFVoRGRTMWhkYzJmUHJqaEZBbEpmV0VZWjZCbFpqeXNpVlVDQXdFQUFhTndNRzR3SFFZRFZSME9CQllFCkZCUXVmSzFMaWJ1Vm05VHMvVmpCeDhMM3VpTmVNQjhHQTFVZEl3UVlNQmFBRkJRdWZLMUxpYnVWbTlUcy9WakIKeDhMM3VpTmVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdHd1lEVlIwUkJCUXdFb0lCS29JTktpNWxlR0Z0Y0d4bApMbU52YlRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWZQUzQxYWdldldNVjNaWHQwQ09GRzN1WWZQRlhuVnc2ClA0MXA5TzZHa2RZc3VxRnZQZVR5eUgyL2RBSUtLd1N6TS9wdGhnOEtuOExabG1KeUZObkExc3RKeG41WGRiVjEKcFBxajhVdllDQnp5ak1JcW1SeW9peUxpUWxib2hNYTBVZEVCS2NIL1BkTEU5SzhUR0pyWmdvR1hxcTFXbWl0RAozdmNQalNlUEtFaVVKVlM5bENoeVNzMEtZNUIraFVRRDBKajZucEZENFprMHhxZHhoMHJXdWVDcXE3dmpxRVl6CnBqNFB3cnVmbjFQQlRtZnhNdVYvVUpWNWViaWtldVpQMzVrV3pMUjdaV0FMN3d1RGRXcC82bzR5azNRTGFuRFEKQ3dnQ0ZjWCtzcyswVnl1TTNZZXJUT1VVOFFWSkp4NFVaQU5aeDYrNDNwZEpaT2NudFBaNENBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
privateKey:
inlineBytes: W3JlZGFjdGVkXQ==
- name: policy-btls-for-backend-1/default-ca
- name: system_ca_certificates
validationContext:
trustedCa:
filename: /etc/ssl/certs/ca-certificates.crt
- name: backend-2/default-ca
validationContext:
trustedCa:
inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
- name: policy-btls-for-backend-3/default-ca
validationContext:
trustedCa:
filename: /etc/ssl/certs/ca-certificates.crt
- name: policy-btls-for-backend-4/default-ca
validationContext:
trustedCa:
filename: /etc/ssl/certs/ca-certificates.crt
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
combinedValidationContext:
defaultValidationContext: {}
validationContextSdsSecretConfig:
name: backend-with-system-ca/default-ca
name: system_ca_certificates
sdsConfig:
ads: {}
resourceApiVersion: V3
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- name: backend-with-system-ca/default-ca
- name: system_ca_certificates
validationContext:
trustedCa:
filename: /etc/ssl/certs/ca-certificates.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
- circuitBreakers:
thresholds:
- maxRetries: 1024
commonLbConfig: {}
connectTimeout: 10s
dnsLookupFamily: V4_PREFERRED
edsClusterConfig:
edsConfig:
ads: {}
resourceApiVersion: V3
serviceName: httproute/envoy-gateway/httproute-btls-1/rule/0
ignoreHealthOnHostRemoval: true
loadBalancingPolicy:
policies:
- typedExtensionConfig:
name: envoy.load_balancing_policies.least_request
typedConfig:
'@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
localityLbConfig:
localityWeightedLbConfig: {}
name: httproute/envoy-gateway/httproute-btls-1/rule/0
perConnectionBufferLimitBytes: 32768
transportSocket:
name: dummy.transport_socket
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
commonTlsContext: {}
transportSocketMatches:
- match:
name: httproute/envoy-gateway/httproute-btls-1/rule/0/tls/0
name: httproute/envoy-gateway/httproute-btls-1/rule/0/tls/0
transportSocket:
name: envoy.transport_sockets.tls
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
commonTlsContext:
combinedValidationContext:
defaultValidationContext:
matchTypedSubjectAltNames:
- matcher:
exact: backend-1.example.com
sanType: DNS
validationContextSdsSecretConfig:
name: system_ca_certificates
sdsConfig:
ads: {}
resourceApiVersion: V3
sni: backend-1.example.com
type: EDS
typedExtensionProtocolOptions:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
'@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
autoConfig:
http2ProtocolOptions:
initialConnectionWindowSize: 1048576
initialStreamWindowSize: 65536
httpProtocolOptions: {}
- circuitBreakers:
thresholds:
- maxRetries: 1024
commonLbConfig: {}
connectTimeout: 10s
dnsLookupFamily: V4_PREFERRED
edsClusterConfig:
edsConfig:
ads: {}
resourceApiVersion: V3
serviceName: httproute/envoy-gateway/httproute-btls-2/rule/0
ignoreHealthOnHostRemoval: true
loadBalancingPolicy:
policies:
- typedExtensionConfig:
name: envoy.load_balancing_policies.least_request
typedConfig:
'@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
localityLbConfig:
localityWeightedLbConfig: {}
name: httproute/envoy-gateway/httproute-btls-2/rule/0
perConnectionBufferLimitBytes: 32768
transportSocket:
name: dummy.transport_socket
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
commonTlsContext: {}
transportSocketMatches:
- match:
name: httproute/envoy-gateway/httproute-btls-2/rule/0/tls/0
name: httproute/envoy-gateway/httproute-btls-2/rule/0/tls/0
transportSocket:
name: envoy.transport_sockets.tls
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
commonTlsContext:
combinedValidationContext:
defaultValidationContext:
matchTypedSubjectAltNames:
- matcher:
exact: backend-2.example.com
sanType: DNS
validationContextSdsSecretConfig:
name: system_ca_certificates
sdsConfig:
ads: {}
resourceApiVersion: V3
sni: backend-2.example.com
type: EDS
typedExtensionProtocolOptions:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
'@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
autoConfig:
http2ProtocolOptions:
initialConnectionWindowSize: 1048576
initialStreamWindowSize: 65536
httpProtocolOptions: {}
- circuitBreakers:
thresholds:
- maxRetries: 1024
commonLbConfig: {}
connectTimeout: 10s
dnsLookupFamily: V4_PREFERRED
edsClusterConfig:
edsConfig:
ads: {}
resourceApiVersion: V3
serviceName: httproute/envoy-gateway/httproute-btls-3/rule/0
ignoreHealthOnHostRemoval: true
loadBalancingPolicy:
policies:
- typedExtensionConfig:
name: envoy.load_balancing_policies.least_request
typedConfig:
'@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
localityLbConfig:
localityWeightedLbConfig: {}
name: httproute/envoy-gateway/httproute-btls-3/rule/0
perConnectionBufferLimitBytes: 32768
transportSocket:
name: dummy.transport_socket
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
commonTlsContext: {}
transportSocketMatches:
- match:
name: httproute/envoy-gateway/httproute-btls-3/rule/0/tls/0
name: httproute/envoy-gateway/httproute-btls-3/rule/0/tls/0
transportSocket:
name: envoy.transport_sockets.tls
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
commonTlsContext:
combinedValidationContext:
defaultValidationContext:
matchTypedSubjectAltNames:
- matcher:
exact: backend-3.example.com
sanType: DNS
validationContextSdsSecretConfig:
name: system_ca_certificates
sdsConfig:
ads: {}
resourceApiVersion: V3
sni: backend-3.example.com
type: EDS
typedExtensionProtocolOptions:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
'@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
autoConfig:
http2ProtocolOptions:
initialConnectionWindowSize: 1048576
initialStreamWindowSize: 65536
httpProtocolOptions: {}
Loading
Loading