Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
967dd1f
Fix leading whitespace in tmpl files
javorszky Apr 30, 2025
21281bf
Add PKCE Enabled flag
javorszky Apr 30, 2025
18dca5c
Implement pkce in configs
javorszky May 8, 2025
f30cae3
Add check for OIDC to guard for a nil pointer
javorszky May 8, 2025
3c2b1fc
Fix some whitespace alignment in tmpl files
javorszky May 8, 2025
96e1aa0
Update snapshots to realign with whitespaces
javorszky May 8, 2025
4a800a7
Add tests for PKCE enabled true
javorszky May 8, 2025
4f00a17
Update CRDs based on policy files
javorszky May 8, 2025
812a9d2
Add pkceEnabled to oidc pytest setup yaml
javorszky May 13, 2025
db28908
Terminate include directive with a ;
javorszky May 13, 2025
b70f3ff
Set pkce enabled to an int instead of a string
javorszky May 14, 2025
d81eea1
OIDC test doesn't need pkce enabled
javorszky May 16, 2025
0348ef2
Add PKCE pytest
javorszky May 16, 2025
730635e
Update snapshot after changing a str -> int
javorszky May 16, 2025
5109020
oidc and pkce pytest fixture scope to function
javorszky May 16, 2025
97737b6
OIDC tests should be class fixtured
javorszky May 16, 2025
318ea45
Remove a parameter from pkce test
javorszky May 16, 2025
84b2977
pkce test fixture should also be class scoped
javorszky May 16, 2025
f0d13c6
Add debug prints
javorszky May 16, 2025
67b8385
Merge pkce test into oidc test file
javorszky May 20, 2025
71d4ddc
Add unit tests for the bool to int util function
javorszky May 20, 2025
df5d0e4
Add docs to create keycloak client via api
javorszky May 27, 2025
94c59be
Reword options because no tabs
javorszky May 27, 2025
7544728
OIDC example deploy keycloak into nginx-ingress ns
javorszky May 28, 2025
1466bae
Add plus-mgmt-configmap.yaml to instructions
javorszky May 28, 2025
76ad8bc
Redo list numbers in oidc example readme
javorszky May 28, 2025
e1ab426
Reset keycloak to be in default namespace
javorszky May 28, 2025
8c8e56c
Add note on not using client secret for PKCE
javorszky May 28, 2025
81ef4a1
Move applying the plus mgmt to common resources
javorszky May 28, 2025
41016cd
Add pkceEnabled to policy resource doc
javorszky May 28, 2025
878cf38
Rename pkceEnabled from past to present tense
javorszky May 28, 2025
20cc312
Fix product name in example readme
javorszky May 29, 2025
9b91031
Change console code type to shell
javorszky May 29, 2025
46286b0
Turn choice into unordered list
javorszky May 29, 2025
6903448
Replace const default pkce secret with init val
javorszky Jun 2, 2025
873b0fc
Change pkce and client secret validations
javorszky Jun 5, 2025
9f7c90f
Update snapshots
javorszky Jun 9, 2025
e4956a1
Do not use default client secret
javorszky Jun 9, 2025
4d4da9f
Add more validation and tests
javorszky Jun 9, 2025
6b22f2a
Add note to OIDC policy docs about pkce-clientsecret
javorszky Jun 9, 2025
515beb9
Remove clientsecret from e2e test for pkce
javorszky Jun 9, 2025
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
32 changes: 0 additions & 32 deletions charts/tests/__snapshots__/helmunit_test.snap
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -911,8 +909,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -1449,8 +1445,6 @@ spec:
- -weight-changes-dynamic-reload=false
- -agent=true
- -agent-instance-group=app-protect-waf-agentv2-nginx-ingress-controller

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -1965,7 +1959,6 @@ spec:
mountPath: /opt/app_protect/config
- name: app-protect-bundles
mountPath: /etc/app_protect/bundles
minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -2547,7 +2540,6 @@ spec:
mountPath: /opt/app_protect/config
- name: app-protect-bundles
mountPath: /etc/app_protect/bundles
minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -2961,8 +2953,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -3406,8 +3396,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -3851,8 +3839,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -4297,8 +4283,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -4763,8 +4747,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -5210,8 +5192,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -5672,8 +5652,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -6141,8 +6119,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -6620,8 +6596,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -7080,8 +7054,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -7540,8 +7512,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down Expand Up @@ -8010,8 +7980,6 @@ spec:
- -ssl-dynamic-reload=true
- -enable-telemetry-reporting=true
- -weight-changes-dynamic-reload=false

