feat(authentik-application): add ldap support - WIP

This commit is contained in:
WrenIX 2024-12-04 16:54:29 +01:00
parent 6ca7741a91
commit cfba30c15b
Signed by: wrenix
GPG key ID: 7AFDB012974B1BB5
16 changed files with 351 additions and 300 deletions

View file

@ -2,7 +2,9 @@ apiVersion: v2
name: authentik-application
description: "A Chart to deploy a secret for the authentik blueprint-sidecar."
type: application
version: "0.4.3"
version: "0.5.0"
# renovate: image=ghcr.io/goauthentik/ldap
appVersion: "2024.12.1"
maintainers:
- name: WrenIX
url: https://wrenix.eu

View file

@ -1,284 +0,0 @@
= authentik-application
image::https://img.shields.io/badge/Version-0.4.3-informational?style=flat-square[Version: 0.4.3]
image::https://img.shields.io/badge/Version-application-informational?style=flat-square[Type: application]
== Maintainers
.Maintainers
|===
| Name | Email | Url
| WrenIX
|
| <https://wrenix.eu>
|===
## Pre-Requirement
Usage of https://github.com/goauthentik/helm/pull/146
## or manual:
Install authentik with this `values.yaml`:
```yaml
serviceAccount:
create: true
additionalContainers:
- name: sidecar-blueprints
image: "ghcr.io/kiwigrid/k8s-sidecar:1.25.1"
env:
- name: "FOLDER"
value: "/blueprints/sidecar"
- name: "LABEL"
value: "goauthentik_blueprint"
- name: "LABEL_VALUE"
value: "1"
# - name: "NAMESPACE"
# value: "ALL"
- name: "RESOURCE"
value: "both"
- name: "UNIQUE_FILENAMES"
value: "true"
volumeMounts:
- name: sidecar-blueprints
mountPath: /blueprints/sidecar
volumeMounts:
- name: sidecar-blueprints
mountPath: /blueprints/sidecar
volumes:
- name: sidecar-blueprints
emptyDir: {}
```
And create an Role and bind them on to the ServiceAccount to read secrets:
```yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: authentik-blueprint-sidecar
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: authentik-blueprint-sidecar
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: authentik-blueprint-sidecar
subjects:
- kind: ServiceAccount
name: authentik
```
== Usage
Helm must be installed and setup to your kubernetes cluster to use the charts.
Refer to Helm's https://helm.sh/docs[documentation] to get started.
Once Helm has been set up correctly, fetch the charts as follows:
[source,bash]
----
helm pull oci://codeberg.org/wrenix/helm-charts/authentik-application
----
You can install a chart release using the following command:
[source,bash]
----
helm install authentik-application-release oci://codeberg.org/wrenix/helm-charts/authentik-application --values values.yaml
----
To uninstall a chart release use `helm`'s delete command:
[source,bash]
----
helm uninstall authentik-application-release
----
== Values
.Values
|===
| Key | Type | Default | Description
| blueprint.application.bindPolicyID
| string
| `nil`
| uuid for bindPolicyID for group - if not set generated on secret for be stable (or groups: [] filled)
| blueprint.application.description
| string
| `""`
| description of application
| blueprint.application.group
| string
| `""`
| put this application in authentik in group
| blueprint.application.icon
| string
| `""`
| icon of application (url)
| blueprint.application.launchURL
| string
| `""`
|
| blueprint.application.name
| string
| `""`
| application name in menu
| blueprint.application.openInNewTab
| bool
| `false`
| open application in new tab
| blueprint.application.policyEngineMode
| string
| `"any"`
|
| blueprint.application.publisher
| string
| `""`
| publisher of application
| blueprint.application.slug
| string
| `"app-name"`
| application slug
| blueprint.authentik.domain
| string
| `"https://auth.wrenix.eu"`
| domain to authentik, used in generated url (like issuer)
| blueprint.groups
| string
| `nil`
| authentik groups created / give access to this application disable any groups by set groups: [] (to a slice) example: - slug: "app: grafana-admin" parent: "app: infra" bindID: uuid
| blueprint.labels
| object
| `{"goauthentik_blueprint":"1"}`
| label of generated secret with blueprint
| blueprint.provider.authorizationFlow
| string
| `"default-provider-authorization-implicit-consent"`
|
| blueprint.provider.enabled
| bool
| `true`
| creat an provider for authentification (otherwise just a like in menu is created)
| blueprint.provider.name
| string
| `""`
|
| blueprint.provider.oidc.clientID
| string
| `nil`
| client id - generated if secret enabled
| blueprint.provider.oidc.clientSecret
| string
| `nil`
| client secret - generated if secret enabled
| blueprint.provider.oidc.clientType
| string
| `"confidential"`
|
| blueprint.provider.oidc.redirectURL
| string
| `""`
|
| blueprint.provider.oidc.scopes
| string
| `nil`
| Scope
| blueprint.provider.oidc.signingKey
| string
| `""`
| Need for non-curve / RSA
| blueprint.provider.proxy.cookieDomain
| string
| `""`
|
| blueprint.provider.proxy.externalHost
| string
| `nil`
|
| blueprint.provider.proxy.ingress.annotations
| list
| `[]`
| annotations to ingress for outpost
| blueprint.provider.proxy.ingress.backend
| string
| `"authentik"`
| service backend to authentik
| blueprint.provider.proxy.ingress.domain
| string
| `nil`
| domain of application (where outpost should be deployed)
| blueprint.provider.proxy.ingress.enabled
| bool
| `false`
| deploy ingress on application domain for e.g. logout (WIP)
| blueprint.provider.proxy.ingress.tls
| list
| `[]`
| tls to ingress for outpost
| blueprint.provider.proxy.skipPathRegex
| string
| `""`
|
| blueprint.provider.saml
| string
| `nil`
|
| blueprint.provider.type
| string
| `"oidc"`
| type of application connection, current support: oidc, saml and proxy
| secret.labels
| object
| `{}`
| label of secret to store generated secret
| secret.name
| string
| `""`
| name of secret to store generated secret (like clientI)
|===
Autogenerated from chart metadata using https://github.com/norwoodj/helm-docs[helm-docs]

