diff --git a/charts/custom-catalogs/templates/subscriptions.yml b/charts/custom-catalogs/templates/subscriptions.yml index 9f29eb6..dfbc4d5 100644 --- a/charts/custom-catalogs/templates/subscriptions.yml +++ b/charts/custom-catalogs/templates/subscriptions.yml @@ -16,7 +16,7 @@ metadata: {{- if .sameNamespace }} spec: targetNamespaces: - - {{ .installNamespace }} + - {{ .installNamespace }} {{- else }} spec: {} {{- end }} @@ -47,7 +47,7 @@ metadata: name: {{ .name }} namespace: {{ default "olm" .installNamespace }} spec: - channel: {{ default "stable" .operatorChannel }} + channel: {{ default "stable" .channel }} name: {{ .name }} source: {{ .source }} sourceNamespace: {{ .sourceNamespace }} diff --git a/charts/keycloak/.helmignore b/charts/keycloak/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/charts/keycloak/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/charts/keycloak/Chart.yaml b/charts/keycloak/Chart.yaml new file mode 100644 index 0000000..81e2a2a --- /dev/null +++ b/charts/keycloak/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +description: | + A chart to manage various keycloak ressources +name: keycloak +version: 0.0.0-dev diff --git a/charts/keycloak/README.md b/charts/keycloak/README.md new file mode 100644 index 0000000..7b0ad1d --- /dev/null +++ b/charts/keycloak/README.md @@ -0,0 +1,30 @@ +# keycloak + +A chart to manage various keycloak ressources + +![Version: 0.0.0-dev](https://img.shields.io/badge/Version-0.0.0--dev-informational?style=flat-square) + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| clients | list | `[]` | Watch [Value file](values.yaml) for examples. | +| ingress.annotations | object | `{}` | Ingress annotations | +| ingress.className | string | `""` | Ingress class name | +| ingress.enabled | bool | `false` | Enable Keycloak ingress | +| ingress.hosts[0] | object | `{"host":"keycloak.danstonkube.fr","paths":[{"path":"/","pathType":"Prefix"}]}` | Ingress hostname | +| ingress.hosts[0].paths[0] | object | `{"path":"/","pathType":"Prefix"}` | Ingress path | +| ingress.hosts[0].paths[0].pathType | string | `"Prefix"` | Ingress path type can be either : `Prefix`, `ImplementationSpecific` or `Exact`, watch [Official Documentation for more informations](https://kubernetes.io/docs/concepts/services-networking/ingress/#examples) | +| ingress.tls | list | `[]` | | +| keycloakConfig.instances | int | `1` | Keycloak instance replicas | +| keycloakConfig.labels | object | `{"mylabel":"label1"}` | Keycloak instance labels | +| keycloakConfig.name | string | `"dtk"` | Keycloak instance name | +| keycloakConfig.storageClassName | string | `"local"` | Keycloak instance storage class | +| nameOverride | string | `""` | Override chart default name | +| realms | list | `[]` | Watch [Value file](values.yaml) for examples. | +| service.name | string | `"keycloak-discovery"` | | +| service.port | int | `8080` | | +| users | list | `[]` | Watch [Value file](values.yaml) for examples. | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) `docker run --rm --volume "$(pwd):/helm-docs" jnorwood/helm-docs:latest`. diff --git a/charts/keycloak/README.md.gotmpl b/charts/keycloak/README.md.gotmpl new file mode 100644 index 0000000..d9a2dfe --- /dev/null +++ b/charts/keycloak/README.md.gotmpl @@ -0,0 +1,9 @@ +{{ template "chart.header" . }} +{{ template "chart.description" . }} +{{ template "chart.badgesSection" . }} + +## Values + +{{ template "chart.valuesTable" . }} + +{{ template "helm-docs.versionFooter" . }} `docker run --rm --volume "$(pwd):/helm-docs" jnorwood/helm-docs:latest`. diff --git a/charts/keycloak/templates/_helpers.tpl b/charts/keycloak/templates/_helpers.tpl new file mode 100644 index 0000000..7b62d34 --- /dev/null +++ b/charts/keycloak/templates/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Custom catalogs +*/}} +{{- define "name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} \ No newline at end of file diff --git a/charts/keycloak/templates/clients.yml b/charts/keycloak/templates/clients.yml new file mode 100644 index 0000000..116a283 --- /dev/null +++ b/charts/keycloak/templates/clients.yml @@ -0,0 +1,17 @@ +{{- range .Values.clients }} +--- +apiVersion: keycloak.org/v1alpha1 +kind: KeycloakClient +metadata: + name: {{ .name }} + labels: {{ .labels | toYaml | nindent 4 }} +spec: + realmSelector: + matchLabels: {{ .matchLabels | toYaml | nindent 12 }} + client: + clientId: {{ .clientId }} + secret: {{ .secret }} + {{- range $key, $val := .additionalConfig }} + {{ $key }}: {{ $val }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/keycloak/templates/ingress.yml b/charts/keycloak/templates/ingress.yml new file mode 100644 index 0000000..a0f0883 --- /dev/null +++ b/charts/keycloak/templates/ingress.yml @@ -0,0 +1,59 @@ +{{- if .Values.ingress.enabled -}} +{{- $svcPort := .Values.service.port -}} +{{- $svcName := .Values.service.name -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ .Values.keycloakConfig.name }}-ingress + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $svcName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $svcName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/keycloak/templates/keycloak_instance.yml b/charts/keycloak/templates/keycloak_instance.yml new file mode 100644 index 0000000..fdfea64 --- /dev/null +++ b/charts/keycloak/templates/keycloak_instance.yml @@ -0,0 +1,10 @@ +apiVersion: keycloak.org/v1alpha1 +kind: Keycloak +metadata: + name: {{ .Values.keycloakConfig.name }} + labels: {{ .Values.keycloakConfig.labels | toYaml | nindent 4 }} +spec: + instances: {{ .Values.keycloakConfig.instances }} + externalAccess: + enabled: false + storageClassName: {{ .Values.keycloakConfig.storageClassName }} \ No newline at end of file diff --git a/charts/keycloak/templates/realms.yml b/charts/keycloak/templates/realms.yml new file mode 100644 index 0000000..c7a65bc --- /dev/null +++ b/charts/keycloak/templates/realms.yml @@ -0,0 +1,16 @@ +{{- range .Values.realms }} +--- +apiVersion: keycloak.org/v1alpha1 +kind: KeycloakRealm +metadata: + name: {{ .name }} + labels: {{ .labels | toYaml | nindent 4 }} +spec: + realm: + id: {{ .id }} + realm: {{ .realmName }} + enabled: {{ .enabled }} + displayName: {{ .displayName }} + instanceSelector: + matchLabels: {{ .matchLabels | toYaml | nindent 12 }} +{{- end }} \ No newline at end of file diff --git a/charts/keycloak/templates/users.yml b/charts/keycloak/templates/users.yml new file mode 100644 index 0000000..de996bc --- /dev/null +++ b/charts/keycloak/templates/users.yml @@ -0,0 +1,26 @@ +{{- range .Values.users }} +--- +apiVersion: keycloak.org/v1alpha1 +kind: KeycloakUser +metadata: + name: {{ .name }} + labels: {{ .labels | toYaml | nindent 4 }} +spec: + user: + username: {{ .username }} + email: {{ .email }} + enabled: {{ .enabled }} + emailVerified: {{ .emailVerified }} + firstName: {{ .firstName }} + lastName: {{ .lastName }} + credentials: + {{- if .password }} + - type: password + value: {{ .password.value }} + temporary: {{ .password.temporary }} + {{- end }} + {{- if .otp }} + - type: otp + value: {{ .otp.value }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/keycloak/values.yaml b/charts/keycloak/values.yaml new file mode 100644 index 0000000..8dbe4e1 --- /dev/null +++ b/charts/keycloak/values.yaml @@ -0,0 +1,76 @@ +--- +# -- Override chart default name +nameOverride: "" + +keycloakConfig: + # -- Keycloak instance name + name: dtk + # -- Keycloak instance labels + labels: + mylabel: label1 + # -- Keycloak instance replicas + instances: 1 + # -- Keycloak instance storage class + storageClassName: local + +service: + name: keycloak-discovery + port: 8080 + +ingress: + # -- Enable Keycloak ingress + enabled: false + # -- Ingress annotations + annotations: {} + # -- Ingress class name + className: "" + hosts: + # -- Ingress hostname + - host: keycloak.danstonkube.fr + paths: + # -- Ingress path + - path: / + # -- Ingress path type can be either : `Prefix`, `ImplementationSpecific` or `Exact`, watch [Official Documentation for more informations](https://kubernetes.io/docs/concepts/services-networking/ingress/#examples) + pathType: Prefix + tls: [] + +# -- Watch [Value file](values.yaml) for examples. +users: [] +# - name: passepartout +# labels: +# mylabel: label1 +# username: passepartout +# email: superadmin@danstonkube.fr +# enabled: true +# emailVerified: true +# firstName: Passe +# lastName: Partout +# password: +# value: changeme +# temporary: true +# otp: +# value: 92192190 + +# -- Watch [Value file](values.yaml) for examples. +realms: [] +# - name: passepartout +# labels: +# mylabel: label1 +# id: dtk +# realmName: dtk +# enabled: true +# displayName: Dans ton kube +# matchLabels: +# mylabeltomatch: dtk + +# -- Watch [Value file](values.yaml) for examples. +clients: [] +# - name: passepartout +# labels: +# mylabel: label1 +# clientId: dtk +# secret: dtk-secret +# additionalConfig: +# protocol: https +# matchLabels: +# realm: dtk diff --git a/cluster/README.md b/cluster/README.md index 5eb5961..19d38de 100644 --- a/cluster/README.md +++ b/cluster/README.md @@ -920,6 +920,61 @@ Traefik is an open-source Edge Router that makes publishing your services a fun ### Security +#### Keycloak + +| Key | Type | Default | Description | +|-----|------|---------|-------------| + +##### Adding realms + +```yaml +realms: + - name: passepartout + labels: + mylabel: label1 + id: dtk + realmName: dtk + enabled: true + displayName: Dans ton kube + matchLabels: + mylabeltomatch: dtk +``` + +##### Adding clients + +```yaml +clients: + - name: passepartout + labels: + mylabel: label1 + clientId: dtk + secret: dtk-secret + additionalConfig: + protocol: https + matchLabels: + realm: dtk +``` + +##### Adding users + +```yaml +users: + - name: passepartout + labels: + mylabel: label1 + username: passepartout + email: superadmin@danstonkube.fr + enabled: true + emailVerified: true + firstName: Passe + lastName: Partout + password: + value: changeme + temporary: true + otp: + value: 92192190 +``` + #### User management User management is a chart hosted on this repository, you can retrieve templates [here](../charts/users/). diff --git a/cluster/README.md.gotmpl b/cluster/README.md.gotmpl index fc316b8..8338e3f 100644 --- a/cluster/README.md.gotmpl +++ b/cluster/README.md.gotmpl @@ -798,6 +798,66 @@ Traefik is an open-source Edge Router that makes publishing your services a fun ### Security +#### Keycloak + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +{{- range .Values }} + {{- if hasPrefix "Keycloak" .Key }} +| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | + {{- end }} +{{- end }} + +##### Adding realms + +```yaml +realms: + - name: passepartout + labels: + mylabel: label1 + id: dtk + realmName: dtk + enabled: true + displayName: Dans ton kube + matchLabels: + mylabeltomatch: dtk +``` + +##### Adding clients + +```yaml +clients: + - name: passepartout + labels: + mylabel: label1 + clientId: dtk + secret: dtk-secret + additionalConfig: + protocol: https + matchLabels: + realm: dtk +``` + +##### Adding users + +```yaml +users: + - name: passepartout + labels: + mylabel: label1 + username: passepartout + email: superadmin@danstonkube.fr + enabled: true + emailVerified: true + firstName: Passe + lastName: Partout + password: + value: changeme + temporary: true + otp: + value: 92192190 +``` + #### User management User management is a chart hosted on this repository, you can retrieve templates [here](../charts/users/). diff --git a/cluster/templates/_helpers.tpl b/cluster/templates/_helpers.tpl index 0416840..289e0ba 100644 --- a/cluster/templates/_helpers.tpl +++ b/cluster/templates/_helpers.tpl @@ -137,7 +137,9 @@ ingress: hosts: {{- if eq $ingressDefinition.dns.mode "wildcard" }} - host: {{ $name }}.{{ $ingressDefinition.dns.wildcard }} - paths: [] + paths: + - path: / + pathType: Prefix {{- else if eq $ingressDefinition.dns.mode "domain" }} - host: {{ $ingressDefinition.dns.domain }} paths: diff --git a/cluster/templates/integration/custom-catalogs.yml b/cluster/templates/integration/custom-catalogs.yml index 3bdc62f..e521d44 100644 --- a/cluster/templates/integration/custom-catalogs.yml +++ b/cluster/templates/integration/custom-catalogs.yml @@ -32,11 +32,19 @@ spec: {{- else }} catalogs: [] {{- end }} - {{- if .Values.customCatalogs.values.subscriptions }} + {{- if or .Values.customCatalogs.values.subscriptions .Values.keycloak.enabled }} subscriptions: {{- with .Values.customCatalogs.values.subscriptions }} {{- toYaml . | nindent 10 }} {{- end }} + {{- if .Values.keycloak.enabled }} + - name: keycloak-operator + channel: alpha + source: operatorhubio-catalog + sourceNamespace: olm + installNamespace: {{ .Values.keycloak.namespace }} + sameNamespace: true + {{- end }} {{- else }} subscriptions: [] {{- end }} diff --git a/cluster/templates/security/00-app-project.yml b/cluster/templates/security/00-app-project.yml index 097cdd1..074a61b 100644 --- a/cluster/templates/security/00-app-project.yml +++ b/cluster/templates/security/00-app-project.yml @@ -1,5 +1,5 @@ {{- define "security.enabled" -}} -{{- or .Values.vault.enabled .Values.userManagement.enabled (eq (include "secrets.isVault" .) "true") -}} +{{- or .Values.keycloak.enabled .Values.vault.enabled .Values.userManagement.enabled (eq (include "secrets.isVault" .) "true") -}} {{- end -}} {{ if eq (include "security.enabled" .) "true" }} apiVersion: argoproj.io/v1alpha1 @@ -18,6 +18,10 @@ spec: - namespace: {{ . }} server: '*' {{- end }} + {{- if .Values.keycloak.enabled }} + - namespace: {{ .Values.keycloak.namespace }} + server: '*' + {{- end }} sourceRepos: - '*' {{ end }} \ No newline at end of file diff --git a/cluster/templates/security/keycloak.yml b/cluster/templates/security/keycloak.yml new file mode 100644 index 0000000..7504821 --- /dev/null +++ b/cluster/templates/security/keycloak.yml @@ -0,0 +1,58 @@ +{{- define "keycloak.enabled" -}} +{{- and .Values.keycloak.enabled .Values.olm.enabled .Values.customCatalogs.enabled -}} +{{- end -}} +{{ if eq (include "keycloak.enabled" .) "true" }} +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: keycloak + namespace: {{ .Values.argocd.namespace }} + finalizers: + {{- include "argocd.applications.finalizers" . | nindent 4 }} +spec: + {{- template "cluster.syncPolicy.default" . }} + destination: + namespace: {{ .Values.keycloak.namespace }} + server: https://kubernetes.default.svc + project: security + source: + path: {{ .Values.keycloak.chart.path }} + repoURL: {{ .Values.keycloak.chart.repo }} + targetRevision: {{ .Values.keycloak.chart.targetRevision }} + helm: + version: v3 + values: |- + keycloakConfig: + name: {{ .Values.keycloak.values.keycloakConfig.name }} + labels: + {{- with .Values.keycloak.values.keycloakConfig.labels }} + {{- toYaml . | nindent 12 }} + {{- end }} + instances: {{ .Values.keycloak.values.keycloakConfig.instances }} + {{- if .Values.default.storageClass }} + storageClassName: {{ .Values.default.storageClass }} + {{- end }} + {{- if and (eq (include "ingress.namespace" .) "traefik-system") .Values.keycloak.values.ingress.enabled }} + {{- include "helm-ingress.alternateSpec" (dict "name" .Values.keycloak.values.ingress.name "ingressDefinition" .Values.ingress.ingressDefinition "annotations" .Values.ingress.traefik.values.ingressAnnotations) | nindent 8 -}} + {{- end }} + {{- if and (eq (include "ingress.namespace" .) "ingress-nginx") .Values.keycloak.values.ingress.enabled }} + {{- include "helm-ingress.alternateSpec" (dict "name" .Values.keycloak.values.ingress.name "ingressDefinition" .Values.ingress.ingressDefinition "annotations" .Values.ingress.nginx.values.ingressAnnotations) | nindent 8 -}} + {{- end }} + {{- if .Values.keycloak.values.users }} + {{- with .Values.keycloak.values.users }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- if .Values.keycloak.values.realms }} + {{- with .Values.keycloak.values.realms }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- if .Values.keycloak.values.clients }} + clients: + {{- with .Values.keycloak.values.clients }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} +{{ end }} diff --git a/cluster/values.yaml b/cluster/values.yaml index 2823b0c..a189ebf 100644 --- a/cluster/values.yaml +++ b/cluster/values.yaml @@ -109,7 +109,7 @@ argocd: alp: # -- Enable Argo Lovely Plugin extension enabled: false - # -- Enable Argo Lovely Plugin version to install + # -- Enable Argo Lovely Plugin version to install version: stable # -- Enable prometheus metrics scraping, you will need to enable Prometheus as well monitor: false @@ -702,6 +702,39 @@ certmanager: # Security +keycloak: + # -- Enable Keycloak chart + enabled: false + # -- Destination namespace + namespace: keycloak + chart: + # -- Helm repository (This own repository) + repo: https://github.com/panzouh/argo-repository.git + # -- Chart path + path: charts/keycloak + # -- Chart target revision, using `HEAD` allow you to use the same version of your cluster spec + targetRevision: HEAD + values: + keycloakConfig: + # -- Keycloak instance name + name: dtk + # -- Keycloak instance labels + labels: + mylabel: label1 + # -- Keycloak instance replicas + instances: 1 + ingress: + # -- Enable Keycloak UI Ingress + enabled: true + # -- Keycloak ingress name or path (weither it is an ingress wildcard or domain) + name: keycloak + # -- Create users watch section below + users: [] + # -- Create realms watch section below + realms: [] + # -- Create clients watch section below + clients: [] + vault: # -- Enable Vault chart enabled: false