Skip to content

Commit fde02bf

Browse files
Add option to customize keycloak themes (#2469)
Co-authored-by: Marcelo Villa <mvilla@quansight.com>
1 parent 22b37ad commit fde02bf

File tree

6 files changed

+96
-1
lines changed

6 files changed

+96
-1
lines changed

src/_nebari/stages/kubernetes_keycloak/__init__.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import time
99
from typing import Any, Dict, List, Optional, Type, Union
1010

11-
from pydantic import Field, ValidationInfo, field_validator
11+
from pydantic import Field, ValidationInfo, field_validator, model_validator
1212

1313
from _nebari.stages.base import NebariTerraformStage
1414
from _nebari.stages.tf_objects import (
@@ -31,6 +31,7 @@ class InputVars(schema.Base):
3131
initial_root_password: str
3232
overrides: List[str]
3333
node_group: Dict[str, str]
34+
themes: Dict[str, Union[bool, str]]
3435

3536

3637
@contextlib.contextmanager
@@ -141,10 +142,28 @@ def random_secure_string(
141142
return "".join(secrets.choice(chars) for i in range(length))
142143

143144

145+
class KeycloakThemes(schema.Base):
146+
enabled: bool = False
147+
repository: Optional[str] = ""
148+
branch: Optional[str] = "main"
149+
150+
@model_validator(mode="before")
151+
@classmethod
152+
def validate_fields_dependencies(cls, data: Any) -> Any:
153+
# Raise and error if themes are enabled but repository or branch are not set
154+
if isinstance(data, dict) and data.get("enabled"):
155+
if not data.get("repository") or not data.get("branch"):
156+
raise ValueError(
157+
"Repository and branch are both required when themes is enabled."
158+
)
159+
return data
160+
161+
144162
class Keycloak(schema.Base):
145163
initial_root_password: str = Field(default_factory=random_secure_string)
146164
overrides: Dict = {}
147165
realm_display_name: str = "Nebari"
166+
themes: KeycloakThemes = Field(default_factory=lambda: KeycloakThemes())
148167

149168

150169
auth_enum_to_model = {
@@ -233,6 +252,7 @@ def input_vars(self, stage_outputs: Dict[str, Dict[str, Any]]):
233252
node_group=stage_outputs["stages/02-infrastructure"]["node_selectors"][
234253
"general"
235254
],
255+
themes=self.config.security.keycloak.themes.model_dump(),
236256
).model_dump()
237257

238258
def check(

src/_nebari/stages/kubernetes_keycloak/template/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@ module "kubernetes-keycloak-helm" {
1717
overrides = var.overrides
1818

1919
node_group = var.node_group
20+
21+
themes = var.themes
2022
}

src/_nebari/stages/kubernetes_keycloak/template/modules/kubernetes/keycloak-helm/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ resource "helm_release" "keycloak" {
2020
}
2121
}
2222
}
23+
customThemes = var.themes
2324
})
2425
], var.overrides)
2526

@@ -32,6 +33,7 @@ resource "helm_release" "keycloak" {
3233
name = "initial_root_password"
3334
value = var.initial_root_password
3435
}
36+
3537
}
3638

3739

src/_nebari/stages/kubernetes_keycloak/template/modules/kubernetes/keycloak-helm/values.yaml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,21 @@ startupScripts:
2222
/opt/jboss/keycloak/bin/add-user-keycloak.sh -r master -u root -p "{{ .Values.initial_root_password }}"
2323
/opt/jboss/keycloak/bin/add-user-keycloak.sh -r master -u nebari-bot -p "{{ .Values.nebari_bot_password }}"
2424
25+
mv-custom-themes.sh: |
26+
#!/bin/sh
27+
printf '=%.0s' {1..73}
28+
echo "Start moving custom themes to /opt/jboss/keycloak/themes"
29+
30+
if [ -d /opt/data/custom-themes/themes ]; then
31+
echo 'Copying custom themes from /opt/data/custom-themes/themes to /opt/jboss/keycloak/themes'
32+
cp -r /opt/data/custom-themes/themes/* /opt/jboss/keycloak/themes/
33+
else
34+
echo 'No custom themes found in /opt/data/custom-themes'
35+
fi
36+
37+
echo "Finished moving custom themes"
38+
printf '=%.0s' {1..73}
39+
2540
extraInitContainers: |
2641
- command:
2742
- sh
@@ -47,11 +62,44 @@ extraInitContainers: |
4762
volumeMounts:
4863
- name: metrics-plugin
4964
mountPath: /data
65+
{{- if .Values.customThemes.enabled }}
66+
- env:
67+
- name: GIT_SYNC_REPO
68+
value: {{ .Values.customThemes.repository }}
69+
- name: GIT_SYNC_BRANCH
70+
value: {{ .Values.customThemes.branch }}
71+
- name: GIT_SYNC_ONE_TIME
72+
value: "true"
73+
- name: GIT_SYNC_GROUP_WRITE
74+
value: "true"
75+
- name: GIT_SYNC_ROOT
76+
value: /opt/data/custom-themes
77+
- name: GIT_SYNC_DEST
78+
value: themes
79+
- name: GIT_SYNC_SSH
80+
value: "false"
81+
image: k8s.gcr.io/git-sync:v3.1.5
82+
imagePullPolicy: IfNotPresent
83+
name: keycloak-git-sync
84+
resources: {}
85+
securityContext:
86+
runAsGroup: 1000
87+
runAsUser: 0
88+
terminationMessagePath: /dev/termination-log
89+
terminationMessagePolicy: File
90+
volumeMounts:
91+
- mountPath: /opt/data/custom-themes
92+
name: custom-themes
93+
{{- end }}
5094
5195
extraVolumeMounts: |
5296
- name: metrics-plugin
5397
mountPath: /opt/jboss/keycloak/providers/
98+
- mountPath: /opt/data/custom-themes
99+
name: custom-themes
54100
55101
extraVolumes: |
56102
- name: metrics-plugin
57103
emptyDir: {}
104+
- name: custom-themes
105+
emptyDir: {}

src/_nebari/stages/kubernetes_keycloak/template/modules/kubernetes/keycloak-helm/variables.tf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,17 @@ variable "node_group" {
3131
value = string
3232
})
3333
}
34+
35+
variable "themes" {
36+
description = "Custom themes configuration for keycloak"
37+
type = object({
38+
enabled = bool
39+
repository = string
40+
branch = string
41+
})
42+
default = {
43+
enabled = false
44+
repository = ""
45+
branch = ""
46+
}
47+
}

src/_nebari/stages/kubernetes_keycloak/template/variables.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,12 @@ variable "node_group" {
3131
value = string
3232
})
3333
}
34+
35+
variable "themes" {
36+
description = "Custom themes configuration for keycloak"
37+
type = object({
38+
enabled = bool
39+
repository = string
40+
branch = string
41+
})
42+
}

0 commit comments

Comments
 (0)