Skip to content

Commit

Permalink
Add ingress for rewriting Keycloak requests from /auth to /
Browse files Browse the repository at this point in the history
Keycloak based on Wilfly had a default relativ path of /auth.
Since the migration to Quarkus this would be / by default.
Existing clients can not be migrated in a big bang scenario.

This adds the capability to serve the Keycloak requests on / and
/auth at the same time. NGNIX-Ingress and OpenShift has been tested.
  • Loading branch information
Gabriel Mainberger committed Jan 8, 2024
1 parent 2553f9b commit 9536940
Show file tree
Hide file tree
Showing 50 changed files with 1,612 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .cruft.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"name": "keycloak",
"slug": "keycloak",
"parameter_key": "keycloak",
"test_cases": "builtin external openshift openshift-postgres",
"test_cases": "builtin builtin-auth-rewrite external openshift openshift-auth-rewrite openshift-postgres",
"add_lib": "n",
"add_pp": "y",
"add_golden": "y",
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ jobs:
matrix:
provider:
- builtin
- builtin-auth-rewrite
- external
- openshift
- openshift-auth-rewrite
- openshift-postgres
defaults:
run:
Expand Down Expand Up @@ -62,8 +64,10 @@ jobs:
matrix:
provider:
- builtin
- builtin-auth-rewrite
- external
- openshift
- openshift-auth-rewrite
- openshift-postgres
defaults:
run:
Expand Down
2 changes: 1 addition & 1 deletion Makefile.vars.mk
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,4 @@ KUBENT_IMAGE ?= ghcr.io/doitintl/kube-no-trouble:latest
KUBENT_DOCKER ?= $(DOCKER_CMD) $(DOCKER_ARGS) $(root_volume) --entrypoint=/app/kubent $(KUBENT_IMAGE)

instance ?= builtin
test_instances = tests/builtin.yml tests/external.yml tests/openshift.yml tests/openshift-postgres.yml
test_instances = tests/builtin.yml tests/builtin-auth-rewrite.yml tests/external.yml tests/openshift.yml tests/openshift-auth-rewrite.yml tests/openshift-postgres.yml
16 changes: 16 additions & 0 deletions class/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,22 @@ parameters:
cert: "?{vaultkv:${cluster:tenant}/${cluster:name}/${_instance}/ingress-cert}"
certKey: "?{vaultkv:${cluster:tenant}/${cluster:name}/${_instance}/ingress-cert-key}"

# Rewriting /auth requests to /
# Used for a migration scanario meanwhile client configs may use /auth or / at the same time
# By rewriting the TLS content, passtrough is technically impossible, so not implemented
ingressAuthRewrite:
enabled: false
annotations:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/proxy-buffer-size: 16k
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
route.openshift.io/termination: reencrypt
haproxy.router.openshift.io/rewrite-target: /
ingressClassName: null
tls:
secretName: ${keycloak:ingress:tls:secretName}

route:
enabled: false

Expand Down
4 changes: 4 additions & 0 deletions class/keycloak.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ parameters:
- keycloak/component/prometheus-netpol.jsonnet
input_type: jsonnet
output_path: ${_instance}
- input_paths:
- keycloak/component/auth-rewrite.jsonnet
input_type: jsonnet
output_path: ${_instance}
- output_path: ${_instance}/01_keycloak_helmchart
input_type: helm
output_type: yaml
Expand Down
64 changes: 64 additions & 0 deletions component/auth-rewrite.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
local kap = import 'lib/kapitan.libjsonnet';
local kube = import 'lib/kube.libjsonnet';
local inv = kap.inventory();
local params = inv.parameters.keycloak;

local ingress_name = 'keycloakx-auth-rewrite';
local keycloak_name = 'keycloakx';
local ingress_class_name =
if params.ingressAuthRewrite.ingressClassName != null then
{ ingressClassName: params.ingressAuthRewrite.ingressClassName }
else
{};
local ingress_path =
if inv.parameters.facts.distribution == 'openshift4' then
'/auth'
else
'/auth(/|$)(.*)';

local ingress =
kube.Ingress(ingress_name) {
metadata+: {
annotations: params.ingressAuthRewrite.annotations,
labels: params.labels,
},
spec+:
ingress_class_name
{
rules: [
{
host: params.fqdn,
http:
{
paths: [
{
path: ingress_path,
pathType: 'Prefix',
backend: {
service: {
name: keycloak_name + '-http',
port: {
name: params.helm_values.ingress.servicePort,
},
},
},
},
],
},
},
],
tls: [
{
hosts: [
params.fqdn,
],
secretName: params.ingressAuthRewrite.tls.secretName,
},
],

},
};

{
[if params.ingressAuthRewrite.enabled then '20_ingress_auth_rewrite']: ingress,
}
35 changes: 35 additions & 0 deletions docs/modules/ROOT/pages/how-tos/change-relative-path.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
= Change relative path /auth to /

The current default relativ path of Keycloak is `/`.
Keycloak based on Quarkus

[source,yaml]
----
parameters:
keycloak:
helm_values:
http:
# Default for Keycloak Quarkus
relativePath: "/"
----

== OpenID Connect Discovery

Because of this change the well known openid configuration still shows the old path.

```
Original path: https://x.x.x.x/auth/realms/my_realm/.well-known/openid-configuration
Ajusted path: https://x.x.x.x/realms/my_realm/.well-known/openid-configuration
```

