diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c5f79f0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+override.yaml
diff --git a/.helmignore b/.helmignore
new file mode 100644
index 0000000..5d27dca
--- /dev/null
+++ b/.helmignore
@@ -0,0 +1,24 @@
+# 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
+override.yaml
+examples/
+LICENSE
diff --git a/Chart.yaml b/Chart.yaml
new file mode 100644
index 0000000..0110760
--- /dev/null
+++ b/Chart.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+description: Helm chart to deploy OIDC stack for Kubernetes auth
+name: kube-oidc
+version: 1.0.0
+maintainers:
+ - email: flav.hardy@gmail.com
+ name: fydrah
+keywords:
+ - kubernetes
+ - oidc
+ - openid
+ - keycloak
+ - loginapp
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..89e0d85
--- /dev/null
+++ b/README.md
@@ -0,0 +1,43 @@
+# kube-oidc
+
+This chart deploys:
+* [dex](https://github.com/dexidp/dex): identity provider supporting multiple connectors (SAML, LDAP...)
+* [loginapp](https://github.com/fydrah/loginapp): web application for Kubernetes cli configuration with OIDC
+* [keycloak proxy](https://github.com/keycloak/keycloak-gatekeeper): OpenID / Keycloak proxy service (used for OIDC dashboard auth)
+
+## Install
+
+* From chart repository:
+
+```
+helm repo add fydrahcharts https://charts.fhardy.fr
+helm repo update
+```
+
+Override [default configuration](./values.yaml) with an `override.yaml` file.
+
+```
+helm install fydrahcharts/kube-oidc -f override.yaml
+```
+
+* From GitHub:
+
+```
+git clone https://github.com/ObjectifLibre/kube-oidc
+```
+
+Override [default configuration](./values.yaml) with an `override.yaml` file.
+
+```
+cd kube-oidc/
+helm install . -f override.yaml
+```
+
+## Configure
+
+See [values.yaml](./values.yaml).
+
+## Examples
+
+* [SAML configuration](./examples/SAML.md)
+* [Cross client configuration for k8s](./examples/cross-client.md)
diff --git a/examples/SAML.md b/examples/SAML.md
new file mode 100644
index 0000000..59a39d2
--- /dev/null
+++ b/examples/SAML.md
@@ -0,0 +1,53 @@
+# Example SAML config
+
+Since dex is a backend app that can support multiple [connectors](https://github.com/dexidp/dex/tree/master/Documentation/connectors), we can modify the chart in order to use SAML as the connector without modyfing the chart itself.
+
+## SAML configuration
+In most SAML Identity Providers (IP) we need to create a metadata file, which registers our application in the IP. This file can be created manually, or by the use of a UI, however the effect should be similar to this:
+
+```xml
+
+
+
+
+
+ dex.k8s.example.org
+
+ IDENTITY_CERT
+
+
+
+
+
+
+
+```
+
+## Dex configuration
+We only need to modify the connectors part of the configuration in order to change our backend:
+
+```yaml
+dex:
+ config:
+ connectors:
+ - type: saml
+ # Required field for connector id.
+ id: APP_ID
+ # Required field for connector name.
+ name: APP_NAME
+ config:
+ # entityId taken from the metadata
+ entityIssuer: dex.k8s.example.org
+ # URL to the POST endpoint of the SSO provider
+ ssoURL: YOUR_SSO_POST_ENDPOINT
+ # Base64 of the same cert we used in the metadata
+ caData: BASE64_IDENTITY_CERT
+ # POST endpoint of DEX
+ redirectURI: https://dex.k8s.example.org/dex/callback
+ # Parameter mapping, similar to LDAP
+ usernameAttr: name
+ emailAttr: email
+ groupsAttr: groups
+ groupsDelim: ", "
+ insecureSkipSignatureValidation: true
+```
diff --git a/examples/cross-client.md b/examples/cross-client.md
new file mode 100644
index 0000000..06679dd
--- /dev/null
+++ b/examples/cross-client.md
@@ -0,0 +1,50 @@
+### Cross client configuration for k8s
+
+A Kubernetes cluster currently allows to setup only one IdP in the configuration.
+
+You will have to configure cross-client trust for loginapp and keycloack proxy.
+
+Full explaination about cross-client trust can be found [here](https://github.com/coreos/dex/blob/master/Documentation/custom-scopes-claims-clients.md#cross-client-trust-and-authorized-party)
+
+The configuration begins on Dex:
+```
+staticClients:
+ - id: cli
+ redirectURIs:
+ - 'https://logincli.example.org/callback/cli'
+ name: 'Login Application'
+ secret: SeCrEtKeyCLI
+ - id: login
+ redirectURIs:
+ - 'https://dashboard.example.org/oauth/callback'
+ name: 'Dashboard Application'
+ secret: SeCrEtKeyDashboard
+ trustedPeers:
+ - cli
+```
+
+Then you must configure Loginapp to use cross-client:
+```
+name: "Kubernetes Auth"
+listen: "0.0.0.0:8080"
+oidc:
+ client:
+ id: "cli"
+ secret: SeCrEtKeyCLI
+ redirect_url: "https://logincli.example.org/callback"
+ issuer:
+ root_ca: "/etc/ssl/ca.pem"
+ url: "https://dex.example.org/dex"
+ extra_scopes:
+ - groups
+ offline_as_scope: true
+ cross_clients:
+ - login
+tls:
+ enabled: false
+log:
+ level: Info
+ format: json
+```
+
+*cross_client: [login]* is the important field.
diff --git a/templates/NOTES.txt b/templates/NOTES.txt
new file mode 100644
index 0000000..908fa62
--- /dev/null
+++ b/templates/NOTES.txt
@@ -0,0 +1,6 @@
+{{- if .Values.loginapp.ingress.enabled }}
+Login application URL accessible at :
+{{- range .Values.loginapp.ingress.hosts }}
+ http{{ if $.Values.loginapp.ingress.tls }}s{{ end }}://{{ . }}
+{{- end -}}
+{{- end -}}
diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl
new file mode 100644
index 0000000..f7e6535
--- /dev/null
+++ b/templates/_helpers.tpl
@@ -0,0 +1,49 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "k8s-ldap.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).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "k8s-ldap.fullname" -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- $fullname := printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- default $fullname .Values.fullNameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "k8s-ldap.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Dex fully qualified app name.
+*/}}
+{{- define "k8s-ldap.dex.fullname" -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- printf "%s-%s-%s" .Release.Name $name .Values.dex.name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Loginapp fully qualified app name.
+*/}}
+{{- define "k8s-ldap.loginapp.fullname" -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- printf "%s-%s-%s" .Release.Name $name .Values.loginapp.name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Keycloak fully qualified app name.
+*/}}
+{{- define "k8s-ldap.keycloakProxy.fullname" -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- printf "%s-%s-%s" .Release.Name $name .Values.keycloakProxy.name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
diff --git a/templates/ca-cm.yaml b/templates/ca-cm.yaml
new file mode 100644
index 0000000..7df4f31
--- /dev/null
+++ b/templates/ca-cm.yaml
@@ -0,0 +1,13 @@
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.loginapp.name }}
+ name: {{ .Release.Name }}-ca
+data:
+ ca.pem: |
+{{ .Values.loginapp.issuerCA | indent 4 }}
diff --git a/templates/dex-cm.yaml b/templates/dex-cm.yaml
new file mode 100644
index 0000000..b3681e4
--- /dev/null
+++ b/templates/dex-cm.yaml
@@ -0,0 +1,15 @@
+{{- if .Values.dex.enabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.dex.name }}
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+data:
+ config.yaml: |
+{{ toYaml .Values.dex.config | indent 4 }}
+{{- end -}}
diff --git a/templates/dex-cr.yaml b/templates/dex-cr.yaml
new file mode 100644
index 0000000..5da6f98
--- /dev/null
+++ b/templates/dex-cr.yaml
@@ -0,0 +1,21 @@
+{{- if .Values.dex.enabled -}}
+{{- if .Values.dex.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1beta1
+kind: ClusterRole
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.dex.name }}
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+rules:
+- apiGroups: ["dex.coreos.com"] # API group created by dex
+ resources: ["*"]
+ verbs: ["*"]
+- apiGroups: ["apiextensions.k8s.io"]
+ resources: ["customresourcedefinitions"]
+ verbs: ["create"] # To manage its own resources identity must be able to create customresourcedefinitions.
+{{- end -}}
+{{- end -}}
diff --git a/templates/dex-crb.yaml b/templates/dex-crb.yaml
new file mode 100644
index 0000000..d8b5bab
--- /dev/null
+++ b/templates/dex-crb.yaml
@@ -0,0 +1,22 @@
+{{- if .Values.dex.enabled -}}
+{{- if .Values.dex.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1beta1
+kind: ClusterRoleBinding
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.dex.name }}
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+subjects:
+- kind: ServiceAccount
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+{{- end -}}
+{{- end -}}
diff --git a/templates/dex-crd.yaml b/templates/dex-crd.yaml
new file mode 100644
index 0000000..4b080e9
--- /dev/null
+++ b/templates/dex-crd.yaml
@@ -0,0 +1,15 @@
+{{- if .Values.dex.enabled }}
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+ name: authcodes.dex.coreos.com
+spec:
+ group: dex.coreos.com
+ names:
+ kind: AuthCode
+ listKind: AuthCodeList
+ plural: authcodes
+ singular: authcode
+ scope: Namespaced
+ version: v1
+{{- end -}}
diff --git a/templates/dex-deployment.yaml b/templates/dex-deployment.yaml
new file mode 100644
index 0000000..7173027
--- /dev/null
+++ b/templates/dex-deployment.yaml
@@ -0,0 +1,77 @@
+{{- if .Values.dex.enabled }}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.dex.name }}
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+spec:
+ replicas: {{ .Values.dex.replicas }}
+ selector:
+ matchLabels:
+ app: {{ template "k8s-ldap.name" . }}
+ component: {{ .Values.dex.name }}
+ template:
+ metadata:
+ annotations:
+ checksum/config: {{ include (print $.Template.BasePath "/dex-cm.yaml") . | sha256sum }}
+ {{- if .Values.dex.podAnnotations }}
+{{ toYaml .Values.dex.podAnnotations | indent 8 }}
+ {{- end }}
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ component: {{ .Values.dex.name }}
+ spec:
+ serviceAccountName: {{ if .Values.dex.rbac.create }}{{ template "k8s-ldap.dex.fullname" . }}{{ else }}"{{ .Values.dex.serviceAccountName }}"{{ end }}
+ containers:
+ - image: {{ .Values.dex.image.repository }}:{{ .Values.dex.image.tag }}
+ imagePullPolicy: {{ .Values.dex.image.pullPolicy }}
+ name: {{ template "k8s-ldap.name" . }}-{{ .Values.dex.name }}
+ command: ["dex", "serve", "/etc/dex/cfg/config.yaml"]
+ ports:
+ - name: http
+ containerPort: {{ .Values.dex.port }}
+ volumeMounts:
+ - name: config
+ mountPath: /etc/dex/cfg
+ {{- if .Values.dex.resources }}
+ resources:
+{{ toYaml .Values.dex.resources | indent 8 }}
+ {{- end }}
+ readinessProbe:
+ httpGet:
+ path: /healthz
+ port: {{ .Values.dex.port }}
+ timeoutSeconds: 5
+ periodSeconds: 5
+ failureThreshold: 5
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ port: {{ .Values.dex.port }}
+ initialDelaySeconds: 30
+ periodSeconds: 5
+ volumes:
+ - name: config
+ configMap:
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+ items:
+ - key: config.yaml
+ path: config.yaml
+ {{- if .Values.dex.nodeSelector }}
+ nodeSelector:
+{{ toYaml .Values.dex.nodeSelector | indent 8 }}
+ {{- end }}
+ {{- if .Values.dex.tolerations }}
+ tolerations:
+{{ toYaml .Values.dex.tolerations | indent 8 }}
+ {{- end }}
+ {{- if .Values.dex.affinity }}
+ affinity:
+{{ toYaml .Values.dex.affinity | indent 8 }}
+ {{- end -}}
+{{- end -}}
diff --git a/templates/dex-ingress.yaml b/templates/dex-ingress.yaml
new file mode 100644
index 0000000..06a5c08
--- /dev/null
+++ b/templates/dex-ingress.yaml
@@ -0,0 +1,34 @@
+{{- if .Values.dex.enabled -}}
+{{- if .Values.dex.ingress.enabled -}}
+{{- $serviceName := include "k8s-ldap.dex.fullname" . }}
+{{- $servicePort := .Values.dex.servicePort -}}
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.dex.name }}
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+{{- if .Values.dex.ingress.annotations }}
+ annotations:
+{{ toYaml .Values.dex.ingress.annotations | indent 4 }}
+{{- end }}
+spec:
+ rules:
+ {{- range .Values.dex.ingress.hosts }}
+ - host: {{ . }}
+ http:
+ paths:
+ - backend:
+ serviceName: {{ $serviceName }}
+ servicePort: {{ $servicePort }}
+ {{- end -}}
+{{- if .Values.dex.ingress.tls }}
+ tls:
+{{ toYaml .Values.dex.ingress.tls | indent 4 }}
+ {{- end -}}
+{{- end -}}
+{{- end -}}
diff --git a/templates/dex-sa.yaml b/templates/dex-sa.yaml
new file mode 100644
index 0000000..8d25438
--- /dev/null
+++ b/templates/dex-sa.yaml
@@ -0,0 +1,14 @@
+{{- if .Values.dex.enabled -}}
+{{- if .Values.dex.rbac.create }}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.dex.name }}
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+{{- end -}}
+{{- end -}}
diff --git a/templates/dex-service.yaml b/templates/dex-service.yaml
new file mode 100644
index 0000000..73850ff
--- /dev/null
+++ b/templates/dex-service.yaml
@@ -0,0 +1,21 @@
+{{- if .Values.dex.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.dex.name }}
+ name: {{ template "k8s-ldap.dex.fullname" . }}
+spec:
+ ports:
+ - name: http
+ port: {{ .Values.dex.port }}
+ protocol: TCP
+ targetPort: {{ .Values.dex.port }}
+ selector:
+ app: {{ template "k8s-ldap.name" . }}
+ component: {{ .Values.dex.name }}
+{{- end -}}
diff --git a/templates/keycloak-proxy-cm.yaml b/templates/keycloak-proxy-cm.yaml
new file mode 100644
index 0000000..5d6093b
--- /dev/null
+++ b/templates/keycloak-proxy-cm.yaml
@@ -0,0 +1,15 @@
+{{- if .Values.keycloakProxy.enabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.keycloakProxy.name }}
+ name: {{ template "k8s-ldap.keycloakProxy.fullname" . }}
+data:
+ config.yaml: |
+{{ toYaml .Values.keycloakProxy.config | indent 4 }}
+{{- end -}}
diff --git a/templates/keycloak-proxy-deployment.yaml b/templates/keycloak-proxy-deployment.yaml
new file mode 100644
index 0000000..c5e62f3
--- /dev/null
+++ b/templates/keycloak-proxy-deployment.yaml
@@ -0,0 +1,86 @@
+{{- if .Values.keycloakProxy.enabled }}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.keycloakProxy.name }}
+ name: {{ template "k8s-ldap.keycloakProxy.fullname" . }}
+spec:
+ replicas: {{ .Values.keycloakProxy.replicas }}
+ selector:
+ matchLabels:
+ app: {{ template "k8s-ldap.name" . }}
+ component: {{ .Values.keycloakProxy.name }}
+ template:
+ metadata:
+ annotations:
+ checksum/config: {{ include (print $.Template.BasePath "/keycloak-proxy-cm.yaml") . | sha256sum }}
+ {{- if .Values.keycloakProxy.podAnnotations }}
+{{ toYaml .Values.keycloakProxy.podAnnotations | indent 8 }}
+ {{- end }}
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ component: {{ .Values.keycloakProxy.name }}
+ spec:
+ containers:
+ - image: {{ .Values.keycloakProxy.image.repository }}:{{ .Values.keycloakProxy.image.tag }}
+ imagePullPolicy: {{ .Values.keycloakProxy.image.pullPolicy }}
+ name: {{ template "k8s-ldap.name" . }}-{{ .Values.keycloakProxy.name }}
+ args:
+ - "--config=/app/config.yaml"
+ - "--skip-openid-provider-tls-verify"
+ ports:
+ - name: http
+ containerPort: {{ .Values.keycloakProxy.port }}
+ volumeMounts:
+ - name: config
+ mountPath: /app/
+ - name: ca
+ mountPath: /etc/ssl/
+ {{- if .Values.keycloakProxy.resources }}
+ resources:
+{{ toYaml .Values.keycloakProxy.resources | indent 8 }}
+ {{- end }}
+ #readinessProbe:
+ # httpGet:
+ # path: /keycloakProxy/healthz
+ # port: {{ .Values.keycloakProxy.port }}
+ # timeoutSeconds: 5
+ # periodSeconds: 5
+ # failureThreshold: 5
+ #livenessProbe:
+ # httpGet:
+ # path: /keycloakProxy/healthz
+ # port: {{ .Values.keycloakProxy.port }}
+ # initialDelaySeconds: 30
+ # periodSeconds: 5
+ volumes:
+ - name: config
+ configMap:
+ name: {{ template "k8s-ldap.keycloakProxy.fullname" . }}
+ items:
+ - key: config.yaml
+ path: config.yaml
+ - name: ca
+ configMap:
+ name: {{ .Release.Name }}-ca
+ items:
+ - key: ca.pem
+ path: ca.pem
+ {{- if .Values.keycloakProxy.nodeSelector }}
+ nodeSelector:
+{{ toYaml .Values.keycloakProxy.nodeSelector | indent 8 }}
+ {{- end }}
+ {{- if .Values.keycloakProxy.tolerations }}
+ tolerations:
+{{ toYaml .Values.keycloakProxy.tolerations | indent 8 }}
+ {{- end }}
+ {{- if .Values.keycloakProxy.affinity }}
+ affinity:
+{{ toYaml .Values.keycloakProxy.affinity | indent 8 }}
+ {{- end -}}
+{{- end -}}
diff --git a/templates/keycloak-proxy-ingress.yaml b/templates/keycloak-proxy-ingress.yaml
new file mode 100644
index 0000000..25674d9
--- /dev/null
+++ b/templates/keycloak-proxy-ingress.yaml
@@ -0,0 +1,34 @@
+{{- if .Values.keycloakProxy.enabled -}}
+{{- if .Values.keycloakProxy.ingress.enabled -}}
+{{- $serviceName := include "k8s-ldap.keycloakProxy.fullname" . }}
+{{- $servicePort := .Values.keycloakProxy.servicePort -}}
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.keycloakProxy.name }}
+ name: {{ template "k8s-ldap.keycloakProxy.fullname" . }}
+{{- if .Values.keycloakProxy.ingress.annotations }}
+ annotations:
+{{ toYaml .Values.keycloakProxy.ingress.annotations | indent 4 }}
+{{- end }}
+spec:
+ rules:
+ {{- range .Values.keycloakProxy.ingress.hosts }}
+ - host: {{ . }}
+ http:
+ paths:
+ - backend:
+ serviceName: {{ $serviceName }}
+ servicePort: {{ $servicePort }}
+ {{- end -}}
+{{- if .Values.keycloakProxy.ingress.tls }}
+ tls:
+{{ toYaml .Values.keycloakProxy.ingress.tls | indent 4 }}
+ {{- end -}}
+{{- end -}}
+{{- end -}}
diff --git a/templates/keycloak-proxy-service.yaml b/templates/keycloak-proxy-service.yaml
new file mode 100644
index 0000000..67ec8db
--- /dev/null
+++ b/templates/keycloak-proxy-service.yaml
@@ -0,0 +1,21 @@
+{{- if .Values.keycloakProxy.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.keycloakProxy.name }}
+ name: {{ template "k8s-ldap.keycloakProxy.fullname" . }}
+spec:
+ ports:
+ - name: http
+ port: {{ .Values.keycloakProxy.servicePort }}
+ protocol: TCP
+ targetPort: {{ .Values.keycloakProxy.port }}
+ selector:
+ app: {{ template "k8s-ldap.name" . }}
+ component: {{ .Values.keycloakProxy.name }}
+{{- end -}}
diff --git a/templates/loginapp-cm.yaml b/templates/loginapp-cm.yaml
new file mode 100644
index 0000000..6864f83
--- /dev/null
+++ b/templates/loginapp-cm.yaml
@@ -0,0 +1,15 @@
+{{- if .Values.loginapp.enabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.loginapp.name }}
+ name: {{ template "k8s-ldap.loginapp.fullname" . }}
+data:
+ config.yaml: |
+{{ toYaml .Values.loginapp.config | indent 4 }}
+{{- end -}}
diff --git a/templates/loginapp-deployment.yaml b/templates/loginapp-deployment.yaml
new file mode 100644
index 0000000..a53de45
--- /dev/null
+++ b/templates/loginapp-deployment.yaml
@@ -0,0 +1,87 @@
+{{- if .Values.loginapp.enabled }}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.loginapp.name }}
+ name: {{ template "k8s-ldap.loginapp.fullname" . }}
+spec:
+ replicas: {{ .Values.loginapp.replicas }}
+ selector:
+ matchLabels:
+ app: {{ template "k8s-ldap.name" . }}
+ component: {{ .Values.loginapp.name }}
+ template:
+ metadata:
+ annotations:
+ checksum/config: {{ include (print $.Template.BasePath "/loginapp-cm.yaml") . | sha256sum }}
+ {{- if .Values.loginapp.podAnnotations }}
+{{ toYaml .Values.loginapp.podAnnotations | indent 8 }}
+ {{- end }}
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ component: {{ .Values.loginapp.name }}
+ spec:
+ containers:
+ - image: {{ .Values.loginapp.image.repository }}:{{ .Values.loginapp.image.tag }}
+ imagePullPolicy: {{ .Values.loginapp.image.pullPolicy }}
+ name: {{ template "k8s-ldap.name" . }}-{{ .Values.loginapp.name }}
+ command:
+ - "/loginapp"
+ - "serve"
+ - "/app/config.yaml"
+ ports:
+ - name: http
+ containerPort: {{ .Values.loginapp.port }}
+ volumeMounts:
+ - name: config
+ mountPath: /app/
+ - name: ca
+ mountPath: /etc/ssl/
+ {{- if .Values.loginapp.resources }}
+ resources:
+{{ toYaml .Values.loginapp.resources | indent 8 }}
+ {{- end }}
+ readinessProbe:
+ httpGet:
+ path: /healthz
+ port: {{ .Values.loginapp.port }}
+ timeoutSeconds: 5
+ periodSeconds: 5
+ failureThreshold: 5
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ port: {{ .Values.loginapp.port }}
+ initialDelaySeconds: 30
+ periodSeconds: 5
+ volumes:
+ - name: config
+ configMap:
+ name: {{ template "k8s-ldap.loginapp.fullname" . }}
+ items:
+ - key: config.yaml
+ path: config.yaml
+ - name: ca
+ configMap:
+ name: {{ .Release.Name }}-ca
+ items:
+ - key: ca.pem
+ path: ca.pem
+ {{- if .Values.loginapp.nodeSelector }}
+ nodeSelector:
+{{ toYaml .Values.loginapp.nodeSelector | indent 8 }}
+ {{- end }}
+ {{- if .Values.loginapp.tolerations }}
+ tolerations:
+{{ toYaml .Values.loginapp.tolerations | indent 8 }}
+ {{- end }}
+ {{- if .Values.loginapp.affinity }}
+ affinity:
+{{ toYaml .Values.loginapp.affinity | indent 8 }}
+ {{- end -}}
+{{- end -}}
diff --git a/templates/loginapp-ingress.yaml b/templates/loginapp-ingress.yaml
new file mode 100644
index 0000000..4bb12e6
--- /dev/null
+++ b/templates/loginapp-ingress.yaml
@@ -0,0 +1,34 @@
+{{- if .Values.loginapp.enabled -}}
+{{- if .Values.loginapp.ingress.enabled -}}
+{{- $serviceName := include "k8s-ldap.loginapp.fullname" . }}
+{{- $servicePort := .Values.loginapp.servicePort -}}
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.loginapp.name }}
+ name: {{ template "k8s-ldap.loginapp.fullname" . }}
+{{- if .Values.loginapp.ingress.annotations }}
+ annotations:
+{{ toYaml .Values.loginapp.ingress.annotations | indent 4 }}
+{{- end }}
+spec:
+ rules:
+ {{- range .Values.loginapp.ingress.hosts }}
+ - host: {{ . }}
+ http:
+ paths:
+ - backend:
+ serviceName: {{ $serviceName }}
+ servicePort: {{ $servicePort }}
+ {{- end -}}
+{{- if .Values.loginapp.ingress.tls }}
+ tls:
+{{ toYaml .Values.loginapp.ingress.tls | indent 4 }}
+ {{- end -}}
+{{- end -}}
+{{- end -}}
diff --git a/templates/loginapp-service.yaml b/templates/loginapp-service.yaml
new file mode 100644
index 0000000..f0cf800
--- /dev/null
+++ b/templates/loginapp-service.yaml
@@ -0,0 +1,21 @@
+{{- if .Values.loginapp.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: {{ template "k8s-ldap.name" . }}
+ chart: {{ template "k8s-ldap.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+ component: {{ .Values.loginapp.name }}
+ name: {{ template "k8s-ldap.loginapp.fullname" . }}
+spec:
+ ports:
+ - name: http
+ port: {{ .Values.loginapp.servicePort }}
+ protocol: TCP
+ targetPort: {{ .Values.loginapp.port }}
+ selector:
+ app: {{ template "k8s-ldap.name" . }}
+ component: {{ .Values.loginapp.name }}
+{{- end -}}
diff --git a/values.yaml b/values.yaml
new file mode 100644
index 0000000..7d18ccd
--- /dev/null
+++ b/values.yaml
@@ -0,0 +1,338 @@
+##############
+### Common ###
+##############
+# fullnameOverride:
+# nameOverride:
+
+###########
+### Dex ###
+###########
+dex:
+ enabled: false
+ name: dex
+
+ # Image
+ image:
+ repository: quay.io/dexidp/dex
+ tag: v2.15.0
+ pullPolicy: IfNotPresent
+
+ # Deployment settings
+ replicas: 1
+ resources: {}
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+ nodeSelector: {}
+ tolerations: []
+ affinity: {}
+ podAnnotations: {}
+ port: 8080
+ servicePort: 8080
+
+ # Ingress
+ ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: 'true'
+ hosts:
+ - dex.example.local
+ tls: []
+ # - secretName: dex-example-tls
+ # hosts:
+ # - dex.example.local
+
+ # RBAC
+ rbac:
+ create: true
+ # Uncomment if rbac.create is false
+ # serviceAccountName:
+
+ # Dex configuration
+ # See https://github.com/coreos/dex/tree/master/Documentation
+ config:
+ issuer: https://dex.k8s.example.org/dex
+ storage:
+ # Kubernetes storage by default, Dex will create CRD on first launch:
+ # * authcodes.dex.coreos.com
+ # * authrequests.dex.coreos.com
+ # * connectors.dex.coreos.com
+ # * oauth2clients.dex.coreos.com
+ # * offlinesessionses.dex.coreos.com
+ # * passwords.dex.coreos.com
+ # * refreshtokens.dex.coreos.com
+ # * signingkeies.dex.coreos.com
+ type: kubernetes
+ config:
+ inCluster: true
+ web:
+ # Be careful this should be equals to dex.port
+ http: 0.0.0.0:8080
+ logger:
+ level: "debug"
+ format: json
+
+ connectors:
+ - type: ldap
+ # Required field for connector id.
+ id: ldap
+ # Required field for connector name.
+ name: LDAP
+ config:
+ # Host and optional port of the LDAP server in the form "host:port".
+ # If the port is not supplied, it will be guessed based on "insecureNoSSL",
+ # and "startTLS" flags. 389 for insecure or StartTLS connections, 636
+ # otherwise.
+ host: ldap.k8s.example.org:1389
+
+ # Following field is required if the LDAP host is not using TLS (port 389).
+ # Because this option inherently leaks passwords to anyone on the same network
+ # as dex, THIS OPTION MAY BE REMOVED WITHOUT WARNING IN A FUTURE RELEASE.
+ #
+ insecureNoSSL: true
+ # If a custom certificate isn't provide, this option can be used to turn on
+ # TLS certificate checks. As noted, it is insecure and shouldn't be used outside
+ # of explorative phases.
+ #
+ insecureSkipVerify: true
+ # When connecting to the server, connect using the ldap:// protocol then issue
+ # a StartTLS command. If unspecified, connections will use the ldaps:// protocol
+ #
+ # startTLS: true
+ # Path to a trusted root certificate file. Default: use the host's root CA.
+ #rootCA: /etc/dex/ldap.ca
+ # A raw certificate file can also be provided inline.
+ #rootCAData:
+ # The DN and password for an application service account. The connector uses
+ # these credentials to search for users and groups. Not required if the LDAP
+ # server provides access for anonymous auth.
+ # Please note that if the bind password contains a `$`, it has to be saved in an
+ # environment variable which should be given as the value to `bindPW`.
+ bindDN: cn=admin,dc=example,dc=org
+ bindPW: admin
+
+ # User search maps a username and password entered by a user to a LDAP entry.
+ userSearch:
+ # BaseDN to start the search from. It will translate to the query
+ # "(&(objectClass=person)(uid=))".
+ baseDN: ou=People,dc=example,dc=org
+ # Optional filter to apply when searching the directory.
+ filter: "(objectClass=posixAccount)"
+ # username attribute used for comparing user entries. This will be translated
+ # and combine with the other filter as "(=)".
+ username: mail
+ # The following three fields are direct mappings of attributes on the user entry.
+ # String representation of the user.
+ idAttr: uid
+ # Required. Attribute to map to Email.
+ emailAttr: mail
+ # Maps to display name of users. No default value.
+ nameAttr: uid
+
+ # Group search queries for groups given a user entry.
+ groupSearch:
+ # BaseDN to start the search from. It will translate to the query
+ # "(&(objectClass=group)(member=))".
+ baseDN: ou=Groups,dc=example,dc=org
+ # Optional filter to apply when searching the directory.
+ filter: "(objectClass=posixGroup)"
+ # Following two fields are used to match a user to a group. It adds an additional
+ # requirement to the filter that an attribute in the group must match the user's
+ # attribute value.
+ userAttr: uid
+ groupAttr: memberUid
+ # Represents group name.
+ nameAttr: cn
+ oauth2:
+ skipApprovalScreen: true
+
+ # Configure static clients.
+ # Warning: ID fields must match client-id field on
+ # your kubernetes API server configuration
+ # Use trusted peers feature if more than one
+ # app should be used by kubernetes.
+ staticClients:
+ - id: cli
+ redirectURIs:
+ - 'https://loginapp.example.local/callback'
+ name: 'Login Application'
+ secret: ZXhhbXBsZS1hcHAtc2VjcmV0
+ # If keycloak is enabled, uncomment and complete
+ # following lines:
+ #- id: login
+ # redirectURIs:
+ # - 'https://dashboard.example.local/oauth/callback'
+ # name: 'Dashboard Application'
+ # secret: iCeiqu5phogh3Eesh5iPu3gaph9eexo6
+ # trustedPeers:
+ # - cli
+
+################
+### Loginapp ###
+################
+loginapp:
+ enabled: false
+ name: loginapp
+
+ # Image
+ image:
+ repository: quay.io/fydrah/loginapp
+ tag: 2.5.0
+ pullPolicy: IfNotPresent
+
+ # Deployment settings
+ replicas: 1
+ resources: {}
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+ nodeSelector: {}
+ tolerations: []
+ affinity: {}
+ podAnnotations: {}
+ port: 8080
+ servicePort: 8080
+
+ # Ingress
+ ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: 'true'
+ hosts:
+ - loginapp.example.local
+ tls: []
+ # - secretName: loginapp-example-tls
+ # hosts:
+ # - loginapp.example.local
+
+ # Loginapp configuration
+ # see: https://github.com/fydrah/loginapp#configuration
+ config:
+ name: "Login Application"
+ listen: "0.0.0.0:5555"
+ oidc:
+ client:
+ id: "loginapp"
+ secret: ZXhhbXBsZS1hcHAtc2VjcmV0
+ redirect_url: "https://loginapp.example.local/callback"
+ issuer:
+ root_ca: "/etc/ssl/ca.pem"
+ url: "https://dex.example.local"
+
+ # Issuer certificate authority
+ issuerCA: ""
+ #
+ # Example: Letsencrypt CA
+ # issuerCA: |
+ # -----BEGIN CERTIFICATE-----
+ # MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
+ # MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+ # DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
+ # PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
+ # Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ # AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
+ # rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
+ # OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
+ # xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
+ # 7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
+ # aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+ # HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
+ # SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
+ # ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
+ # AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
+ # R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
+ # JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
+ # Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+ # -----END CERTIFICATE-----
+
+######################
+### Keycloak Proxy ###
+######################
+keycloakProxy:
+ enabled: false
+ name: keycloak-proxy
+
+ # Image
+ image:
+ repository: keycloak/keycloak-gatekeeper
+ tag: 4.6.0.Final
+ pullPolicy: IfNotPresent
+
+ # Deployment settings
+ replicas: 1
+ resources: {}
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+ nodeSelector: {}
+ tolerations: []
+ affinity: {}
+ podAnnotations: {}
+ port: 8080
+ servicePort: 8080
+
+ # Ingress
+ ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: 'true'
+ hosts:
+ - dashboard.example.local
+ tls: []
+ # - secretName: dashboard-example-tls
+ # hosts:
+ # - dashboard.example.local
+
+ # Keycloak-proxy configuration
+ # See https://www.keycloak.org/docs/latest/securing_apps/index.html#example-usage-and-configuration
+ config:
+ client-id: CLIENT_ID
+ client-secret: CLIENT_SECRET
+ listen: ":8080"
+ enable-refresh-tokens: true
+ discovery-url: https://dex.example.org/dex/.well-known/openid-configuration
+ encryption-key: 0626a8d4c2544b141e629a9abf6c5db378b0e353
+ # By default, insecure communication between
+ # keycloak proxy and k8s dashboard (in-cluster communication)
+ upstream-url: http://kubernetes-dashboard.kube-system:80
+ scopes: []
+ resources: []
+
+ # Issuer certificate authority
+ issuerCA: ""
+ #
+ # Example: Letsencrypt CA
+ # issuerCA: |
+ # -----BEGIN CERTIFICATE-----
+ # MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
+ # MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+ # DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
+ # PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
+ # Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ # AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
+ # rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
+ # OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
+ # xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
+ # 7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
+ # aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+ # HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
+ # SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
+ # ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
+ # AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
+ # R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
+ # JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
+ # Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+ # -----END CERTIFICATE-----
+