View file

@ -0,0 +1,6 @@
blueprint:
provider:
type: ldap
ldap:
autoscaling:
enabled: true

View file

@ -1,6 +1,6 @@
{{- with get . "root" }}
- model: authentik_core.Application
id: {{ .Values.blueprint.application.name | default (include "authentik-application.fullname" .) }}
id: app
identifiers:
slug: {{ .Values.blueprint.application.slug }}
state: present
@ -8,7 +8,7 @@
name: {{ .Values.blueprint.application.name | default (include "authentik-application.fullname" .) }}
slug: {{ .Values.blueprint.application.slug }}
{{- if .Values.blueprint.provider.enabled }}
provider: !KeyOf {{ .Values.blueprint.provider.name | default (include "authentik-application.fullname" .) }}
provider: !KeyOf provider
{{- end }}
policy_engine_mode: {{ .Values.blueprint.application.policyEngineMode }}
{{- with .Values.blueprint.application.group }}

View file

@ -4,7 +4,7 @@
{{- if (not (kindIs "slice" .Values.blueprint.groups)) }}
- model: authentik_core.group
id: "app: {{ .Values.blueprint.application.slug }}"
id: group
identifiers:
name: "app: {{ .Values.blueprint.application.slug }}"
state: "present"
@ -16,9 +16,9 @@
identifiers:
pk: {{ $bindPolicyID | quote }}
attrs:
group: !KeyOf "app: {{ .Values.blueprint.application.slug }}"
group: !KeyOf group
order: 10
target: !Find [authentik_core.Application, [slug, {{ .Values.blueprint.application.slug }}]]
target: !KeyOf app
{{- end }}
{{- range $group := .Values.blueprint.groups }}
@ -44,6 +44,7 @@
pk: {{ $group.bindID | quote }}
group: !KeyOf {{ $group.slug | quote}}
order: 10
target: !Find [authentik_core.Application, [slug, {{ $.Values.blueprint.application.slug }}]]
target: !KeyOf app
{{- end }}
{{- end }}{{/* end with of get-root */}}
{{ end }}{{/* end with of get-root */}}