minReadySeconds: 0
/-/-/-/
# Source: nginx-ingress/templates/controller-ingress-class.yaml
apiVersion: networking.k8s.io/v1
Expand Down
2 changes: 2 additions & 0 deletions config/crd/bases/k8s.nginx.org_policies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ spec:
type: string
jwksURI:
type: string
pkceEnable:
type: boolean
postLogoutRedirectURI:
type: string
redirectURI:
Expand Down
2 changes: 2 additions & 0 deletions deploy/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@ spec:
type: string
jwksURI:
type: string
pkceEnable:
type: boolean
postLogoutRedirectURI:
type: string
redirectURI:
Expand Down
57 changes: 36 additions & 21 deletions examples/custom-resources/oidc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,24 @@ application using an OpenID Connect policy and [Keycloak](https://www.keycloak.o

**Note**: The KeyCloak container does not support IPv6 environments.

**Note**: This example assumes that your default namespace is set to `default`. You can check this with

```shell
kubectl config view --minify | grep namespace
```

If it's not empty, and anything other than `default`, you can set to `default` with the following command:

```shell
kubectl config set-context --namespace default --current
```

## Prerequisites

1. Follow the [installation](https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/)
instructions to deploy the Ingress Controller. This example requires that the HTTPS port of the Ingress Controller is
`443`.
1. Save the public IP address of the Ingress Controller into `/etc/hosts` of your machine:
instructions to deploy NGINX Ingress Controller. This example requires that the HTTPS port of the Ingress
Controller is `443`.
2. Save the public IP address of the Ingress Controller into `/etc/hosts` of your machine:

```text
...
Expand All @@ -27,29 +39,29 @@ application using an OpenID Connect policy and [Keycloak](https://www.keycloak.o
Create a secret with the TLS certificate and key that will be used for TLS termination of the web application and
Keycloak:

```console
```shell
kubectl apply -f tls-secret.yaml
```

## Step 2 - Deploy a Web Application

Create the application deployment and service:

```console
```shell
kubectl apply -f webapp.yaml
```

## Step 3 - Deploy Keycloak

1. Create the Keycloak deployment and service:

```console
```shell
kubectl apply -f keycloak.yaml
```

1. Create a VirtualServer resource for Keycloak:
2. Create a VirtualServer resource for Keycloak:

```console
```shell
kubectl apply -f virtual-server-idp.yaml
```

Expand All @@ -59,27 +71,30 @@ To set up Keycloak:

1. Follow the steps in the "Configuring Keycloak" [section of the documentation](https://docs.nginx.com/nginx/deployment-guides/single-sign-on/keycloak/#configuring-keycloak):
1. To connect to Keycloak, use `https://keycloak.example.com`.
1. Make sure to save the client secret for NGINX-Plus client to the `SECRET` shell variable:
2. Make sure to save the client secret for NGINX-Plus client to the `SECRET` shell variable:

```console
```shell
SECRET=value
```

1. Alternatively, [execute the commands](./keycloak_setup.md).
2. Alternatively, [execute the commands](./keycloak_setup.md).

## Step 5 - Deploy the Client Secret

**Note**: If you're using PKCE, skip this step. PKCE clients do not have client secrets. Applying this will result
in a broken deployment.

1. Encode the secret, obtained in the previous step:

```console
```shell
echo -n $SECRET | base64
```

1. Edit `client-secret.yaml`, replacing `<insert-secret-here>` with the encoded secret.
2. Edit `client-secret.yaml`, replacing `<insert-secret-here>` with the encoded secret.

1. Create a secret with the name `oidc-secret` that will be used by the OIDC policy:
3. Create a secret with the name `oidc-secret` that will be used by the OIDC policy:

```console
```shell
kubectl apply -f client-secret.yaml
```

Expand All @@ -96,23 +111,23 @@ Steps:

1. Apply the ConfigMap `nginx-config.yaml`, which contains `zone-sync` configuration parameter that enable zone synchronization and the resolver using the kube-dns service.

```console
```shell
kubectl apply -f nginx-config.yaml
```

## Step 7 - Deploy the OIDC Policy

Create a policy with the name `oidc-policy` that references the secret from the previous step:

```console
```shell
kubectl apply -f oidc.yaml
```

## Step 8 - Configure Load Balancing

Create a VirtualServer resource for the web application:

```console
```shell
kubectl apply -f virtual-server.yaml
```

Expand All @@ -122,15 +137,15 @@ Note that the VirtualServer references the policy `oidc-policy` created in Step

1. Open a web browser and navigate to the URL of the web application: `https://webapp.example.com`. You will be
redirected to Keycloak.
1. Log in with the username and password for the user you created in Keycloak, `nginx-user` and `test`.
2. Log in with the username and password for the user you created in Keycloak, `nginx-user` and `test`.
![keycloak](./keycloak.png)
1. Once logged in, you will be redirected to the web application and get a response from it. Notice the field `User ID`
3. Once logged in, you will be redirected to the web application and get a response from it. Notice the field `User ID`
in the response, this will match the ID for your user in Keycloak. ![webapp](./webapp.png)

## Step 10 - Log Out

1. To log out, navigate to `https://webapp.example.com/logout`. Your session will be terminated, and you will be
redirected to the default post logout URI `https://webapp.example.com/_logout`.
![logout](./logout.png)
1. To confirm that you have been logged out, navigate to `https://webapp.example.com`. You will be redirected to
2. To confirm that you have been logged out, navigate to `https://webapp.example.com`. You will be redirected to
Keycloak to log in again.
58 changes: 41 additions & 17 deletions examples/custom-resources/oidc/keycloak_setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,39 +17,63 @@ Steps:

1. Save the address of Keycloak into a shell variable:

```console
```shell
KEYCLOAK_ADDRESS=keycloak.example.com
```

1. Retrieve the access token and store it into a shell variable:
2. Retrieve the access token and store it into a shell variable:

```console
```shell
TOKEN=`curl -sS -k --data "username=admin&password=admin&grant_type=password&client_id=admin-cli" "https://${KEYCLOAK_ADDRESS}/realms/master/protocol/openid-connect/token" | jq -r .access_token`
```

Ensure the request was successful and the token is stored in the shell variable by running:

```console
```shell
echo $TOKEN
```

***Note***: The access token lifespan is very short. If it expires between commands, retrieve it again with the
command above.

1. Create the user `nginx-user`:
3. Create the user `nginx-user`:

```console
```shell
curl -sS -k -X POST -d '{ "username": "nginx-user", "enabled": true, "credentials":[{"type": "password", "value": "test", "temporary": false}]}' -H "Content-Type:application/json" -H "Authorization: bearer ${TOKEN}" https://${KEYCLOAK_ADDRESS}/admin/realms/master/users
```

1. Create the client `nginx-plus` and retrieve the secret:

```console
SECRET=`curl -sS -k -X POST -d '{ "clientId": "nginx-plus", "redirectUris": ["https://webapp.example.com:443/_codexch"], "attributes": {"post.logout.redirect.uris": "https://webapp.example.com:443/*"}}' -H "Content-Type:application/json" -H "Authorization: bearer ${TOKEN}" https://${KEYCLOAK_ADDRESS}/realms/master/clients-registrations/default | jq -r .secret`
```

If everything went well you should have the secret stored in $SECRET. To double check run:

```console
echo $SECRET
```
4. Create the client `nginx-plus`:

- If you are not using PKCE, use the following command to create an OIDC client that does not use PKCE:

```shell
SECRET=`curl -sS -k -X POST -d '{ "clientId": "nginx-plus", "redirectUris": ["https://webapp.example.com:443/_codexch"], "attributes": {"post.logout.redirect.uris": "https://webapp.example.com:443/*"}}' -H "Content-Type:application/json" -H "Authorization: bearer ${TOKEN}" https://${KEYCLOAK_ADDRESS}/realms/master/clients-registrations/default | jq -r .secret`
```

If everything went well, you should have the secret stored in $SECRET. To double-check, run:

```shell
echo $SECRET
```

- Or if you are using PKCE with OIDC, use the following command to create the client:

```shell
curl -sS -k -H "Content-Type: application/json" -H "Authorization: Bearer ${TOKEN}" \
--data '{
"clientId": "nginx-plus",
"enabled": true,
"standardFlowEnabled": true,
"directAccessGrantsEnabled": false,
"publicClient": true,
"redirectUris": [
"https://webapp.example.com:443/_codexch"
],
"attributes": {
"pkce.code.challenge.method":"S256",
"post.logout.redirect.uris": "https://webapp.example.com:443/*"
},
"protocol": "openid-connect"
}' \
https://${KEYCLOAK_ADDRESS}/admin/realms/master/clients
```
Loading
Loading