Skip to content

Commit

Permalink
Keycloak v19 updates (#3281)
Browse files Browse the repository at this point in the history
* Update tests
* Fix for custom value of http.relativePath
* Set Keycloak to be disabled by default
* Change proxy mode
* Idempotent autogenerated certs
* Idempotent autogenerated certs - another approach
* Add atomic option
* Add loop label
* Mount CA cert
* Fix for restarting PG apps
* Gather facts for postgresql
* Better when condition
* Set database.hostname to pgbouncer when enabled
* Update alternative names of tls.crt
* Add doc
* Enable metrics by default for readinessProbe
* Add podAntiAffinity to be just preferred
* Add busybox image for dbchecker option
* Use local repo also for dbchecker image
* Update chart version to bump its appVersion
  • Loading branch information
tomasz-baran authored Oct 10, 2022
1 parent 8d3db1a commit 3b574be
Show file tree
Hide file tree
Showing 19 changed files with 299 additions and 129 deletions.
4 changes: 4 additions & 0 deletions ansible/playbooks/keycloak.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
---
# Ansible playbook that deploys Keycloak on Kubernetes

- hosts: postgresql
gather_facts: true
tasks: []

- hosts: 127.0.0.1
gather_facts: false
become: false
Expand Down
2 changes: 1 addition & 1 deletion ansible/playbooks/roles/keycloak/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
keycloak_helm_chart_file_name: keycloakx-1.6.0.tgz
keycloak_helm_chart_file_name: keycloakx-1.6.1.tgz
25 changes: 16 additions & 9 deletions ansible/playbooks/roles/keycloak/tasks/create-database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
set_fact:
postgres_primary: "{{ item.item }}"
loop: "{{ in_recovery_state.results }}"
loop_control:
label: {in_recovery: "{{ item.in_recovery }}"}
when: not item.in_recovery

- name: Create DB objects
Expand Down Expand Up @@ -42,18 +44,23 @@
- name: Refresh password file in PgPool and users list in PgBouncer
when:
- create_keycloak_user.changed
- groups.postgresql | count > 1 or "'pgbouncer' in _chart_values.database.hostname"
- applications_vars.specification.applications is defined
vars:
_pgbouncer_spec: >-
{{ applications_vars.specification.applications | selectattr('name', '==', 'pgbouncer') }}
_pgpool_spec: >-
{{ applications_vars.specification.applications | selectattr('name', '==', 'pgpool') }}
block:
- name: Restart PgPool deployment to update pool_passwd file
when:
- _pgpool_spec | count > 0
- (_pgpool_spec | first).enabled
command: |
kubectl rollout restart deployment/pgpool -n {{ _namespace }}
vars:
_namespace: >-
{{ (applications_vars.specification.applications | selectattr('name', '==', 'pgpool') | first).namespace }}
kubectl rollout restart deployment/pgpool -n {{ (_pgpool_spec | first).namespace }}
- name: Restart PgBouncer deployment to update users list
when:
- _pgbouncer_spec | count > 0
- (_pgbouncer_spec | first).enabled
command: |
kubectl rollout restart deployment/pgbouncer -n {{ _namespace }}
vars:
_namespace: >-
{{ (applications_vars.specification.applications | selectattr('name', '==', 'pgbouncer') | first).namespace }}
kubectl rollout restart deployment/pgbouncer -n {{ (_pgbouncer_spec | first).namespace }}
3 changes: 2 additions & 1 deletion ansible/playbooks/roles/keycloak/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
include_vars:
file: roles/applications/vars/main.yml
name: applications_vars
when: groups.postgresql | count > 1 or "'pgbouncer' in _chart_values.database.hostname"
when: groups.applications is defined

- name: Include database configuration when Epiphany storage is used
include_tasks: create-database.yml
Expand Down Expand Up @@ -40,6 +40,7 @@
helm upgrade keycloak {{ download_directory }}/{{ keycloak_helm_chart_file_name }} \
-f {{ vault_location }}/keycloak-chart-values.yml \
-n {{ specification.namespace }} \
--atomic \
--create-namespace \
--install
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
#jinja2: lstrip_blocks: True

# Keep data structure in sync with Helm chart's values.
# ref: https://raw.githubusercontent.com/codecentric/helm-charts/keycloakx-1.6.0/charts/keycloakx/values.yaml
{#-
This file is used only locally to override chart's values defined in `configuration/keycloak` doc.
Keep data structure in sync with Helm chart's values.
ref: https://github.com/codecentric/helm-charts/blob/keycloakx-1.6.1/charts/keycloakx/values.yaml
-#}

{% if specification.image_registry.use_local %}
image:
repository: {{ image_registry_address }}/{{ _chart_values.image.repository }}
{% else %}
image:
repository: {{ _chart_values.image.repository }}
dbchecker:
image:
repository: {{ image_registry_address }}/{{ _chart_values.dbchecker.image.repository }}
{% endif %}

{% if specification.database.epiphany_managed and _chart_values.database.hostname | lower == 'autoconfigured' %}
database:
{% if groups.postgresql | count == 1 %}
hostname: {{ hostvars[groups.postgresql[0]].ansible_default_ipv4.address }}
{% set pgbouncer_items = applications_vars.specification.applications | default([]) | selectattr('name', '==', 'pgbouncer') %}
{% if pgbouncer_items | count > 0 and pgbouncer_items[0].enabled is defined and pgbouncer_items[0].enabled %}
hostname: {{ pgbouncer_items[0].pgbouncer.env.DB_HOST }}
{% else %}
hostname: {{ (applications_vars.specification.applications | selectattr('name', '==', 'pgbouncer') | first).pgbouncer.env.DB_HOST }}
hostname: {{ hostvars[groups.postgresql[0]].ansible_default_ipv4.address }}
{% endif %}
{% endif %}
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ files:

keycloak:
options:
- url: 'https://github.com/codecentric/helm-charts/releases/download/keycloakx-1.6.0/keycloakx-1.6.0.tgz'
sha256: 11c5536008f47257ea6255d6129948df1178c7d009519b6a460a35995e74356a
- url: 'https://github.com/codecentric/helm-charts/releases/download/keycloakx-1.6.1/keycloakx-1.6.1.tgz'
sha256: 9a29ccf04343b2b1b8a877e9259aa07332606945017d8c17d85702506aac38f3
deps: [keycloak]

# --- OpenSearch Bundle ---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ images:
sha1: 003cefb9c3309c55fa67f68067db9355750513d6

keycloak:
# optional - can be used by Helm chart to check database readiness at startup
'docker.io/busybox:1.32':
sha1: 90402d70a03ed8248ec353ec8158da8cc3e8066a

'quay.io/keycloak/keycloak:19.0.2':
sha1: 484d69fc4690b4816ec4c1ad66ad2352017aa19c

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ files:

keycloak:
options:
- url: 'https://github.com/codecentric/helm-charts/releases/download/keycloakx-1.6.0/keycloakx-1.6.0.tgz'
sha256: 11c5536008f47257ea6255d6129948df1178c7d009519b6a460a35995e74356a
- url: 'https://github.com/codecentric/helm-charts/releases/download/keycloakx-1.6.1/keycloakx-1.6.1.tgz'
sha256: 9a29ccf04343b2b1b8a877e9259aa07332606945017d8c17d85702506aac38f3
deps: [keycloak]

# --- OpenSearch Bundle ---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ images:
sha1: 2705b05f9ac0bda6a4136fc8d66dc99295daa95d

keycloak:
# optional - can be used by Helm chart to check database readiness at startup
'docker.io/busybox:1.32':
sha1: 0355284f96b69167cc50641845691ef737724414

'quay.io/keycloak/keycloak:19.0.2':
sha1: ffbe5f8fff32eaa1f14043c5aa5f558a4ba17b52

Expand Down
2 changes: 1 addition & 1 deletion cli/src/commands/Test.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def __is_env_preparation_needed(self) -> bool:
Check whether additional actions are needed in order to run selected test groups
"""
if self.kubeconfig_remote_path:
kubectl_groups = ['applications', 'kubernetes_master']
kubectl_groups = ('applications', 'keycloak', 'kubernetes_master')
if any(group in kubectl_groups for group in self.selected_groups):
return True
if 'all' in self.selected_groups and any(group in kubectl_groups for group in self.available_groups):
Expand Down
3 changes: 3 additions & 0 deletions docs/home/HOWTO.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
- [Persistent storage](./howto/kubernetes/PERSISTENT_STORAGE.md)
- [Certificate management](./howto/kubernetes/CERTIFICATES.md)

- [Keycloak](./howto/KEYCLOAK.md)
- [How to run Keycloak](./howto/KEYCLOAK.md#how-to-run-keycloak)

- [Helm](./howto/HELM.md)
- [Helm "system" chart repository](./howto/HELM.md#helm-system-chart-repository)
- [Installing Helm charts from the "system" repository](./howto/HELM.md#installing-helm-charts-from-the-system-repository)
Expand Down
131 changes: 131 additions & 0 deletions docs/home/howto/KEYCLOAK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Keycloak

## How to run Keycloak

1. Enable `kubernetes_master`, `kubernetes_node`, `repository` and `postgresql` components in the input manifest (yaml)
by increasing `count` value. Enable `load_balancer` if needed.

```yaml
kind: epiphany-cluster
title: Epiphany cluster Config
provider: azure
name: default
specification:
components:
repository:
count: 1
kubernetes_master:
count: 1
kubernetes_node:
count: 2
postgresql:
count: 2
load_balancer:
count: 1
```
2. Enable `keycloak` in `configuration/features` doc:

```yaml
kind: configuration/features
title: Features to be enabled/disabled
name: default
specification:
features:
...
- name: keycloak
enabled: true
```

3. Enable PostgreSQL related applications by setting `enabled: true` and adjust other parameters in `configuration/applications`
doc.

The default applications configuration is
available [here](https://github.com/epiphany-platform/epiphany/blob/develop/schema/common/defaults/configuration/applications.yml)

Note: To get working with Pgbouncer, Keycloak requires Pgbouncer configuration parameter `POOL_MODE` set to `session`,
see [Installing Pgbouncer and Pgpool](DATABASES.md#installing-pgbouncer-and-pgpool) section. The reason is that Keycloak
uses SET SQL statements. For details, see [SQL feature map for pooling modes](https://www.pgbouncer.org/features.html).

4. Adjust default Keycloak settings to your needs by editing `configuration/keycloak` doc.

By default, only HTTPS protocol is enabled and auto-generated TLS certificate is used.

You can provide your own certificate:

```yaml
kind: configuration/keycloak
title: Keycloak Config
name: default
specification:
...
chart_values:
secrets:
...
tls-certs:
type: kubernetes.io/tls
data:
# the data is abbreviated in this example
# `ca.crt` is optional (not used by Keycloak)
ca.crt: |
LS0tLS1CRUdJTiBDRVJUSUZJQ0FUR...
# a server certificate or certificate chain in PEM format
tls.crt: |
MIIC2DCCAcCgAwIBAgIBATANBgkqh...
tls.key: |
MIIEpgIBAAKCAQEA7yn3bRHQ5FHMQ...
```
All default passwords should be changed. You may need to adjust `specification.chart_values.resources`.

By default, Epiphany managed PostgreSQL cluster is used for Keycloak database
and `specification.chart_values.database.hostname` is set to `AUTOCONFIGURED`
which means: `pgbouncer` `ClusterIP` service is used if enabled, otherwise the first host of `postgresql` group.

5. Run `epicli apply` on your input manifest.

6. Reconfigure HA proxy (if needed).

By default, Keycloak listens only for HTTPS traffic on port which is exposed via `NodePort` service.

Some Keycloak features rely on the assumption that the remote address of the HTTP request connecting to Keycloak
is the real IP address of the client machine.

When you have HAProxy in front of Keycloak, this might not be the case, so we need to ensure that the X-Forwarded-For
header is set by HAProxy. In order to achive this the content has to be modified by HAProxy. For that reason,
TLS is terminated by HAProxy and the modified content is re-encrypted. Different keys and certificates are used on HAProxy
as well as on Keycloak.

Example of backend configuration:

```text
backend keycloak
balance roundrobin
option forwardfor
server kubernetes-node-vm-0 10.1.1.151:30104 check ssl verify required ca-file /etc/ssl/haproxy/epiphany-keycloak-ca.crt
server kubernetes-node-vm-1 10.1.1.235:30104 check ssl verify required ca-file /etc/ssl/haproxy/epiphany-keycloak-ca.crt
```

It's recommended to not expose some endpoints, see https://www.keycloak.org/server/reverseproxy#_exposed_path_recommendations.

Example of frontend configuration:

```text
frontend https_fe
bind *:443 ssl crt /etc/ssl/haproxy/cert.crt
# Do not expose health checks & metrics, see https://www.keycloak.org/server/reverseproxy#_exposed_path_recommendations
http-request deny if { path_beg /auth/health/ } || { path /auth/health } || { path_beg /auth/metrics/ } || { path /auth/metrics }
use_backend keycloak if { path -m beg /auth/ } || { path /auth }
```

7. Log into GUI

Note: Accessing the Keycloak GUI depends on your configuration.

One method for reaching GUI is to use SSH tunnel with forwarding `NodePort`:

```bash
ssh -L 30104:localhost:30104 <user>@<k8s_host> -i <ssh_key_file>
```

GUI should be reachable at: https://localhost:30104/auth
2 changes: 1 addition & 1 deletion schema/common/defaults/configuration/features.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ specification:
- name: applications
enabled: true
- name: keycloak
enabled: true
enabled: false
- name: rook
enabled: false
4 changes: 4 additions & 0 deletions schema/common/defaults/configuration/image-registry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ specification:
- name: "bitnami/pgbouncer:1.16.0"
file_name: pgbouncer-1.16.0.tar
keycloak:
- name: "docker.io/busybox:1.32"
file_name: busybox-1.32.tar
- name: "quay.io/keycloak/keycloak:19.0.2"
file_name: keycloak-19.0.2.tar
kubernetes-master:
Expand Down Expand Up @@ -163,6 +165,8 @@ specification:
- name: "rabbitmq:3.8.9"
file_name: rabbitmq-3.8.9.tar
keycloak:
- name: "docker.io/busybox:1.32"
file_name: busybox-1.32.tar
- name: "quay.io/keycloak/keycloak:19.0.2"
file_name: keycloak-19.0.2.tar
kubernetes-master:
Expand Down
Loading

0 comments on commit 3b574be

Please sign in to comment.