Compare commits
5 Commits
main
..
edd78fa6be
| Author | SHA1 | Date | |
|---|---|---|---|
| edd78fa6be | |||
| 1deee78ac8 | |||
| 402565d650 | |||
| aefd30886a | |||
| 6d3431c2d5 |
-10
@@ -1,12 +1,2 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
*.tmp
|
*.tmp
|
||||||
|
|
||||||
# Real secrets: only secret.example.yaml is versioned.
|
|
||||||
# k8s/kustomization.yaml still references secret.yaml, so a fresh clone must
|
|
||||||
# create it first — see README.
|
|
||||||
k8s/secret.yaml
|
|
||||||
|
|
||||||
# TLS material
|
|
||||||
*.crt
|
|
||||||
*.key
|
|
||||||
*.pem
|
|
||||||
|
|||||||
@@ -42,18 +42,6 @@ k8s/
|
|||||||
|
|
||||||
## Déploiement
|
## Déploiement
|
||||||
|
|
||||||
`k8s/secret.yaml` n'est pas versionné : il porte les mots de passe réels (base
|
|
||||||
PostgreSQL, admin Keycloak, secrets clients OIDC). Le créer une fois depuis le
|
|
||||||
gabarit, puis renseigner chaque `<CHANGE_ME>` :
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp k8s/secret.example.yaml k8s/secret.yaml
|
|
||||||
$EDITOR k8s/secret.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
`k8s/kustomization.yaml` le référence, donc le déploiement échoue tant qu'il
|
|
||||||
est absent.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
kubectl apply -k k8s/
|
kubectl apply -k k8s/
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -19,135 +19,8 @@ spec:
|
|||||||
app.kubernetes.io/name: keycloak
|
app.kubernetes.io/name: keycloak
|
||||||
app.kubernetes.io/component: idp
|
app.kubernetes.io/component: idp
|
||||||
app.kubernetes.io/part-of: keycloak
|
app.kubernetes.io/part-of: keycloak
|
||||||
annotations:
|
|
||||||
# Discovered by the Prometheus in the observability namespace.
|
|
||||||
# Endpoint exposed by KC_METRICS_ENABLED=true, on the management
|
|
||||||
# port (9000), never on the application port.
|
|
||||||
prometheus.io/scrape: "true"
|
|
||||||
prometheus.io/port: "9000"
|
|
||||||
prometheus.io/path: "/metrics"
|
|
||||||
spec:
|
spec:
|
||||||
initContainers:
|
initContainers:
|
||||||
# Re-imports the realm from configmap-realm.yaml on every start, so that
|
|
||||||
# file is the source of truth rather than a first-install seed.
|
|
||||||
#
|
|
||||||
# It has to be a separate command: `start --import-realm` skips a realm
|
|
||||||
# that already exists and there is no option to change that — the
|
|
||||||
# --override flag exists only on the standalone `import` command. With
|
|
||||||
# the default behaviour, editing the ConfigMap changed nothing on a
|
|
||||||
# restart and the truth drifted into the database. It already had: four
|
|
||||||
# scope grants existed only in the running realm.
|
|
||||||
#
|
|
||||||
# What this costs, deliberately: the realm is replaced at every start,
|
|
||||||
# so anything created at runtime and not written back to the file is
|
|
||||||
# lost, and active sessions are dropped. Users survive only because they
|
|
||||||
# are declared in the file. Create nothing through the admin console
|
|
||||||
# expecting it to last.
|
|
||||||
- name: import-realm
|
|
||||||
image: quay.io/keycloak/keycloak:26.6.0
|
|
||||||
args:
|
|
||||||
- "import"
|
|
||||||
- "--dir"
|
|
||||||
- "/opt/keycloak/data/import"
|
|
||||||
- "--override"
|
|
||||||
- "true"
|
|
||||||
env:
|
|
||||||
- name: KC_DB
|
|
||||||
value: "postgres"
|
|
||||||
- name: KC_DB_URL_HOST
|
|
||||||
value: "keycloak-postgresql"
|
|
||||||
- name: KC_DB_URL_PORT
|
|
||||||
value: "5432"
|
|
||||||
- name: KC_DB_URL_DATABASE
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: keycloak-secrets
|
|
||||||
key: POSTGRES_DB
|
|
||||||
- name: KC_DB_USERNAME
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: keycloak-secrets
|
|
||||||
key: KC_DB_USERNAME
|
|
||||||
- name: KC_DB_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: keycloak-secrets
|
|
||||||
key: KC_DB_PASSWORD
|
|
||||||
- name: KC_BOOTSTRAP_ADMIN_USERNAME
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: keycloak-secrets
|
|
||||||
key: KC_BOOTSTRAP_ADMIN_USERNAME
|
|
||||||
- name: KC_BOOTSTRAP_ADMIN_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: keycloak-secrets
|
|
||||||
key: KC_BOOTSTRAP_ADMIN_PASSWORD
|
|
||||||
- name: KEYCLOAK_ADMIN
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: keycloak-secrets
|
|
||||||
key: KEYCLOAK_ADMIN
|
|
||||||
- name: KEYCLOAK_ADMIN_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: keycloak-secrets
|
|
||||||
key: KEYCLOAK_ADMIN_PASSWORD
|
|
||||||
- name: KC_HTTP_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- name: KC_PROXY_HEADERS
|
|
||||||
value: "xforwarded"
|
|
||||||
- name: KC_HOSTNAME
|
|
||||||
value: "https://keycloak.sttlab.local"
|
|
||||||
- name: KC_HOSTNAME_STRICT
|
|
||||||
value: "false"
|
|
||||||
- name: KC_HOSTNAME_BACKCHANNEL_DYNAMIC
|
|
||||||
value: "false"
|
|
||||||
- name: KC_FEATURES
|
|
||||||
value: "token-exchange,admin-fine-grained-authz,log-mdc"
|
|
||||||
# Emptied for this container only: it inherits the main container's env,
|
|
||||||
# which loads the OpenTelemetry agent from a volume the other init
|
|
||||||
# container downloads into and this one does not mount. Inheriting it
|
|
||||||
# verbatim fails the JVM before the import runs.
|
|
||||||
- name: JAVA_OPTS_APPEND
|
|
||||||
value: ""
|
|
||||||
- name: OTEL_SERVICE_NAME
|
|
||||||
value: "keycloak"
|
|
||||||
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
|
||||||
value: "http://tempo.observability.svc.cluster.local:4318"
|
|
||||||
- name: OTEL_EXPORTER_OTLP_PROTOCOL
|
|
||||||
value: "http/protobuf"
|
|
||||||
- name: OTEL_TRACES_EXPORTER
|
|
||||||
value: "otlp"
|
|
||||||
- name: OTEL_METRICS_EXPORTER
|
|
||||||
value: "none"
|
|
||||||
- name: OTEL_LOGS_EXPORTER
|
|
||||||
value: "none"
|
|
||||||
- name: KC_HTTP_ACCESS_LOG_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- name: KC_LOG_LEVEL
|
|
||||||
value: "INFO,org.keycloak.events:DEBUG"
|
|
||||||
- name: KC_LOG_CONSOLE_OUTPUT
|
|
||||||
value: "json"
|
|
||||||
- name: KC_LOG_MDC_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- name: KC_LOG_SERVICE_NAME
|
|
||||||
value: "keycloak"
|
|
||||||
- name: KC_LOG_SERVICE_ENVIRONMENT
|
|
||||||
value: "local"
|
|
||||||
- name: KC_HEALTH_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- name: KC_METRICS_ENABLED
|
|
||||||
value: "true"
|
|
||||||
volumeMounts:
|
|
||||||
- name: realm-import
|
|
||||||
mountPath: /opt/keycloak/data/import
|
|
||||||
envFrom:
|
|
||||||
# Supplies the ${KC_SECRET_*} and ${KC_USER_*} placeholders the realm
|
|
||||||
# file carries in place of the values it used to hold in clear.
|
|
||||||
# Keycloak resolves them from the environment at import time.
|
|
||||||
- secretRef:
|
|
||||||
name: keycloak-realm-secrets
|
|
||||||
- name: download-otel-agent
|
- name: download-otel-agent
|
||||||
image: curlimages/curl:8.10.0
|
image: curlimages/curl:8.10.0
|
||||||
command:
|
command:
|
||||||
@@ -162,6 +35,7 @@ spec:
|
|||||||
image: quay.io/keycloak/keycloak:26.6.0
|
image: quay.io/keycloak/keycloak:26.6.0
|
||||||
args:
|
args:
|
||||||
- "start"
|
- "start"
|
||||||
|
- "--import-realm"
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 8080
|
containerPort: 8080
|
||||||
@@ -228,7 +102,7 @@ spec:
|
|||||||
- name: OTEL_SERVICE_NAME
|
- name: OTEL_SERVICE_NAME
|
||||||
value: "keycloak"
|
value: "keycloak"
|
||||||
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
||||||
value: "http://tempo.observability.svc.cluster.local:4318"
|
value: "http://jaeger.observability.svc.cluster.local:4318"
|
||||||
- name: OTEL_EXPORTER_OTLP_PROTOCOL
|
- name: OTEL_EXPORTER_OTLP_PROTOCOL
|
||||||
value: "http/protobuf"
|
value: "http/protobuf"
|
||||||
- name: OTEL_TRACES_EXPORTER
|
- name: OTEL_TRACES_EXPORTER
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
|||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
- secrets
|
|
||||||
- namespace.yaml
|
- namespace.yaml
|
||||||
- secret.yaml
|
- secret.yaml
|
||||||
- postgresql/pvc.yaml
|
- postgresql/pvc.yaml
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: keycloak-secrets
|
||||||
|
namespace: keycloak
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
POSTGRES_USER: keycloak
|
||||||
|
POSTGRES_PASSWORD: keycloak-db-pass-2026
|
||||||
|
POSTGRES_DB: keycloak
|
||||||
|
KC_DB_USERNAME: keycloak
|
||||||
|
KC_DB_PASSWORD: keycloak-db-pass-2026
|
||||||
|
KC_BOOTSTRAP_ADMIN_USERNAME: admin
|
||||||
|
KC_BOOTSTRAP_ADMIN_PASSWORD: mermAid-giganTic-s3ea
|
||||||
|
KEYCLOAK_ADMIN: admin
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD: mermAid-giganTic-s3ea
|
||||||
|
LIBRECHAT_OIDC_SECRET: librechat-oidc-secret-2026
|
||||||
|
CLIENT_SECRET: classic-models-client-secret-2026
|
||||||
|
USER_PASSWORD: Password123@
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Reads secrets/keycloak/* from Vault. A store of its own rather than reusing
|
|
||||||
# vault-kong-v2 or vault-observability: each carries a policy scoped to its own
|
|
||||||
# path, so a reader for one estate cannot see another's. Widening an existing
|
|
||||||
# policy would have handed Kong's reader every client secret in the realm.
|
|
||||||
#
|
|
||||||
# The AppRole credentials are NOT in git. Created once against Vault:
|
|
||||||
# vault policy write keycloak-readonly (read on secrets/{data,metadata}/keycloak/*)
|
|
||||||
# vault write auth/approle/role/keycloak-eso token_policies=keycloak-readonly
|
|
||||||
# vault read auth/approle/role/keycloak-eso/role-id
|
|
||||||
# vault write -f auth/approle/role/keycloak-eso/secret-id
|
|
||||||
# kubectl -n external-secrets create secret generic vault-approle-keycloak \
|
|
||||||
# --from-literal=roleId=<...> --from-literal=secretId=<...>
|
|
||||||
apiVersion: external-secrets.io/v1
|
|
||||||
kind: ClusterSecretStore
|
|
||||||
metadata:
|
|
||||||
name: vault-keycloak
|
|
||||||
spec:
|
|
||||||
provider:
|
|
||||||
vault:
|
|
||||||
server: https://vault.sttlab.eu
|
|
||||||
path: secrets
|
|
||||||
version: v2
|
|
||||||
auth:
|
|
||||||
appRole:
|
|
||||||
path: approle
|
|
||||||
roleRef:
|
|
||||||
name: vault-approle-keycloak
|
|
||||||
namespace: external-secrets
|
|
||||||
key: roleId
|
|
||||||
secretRef:
|
|
||||||
name: vault-approle-keycloak
|
|
||||||
namespace: external-secrets
|
|
||||||
key: secretId
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# The client secrets and user passwords the realm file used to carry in clear.
|
|
||||||
# Keycloak resolves ${PLACEHOLDER} in a realm import file from the environment,
|
|
||||||
# so the file keeps the structure and this Secret supplies the values.
|
|
||||||
apiVersion: external-secrets.io/v1
|
|
||||||
kind: ExternalSecret
|
|
||||||
metadata:
|
|
||||||
name: keycloak-realm-secrets
|
|
||||||
namespace: keycloak
|
|
||||||
spec:
|
|
||||||
refreshInterval: 1h
|
|
||||||
secretStoreRef:
|
|
||||||
kind: ClusterSecretStore
|
|
||||||
name: vault-keycloak
|
|
||||||
target:
|
|
||||||
name: keycloak-realm-secrets
|
|
||||||
creationPolicy: Owner
|
|
||||||
dataFrom:
|
|
||||||
# Whole-path pull: adding a client in the realm means adding its secret in
|
|
||||||
# Vault, with no edit here.
|
|
||||||
- extract:
|
|
||||||
key: keycloak/classic-models-realm
|
|
||||||
data:
|
|
||||||
# The token-exchange broker was renamed to drop the middleware's name from
|
|
||||||
# a contract every agent has to repeat. The Vault property still carries the
|
|
||||||
# old name — renaming it there means re-issuing the value to every gateway
|
|
||||||
# that holds a copy — so it is mapped here instead. Same secret, neutral
|
|
||||||
# name everywhere the cluster can see.
|
|
||||||
- secretKey: KC_SECRET_TOKEN_EXCHANGE_BROKER
|
|
||||||
remoteRef:
|
|
||||||
key: keycloak/classic-models-realm
|
|
||||||
property: KC_SECRET_KONG_TOKEN_EXCHANGE_BROKER
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
resources:
|
|
||||||
- clustersecretstore.yaml
|
|
||||||
- externalsecret-realm.yaml
|
|
||||||
Reference in New Issue
Block a user