Skip to content

Commit

Permalink
xds translation
Browse files Browse the repository at this point in the history
Signed-off-by: Huabing Zhao <[email protected]>
  • Loading branch information
zhaohuabing committed Jan 7, 2025
1 parent 5992ad7 commit b65eb93
Show file tree
Hide file tree
Showing 12 changed files with 386 additions and 57 deletions.
6 changes: 4 additions & 2 deletions internal/gatewayapi/securitypolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,8 @@ func wildcard2regex(wildcard string) string {
func (t *Translator) buildJWT(
policy *egv1a1.SecurityPolicy,
resources *resource.Resources,
envoyProxy *egv1a1.EnvoyProxy) (*ir.JWT, error) {
envoyProxy *egv1a1.EnvoyProxy,
) (*ir.JWT, error) {
if err := validateJWTProvider(policy.Spec.JWT.Providers); err != nil {
return nil, err
}

Check warning on line 585 in internal/gatewayapi/securitypolicy.go

View check run for this annotation

Codecov / codecov/patch

internal/gatewayapi/securitypolicy.go#L584-L585

Added lines #L584 - L585 were not covered by tests
Expand Down Expand Up @@ -677,7 +678,8 @@ func (t *Translator) buildRemoteJWKS(
remoteJWKS *egv1a1.RemoteJWKS,
index int,
resources *resource.Resources,
envoyProxy *egv1a1.EnvoyProxy) (*ir.RemoteJWKS, error) {
envoyProxy *egv1a1.EnvoyProxy,
) (*ir.RemoteJWKS, error) {
var (
protocol ir.AppProtocol
rd *ir.RouteDestination
Expand Down
3 changes: 2 additions & 1 deletion internal/gatewayapi/securitypolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import (
"regexp"
"testing"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
)

func Test_wildcard2regex(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,50 @@ backends:
- fqdn:
hostname: 'foo.bar.com'
port: 443
configMaps:
- apiVersion: v1
kind: ConfigMap
metadata:
name: ca-cmap
namespace: default
data:
ca.crt: |
-----BEGIN CERTIFICATE-----
MIIDJzCCAg+gAwIBAgIUAl6UKIuKmzte81cllz5PfdN2IlIwDQYJKoZIhvcNAQEL
BQAwIzEQMA4GA1UEAwwHbXljaWVudDEPMA0GA1UECgwGa3ViZWRiMB4XDTIzMTAw
MjA1NDE1N1oXDTI0MTAwMTA1NDE1N1owIzEQMA4GA1UEAwwHbXljaWVudDEPMA0G
A1UECgwGa3ViZWRiMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwSTc
1yj8HW62nynkFbXo4VXKv2jC0PM7dPVky87FweZcTKLoWQVPQE2p2kLDK6OEszmM
yyr+xxWtyiveremrWqnKkNTYhLfYPhgQkczib7eUalmFjUbhWdLvHakbEgCodn3b
kz57mInX2VpiDOKg4kyHfiuXWpiBqrCx0KNLpxo3DEQcFcsQTeTHzh4752GV04RU
Ti/GEWyzIsl4Rg7tGtAwmcIPgUNUfY2Q390FGqdH4ahn+mw/6aFbW31W63d9YJVq
ioyOVcaMIpM5B/c7Qc8SuhCI1YGhUyg4cRHLEw5VtikioyE3X04kna3jQAj54YbR
bpEhc35apKLB21HOUQIDAQABo1MwUTAdBgNVHQ4EFgQUyvl0VI5vJVSuYFXu7B48
6PbMEAowHwYDVR0jBBgwFoAUyvl0VI5vJVSuYFXu7B486PbMEAowDwYDVR0TAQH/
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAMLxrgFVMuNRq2wAwcBt7SnNR5Cfz
2MvXq5EUmuawIUi9kaYjwdViDREGSjk7JW17vl576HjDkdfRwi4E28SydRInZf6J
i8HZcZ7caH6DxR335fgHVzLi5NiTce/OjNBQzQ2MJXVDd8DBmG5fyatJiOJQ4bWE
A7FlP0RdP3CO3GWE0M5iXOB2m1qWkE2eyO4UHvwTqNQLdrdAXgDQlbam9e4BG3Gg
d/6thAkWDbt/QNT+EJHDCvhDRKh1RuGHyg+Y+/nebTWWrFWsktRrbOoHCZiCpXI1
3eXE6nt0YkgtDxG22KqnhpAg9gUSs2hlhoxyvkzyF0mu6NhPlwAgnq7+/Q==
-----END CERTIFICATE-----
backendTLSPolicies:
- apiVersion: gateway.networking.k8s.io/v1alpha2
kind: BackendTLSPolicy
metadata:
name: policy-btls
namespace: default
spec:
targetRefs:
- group: "gateway.envoyproxy.io"
kind: Backend
name: backend-fqdn
validation:
caCertificateRefs:
- name: ca-cmap
group: ""
kind: ConfigMap
hostname: foo.bar.com
securityPolicies:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
backendTLSPolicies:
- apiVersion: gateway.networking.k8s.io/v1alpha2
kind: BackendTLSPolicy
metadata:
creationTimestamp: null
name: policy-btls
namespace: default
spec:
targetRefs:
- group: gateway.envoyproxy.io
kind: Backend
name: backend-fqdn
validation:
caCertificateRefs:
- group: ""
kind: ConfigMap
name: ca-cmap
hostname: foo.bar.com
status:
ancestors:
- ancestorRef:
group: gateway.envoyproxy.io
kind: SecurityPolicy
name: policy-for-route
namespace: default
conditions:
- lastTransitionTime: null
message: Policy has been accepted.
reason: Accepted
status: "True"
type: Accepted
controllerName: gateway.envoyproxy.io/gatewayclass-controller
backends:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
Expand Down Expand Up @@ -228,6 +260,12 @@ xdsIR:
- host: foo.bar.com
port: 443
protocol: HTTPS
tls:
alpnProtocols: null
caCertificate:
certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
name: policy-btls/default-ca
sni: foo.bar.com
weight: 1
traffic:
retry:
Expand Down
46 changes: 2 additions & 44 deletions internal/ir/xds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,10 @@ var (
},
Security: &SecurityFeatures{
JWT: &JWT{
Providers: []egv1a1.JWTProvider{
Providers: []JWTProvider{
{
Name: "test1",
RemoteJWKS: egv1a1.RemoteJWKS{
RemoteJWKS: RemoteJWKS{
URI: "https://test1.local",
},
},
Expand Down Expand Up @@ -1236,48 +1236,6 @@ func TestValidateStringMatch(t *testing.T) {
}
}

func TestValidateJWT(t *testing.T) {
tests := []struct {
name string
input JWT
want error
}{
{
name: "nil rules",
input: JWT{
Providers: nil,
},
want: nil,
},
{
name: "provider with remote jwks uri",
input: JWT{
Providers: []egv1a1.JWTProvider{
{
Name: "test",
Issuer: "https://test.local",
Audiences: []string{"test1", "test2"},
RemoteJWKS: egv1a1.RemoteJWKS{
URI: "https://test.local",
},
},
},
},
want: nil,
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
if test.want == nil {
require.NoError(t, test.input.Validate())
} else {
require.EqualError(t, test.input.Validate(), test.want.Error())
}
})
}
}

func TestValidateLoadBalancer(t *testing.T) {
tests := []struct {
name string
Expand Down
48 changes: 38 additions & 10 deletions internal/xds/translator/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,29 @@ func buildJWTAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication,

var reqs []*jwtauthnv3.JwtRequirement
for i := range route.Security.JWT.Providers {
irProvider := route.Security.JWT.Providers[i]
// Create the cluster for the remote jwks, if it doesn't exist.
jwksCluster, err := url2Cluster(irProvider.RemoteJWKS.URI)
if err != nil {
return nil, err
var (
irProvider = route.Security.JWT.Providers[i]
jwks = irProvider.RemoteJWKS
jwksCluster string
err error
)

if jwks.Destination != nil && len(jwks.Destination.Settings) > 0 {
jwksCluster = jwks.Destination.Name
} else {
var cluster *urlCluster
if cluster, err = url2Cluster(jwks.URI); err != nil {
return nil, err
}

Check warning on line 118 in internal/xds/translator/jwt.go

View check run for this annotation

Codecov / codecov/patch

internal/xds/translator/jwt.go#L117-L118

Added lines #L117 - L118 were not covered by tests
jwksCluster = cluster.name
}

remote := &jwtauthnv3.JwtProvider_RemoteJwks{
RemoteJwks: &jwtauthnv3.RemoteJwks{
HttpUri: &corev3.HttpUri{
Uri: irProvider.RemoteJWKS.URI,
HttpUpstreamType: &corev3.HttpUri_Cluster{
Cluster: jwksCluster.name,
Cluster: jwksCluster,
},
Timeout: &durationpb.Duration{Seconds: defaultExtServiceRequestTimeout},
},
Expand All @@ -123,6 +133,15 @@ func buildJWTAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication,
},
}

// Set the retry policy if it exists.
if jwks.Traffic != nil && jwks.Traffic.Retry != nil {
var rp *corev3.RetryPolicy
if rp, err = buildNonRouteRetryPolicy(jwks.Traffic.Retry); err != nil {
return nil, err
}

Check warning on line 141 in internal/xds/translator/jwt.go

View check run for this annotation

Codecov / codecov/patch

internal/xds/translator/jwt.go#L140-L141

Added lines #L140 - L141 were not covered by tests
remote.RemoteJwks.RetryPolicy = rp
}

claimToHeaders := []*jwtauthnv3.JwtClaimToHeader{}
for _, claimToHeader := range irProvider.ClaimToHeaders {
claimToHeader := &jwtauthnv3.JwtClaimToHeader{
Expand Down Expand Up @@ -264,17 +283,26 @@ func (*jwt) patchResources(tCtx *types.ResourceVersionTable, routes []*ir.HTTPRo
return errors.New("xds resource table is nil")
}

var err, errs error
var errs error
for _, route := range routes {
if !routeContainsJWTAuthn(route) {
continue
}

for i := range route.Security.JWT.Providers {
provider := route.Security.JWT.Providers[i]
jwks := route.Security.JWT.Providers[i].RemoteJWKS

if err = addClusterFromURL(provider.RemoteJWKS.URI, tCtx); err != nil {
errs = errors.Join(errs, err)
// If the rmote JWKS has a destination, use it.
if jwks.Destination != nil && len(jwks.Destination.Settings) > 0 {
if err := createExtServiceXDSCluster(
jwks.Destination, jwks.Traffic, tCtx); err != nil {
errs = errors.Join(errs, err)
}

Check warning on line 300 in internal/xds/translator/jwt.go

View check run for this annotation

Codecov / codecov/patch

internal/xds/translator/jwt.go#L299-L300

Added lines #L299 - L300 were not covered by tests
} else {
// Create a cluster with the token endpoint url.
if err := addClusterFromURL(jwks.URI, tCtx); err != nil {
errs = errors.Join(errs, err)
}

Check warning on line 305 in internal/xds/translator/jwt.go

View check run for this annotation

Codecov / codecov/patch

internal/xds/translator/jwt.go#L304-L305

Added lines #L304 - L305 were not covered by tests
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
http:
- address: 0.0.0.0
hostnames:
- '*'
isHTTP2: false
metadata:
kind: Gateway
name: gateway-1
namespace: default
sectionName: http
name: default/gateway-1/http
path:
escapedSlashesAction: UnescapeAndRedirect
mergeSlashes: true
port: 10080
routes:
- destination:
name: httproute/default/httproute-1/rule/0
settings:
- addressType: IP
endpoints:
- host: 7.7.7.7
port: 8080
protocol: HTTP
weight: 1
hostname: gateway.envoyproxy.io
isHTTP2: false
metadata:
kind: HTTPRoute
name: httproute-1
namespace: default
name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
pathMatch:
distinct: false
name: ""
prefix: /
security:
jwt:
providers:
- audiences:
- foo.bar.com
claimToHeaders:
- claim: claim
header: claim-header
issuer: https://foo.bar.com
name: foobar
remoteJWKS:
destination:
name: securitypolicy/default/policy-for-route/jwt/0
settings:
- addressType: FQDN
endpoints:
- host: foo.bar.com
port: 443
protocol: HTTPS
tls:
alpnProtocols: null
caCertificate:
certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
name: policy-btls/default-ca
sni: foo.bar.com
weight: 1
traffic:
retry:
numRetries: 3
perRetry:
backOff:
baseInterval: 1s
maxInterval: 5s
retryOn:
triggers:
- 5xx
- gateway-error
- reset
uri: https://foo.bar.com/jwt/public-key/jwks.json
Loading

0 comments on commit b65eb93

Please sign in to comment.