From 94446a9169a3e6ec424c77ce5a4fc91df872854b Mon Sep 17 00:00:00 2001 From: fydrah Date: Wed, 6 Mar 2019 19:38:23 +0100 Subject: [PATCH] k8s-ldap migration, init new repository This commit includes: * Repository migration * `keycloak-proxy` replaced by `keycloak-gatekeeper` * Add loginapp configuration in values.yaml * Helm chart repository --- .gitignore | 1 + .helmignore | 24 ++ Chart.yaml | 13 + README.md | 43 +++ examples/SAML.md | 53 ++++ examples/cross-client.md | 50 ++++ templates/NOTES.txt | 6 + templates/_helpers.tpl | 49 ++++ templates/ca-cm.yaml | 13 + templates/dex-cm.yaml | 15 + templates/dex-cr.yaml | 21 ++ templates/dex-crb.yaml | 22 ++ templates/dex-crd.yaml | 15 + templates/dex-deployment.yaml | 77 ++++++ templates/dex-ingress.yaml | 34 +++ templates/dex-sa.yaml | 14 + templates/dex-service.yaml | 21 ++ templates/keycloak-proxy-cm.yaml | 15 + templates/keycloak-proxy-deployment.yaml | 86 ++++++ templates/keycloak-proxy-ingress.yaml | 34 +++ templates/keycloak-proxy-service.yaml | 21 ++ templates/loginapp-cm.yaml | 15 + templates/loginapp-deployment.yaml | 87 ++++++ templates/loginapp-ingress.yaml | 34 +++ templates/loginapp-service.yaml | 21 ++ values.yaml | 338 +++++++++++++++++++++++ 26 files changed, 1122 insertions(+) create mode 100644 .gitignore create mode 100644 .helmignore create mode 100644 Chart.yaml create mode 100644 README.md create mode 100644 examples/SAML.md create mode 100644 examples/cross-client.md create mode 100644 templates/NOTES.txt create mode 100644 templates/_helpers.tpl create mode 100644 templates/ca-cm.yaml create mode 100644 templates/dex-cm.yaml create mode 100644 templates/dex-cr.yaml create mode 100644 templates/dex-crb.yaml create mode 100644 templates/dex-crd.yaml create mode 100644 templates/dex-deployment.yaml create mode 100644 templates/dex-ingress.yaml create mode 100644 templates/dex-sa.yaml create mode 100644 templates/dex-service.yaml create mode 100644 templates/keycloak-proxy-cm.yaml create mode 100644 templates/keycloak-proxy-deployment.yaml create mode 100644 templates/keycloak-proxy-ingress.yaml create mode 100644 templates/keycloak-proxy-service.yaml create mode 100644 templates/loginapp-cm.yaml create mode 100644 templates/loginapp-deployment.yaml create mode 100644 templates/loginapp-ingress.yaml create mode 100644 templates/loginapp-service.yaml create mode 100644 values.yaml 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----- +