Skip to content

Commit

Permalink
allow multiple routes using the same OIDC configuration
Browse files Browse the repository at this point in the history
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
  • Loading branch information
zhaohuabing committed Apr 23, 2024
1 parent c27424e commit f47625e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 9 deletions.
13 changes: 12 additions & 1 deletion internal/gatewayapi/securitypolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,18 @@ func (t *Translator) buildOIDC(
}

// Generate a unique cookie suffix for oauth filters
suffix := utils.Digest32(string(policy.UID))
// We use the digest of the redirect URL to generate the cookie suffix so that
// multiple OIDC configurations with the same redirect URL will have the same
// cookie suffix. This allows us to share the same cookies across multiple
// oauth filters at multiple routes. Once users log in at one route, they will
// be able to access other routes with the same OIDC redirect URL (the same
// OIDC clientID) without logging in again.
//
// zhaohuabing: This is a workaround to allow multiple routes to share the same OIDC configuration.
// We should change this back to use policy UID after Gateway API supports
// targeting a policy to multiple routes.
// See https://github.com/kubernetes-sigs/gateway-api/discussions/2927#discussioncomment-8991869
suffix := utils.Digest32(*oidc.RedirectURL)

// Get the HMAC secret
// HMAC secret is generated by the CertGen job and stored in a secret
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ xdsIR:
oidc:
clientID: client2.oauth.foo.com
clientSecret: Y2xpZW50MTpzZWNyZXQK
cookieSuffix: 5f93c2e4
cookieSuffix: 7f4620b9
hmacSecret: qrOYACHXoe7UEDI/raOjNSx+Z9ufXSc/22C3T6X/zPY=
logoutPath: /foo/logout
name: securitypolicy/default/policy-for-http-route
Expand Down Expand Up @@ -299,7 +299,7 @@ xdsIR:
oidc:
clientID: client1.apps.googleusercontent.com
clientSecret: Y2xpZW50MTpzZWNyZXQK
cookieSuffix: b0a1b740
cookieSuffix: d3d6eea4
hmacSecret: qrOYACHXoe7UEDI/raOjNSx+Z9ufXSc/22C3T6X/zPY=
logoutPath: /bar/logout
name: securitypolicy/envoy-gateway/policy-for-gateway
Expand Down
2 changes: 1 addition & 1 deletion internal/infrastructure/kubernetes/proxy/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func expectedProxyContainers(infra *ir.ProxyInfra,
fmt.Sprintf("--service-cluster %s", infra.Name),
fmt.Sprintf("--service-node $(%s)", envoyPodEnvVar),
fmt.Sprintf("--config-yaml %s", bootstrapConfigurations),
fmt.Sprintf("--log-level %s", "debug"),
fmt.Sprintf("--log-level %s", logging.DefaultEnvoyProxyLoggingLevel()),
"--cpuset-threads",
}

Expand Down
45 changes: 42 additions & 3 deletions test/e2e/testdata/oidc-securitypolicy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-with-oidc
name: http-with-oidc-myapp
namespace: gateway-conformance-infra
spec:
parentRefs:
Expand All @@ -19,6 +19,24 @@ spec:
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-with-oidc-foo
namespace: gateway-conformance-infra
spec:
parentRefs:
- name: same-namespace
hostnames: ["www.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /foo # This is the path that will be protected by OIDC
backendRefs:
- name: infra-backend-v1
port: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-without-oidc
namespace: gateway-conformance-infra
Expand Down Expand Up @@ -60,13 +78,34 @@ data:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: oidc-test
name: oidc-test-myapp
namespace: gateway-conformance-infra
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-with-oidc-myapp
oidc:
provider:
issuer: "http://keycloak.gateway-conformance-infra/realms/master"
authorizationEndpoint: "http://keycloak.gateway-conformance-infra/realms/master/protocol/openid-connect/auth"
tokenEndpoint: "http://keycloak.gateway-conformance-infra/realms/master/protocol/openid-connect/token"
clientID: "oidctest"
clientSecret:
name: "oidctest-secret"
redirectURL: "http://www.example.com/myapp/oauth2/callback"
logoutPath: "/myapp/logout"
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: oidc-test-foo
namespace: gateway-conformance-infra
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-with-oidc
name: http-with-oidc-foo
oidc:
provider:
issuer: "http://keycloak.gateway-conformance-infra/realms/master"
Expand Down
12 changes: 10 additions & 2 deletions test/e2e/tests/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var OIDCTest = suite.ConformanceTest{
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
t.Run("http route with oidc authentication", func(t *testing.T) {
ns := "gateway-conformance-infra"
routeNN := types.NamespacedName{Name: "http-with-oidc", Namespace: ns}
routeNN := types.NamespacedName{Name: "http-with-oidc-myapp", Namespace: ns}
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)

Expand All @@ -57,7 +57,8 @@ var OIDCTest = suite.ConformanceTest{
Namespace: gatewayapi.NamespacePtr(gwNN.Namespace),
Name: gwv1.ObjectName(gwNN.Name),
}
SecurityPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "oidc-test", Namespace: ns}, suite.ControllerName, ancestorRef)
SecurityPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "oidc-test-myapp", Namespace: ns}, suite.ControllerName, ancestorRef)
SecurityPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "oidc-test-foo", Namespace: ns}, suite.ControllerName, ancestorRef)

podInitialized := corev1.PodCondition{Type: corev1.PodInitialized, Status: corev1.ConditionTrue}

Expand Down Expand Up @@ -101,6 +102,13 @@ var OIDCTest = suite.ConformanceTest{
require.Equal(t, http.StatusOK, res.StatusCode)
require.Contains(t, string(body), "infra-backend-v1", "Expected response from the application")

// Myapp and bar are using the same OIDC configuration, so the client
// should be able to access bar without logging in again
res, err = client.Get("http://www.example.com/foo", false)
require.NoError(t, err)
require.Equal(t, http.StatusOK, res.StatusCode)
require.Contains(t, string(body), "infra-backend-v1", "Expected response from the application")

// Verify that we can logout
// Note: OAuth2 filter just clears its cookies and does not log out from the IdP.
res, err = client.Get(logoutURL, false)
Expand Down

0 comments on commit f47625e

Please sign in to comment.