Skip to content

Commit 0aca31e

Browse files
haywoodshpre-commit-ci[bot]“shaun-nx”vepatelADubhlaoich
authored
Import JWKS from URL on JWT policy (#3347)
* add new crd fields and validation functions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * update template * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update validation for policy.go * Remove unused tests for VirtualServer * Remove TODO comments * Update controller to not create secretRef for JWK policy when using JwksURI field. Python tests added for update. * Add README to jwks example folder * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update CRDs and README * Update jwks_uri location to proxy_pass to an upstream * Prevent Nginx reload fail when JwksUri host can't be resolved * Update template to make unique proxy cache directory * Update README * Remove comments and blank space * Update template to check if JwksUri.JwksHost is empty * Update README to add example of ConfigMap with resolver * Allow user input for uri scheme and remove tests * update unit tests * update unit tests * add web docs for jwksURI feature * update readme * Fixes typo, adds proper title capitalisation Co-authored-by: Alan Dooley <ADubhlaoich@users.noreply.github.com> Signed-off-by: Venktesh Shivam Patel <ve.patel@f5.com> * Update docs, jwksuri readme & example * set proxy_cache_valid to 12h * Updates to example files and README * Revert jwks example yaml files * update readme to include links to docs * Update REAMDE * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: update github url for app-protect-waf (#3412) * Add spacing * update readme formatting * Code review updates * use validateTime instead of a new function. Signed-off-by: Venktesh Shivam Patel <ve.patel@f5.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: “shaun-nx” <“s.odonovan@f5.com”> Co-authored-by: Venktesh <ve.patel@f5.com> Co-authored-by: Alan Dooley <ADubhlaoich@users.noreply.github.com> Co-authored-by: Jcahilltorre <78599298+Jcahilltorre@users.noreply.github.com> Co-authored-by: Shaun <s.odonovan@f5.com>
1 parent 7b8ccb8 commit 0aca31e

File tree

20 files changed

+641
-34
lines changed

20 files changed

+641
-34
lines changed

deployments/common/crds/k8s.nginx.org_policies.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ spec:
100100
description: JWTAuth holds JWT authentication configuration.
101101
type: object
102102
properties:
103+
jwksURI:
104+
type: string
105+
keyCache:
106+
type: string
103107
realm:
104108
type: string
105109
secret:

deployments/helm-chart/crds/k8s.nginx.org_policies.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ spec:
100100
description: JWTAuth holds JWT authentication configuration.
101101
type: object
102102
properties:
103+
jwksURI:
104+
type: string
105+
keyCache:
106+
type: string
103107
realm:
104108
type: string
105109
secret:

docs/content/configuration/policy-resource.md

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,13 @@ policies:
163163
```
164164
In this example the Ingress Controller will use the configuration from the first policy reference `basic-auth-policy-one`, and ignores `basic-auth-policy-two`.
165165

166-
### JWT
166+
### JWT Using Local Kubernetes Secret
167167

168168
> Note: This feature is only available in NGINX Plus.
169169

170170
The JWT policy configures NGINX Plus to authenticate client requests using JSON Web Tokens.
171171

172-
For example, the following policy will reject all requests that do not include a valid JWT in the HTTP header `token`:
172+
The following example policy will reject all requests that do not include a valid JWT in the HTTP header `token`:
173173
```yaml
174174
jwt:
175175
secret: jwk-secret
@@ -194,7 +194,7 @@ We use the `requestHeaders` of the [Action.Proxy](/nginx-ingress-controller/conf
194194
The value of the `${jwt_claim_user}` variable is the `user` claim of a JWT. For other claims, use `${jwt_claim_name}`, where `name` is the name of the claim. Note that nested claims and claims that include a period (`.`) are not supported. Similarly, use `${jwt_header_name}` where `name` is the name of a header. In our example, we use the `alg` header.
195195

196196

197-
> Note: The feature is implemented using the NGINX Plus [ngx_http_auth_jwt_module](https://nginx.org/en/docs/http/ngx_http_auth_jwt_module.html).
197+
> Note: This feature is implemented using the NGINX Plus [ngx_http_auth_jwt_module](https://nginx.org/en/docs/http/ngx_http_auth_jwt_module.html).
198198

199199
{{% table %}}
200200
|Field | Description | Type | Required |
@@ -206,7 +206,43 @@ The value of the `${jwt_claim_user}` variable is the `user` claim of a JWT. For
206206

207207
#### JWT Merging Behavior
208208

209-
A VirtualServer/VirtualServerRoute can reference multiple JWT policies. However, only one can be applied. Every subsequent reference will be ignored. For example, here we reference two policies:
209+
A VirtualServer/VirtualServerRoute can reference multiple JWT policies. However, only one can be applied: every subsequent reference will be ignored. For example, here we reference two policies:
210+
```yaml
211+
policies:
212+
- name: jwt-policy-one
213+
- name: jwt-policy-two
214+
```
215+
In this example the Ingress Controller will use the configuration from the first policy reference `jwt-policy-one`, and ignores `jwt-policy-two`.
216+
217+
### JWT Using JWKS From Remote Location
218+
219+
> Note: This feature is only available in NGINX Plus.
220+
221+
The JWT policy configures NGINX Plus to authenticate client requests using JSON Web Tokens, allowing import of the keys (JWKS) for JWT policy by means of a URL (for a remote server or an identity provider) as a result they don't have to be copied and updated to the IC pod.
222+
223+
The following example policy will reject all requests that do not include a valid JWT in the HTTP header fetched from the identity provider:
224+
```yaml
225+
jwt:
226+
realm: MyProductAPI
227+
token: $http_token
228+
jwksURI: <uri_to_remote_server_or_idp>
229+
keyCache: 1h
230+
```
231+
232+
> Note: This feature is implemented using the NGINX Plus directive [auth_jwt_key_request](http://nginx.org/en/docs/http/ngx_http_auth_jwt_module.html#auth_jwt_key_request) under [ngx_http_auth_jwt_module](https://nginx.org/en/docs/http/ngx_http_auth_jwt_module.html).
233+
234+
{{% table %}}
235+
|Field | Description | Type | Required |
236+
| ---| ---| ---| --- |
237+
|``jwksURI`` | The remote URI where the request will be sent to retrieve JSON Web Key set| ``string`` | Yes |
238+
|``keyCache`` | Enables the caching of keys that are obtained from the ``jwksURI`` and sets a valid time for expiration | ``string`` | Yes |
239+
|``realm`` | The realm of the JWT. | ``string`` | Yes |
240+
|``token`` | The token specifies a variable that contains the JSON Web Token. By default the JWT is passed in the ``Authorization`` header as a Bearer Token. JWT may be also passed as a cookie or a part of a query string, for example: ``$cookie_auth_token``. Accepted variables are ``$http_``, ``$arg_``, ``$cookie_``. | ``string`` | No |
241+
{{% /table %}}
242+
243+
#### JWT Merging Behavior
244+
245+
This behavior is similar to using a local Kubernetes secret where a VirtualServer/VirtualServerRoute can reference multiple JWT policies. However, only one can be applied: every subsequent reference will be ignored. For example, here we reference two policies:
210246
```yaml
211247
policies:
212248
- name: jwt-policy-one
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# JWKS
2+
3+
In this example we deploy a web application, configure load balancing with a VirtualServer, and apply a JWT policy.
4+
Instead of using a local secret to verify the client request such as in the [jwt](https://github.com/nginxinc/kubernetes-ingress/tree/main/examples/custom-resources/jwt) example, we will define an external Identity Provider (IdP) using the `JwksURI` field.
5+
6+
We will be using a deployment of [KeyCloak](https://www.keycloak.org/) to work as our IdP in this example.
7+
In this example, KeyCloak is deployed as a single container for the purpose of exposing it with an Ingress Controller.
8+
9+
## Prerequisites
10+
11+
1. Follow the [installation](https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/) instructions to deploy the Ingress Controller.
12+
13+
2. Save the public IP address of the Ingress Controller into `/etc/hosts` of your machine:
14+
```
15+
...
16+
17+
XXX.YYY.ZZZ.III webapp.example.com
18+
XXX.YYY.ZZZ.III keycloak.example.com
19+
```
20+
Here `webapp.example.com` is the domain for the web application and `keycloak.example.com` is the domain for Keycloak.
21+
22+
## Step 1 - Deploy a TLS Secret
23+
24+
Create a secret with the TLS certificate and key that will be used for TLS termination of the web application and Keycloak:
25+
```
26+
$ kubectl apply -f tls-secret.yaml
27+
```
28+
29+
## Step 2 - Deploy a Web Application
30+
31+
Create the application deployment and service:
32+
```
33+
$ kubectl apply -f webapp.yaml
34+
```
35+
36+
## Step 3 - Deploy Keycloak
37+
38+
1. Create the Keycloak deployment and service:
39+
```
40+
$ kubectl apply -f keycloak.yaml
41+
```
42+
1. Create a VirtualServer resource for Keycloak:
43+
```
44+
$ kubectl apply -f virtual-server-idp.yaml
45+
```
46+
47+
## Step 4 - Configure Keycloak
48+
49+
To set up Keycloak:
50+
1. To connect to Keycloak, use `https://keycloak.example.com`.
51+
52+
2. Create a new Realm. We will use `jwks-example` for this example. This can be done by selecting the dropdown menu on the left and selecting `Create Realm`
53+
54+
3. Create a new Client called `jwks-client`. This can be done by selecting the `Client`s tab on the left and then selecting `Create client`.
55+
- When creating the Client, ensure both `Client authentication` and `Authorization` are enabled.
56+
57+
4. Once the client is created, navigate to the `Credentials` tab for that client and copy the client secret.
58+
- This can be saved in the `SECRET` shell variable for later:
59+
```
60+
export SECRET=<client secret>
61+
```
62+
63+
5. Create a new User called `jwks-user` by selecting the Users tab on the left and then selecting Create client.
64+
65+
6. Once the user is created, navigate to the `Credentials` tab for that user and select `Set password`. For this example the password can be whatever you want.
66+
- This can be saved in the `PASSWORD` shell variable for later:
67+
```
68+
export PASSWORD=<user password>
69+
```
70+
71+
## Step 5 - Deploy the JWT Policy
72+
73+
1. Create a policy with the name `jwt-policy` and configure the `JwksURI` field so that it only permits requests to our web application that contain a valid JWT.
74+
In the example policy below, replace `<your_realm>` with the realm created in Step 4. We used `jwks-example` as our realm name.
75+
The value of `spec.jwt.token` is set to `$http_token` in this example as we are sending the client token in an HTTP header.
76+
```
77+
apiVersion: k8s.nginx.org/v1
78+
kind: Policy
79+
metadata:
80+
name: jwt-policy
81+
spec:
82+
jwt:
83+
realm: MyProductAPI
84+
token: $http_token
85+
jwksURI: http://keycloak.default.svc.cluster.local:8080/realms/<your_realm>/protocol/openid-connect/certs
86+
keyCache: 1h
87+
```
88+
89+
2. Deploy the policy:
90+
```
91+
$ kubectl apply -f jwks.yaml
92+
```
93+
94+
## Step 6 - Deploy a config map with a resolver
95+
96+
If the value of `jwksURI` uses a hostname, the Ingress Controller will need to reference a resolver.
97+
This can be done by deploying a ConfigMap with the `resolver-addresses` data field
98+
```
99+
kind: ConfigMap
100+
apiVersion: v1
101+
metadata:
102+
name: nginx-config
103+
namespace: nginx-ingress
104+
data:
105+
resolver-addresses: <resolver-address>
106+
```
107+
In this example, we create a ConfigMap using Kubernetes' default DNS `kube-dns.kube-system.svc.cluster.local` for the resolver address. For more information on `resolver-addresses` and other related ConfigMap keys, please refer to our documentation [ConfigMap Resource](https://docs.nginx.com/nginx-ingress-controller/configuration/global-configuration/configmap-resource/#summary-of-configmap-keys) and our blog post [Using DNS for Service Discovery with NGINX and NGINX Plus](https://www.nginx.com/blog/dns-service-discovery-nginx-plus)
108+
109+
NOTE: When setting the value of `jwksURI` in Step 5, the response will differ depending on the IDP used. In some cases the response will be too large for NGINX to properly handle.
110+
If this occurs you will need to configure the [subrequest_output_buffer_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#subrequest_output_buffer_size) directive in the http context.
111+
This can currently be done using `http-snippets`. Please refer to our document on [snippets and custom templates](https://docs.nginx.com/nginx-ingress-controller/configuration/global-configuration/configmap-resource/#snippets-and-custom-templates) for details on how to configure this directive.
112+
113+
The code block below is an example of the updated configmap which adds `subrequest_output_buffer_size` under the http context in the nginx.conf.
114+
115+
NOTE: The value of `subrequest_output_buffer_size` is only an example value and should be changed to suite your environment.
116+
```
117+
kind: ConfigMap
118+
apiVersion: v1
119+
metadata:
120+
name: nginx-config
121+
namespace: nginx-ingress
122+
data:
123+
resolver-addresses: <resolver-address>
124+
http-snippets: |
125+
subrequest_output_buffer_size 64k;
126+
```
127+
128+
```
129+
$ kubectl apply -f nginx-config.yaml
130+
```
131+
132+
## Step 7 - Configure Load Balancing
133+
134+
Create a VirtualServer resource for the web application:
135+
```
136+
$ kubectl apply -f virtual-server.yaml
137+
```
138+
139+
Note that the VirtualServer references the policy `jwt-policy` created in Step 5.
140+
141+
## Step 8 - Get the client token
142+
143+
For the client to have permission to send requests to the web application they must send a Bearer token to the application.
144+
To get this token, run the following `curl` command:
145+
```
146+
$ export TOKEN=$(curl -k -L -X POST 'https://keycloak.example.com/realms/jwks-example/protocol/openid-connect/token' \
147+
-H 'Content-Type: application/x-www-form-urlencoded' \
148+
--data-urlencode grant_type=password \
149+
--data-urlencode scope=openid \
150+
--data-urlencode client_id=jwks-client \
151+
--data-urlencode client_secret=$SECRET \
152+
--data-urlencode username=jwks-user \
153+
--data-urlencode password=$PASSWORD \
154+
| jq -r .access_token)
155+
```
156+
157+
This command will save the token in the `TOKEN` shell variable.
158+
159+
## Step 9 - Test the Configuration
160+
161+
If you attempt to access the application without providing the bearer token, NGINX will reject your requests for that VirtualServer:
162+
```
163+
$ curl -H 'Accept: application/json' webapp.example.com
164+
<html>
165+
<head><title>401 Authorization Required</title></head>
166+
<body>
167+
<center><h1>401 Authorization Required</h1></center>
168+
<hr><center>nginx/1.23.2</center>
169+
</body>
170+
</html>
171+
```
172+
173+
If a valid bearer token is provided, the request will succeed:
174+
```
175+
$ curl -H 'Accept: application/json' -H "token: ${TOKEN}" webapp.example.com
176+
Server address: 10.42.0.7:8080
177+
Server name: webapp-5c6fdbcbf9-pt9tp
178+
Date: 13/Dec/2022:14:50:33 +0000
179+
URI: /
180+
Request ID: f1241390ac51318afa4fcc39d2341359
181+
```
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: k8s.nginx.org/v1
2+
kind: Policy
3+
metadata:
4+
name: jwt-policy
5+
spec:
6+
jwt:
7+
realm: MyProductAPI
8+
token: $http_token
9+
jwksURI: http://keycloak.default.svc.cluster.local:8080/realms/jwks-example/protocol/openid-connect/certs
10+
keyCache: 1h
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
namespace: default
20+
labels:
21+
app: keycloak
22+
spec:
23+
replicas: 1
24+
selector:
25+
matchLabels:
26+
app: keycloak
27+
template:
28+
metadata:
29+
labels:
30+
app: keycloak
31+
spec:
32+
containers:
33+
- name: keycloak
34+
image: quay.io/keycloak/keycloak:20.0.1
35+
args: ["start-dev"]
36+
env:
37+
- name: KEYCLOAK_ADMIN
38+
value: "admin"
39+
- name: KEYCLOAK_ADMIN_PASSWORD
40+
value: "admin"
41+
- name: KC_PROXY
42+
value: "edge"
43+
ports:
44+
- name: http
45+
containerPort: 8080
46+
- name: https
47+
containerPort: 8443
48+
readinessProbe:
49+
httpGet:
50+
path: /realms/master
51+
port: 8080
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
kind: ConfigMap
2+
apiVersion: v1
3+
metadata:
4+
name: nginx-config
5+
namespace: nginx-ingress
6+
data:
7+
resolver-addresses: "kube-dns.kube-system.svc.cluster.local"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: tls-secret
5+
type: kubernetes.io/tls
6+
data:
7+
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFVENDQWZtZ0F3SUJBZ0lVS2hTQzBBcnhUblYrbjBhVnNENkFVTE5VQWhZd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0dERVdNQlFHQTFVRUF3d05LaTVsZUdGdGNHeGxMbU52YlRBZUZ3MHlNVEF4TVRZd01qSXpNekZhRncwegpNVEF4TVRRd01qSXpNekZhTUJneEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHClNJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURGeU1DSlhlSm9tMTdhcUVQc01NbTNlVzlpQzFHdlI4YW8KaDJhNmgvZWRXTUFndEtWSERmR2tPQ2V5NDBEdGtXTDN3U0NvZE1McnhPcnN2Lzhuc1VablFwQmNBekxBbzBJVgptYnhoS21WaS9EMkJpb2pBcDlqVXlsMjNma2RWMFdYM3NYV0JQekhSa3RyK0ozaW83YVcvNUl0WVBNWWFYM3dmCkZYRWFXVmQ4QmJDQ0hyVlZ3ckMvem9aTEF3dFE0d1I5NUI2NHdtd2d4TEhNZDlWZDRSZ1l2U0ppc1QzWi9IRkkKTGpaTGdMa0FlMGlDci9xdmFsdnVhU3BNVmJUd1lQZ2l6YWhXSVFTYjVyd29JeUhnYXFBWnRYSEhjNSsydDVoZQpMMDc2RjgrOE84b0hpdDR6WGpsR1V4TFNjTWFPTnI2ZHI0Q256NmlXZzJNTGlJcno0VnR4QWdNQkFBR2pVekJSCk1CMEdBMVVkRGdRV0JCUTdCSGpyZHlicnpWNHIwVkRrc2k3TXFPNWRKREFmQmdOVkhTTUVHREFXZ0JRN0JIanIKZHlicnpWNHIwVkRrc2k3TXFPNWRKREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQQpBNElCQVFDdm5TdUY4dUFUWFl2VHVjVGhEcG9jKzI5RU1LVFp2VDBmSmJrNWZMaWQzYjhFTDQxdk5tTjRwUTUrCmJtSFh1bkhLL29aSm43bWVNTngwc0ZQMW1Pa1U5MXBqZVJLWmoxOXVNQjlvTVBreXdXRENuQ1BHYWtFUHpxOS8KWjFwcERKQ0FJc2cvME8wZ1BCMDdFSm9RcU0wdDlZc3BuMlJ4djMwUGdBZ3ZuSXduUlNzUWpvOEpxQ1VuemZJLwpPdXovNVl1UkhJRHQzY0RpdTdzWG1DTW01cFJ5eUd2WGZiWEsrSVFWOHZDRTZlZS9FTlNFcnB0NUdzeVNURjZKCk5LdDhXM1VwNkUvL2dwMkRvTXBxS0tGQkE0aG5OQXVzQVphTkNQdi9EY0xueG9xQUp4S0V5cmpxelJBeTlCRXkKRzBhSTJ5bitKWW5yVW8wMmc1OWFXalZMTzg4RwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
8+
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRREZ5TUNKWGVKb20xN2EKcUVQc01NbTNlVzlpQzFHdlI4YW9oMmE2aC9lZFdNQWd0S1ZIRGZHa09DZXk0MER0a1dMM3dTQ29kTUxyeE9ycwp2Lzhuc1VablFwQmNBekxBbzBJVm1ieGhLbVZpL0QyQmlvakFwOWpVeWwyM2ZrZFYwV1gzc1hXQlB6SFJrdHIrCkozaW83YVcvNUl0WVBNWWFYM3dmRlhFYVdWZDhCYkNDSHJWVndyQy96b1pMQXd0UTR3Ujk1QjY0d213Z3hMSE0KZDlWZDRSZ1l2U0ppc1QzWi9IRklMalpMZ0xrQWUwaUNyL3F2YWx2dWFTcE1WYlR3WVBnaXphaFdJUVNiNXJ3bwpJeUhnYXFBWnRYSEhjNSsydDVoZUwwNzZGOCs4TzhvSGl0NHpYamxHVXhMU2NNYU9OcjZkcjRDbno2aVdnMk1MCmlJcno0VnR4QWdNQkFBRUNnZ0VBQXhBcjR6VEFCK3k0R0Z6WXlIU3MreGwzWHlaYnVvSTdFbXNlYlM4ajU1enoKUk01bmJPVkxZOGEyM3E5a1Z3bVVaYy9vNkpMK1hkWnI2UVRFTitJbisvdHM3dS9odmxnSTh2cXhqek92NUV1Ugp6RXJQK1dQZ0dOT1ZoZnovcjlXUlpiZXE0VGlRVmZXWFRLNWgwUVAxT0RhYTdkL3JGWWQ3RGFRd1h6OFkrc080CnhqV0dNNFprOW1oWm1PbG9nZjNtYyszUFhYTWV6RFRMY2kzRWNpZVlaTkhTeXIzWkg2NU8rSkdsOFZ2bkZUWS8KQytQZi9tYmJKL282dlNWWDNWQUVIM29BY05qd1dqMkdBNUhiRk5RTnV0ckhRcnNkR0ZqUVB5aHNBYjNOV1h2bwo2M3hoS1NNbHpxSWd2WXZMbENOS0VjZmJsVjRuelJ4NVhhM0dzZjJkUFFLQmdRRDlYeEs4ekhpN2g4WjlQV2sxCktDZFlvZDFVa2ViWktYUVQvOUtNcmhrOE9abG1oV2hFK1lBY3lJRElVeFZuZ2xkR0d3RVViTFcyWEVnVStQVmEKM1ZlaUNCTlRWM3FwV3lYWXdIdG9yYm5WbGtlMGh4eE9WakhvSmpZWitmV0h6MDU0algvYkdsdWp5bVJGMWpoWApuMnhNUW5RUkV0S2FGN0R2d2FGK083dGExd0tCZ1FESDFndWRlVCsvQ3M1R3g3eEkwUnhwRUt4c0FtcUV3blBECklsaHoxZHJqbGZFaTRPZ25wK0ZOK05acGJiMHRaWmUyTTM2QXpMVENIUURmQVNJTlBDMkxzOHEvTjAyR2xzcG8KalVTd3M4cWc2N2ZjcG1UN1FVVTVMZmZuaDE3S1A5ZEdCdlRuK3Vza1MwVjRFZ2M0Ti9lS2pUQi9xcjYzYWRHUwp4dmRaYzdnNjl3S0JnRE9CQWdRUzVHL3FkN1M1cVFzL01GQmFCdTNNQXNzZUhCUjhxa1lpbGNxaVFzYU9VOVhCCmlnTlAxcTNpQmJYV3p2clhQbTd5Y2pXeHFJMXExaVUwWFQzNHVrVDB3V0J2d00vQXdOVlVpelFacWxYT0tUamIKV0tYQ0xyazFFRzRjKyt5Umh1MzQrNnZkMW1oRDFZd3FRZzkyYXJXVngrMis1eDYxazZoZmFBUmRBb0dCQU1Kcgp0QmM4VE5IQVlKb3FYenYwL3BBVm9icmZ5dVJwRHhsdFErTkd6OVFXSUduUHFPNVQvZmJQUDBPSmVjRStFeEU0CkhqNlBhdGxrUUdHMmgzdWE3YkQ2ZGluOVV4YTdoQ2VlTVpNOUNNbnhLNHVuODUwampvYW4rNFd0aFlKK0JDSmsKU0VlZUxzRzczZFdJcks5OGZBQzNodFRldVBoWElvZUx2a0N3UGpCWEFvR0JBUFBteVJJRGs5bUF5M2ZINnBtVwplRWlqYlBWbFdDd3FjalI5ZjQ0L3duVEpha0h4cVVxRk04cTVLNnJJejdPMmMvcDdmTm83andrVHc0R0hIVWcrCjQyVkpGOXRrdnRDbEhOZ3l6cXNjT3FjN0p2ZDNyYnBFbGVpNGgyTHo4Z0RDNFo4WldqWDBBKzVTaTlQd3RMaFEKN3pBZEJUMHk5WjZuNGYxMVg0UWhKSkR1Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: k8s.nginx.org/v1
2+
kind: VirtualServer
3+
metadata:
4+
name: keycloak
5+
spec:
6+
host: keycloak.example.com
7+
tls:
8+
secret: tls-secret
9+
redirect:
10+
enable: true
11+
upstreams:
12+
- name: keycloak
13+
service: keycloak
14+
port: 8080
15+
routes:
16+
- path: /
17+
action:
18+
pass: keycloak
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: k8s.nginx.org/v1
2+
kind: VirtualServer
3+
metadata:
4+
name: webapp
5+
spec:
6+
host: webapp.example.com
7+
policies:
8+
- name: jwt-policy
9+
upstreams:
10+
- name: webapp
11+
service: webapp-svc
12+
port: 80
13+
routes:
14+
- path: /
15+
action:
16+
pass: webapp

0 commit comments

Comments
 (0)