From 762328a0049d7cbb11d601bd9a22c720a3f0a6f0 Mon Sep 17 00:00:00 2001 From: Peter Holloway Date: Fri, 1 Nov 2024 16:18:15 +0000 Subject: [PATCH] Use OIDC metadata discovery to find jwks_uri --- .devcontainer/docker-compose.yml | 2 +- charts/opa/Chart.yaml | 2 +- charts/opa/templates/deployment.yaml | 4 ++-- charts/opa/values.yaml | 2 +- docs/how-tos/deploy-docker-compose.md | 6 +++--- docs/how-tos/verify-cas-access-token.md | 2 +- docs/how-tos/verify-json-web-token.md | 13 ++++++++++--- policy/diamond/policy/token/token.rego | 16 ++++++++++++---- 8 files changed, 31 insertions(+), 16 deletions(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 17510c85..c56de223 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -28,7 +28,7 @@ services: - ../policy/:/org-policy:cached,z environment: TRACING_ADDRESS: collector:4317 - JWKS_ENDPOINT: https://authn.diamond.ac.uk/realms/master/protocol/openid-connect/certs + ISSUER: https://authn.diamond.ac.uk/realms/master ispyb: image: ghcr.io/diamondlightsource/ispyb-database:v3.0.0 diff --git a/charts/opa/Chart.yaml b/charts/opa/Chart.yaml index b4e24efc..34373b1e 100644 --- a/charts/opa/Chart.yaml +++ b/charts/opa/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: opa description: An OPA deployment to run alongside applications requiring authorization type: application -version: 0.5.0 +version: 0.6.0 appVersion: 0.59.0 maintainers: - name: garryod diff --git a/charts/opa/templates/deployment.yaml b/charts/opa/templates/deployment.yaml index edcbdacc..20952602 100644 --- a/charts/opa/templates/deployment.yaml +++ b/charts/opa/templates/deployment.yaml @@ -60,8 +60,8 @@ spec: key: {{ .Values.orgData.bundlerSecret.key }} {{- end -}} {{- if and .Values.orgPolicy.enabled .Values.orgPolicy.jwksEndpoint }} - - name: JWKS_ENDPOINT - value: {{ .Values.orgPolicy.jwksEndpoint }} + - name: ISSUER + value: {{ .Values.orgPolicy.issuer }} {{- end }} {{- if .Values.extraEnv }} {{- .Values.extraEnv | toYaml | nindent 12 }} diff --git a/charts/opa/values.yaml b/charts/opa/values.yaml index 3133e480..8adf3ecd 100644 --- a/charts/opa/values.yaml +++ b/charts/opa/values.yaml @@ -17,7 +17,7 @@ orgData: key: bearer-token orgPolicy: enabled: false - jwksEndpoint: https://authn.diamond.ac.uk/realms/master/protocol/openid-connect/certs + issuer: https://authn.diamond.ac.uk/realms/master configOverride: {} extraConfig: {} extraServices: {} diff --git a/docs/how-tos/deploy-docker-compose.md b/docs/how-tos/deploy-docker-compose.md index d94a3ac2..b687e78a 100644 --- a/docs/how-tos/deploy-docker-compose.md +++ b/docs/how-tos/deploy-docker-compose.md @@ -14,7 +14,7 @@ The example below makes use of the [Diamond Data Bundle](../references/diamond-d Local policy which may be actively developed should not be included in the configuration file, instead it should be mounted into the OPA container and included using the `--watch` argument on the command. -!!! example +!!! example ```yaml title="opa.yml" services: @@ -51,7 +51,7 @@ If using the [Diamond Data Bundle](../references/diamond-data-bundle.md) you sho ### Using the Organisational Policy -If using the [Organisational Policy](../references/organisational-policy.md) you should set the `JWKS_ENDPOINT` environment variable to the KeyCloak JSON Web Key Set (JWKS) endpoint - `https://authn.diamond.ac.uk/realms/master/protocol/openid-connect/certs` - using the `environment` list. +If using the [Organisational Policy](../references/organisational-policy.md) you should set the `ISSUER` environment variable to the KeyCloak instance - `https://authn.diamond.ac.uk/realms/master` - using the `environment` list. ### Using Local Policy @@ -88,6 +88,6 @@ To utilize local policy you should mount in the policy volume and setting the `- - ./opa.yml:/config.yml:cached,z - ../policy:/policy:cached,z environment: - JWKS_ENDPOINT: https://authn.diamond.ac.uk/realms/master/protocol/openid-connect/certs + ISSUER: https://authn.diamond.ac.uk/realms/master env_file: opa.env ``` diff --git a/docs/how-tos/verify-cas-access-token.md b/docs/how-tos/verify-cas-access-token.md index b44d805a..1532673f 100644 --- a/docs/how-tos/verify-cas-access-token.md +++ b/docs/how-tos/verify-cas-access-token.md @@ -8,7 +8,7 @@ It is recommended you delegate this operation to the [Organisational Policy](../ ## Using Organisational Policy -When loaded, you can delegate KeyCloak token verification decisions to the [Organisational Policy Bundle](../references/organisational-policy.md) by referencing the `data.diamond.policy.token.claims` variable in your policy and setting the `JWKS_ENDPOINT` environment variable to point to the KeyCloak JWKS endpoint - e.g. `https://authn.diamond.ac.uk/realms/master/protocol/openid-connect/certs`. +When loaded, you can delegate KeyCloak token verification decisions to the [Organisational Policy Bundle](../references/organisational-policy.md) by referencing the `data.diamond.policy.token.claims` variable in your policy and setting the `ISSUER` environment variable to point to the KeyCloak instance - e.g. `https://authn.diamond.ac.uk/realms/master`. The example below shows how you might write a system package which allows the action if `input.action` is "do_thing" and the `input.token` is for the subject "bob". diff --git a/docs/how-tos/verify-json-web-token.md b/docs/how-tos/verify-json-web-token.md index bcb361e3..c88debb2 100644 --- a/docs/how-tos/verify-json-web-token.md +++ b/docs/how-tos/verify-json-web-token.md @@ -10,7 +10,7 @@ We do not yet provide an organisational JWT verification policy. However the imp Verification of JSON Web Tokens (JWTs) may be performed without a round trip to the Single Sign On (SSO) provider by utilizing the JSON Web Key Set (JWKS) to cryptographically verify that the signature on the JWT is genuine. JSON Web Key Sets rotate periodically, thus we must occasionally fetch the current set via the JWKS endpoint with the Key ID (`kid`) supplied encoded within the JWT. -The following code expects the `JWKS` endpoint (e.g. `https://authn.diamond.ac.uk/realms/master/protocol/openid-connect/certs`) to be supplied in the `JWKS_ENDPOINT` environment variable. +The following code expects the OIDC provider (e.g. `https://authn.diamond.ac.uk/realms/master`) to be supplied in the `ISSUER` environment variable. ```rego package token @@ -24,7 +24,14 @@ fetch_jwks(url) := http.send({ "force_cache_duration_seconds": 3600, }) -jwks_endpoint := opa.runtime().env.JWKS_ENDPOINT +oidc_issuer := opa.runtime().env.ISSUER + +jwks_endpoint := http.send({ + "url": concat("", [oidc_issuer, "/.well-known/openid-configuration"]), + "method": "GET", + "force_cache": true, + "force_cache_duration_seconds": 84600 + }).body.jwks_uri unverified := io.jwt.decode(input.token) @@ -40,5 +47,5 @@ valid := io.jwt.decode_verify(input.token, { "aud": "account", }) -claims := valid[2] +claims := valid[2] ``` diff --git a/policy/diamond/policy/token/token.rego b/policy/diamond/policy/token/token.rego index 81e55b29..b4826a5e 100644 --- a/policy/diamond/policy/token/token.rego +++ b/policy/diamond/policy/token/token.rego @@ -2,6 +2,18 @@ package diamond.policy.token import rego.v1 +issuer := opa.runtime().env.ISSUER + +jwks_endpoint := jwks_endpoint if { + metadata := http.send({ + "url": concat("", [issuer, "/.well-known/openid-configuration"]), + "method": "GET", + "force_cache": true, + "force_cache_duration_seconds": 86400, + }).body + jwks_endpoint := metadata.jwks_uri +} + fetch_jwks(url) := http.send({ "url": url, "method": "GET", @@ -9,10 +21,6 @@ fetch_jwks(url) := http.send({ "force_cache_duration_seconds": 86400, }) -jwks_endpoint := opa.runtime().env.JWKS_ENDPOINT - -issuer := opa.runtime().env.ISSUER - unverified := io.jwt.decode(input.token) jwt_header := unverified[0]