The verification check does detect the different paths fail and prevent the login.

```
ERROR: Failed to initialise OAuth2 Proxy: error intiailising provider: could not create provider data: error building OIDC ProviderVerifier: could not get verifier builder: error while discovery OIDC configuration: oidc: issuer did not match the issuer returned by provider,
```

As a example for oauth2-proxy: To prevent the OIDC client does reject itself you can add the https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#command-line-options[parameter] to ignore the different paths:

```
--insecure-oidc-skip-issuer-verification
```
57 changes: 57 additions & 0 deletions docs/modules/ROOT/pages/references/parameters.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,63 @@ type:: string
default:: `?{vaultkv:${cluster:tenant}/${cluster:name}/${_instance}/ingress-cert-key}`


=== `ingressAuthRewrite.enabled`

[horizontal]
type:: bool
default:: `false`

Creates an additional ingress object to rewrite all traffic from `/auth` to `/`.

This is intended to be used for the migration from the realm path including `/auth` to the current Keycloak default of `/`.
The clients can interact with Keycloak on both URLs.
This allows a soft migration over time.


[IMPORTANT]
====
Keycloak relative path MUST be set to `/` to be.
[source,bash]
----
parameters:
keycloak:
helm_values:
http:
relativePath: "/"
----
====


=== `ingressAuthRewrite.annotations`

[horizontal]
type:: dict
default:: `{}`

Annotations for the `/auth` rewrite ingrss object.


== `ingressAuthRewrite.ingressClassName`

[horizontal]
type:: string
default:: `null`

IngressClassName for the `/auth` rewrite ingrss object.


== `ingressAuthRewrite.tls.secretName`

[horizontal]
type:: string
default:: `${keycloak:ingress:tls:secretName}`

TLS secret name for the `/auth` rewrite ingrss object.


== `route.enabled`

[horizontal]
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/partials/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* xref:how-tos/upgrade-12.x-to-13.x.adoc[Upgrade 12.x to 13.x]
* xref:how-tos/openshift-4.adoc[Install on OpenShift 4]
* xref:how-tos/pin-versions.adoc[Pin versions]
* xref:how-tos/change-relative-path.adoc[Change relative path /auth to /]
.Explanations
* xref:explanations/default-features.adoc[Default features]
Expand Down
52 changes: 52 additions & 0 deletions tests/builtin-auth-rewrite.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
applications:
- prometheus

parameters:
kapitan:
dependencies:
- type: https
source: https://raw.githubusercontent.com/projectsyn/component-prometheus/master/lib/prometheus.libsonnet
output_path: vendor/lib/prometheus.libsonnet

prometheus:
defaultInstance: monitoring

keycloak:
namespaceLabels:
test: testing
extraEnv:
FOO:
value: "bar"
KC_DB_URL_PORT:
value: "patched"
extraInitContainers:
theme-provider:
image: company/keycloak-theme:v1.0.0
imagePullPolicy: IfNotPresent
command:
- sh
args:
- -c
- |
echo "Copying theme..."
cp -R /theme/* /company-theme
volumeMounts:
- name: theme
mountPath: /company-theme
extraVolumes:
theme:
emptyDir: {}
extraVolumeMounts:
test:
name: theme
readOnly: true
mountPath: /opt/test
ingressAuthRewrite:
enabled: true
helm_values:
networkPolicy:
enabled: true
http:
# Default for Keycloak Quarkus
relativePath: "/"
21 changes: 21 additions & 0 deletions tests/builtin-auth-rewrite/ingress_auth_reqrite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package builtin_auth_rewrite

import (
"testing"

"github.com/projectsyn/component-keycloak/common"
"github.com/stretchr/testify/assert"
networkingv1 "k8s.io/api/networking/v1"
)

var (
basePath = "../../compiled/builtin-auth-rewrite/builtin-auth-rewrite"
ingressPath = "/20_ingress_auth_rewrite.yaml"
)

func Test_IngressApiVersion(t *testing.T) {
subject := &networkingv1.Ingress{}
scheme := common.NewSchemeWithDefault(t)
ingress := common.DecodeWithSchema(t, basePath+ingressPath, subject, scheme).(*networkingv1.Ingress)
assert.Equal(t, "keycloakx-auth-rewrite", ingress.Name)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
spec:
ignoreDifferences:
- group: ''
jsonPointers:
- /imagePullSecrets
kind: ServiceAccount
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Namespace
metadata:
annotations: {}
labels:
monitoring.syn.tools/monitoring: 'true'
name: syn-builtin-auth-rewrite
test: testing
name: syn-builtin-auth-rewrite
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-production
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
route.openshift.io/termination: reencrypt
labels:
app.kubernetes.io/component: keycloak
app.kubernetes.io/instance: builtin-auth-rewrite
app.kubernetes.io/managed-by: commodore
app.kubernetes.io/name: keycloak
app.kubernetes.io/version: 21.1.2
helm.sh/chart: keycloakx-2.2.2
name: keycloakx
namespace: syn-builtin-auth-rewrite
spec:
rules:
- host: keycloak.example.com
http:
paths:
- backend:
service:
name: keycloakx-http
port:
name: https
path: /
pathType: Prefix
tls:
- hosts:
- keycloak.example.com
secretName: ingress-tls
Loading

0 comments on commit 9536940

Please sign in to comment.