Skip to content
Merged
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
20 changes: 20 additions & 0 deletions internal/infrastructure/common/proxy_jwt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

package common

import "fmt"

const (
// #nosec G101 - This is a file path, not a credential
SdsServiceAccountTokenFilename = "xds_service_account_token.json"
)

func GetSdsServiceAccountTokenConfigMapData(tokenPath string) string {
return fmt.Sprintf(`{"resources":[{`+
`"@type":"type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret",`+
`"name":"jwt-sa-bearer",`+
`"generic_secret":{"secret":{"filename":"%s"}}}]}`, tokenPath)
}
8 changes: 8 additions & 0 deletions internal/infrastructure/kubernetes/proxy/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ func expectedProxyContainers(infra *ir.ProxyInfra,
TopologyInjectorDisabled: topologyInjectorDisabled,
}

if gatewayNamespaceMode {
bootstrapConfigOptions.SdsConfig.ServiceAccountToken = filepath.Join("/sds", common.SdsServiceAccountTokenFilename)
}

args, err := common.BuildProxyArgs(infra, shutdownConfig, bootstrapConfigOptions, fmt.Sprintf("$(%s)", envoyPodEnvVar), gatewayNamespaceMode)
if err != nil {
return nil, err
Expand Down Expand Up @@ -400,6 +404,10 @@ func sdsConfigMapItems(gatewayNamespaceMode bool) []corev1.KeyToPath {
Key: common.SdsCAFilename,
Path: common.SdsCAFilename,
},
{
Key: common.SdsServiceAccountTokenFilename,
Path: common.SdsServiceAccountTokenFilename,
},
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ import (
)

const (
// XdsServiceAccountTokenFilepath is the fully qualified path of the file containing
// the service account token used for authentication in GatewayNamespaceMode.
// #nosec G101 - This is a file path, not a credential
XdsServiceAccountTokenFilepath = "/var/run/secrets/token/sa-token"
// XdsTLSCertFilepath is the fully qualified path of the file containing Envoy's
// xDS server TLS certificate.
XdsTLSCertFilepath = "/certs/tls.crt"
Expand Down Expand Up @@ -319,6 +323,11 @@ func (r *ResourceRender) ConfigMap(cert string) (*corev1.ConfigMap, error) {
common.SdsCAFilename: common.GetSdsCAConfigMapData(XdsTLSCaFilepath),
common.SdsCertFilename: common.GetSdsCertConfigMapData(XdsTLSCertFilepath, XdsTLSKeyFilepath),
}

if r.GatewayNamespaceMode {
data[common.SdsServiceAccountTokenFilename] = common.GetSdsServiceAccountTokenConfigMapData(XdsServiceAccountTokenFilepath)
}

if cert != "" {
data[XdsTLSCaFileName] = cert
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ apiVersion: v1
data:
xds-certificate.json: '{"resources":[{"@type":"type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret","name":"xds_certificate","tls_certificate":{"certificate_chain":{"filename":"/certs/tls.crt"},"private_key":{"filename":"/certs/tls.key"}}}]}'
xds-trusted-ca.json: '{"resources":[{"@type":"type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret","name":"xds_trusted_ca","validation_context":{"trusted_ca":{"filename":"/certs/ca.crt"},"match_typed_subject_alt_names":[{"san_type":"DNS","matcher":{"exact":"envoy-gateway"}}]}}]}'
xds_service_account_token.json: '{"resources":[{"@type":"type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret","name":"jwt-sa-bearer","generic_secret":{"secret":{"filename":"/var/run/secrets/token/sa-token"}}}]}'
kind: ConfigMap
metadata:
creationTimestamp: null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ spec:
"@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic
credential:
name: jwt-sa-bearer
sds_config:
path_config_source:
path: /sds/xds_service_account_token.json
resource_api_version: V3
overwrite: true
- name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec
typed_config:
Expand All @@ -197,11 +201,6 @@ spec:
path_config_source:
path: /sds/xds-trusted-ca.json
resource_api_version: V3
secrets:
- name: jwt-sa-bearer
generic_secret:
secret:
filename: "/var/run/secrets/token/sa-token"
overload_manager:
refresh_interval: 0.25s
resource_monitors:
Expand Down Expand Up @@ -403,6 +402,8 @@ spec:
items:
- key: xds-trusted-ca.json
path: xds-trusted-ca.json
- key: xds_service_account_token.json
path: xds_service_account_token.json
name: gateway-1
optional: false
name: sds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ spec:
"@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic
credential:
name: jwt-sa-bearer
sds_config:
path_config_source:
path: /sds/xds_service_account_token.json
resource_api_version: V3
overwrite: true
- name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec
typed_config:
Expand All @@ -201,11 +205,6 @@ spec:
path_config_source:
path: /sds/xds-trusted-ca.json
resource_api_version: V3
secrets:
- name: jwt-sa-bearer
generic_secret:
secret:
filename: "/var/run/secrets/token/sa-token"
overload_manager:
refresh_interval: 0.25s
resource_monitors:
Expand Down Expand Up @@ -407,6 +406,8 @@ spec:
items:
- key: xds-trusted-ca.json
path: xds-trusted-ca.json
- key: xds_service_account_token.json
path: xds_service_account_token.json
name: gateway-1
optional: false
name: sds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ spec:
"@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic
credential:
name: jwt-sa-bearer
sds_config:
path_config_source:
path: /sds/xds_service_account_token.json
resource_api_version: V3
overwrite: true
- name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec
typed_config:
Expand All @@ -201,11 +205,6 @@ spec:
path_config_source:
path: /sds/xds-trusted-ca.json
resource_api_version: V3
secrets:
- name: jwt-sa-bearer
generic_secret:
secret:
filename: "/var/run/secrets/token/sa-token"
overload_manager:
refresh_interval: 0.25s
resource_monitors:
Expand Down Expand Up @@ -407,6 +406,8 @@ spec:
items:
- key: xds-trusted-ca.json
path: xds-trusted-ca.json
- key: xds_service_account_token.json
path: xds_service_account_token.json
name: gateway-1
optional: false
name: sds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ spec:
"@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic
credential:
name: jwt-sa-bearer
sds_config:
path_config_source:
path: /sds/xds_service_account_token.json
resource_api_version: V3
overwrite: true
- name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec
typed_config:
Expand All @@ -201,11 +205,6 @@ spec:
path_config_source:
path: /sds/xds-trusted-ca.json
resource_api_version: V3
secrets:
- name: jwt-sa-bearer
generic_secret:
secret:
filename: "/var/run/secrets/token/sa-token"
overload_manager:
refresh_interval: 0.25s
resource_monitors:
Expand Down Expand Up @@ -407,6 +406,8 @@ spec:
items:
- key: xds-trusted-ca.json
path: xds-trusted-ca.json
- key: xds_service_account_token.json
path: xds_service_account_token.json
name: gateway-1
optional: false
name: sds
Expand Down Expand Up @@ -596,6 +597,10 @@ spec:
"@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic
credential:
name: jwt-sa-bearer
sds_config:
path_config_source:
path: /sds/xds_service_account_token.json
resource_api_version: V3
overwrite: true
- name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec
typed_config:
Expand All @@ -615,11 +620,6 @@ spec:
path_config_source:
path: /sds/xds-trusted-ca.json
resource_api_version: V3
secrets:
- name: jwt-sa-bearer
generic_secret:
secret:
filename: "/var/run/secrets/token/sa-token"
overload_manager:
refresh_interval: 0.25s
resource_monitors:
Expand Down Expand Up @@ -821,6 +821,8 @@ spec:
items:
- key: xds-trusted-ca.json
path: xds-trusted-ca.json
- key: xds_service_account_token.json
path: xds_service_account_token.json
name: gateway-2
optional: false
name: sds
Expand Down
5 changes: 3 additions & 2 deletions internal/infrastructure/kubernetes/proxy_configmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,9 @@ func TestCreateOrUpdateProxyConfigMap(t *testing.T) {
},
},
Data: map[string]string{
common.SdsCAFilename: common.GetSdsCAConfigMapData(proxy.XdsTLSCaFilepath),
common.SdsCertFilename: common.GetSdsCertConfigMapData(proxy.XdsTLSCertFilepath, proxy.XdsTLSKeyFilepath),
common.SdsCAFilename: common.GetSdsCAConfigMapData(proxy.XdsTLSCaFilepath),
common.SdsCertFilename: common.GetSdsCertConfigMapData(proxy.XdsTLSCertFilepath, proxy.XdsTLSKeyFilepath),
common.SdsServiceAccountTokenFilename: common.GetSdsServiceAccountTokenConfigMapData(proxy.XdsServiceAccountTokenFilepath),
},
},
},
Expand Down
12 changes: 12 additions & 0 deletions internal/xds/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const (

defaultSdsTrustedCAPath = "/sds/xds-trusted-ca.json"
defaultSdsCertificatePath = "/sds/xds-certificate.json"
// #nosec G101 - This is a file path, not a credential
defaultServiceAccountTokenPath = "/sds/xds-service-account-token.json"

defaultServiceClusterName = "local_cluster"
)
Expand Down Expand Up @@ -101,6 +103,8 @@ type bootstrapParameters struct {
ServiceClusterName string
// TopologyInjectorDisabled controls whether to render the local cluster for use with zone aware routing
TopologyInjectorDisabled bool
// ServiceAccountTokenPath is the path to the service account token file used for authentication in GatewayNamespaceMode.
ServiceAccountTokenPath string
}