View file

@ -0,0 +1,74 @@
{{- $name := include "authentik-application.fullname" .root }}
{{- $token := get . "ldapToken" }}
{{- with get . "root" }}
- model: authentik_providers_ldap.LDAPProvider
id: provider
identifiers:
name: {{ .Values.blueprint.provider.name | default $name }}
state: present
attrs:
base_dn: "DC=ldap,DC=goauthentik,DC=io"
bind_mode: "direct"
search_mode: "direct"
mfa_support: False
authorization_flow: !Find [authentik_flows.flow, [slug, default-authentication-flow]]
invalidation_flow: !Find [authentik_flows.flow, [slug, default-invalidation-flow]]
- model: authentik_core.user
id: outpost-user
state: present
identifiers:
username: {{ printf "outpost-user-%s" $name | quote }}
attrs:
username: {{ printf "outpost-user-%s" $name | quote }}
type: "service_account"
name: {{ printf "Outpost %s Service-Account" $name | quote }}
path: "goauthentik.io/outposts"
{{/*
- model: authentik_core.Token
id: outpost-token
identifiers:
identifier: {{ printf "outpost-token-%s-api" $name | quote }}
state: present
attrs:
identifier: {{ printf "outpost-token-%s-api" $name | quote }}
intent: "api"
user: !KeyOf outpost-user
description: {{ printf "Autogenerated by authentik for Outpost %s" $name | quote }}
key: {{ $token | quote }}
expiring: False
*/}}
- model: authentik_outposts.Outpost
id: outpost
identifiers:
name: {{ .Values.blueprint.provider.name | default (include "authentik-application.fullname" .) }}
state: present
attrs:
type: ldap
providers:
- !KeyOf provider
config:
authentik_host: {{ .Values.blueprint.authentik.domain | quote }}
authentik_host_insecure: False
user: !KeyOf "outpost-user"
{{/*
token: !KeyOf "outpost-token"
or:
- model: UserObjectPermission
identifiers:
user: !KeyOf "outpost-user"
content_type: "authentik_outposts.outpost"
state: present
attrs:
user: !KeyOf "outpost-user"
content_type: "authentik_outposts.outpost"
object_pk: !KeyOf "outpost"
permission: "view_outpost"
*/}}
{{- end }}{{/* end with of get-root */}}

View file

@ -16,7 +16,7 @@
{{- end }}
- model: authentik_providers_oauth2.OAuth2Provider
id: {{ .Values.blueprint.provider.name | default (include "authentik-application.fullname" .) }}
id: provider
identifiers:
name: {{ .Values.blueprint.provider.name | default (include "authentik-application.fullname" .) }}
state: present

View file

@ -1,6 +1,6 @@
{{- with get . "root" }}
- model: authentik_providers_proxy.ProxyProvider
id: {{ .Values.blueprint.provider.name | default (include "authentik-application.fullname" .) }}
id: provider
identifiers:
name: {{ .Values.blueprint.provider.name | default (include "authentik-application.fullname" .) }}
state: present

View file

@ -0,0 +1,30 @@
{{- with get . "root" }}
{{- $ = . }}
{{- range $user := .Values.blueprint.users }}
- model: authentik_core.group
id: {{ $user.username | quote }}
identifiers:
name: {{ $user.username | quote }}
state: {{ $user.state | default "present" | quote }}
attrs:
name: {{ $user.name | quote }}
ak_groups:
{{- range $group := $user.groups }}
- !Find [authentik_core.group, [name, {{ $group | quote }}]]
{{- else }}
{{- if (not (kindIs "slice" $.Values.blueprint.groups)) }}
- !Find [authentik_core.group, [name, "app: {{ .Values.blueprint.application.slug }}"]]
{{- end }}
{{- end }}{{/* end range-else */}}
{{- with $user.type }}
type: {{ . | quote }}
{{- end }}
{{- with $user.path }}
path: {{ . | quote }}
{{- end }}
{{- end }}
{{ end }}{{/* end with of get-root */}}

