Skip to content

Commit b53cf4c

Browse files
javorszkyrenovate[bot]pdabelf5
authored
Implement OIDC front channel logout NGINX directives (#8340)
* Update the openid-connect.js to current latest version * Update pytest keycloak from 25.0.2 to 26.3 * Remove unused variable from test_oidc.py * Add front channel logout configs to oidc conf * Move the idp sid keyval into virtualserver template * Update keycloak image version and env vars * Fix virtualserver template and snaps * Keycloak 26.4 uses button type submit * Add fclo example * Turn on oidc debug flag if main error level is debug * Add logic to enable oidc debug variable * Add oidc fclo test files * Fix the create keycloak and test setup functionality * Add fclo page tests * Finish pytest for oidc fclo * Add configmap and snap tests * Rewrite readme for examples/oidc-fclo * Update python:3.14-bookworm Docker digest to 0cc5dcf (main) (#8450) Update python:3.14-bookworm Docker digest to 0cc5dcf Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Use renovate to monitor test data yaml files (#8445) * Factor out creating oidc policy in fclo pytest * Reword OIDC Policies in fclo example readme * Add more detail to fclo readme --------- Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Paul Abel <[email protected]>
1 parent 3a10709 commit b53cf4c

36 files changed

+1481
-573
lines changed

charts/tests/__snapshots__/helmunit_test.snap

Lines changed: 0 additions & 463 deletions
Large diffs are not rendered by default.
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# OIDC with Front Channel Logout
2+
3+
In this example, we deploy two web applications, configure load balancing for them via VirtualServers, and protect the
4+
applications using an [OIDC Policies](https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/#oidc) and [Keycloak](https://www.keycloak.org/), and ensure behaviour is consistent across multiple replicas by enabling [Zone Synchronization](https://docs.nginx.com/nginx/admin-guide/high-availability/zone_sync/).
5+
6+
**Note**: The KeyCloak container does not support IPv6 environments.
7+
8+
**Note**: This example assumes that your default namespace is set to `default`. You can check this with
9+
10+
```shell
11+
kubectl config view --minify | grep namespace
12+
```
13+
14+
If it's not empty, and anything other than `default`, you can set to `default` with the following command:
15+
16+
```shell
17+
kubectl config set-context --namespace default --current
18+
```
19+
20+
## Prerequisites
21+
22+
1. Follow the [installation](https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/)
23+
instructions to deploy NGINX Ingress Controller. This example requires that the HTTPS port of the Ingress
24+
Controller is `443`.
25+
2. Save the public IP address of the Ingress Controller into `/etc/hosts` of your machine:
26+
27+
```text
28+
...
29+
30+
XXX.YYY.ZZZ.III fclo-one.example.com
31+
XXX.YYY.ZZZ.III fclo-two.example.com
32+
XXX.YYY.ZZZ.III keycloak.example.com
33+
```
34+
35+
Here `fclo-one.example.com` and `fclo-two.example.com` are the domains for the two web applications protected by OIDC authentication, and `keycloak.example.com` is the domain for the Keycloak IdP.
36+
37+
## Step 1 - Deploy a TLS Secret
38+
39+
Create a secret with the TLS certificate and key that will be used for TLS termination of the web applications and
40+
Keycloak:
41+
42+
```shell
43+
kubectl apply -f tls-secret.yaml
44+
```
45+
46+
## Step 2 - Deploy a Web Application
47+
48+
Create the application deployments and services:
49+
50+
```shell
51+
kubectl apply -f two-webapps.yaml
52+
```
53+
54+
## Step 3 - Deploy Keycloak
55+
56+
1. Create the Keycloak deployment and service:
57+
58+
```shell
59+
kubectl apply -f keycloak.yaml
60+
```
61+
62+
2. Create a VirtualServer resource for Keycloak:
63+
64+
```shell
65+
kubectl apply -f virtual-server-idp.yaml
66+
```
67+
68+
## Step 4 - Configure Keycloak
69+
70+
To set up Keycloak follow the steps in the "Configuring Keycloak" [section of the documentation](keycloak_setup.md). That guide will get you to create a user, two OIDC clients, and save the client secrets in the necessary files.
71+
72+
## Step 5 - Deploy the Client Secrets
73+
74+
By this step, you should have encoded and edited both the `client-secret-one.yaml` and `client-secret-two.yaml` files. If you haven't, go back to the previous step.
75+
76+
Apply the secrets that will be used by the OIDC policies for the two virtual server:
77+
78+
```shell
79+
kubectl apply -f client-secret-one.yaml
80+
kubectl apply -f client-secret-two.yaml
81+
```
82+
83+
## Step 6 - Configure Zone Synchronization and Resolver
84+
85+
In this step we configure:
86+
87+
- [Zone Synchronization](https://docs.nginx.com/nginx/admin-guide/high-availability/zone_sync/). For the OIDC feature to
88+
work when you have two or more replicas of the Ingress Controller, it is necessary to enable zone synchronization
89+
among the replicas. This is to ensure that each replica has access to the required session information when authenticating via IDP such as Keycloak.
90+
- The resolver can resolve the host names.
91+
92+
Steps:
93+
94+
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.
95+
96+
```shell
97+
kubectl apply -f nginx-config.yaml
98+
```
99+
100+
## Step 7 - Deploy the OIDC Policies
101+
102+
Create policies with the names `oidc-one-policy` and `oidc-two-policy` that references the secrets from the previous step:
103+
104+
```shell
105+
kubectl apply -f oidc-one.yaml
106+
kubectl apply -f oidc-two.yaml
107+
```
108+
109+
## Step 8 - Configure Load Balancing
110+
111+
Create VirtualServer resources for the web applications:
112+
113+
```shell
114+
kubectl apply -f two-virtual-servers.yaml
115+
```
116+
117+
Note that the VirtualServers reference the policies `oidc-one-policy` and `oidc-two-policy` created in Step 6.
118+
119+
## Step 9 - Test the Configuration
120+
121+
1. Open a web browser and navigate to the URL of one of the web applications: `https://fclo-one.example.com`. You will be
122+
redirected to Keycloak.
123+
2. Log in with the username and password for the user you created in Keycloak, `nginx-user` and `test`.
124+
![keycloak](./keycloak.webp)
125+
3. Once logged in, you will be redirected to the web application and get a response from it. Notice the field `User ID`
126+
in the response, this will match the ID for your user in Keycloak. ![webapp](./webapp.webp)
127+
4. If you then navigate to the URL of the other web application, `https://fclo-two.example.com`, you will already be authenticated, and you will see the same `User ID` on the page.
128+
129+
## Step 10 - Log Out
130+
131+
**Note:** As Front Channel Logout depends on an invisible iframe from keycloak that points to different domains, your browser's Content Security Policy will normally refuse to make the request. In order to make this work, you will need to install a browser extension that disables applying any CSP headers. This will lower your browser's protection, so please make sure to remove or disable the extension as soon as you're done with the test.
132+
133+
1. To log out, navigate to `https://fclo-one.example.com/logout`. Your session will be terminated, and you will be
134+
redirected to the default post logout URI `https://fclo-one.example.com/_logout`.
135+
![logout](./logout.webp). You can also initiate this logout from the other webapp as well
136+
2. To confirm that you have been logged out, navigate to `https://fclo-one.example.com` or `https://fclo-two.example.com`. You will be redirected to Keycloak to log in again.
137+
3. To confirm that front channel logout was responsible for this, you can look at the `nginx-ingress` pod's logs. You should look for the following two lines:
138+
139+
```text
140+
OIDC Front-Channel Logout initiated for sid: <uuid v4>
141+
GET /front_channel_logout?sid=<uuid v4>
142+
```
143+
144+
These should show up twice, once for each client.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: fclo-secret-one
5+
type: nginx.org/oidc
6+
data:
7+
client-secret: <client secret here>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: fclo-secret-two
5+
type: nginx.org/oidc
6+
data:
7+
client-secret: <client secret here>
153 KB
Loading
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: keycloak
5+
labels:
6+
app: keycloak
7+
spec:
8+
ports:
9+
- name: http
10+
port: 8080
11+
targetPort: 8080
12+
selector:
13+
app: keycloak
14+
---
15+
apiVersion: apps/v1
16+
kind: Deployment
17+
metadata:
18+
name: keycloak
19+
labels:
20+
app: keycloak
21+
spec:
22+
replicas: 1
23+
selector:
24+
matchLabels:
25+
app: keycloak
26+
template:
27+
metadata:
28+
labels:
29+
app: keycloak
30+
spec:
31+
containers:
32+
- name: keycloak
33+
image: quay.io/keycloak/keycloak:26.4
34+
args: ["start-dev"]
35+
env:
36+
- name: KC_BOOTSTRAP_ADMIN_USERNAME
37+
value: "admin"
38+
- name: KC_BOOTSTRAP_ADMIN_PASSWORD
39+
value: "admin"
40+
- name: KC_PROXY_HEADERS
41+
value: "xforwarded"
42+
ports:
43+
- name: http
44+
containerPort: 8080
45+
- name: https
46+
containerPort: 8443
47+
readinessProbe:
48+
httpGet:
49+
path: /realms/master
50+
port: 8080
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Keycloak Setup for Front Channel Logout example
2+
3+
This guide will help you configure KeyCloak using its administration dashboard:
4+
5+
- Create two `client`s with IDs `fclo-one` and `fclo-two`.
6+
- Add a user `nginx-user` with the password `test`.
7+
8+
**Notes**:
9+
10+
- This guide has been tested with keycloak 26.4 and later. If you modify `keycloak.yaml` to use an older version,
11+
Keycloak may not start correctly or the commands in this guide may not work as expected. The Keycloak OpenID
12+
endpoints in `oidc-one.yaml` and `oidc-two.yaml` might also be different in older versions of Keycloak.
13+
- if you changed the admin username and password for Keycloak in `keycloak.yaml`, modify the commands accordingly.
14+
15+
Steps:
16+
17+
1. Make sure that you can reach the Keycloak admin page by going to <https://keycloak.example.com>
18+
2. Log in with the admin username and password that's in the `keycloak.yaml` file
19+
3. Create the user `nginx-user` by clicking the Users menu on the left sidebar, and then the Add User button
20+
1. Set "email verified" to be true, enter username as `nginx-user`, and click Create
21+
2. After you created the user, click the Credentials tab (second from the left), and click Set Password button
22+
3. Enter a password, and make sure the Temporary toggle is turned off. Click Save, then click the red Save Password prompt
23+
4. Create the two clients. Start by clicking the Client menu option on the sidebar on the left
24+
5. For each of the clients
25+
1. Click the blue Create Client button
26+
2. Enter a new Client ID: either `fclo-one` or `fclo-two`. These are important, as the yaml files refer to the clients by them
27+
3. Enter a name so they show up on a logout page, this can be anything you choose, as long as it's not empty
28+
4. Make sure the Always Display in UI toggle is turned on
29+
5. Click Next
30+
6. Set Client Authentication to be "On"
31+
7. Click Next
32+
8. For root and home urls, enter `https://fclo-one.example.com`. Adjust to `fclo-two` for the other one
33+
9. As valid redirect URIs, enter `https://fclo-one.example.com:443/*`. Both the port and the asterisk are important. Adjust to `fclo-two` for the other one
34+
10. Click Save
35+
11. Scroll down to the bottom to the Front Channel Logout section
36+
12. Enter the front channel logout url: `https://fclo-one.example.com/front_channel_logout`. Adjust to `fclo-two` for the other client
37+
13. Click save
38+
14. Click on the Credentials tab at the top, and copy the Client Secret
39+
15. In your terminal, base64 encode that secret with the following command: `echo -n "<secret>" | base64`
40+
16. Copy the result into the `client-secret-one.yaml` file or `client-secret-two.yaml` file
47.3 KB
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
kind: ConfigMap
2+
apiVersion: v1
3+
metadata:
4+
name: nginx-config
5+
namespace: nginx-ingress
6+
data:
7+
zone-sync: "true"
8+
resolver-addresses: kube-dns.kube-system.svc.cluster.local
9+
resolver-valid: 5s
10+
error-log-level: "debug"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: k8s.nginx.org/v1
2+
kind: Policy
3+
metadata:
4+
name: oidc-one-policy
5+
spec:
6+
oidc:
7+
clientID: fclo-one
8+
clientSecret: fclo-secret-one
9+
authEndpoint: https://keycloak.example.com/realms/master/protocol/openid-connect/auth
10+
tokenEndpoint: http://keycloak.nginx-ingress.svc.cluster.local:8080/realms/master/protocol/openid-connect/token
11+
jwksURI: http://keycloak.nginx-ingress.svc.cluster.local:8080/realms/master/protocol/openid-connect/certs
12+
endSessionEndpoint: https://keycloak.example.com/realms/master/protocol/openid-connect/logout
13+
scope: openid+profile+email
14+
accessTokenEnable: true

0 commit comments

Comments
 (0)