type serverParameters struct {
Expand Down Expand Up @@ -149,11 +153,14 @@ type RenderBootstrapConfigOptions struct {
MaxHeapSizeBytes uint64
GatewayNamespaceMode bool
TopologyInjectorDisabled bool
ServiceAccountTokenPath string
}

type SdsConfigPath struct {
Certificate string
TrustedCA string
// ServiceAccountToken is the path to the service account token file used for authentication in GatewayNamespaceMode.
ServiceAccountToken string
}

// render the stringified bootstrap config in yaml format.
Expand Down Expand Up @@ -263,6 +270,7 @@ func GetRenderedBootstrapConfig(opts *RenderBootstrapConfigOptions) (string, err
PrometheusCompressionLibrary: prometheusCompressionLibrary,
OtelMetricSinks: metricSinks,
ServiceClusterName: defaultServiceClusterName,
ServiceAccountTokenPath: defaultServiceAccountTokenPath,
},
}

Expand Down Expand Up @@ -306,6 +314,10 @@ func GetRenderedBootstrapConfig(opts *RenderBootstrapConfigOptions) (string, err
}
}
cfg.parameters.GatewayNamespaceMode = opts.GatewayNamespaceMode
if opts.GatewayNamespaceMode && len(opts.SdsConfig.ServiceAccountToken) > 0 {
cfg.parameters.ServiceAccountTokenPath = opts.SdsConfig.ServiceAccountToken
}