View file

@ -52,12 +52,23 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{/*
Create the name of the service account to use
needs argument:
root: $.Values
part: "ldap"
*/}}
{{- define "authentik-application.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "authentik-application.fullname" .) .Values.serviceAccount.name }}
{{- $ := get . "root" }}
{{- $part := get . "part" }}
{{- $partObj := get $.Values $part }}
{{- if $partObj.serviceAccount.create }}
{{- $defaultName := include "authentik-application.fullname" $ }}
{{- if $part }}
{{- $partObj.serviceAccount.name | default (printf "%s-%s" $defaultName $part) }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- $partObj.serviceAccount.name | default $defaultName }}
{{- end }}
{{- else }}
{{- $partObj.serviceAccount.name | default "default" }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,88 @@
{{- if (eq .Values.blueprint.provider.type "ldap") }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "authentik-application.fullname" . }}-ldap
labels:
{{- include "authentik-application.labels" . | nindent 4 }}
spec:
{{- if not .Values.ldap.autoscaling.enabled }}
replicas: {{ .Values.ldap.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "authentik-application.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: ldap
template:
metadata:
annotations:
{{- with .Values.ldap.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "authentik-application.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: ldap
{{- with .Values.ldap.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.ldap.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "authentik-application.serviceAccountName" (dict "root" . "part" "ldap") }}
securityContext:
{{- toYaml .Values.ldap.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}-ldap
securityContext:
{{- toYaml .Values.ldap.securityContext | nindent 12 }}
image: "{{ .Values.ldap.image.registry }}/{{ .Values.ldap.image.repository }}:{{ .Values.ldap.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.ldap.image.pullPolicy }}
env:
- name: "AUTHENTIK_LISTEN__LDAP"
value: ":{{ .Values.ldap.config.listen.ldap }}"
- name: "AUTHENTIK_LISTEN__LDAPS"
value: ":{{ .Values.ldap.config.listen.ldaps }}"
- name: "AUTHENTIK_LISTEN__METRICS"
value: ":{{ .Values.ldap.config.listen.metrics }}"
- name: "AUTHENTIK_HOST"
value: {{ .Values.blueprint.authentik.domain | quote }}
- name: "AUTHENTIK_TOKEN"
valueFrom:
secretKeyRef:
name: {{ include "authentik-application.fullname" . }}
key: "ldapToken"
ports:
- name: ldap
containerPort: {{ .Values.ldap.config.listen.ldap }}
protocol: TCP
- name: ldaps
containerPort: {{ .Values.ldap.config.listen.ldaps }}
protocol: TCP
- name: metrics
containerPort: {{ .Values.ldap.config.listen.metrics }}
protocol: TCP
livenessProbe:
httpGet:
path: /metrics
port: metrics
readinessProbe:
httpGet:
path: /metrics
port: metrics
resources:
{{- toYaml .Values.ldap.resources | nindent 12 }}
{{- with .Values.ldap.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.ldap.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.ldap.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,28 @@
{{- if and (eq .Values.blueprint.provider.type "ldap") .Values.ldap.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "authentik-application.fullname" . }}-ldap
labels:
{{- include "authentik-application.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "authentik-application.fullname" . }}-ldap
minReplicas: {{ .Values.ldap.autoscaling.minReplicas }}
maxReplicas: {{ .Values.ldap.autoscaling.maxReplicas }}
metrics:
{{- if .Values.ldap.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ .Values.ldap.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.ldap.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
targetAverageUtilization: {{ .Values.ldap.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,18 @@
{{- if (eq .Values.blueprint.provider.type "ldap") }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "authentik-application.fullname" . }}-ldap
labels:
{{- include "authentik-application.labels" . | nindent 4 }}
spec:
selector:
{{- include "authentik-application.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: ldap
type: {{ .Values.ldap.service.type }}
ports:
- name: ldap
protocol: TCP
port: {{ .Values.ldap.service.port }}
targetPort: ldap
{{- end }}

View file

@ -0,0 +1,12 @@
{{- if and (eq .Values.blueprint.provider.type "ldap") .Values.ldap.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "authentik-application.serviceAccountName" (dict "root" . "part" "ldap" ) }}
labels:
{{- include "authentik-application.labels" . | nindent 4 }}
{{- with .Values.ldap.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View file

@ -1,5 +1,6 @@
{{- $clientID := include "authentik-application.staticValue" (dict "root" $ "name" "clientID" "default" (randAlphaNum 32) "overwrite" .Values.blueprint.provider.oidc.clientID) }}
{{- $clientSecret := include "authentik-application.staticValue" (dict "root" $ "name" "clientSecret" "default" (randAlphaNum 32) "overwrite" .Values.blueprint.provider.oidc.clientSecret) }}
{{- $ldapToken := include "authentik-application.staticValue" (dict "root" $ "name" "ldapToken" "default" (randAlphaNum 32) "overwrite" .Values.blueprint.provider.ldap.token) }}
{{- $bindPolicyID := include "authentik-application.staticValue" (dict "root" $ "name" "bindPolicyID" "default" (uuidv4) "overwrite" .Values.blueprint.application.bindPolicyID) }}
---
apiVersion: v1
@ -39,6 +40,11 @@ stringData:
claimGroups: {{ . | quote }}
{{- end }}
{{- end }}{{/* end with oidc */}}
{{- with .Values.blueprint.provider.ldap }}
ldapToken: {{ $ldapToken | quote }}
{{- end }}{{/* end with ldap */}}
{{- end }}{{/* end if provider */}}
---
apiVersion: v1
@ -56,10 +62,14 @@ stringData:
metadata:
name: {{ include "authentik-application.fullname" . }}
entries:
{{- $tplValues := (dict "root" $ "Template" .Template "bindPolicyID" $bindPolicyID "clientID" $clientID "clientSecret" $clientSecret) }}
{{- $tplValues := (dict "root" $ "Template" .Template "bindPolicyID" $bindPolicyID "clientID" $clientID "clientSecret" $clientSecret "ldapToken" $ldapToken) }}
{{- if .Values.blueprint.provider.enabled }}
{{- tpl (.Files.Get (printf "files/provider/%s.yaml.gotmpl" .Values.blueprint.provider.type)) $tplValues | nindent 6 }}
{{- end }}
{{- tpl (.Files.Get "files/application.yaml.gotmpl") $tplValues | nindent 6 }}
{{- tpl (.Files.Get "files/groups.yaml.gotmpl") $tplValues | nindent 6 }}
{{- tpl (.Files.Get "files/users.yaml.gotmpl") $tplValues | nindent 6 }}
{{- with .Values.blueprint.extras }}
{{- toYaml . | nindent 6 }}
{{- end }}

View file

@ -16,7 +16,7 @@ blueprint:
enabled: true
name: ""
authorizationFlow: "default-provider-authorization-implicit-consent"
# -- type of application connection, current support: oidc, saml and proxy
# -- type of application connection, current support: oidc, ldap and proxy
type: "oidc"
oidc:
clientType: "confidential"
@ -33,6 +33,10 @@ blueprint:
# scope_name:
# expression:
saml:
ldap:
# -- token - generated if secret enabled
token:
proxy:
externalHost:
skipPathRegex: ""
@ -75,4 +79,55 @@ blueprint:
# parent: "app: infra"
# bindID: uuid
#
groups:
groups: []
# -- Add users
# example:
# - username: ""
# name: ""
# groups: # optional
# - "name"
# type: "" # optional
# path: "users" # optional
users: []
# add additional groups
extras: []
ldap:
replicaCount: 1
image:
registry: ghcr.io
repository: goauthentik/ldap
# -- Overrides the image tag whose default is the chart appVersion.
tag: ""
pullPolicy: IfNotPresent
imagePullSecrets: []
config:
listen:
ldap: 3389
ldaps: 6636
metrics: 9300
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podLabels: {}
podAnnotations: {}
podSecurityContext: {}
securityContext: {}
service:
type: ClusterIP
port: 389
resources: {}
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations: []
affinity: {}