cfg.parameters.OverloadManager.MaxHeapSizeBytes = opts.MaxHeapSizeBytes
if opts.ServiceClusterName != nil {
cfg.parameters.ServiceClusterName = *opts.ServiceClusterName
Expand Down
11 changes: 4 additions & 7 deletions internal/xds/bootstrap/bootstrap.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ static_resources:
"@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic
credential:
name: jwt-sa-bearer
sds_config:
path_config_source:
path: {{ .ServiceAccountTokenPath }}
resource_api_version: V3
overwrite: true
- name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec
typed_config:
Expand Down Expand Up @@ -251,13 +255,6 @@ static_resources:
path_config_source:
path: {{ .SdsTrustedCAPath }}
resource_api_version: V3
{{- if .GatewayNamespaceMode }}
secrets:
- name: jwt-sa-bearer
generic_secret:
secret:
filename: "/var/run/secrets/token/sa-token"
{{- end }}
overload_manager:
refresh_interval: 0.25s
resource_monitors:
Expand Down
4 changes: 4 additions & 0 deletions internal/xds/server/kubejwt/tokenreview.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ func (i *JWTAuthInterceptor) validateKubeJWT(ctx context.Context, token, nodeID
return fmt.Errorf("failed to call TokenReview API to verify service account JWT: %w", err)
}

if tokenReview.Status.Error != "" {
return fmt.Errorf("token review found error: %s", tokenReview.Status.Error)
}

if !slices.Contains(tokenReview.Status.User.Groups, "system:serviceaccounts") {
return fmt.Errorf("the token is not a service account")
}
Expand Down
1 change: 1 addition & 0 deletions release-notes/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ bug fixes: |
Fixed Lua validator log level to be suppressed by default.
Fixed ProxyTopologyInjector cache sync race condition that caused injection failures
Fixed validation for grpc routes with extension ref filters.
Fixed service account token handling in GatewayNamespaceMode to use SDS for properly refreshing expired token.

# Enhancements that improve performance.
performance improvements: |
Expand Down