Skip to content

Commit

Permalink
charts: Provide 3 options for oidc configuration
Browse files Browse the repository at this point in the history
Now users have 3 different way they can set oidc configuration

- Directly set values of respective config.oidc.clientID and others
  which inject them into ENV variable, to be used by args.
- Use external i.e. already created secret with the same keys as args.
- Use config.oidc.secret.create functionality to create secret and have
  them dynamically loaded into the headlamp deployment.

Fixes: #1897
Signed-off-by: Kautilya Tripathi <ktripathi@microsoft.com>
  • Loading branch information
knrt10 authored and skoeva committed Jun 21, 2024
1 parent 6a7403c commit c49994a
Show file tree
Hide file tree
Showing 15 changed files with 725 additions and 30 deletions.
23 changes: 12 additions & 11 deletions charts/headlamp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,15 @@ See [MAINTAINERS.md](https://github.com/headlamp-k8s/headlamp/blob/main/MAINTAIN

### Headlamp Configuration

| Key | Type | Default | Description |
|---------------------------|--------|-----------------------|-------------------------------------------------------------------------------------------------------|
| config.baseURL | string | `""` | base url path at which headlamp should run |
| config.extraArgs | object | `{}` | Extra arguments that can be given to the headlamp container |
| config.oidc.clientID | string | `""` | OIDC client ID |
| config.oidc.clientSecret | string | `""` | OIDC client secret |
| config.oidc.issuerURL | string | `""` | OIDC issuer URL |
| config.oidc.scopes | string | `""` | OIDC scopes to be used |
| config.oidc.secret.create | bool | `true` | Enable this option to have the chart automatically create the OIDC secret using the specified values. |
| config.oidc.secret.name | string | `oidc` | Name of the OIDC secret used by headlamp |
| config.pluginsDir | string | `"/headlamp/plugins"` | directory to look for plugins |
| Key | Type | Default | Description |
|------------------------------------|--------|-----------------------|-------------------------------------------------------------------------------------------------------|
| config.baseURL | string | `""` | base url path at which headlamp should run |
| config.oidc.clientID | string | `""` | OIDC client ID |
| config.oidc.clientSecret | string | `""` | OIDC client secret |
| config.oidc.issuerURL | string | `""` | OIDC issuer URL |
| config.oidc.scopes | string | `""` | OIDC scopes to be used |
| config.oidc.secret.create | bool | `true` | Enable this option to have the chart automatically create the OIDC secret using the specified values. |
| config.oidc.secret.name | string | `oidc` | Name of the OIDC secret used by headlamp |
| config.oidc.externalSecret.enabled | bool | `false` | Enable this option if you want to use an external secret for OIDC configuration. |
| config.oidc.externalSecret.name | string | `""` | Name of the external OIDC secret to be used by headlamp. |
| config.pluginsDir | string | `"/headlamp/plugins"` | directory to look for plugins |
87 changes: 73 additions & 14 deletions charts/headlamp/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
{{- $oidc := .Values.config.oidc }}
{{- $env := .Values.env }}

{{- $clientID := "" }}
{{- $clientSecret := "" }}
{{- $issuerURL := "" }}
{{- $scopes := "" }}

# This block of code is used to extract the values from the env.
# This is done to check if the values are non-empty and if they are, they are used in the deployment.yaml.
{{- range $env }}
{{- if eq .name "OIDC_CLIENT_ID" }}
{{- $clientID = .value }}
{{- end }}
{{- if eq .name "OIDC_CLIENT_SECRET" }}
{{- $clientSecret = .value }}
{{- end }}
{{- if eq .name "OIDC_ISSUER_URL" }}
{{- $issuerURL = .value }}
{{- end }}
{{- if eq .name "OIDC_SCOPES" }}
{{- $scopes = .value }}
{{- end }}
{{- end }}

apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -35,37 +60,59 @@ spec:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.registry}}/{{ .Values.image.repository }}:{{ .Values.image.tag | default (printf "v%s" .Chart.AppVersion) }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{ if or .Values.config.oidc .Values.env }}
{{ if or $oidc .Values.env }}
env:
{{- with .Values.config.oidc }}
{{- if or .clientID (not .secret.create) }}
{{- if $oidc.secret.create }}
{{- if $oidc.clientID }}
- name: OIDC_CLIENT_ID
valueFrom:
secretKeyRef:
name: {{ .secret.name }}
name: {{ $oidc.secret.name }}
key: clientID
{{- end }}
{{- if or .clientSecret (not .secret.create) }}
{{- if $oidc.clientSecret }}
- name: OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: {{ .secret.name }}
name: {{ $oidc.secret.name }}
key: clientSecret
{{- end }}
{{- if or .issuerURL (not .secret.create) }}
{{- if $oidc.issuerURL }}
- name: OIDC_ISSUER_URL
valueFrom:
secretKeyRef:
name: {{ .secret.name }}
name: {{ $oidc.secret.name }}
key: issuerURL
{{- end }}
{{- if or .scopes (not .secret.create) }}
{{- if $oidc.scopes }}
- name: OIDC_SCOPES
valueFrom:
secretKeyRef:
name: {{ .secret.name }}
name: {{ $oidc.secret.name }}
key: scopes
{{- end }}
{{- else if $oidc.externalSecret.enabled }}
# Check if externalSecret is enabled
envFrom:
- secretRef:
name: {{ $oidc.externalSecret.name }}
{{- else }}
{{- if $oidc.clientID }}
- name: OIDC_CLIENT_ID
value: {{ $oidc.clientID }}
{{- end }}
{{- if $oidc.clientSecret }}
- name: OIDC_CLIENT_SECRET
value: {{ $oidc.clientSecret }}
{{- end }}
{{- if $oidc.issuerURL }}
- name: OIDC_ISSUER_URL
value: {{ $oidc.issuerURL }}
{{- end }}
{{- if $oidc.scopes }}
- name: OIDC_SCOPES
value: {{ $oidc.scopes }}
{{- end }}
{{- end }}
{{- if .Values.env }}
{{- toYaml .Values.env | nindent 12 }}
Expand All @@ -76,16 +123,28 @@ spec:
{{- with .Values.config.pluginsDir}}
- "-plugins-dir={{ . }}"
{{- end }}
{{- if or .Values.config.oidc.clientID (not .Values.config.oidc.secret.create) }}
{{- if not $oidc.externalSecret.enabled}}
# Check if externalSecret is disabled
{{- if or (ne $oidc.clientID "") (ne $clientID "") }}
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
{{- end }}
{{- if or .Values.config.oidc.clientSecret (not .Values.config.oidc.secret.create) }}
{{- if or (ne $oidc.clientSecret "") (ne $clientSecret "") }}
# Check if clientSecret is non empty either from env or oidc.config
- "-oidc-client-secret=$(OIDC_CLIENT_SECRET)"
{{- end }}
{{- if or .Values.config.oidc.issuerURL (not .Values.config.oidc.secret.create) }}
{{- if or (ne $oidc.issuerURL "") (ne $issuerURL "") }}
# Check if issuerURL is non empty either from env or oidc.config
- "-oidc-idp-issuer-url=$(OIDC_ISSUER_URL)"
{{- end }}
{{- if or .Values.config.oidc.scopes (not .Values.config.oidc.secret.create) }}
{{- if or (ne $oidc.scopes "") (ne $scopes "") }}
# Check if scopes are non empty either from env or oidc.config
- "-oidc-scopes=$(OIDC_SCOPES)"
{{- end }}
{{- else }}
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
- "-oidc-client-secret=$(OIDC_CLIENT_SECRET)"
- "-oidc-idp-issuer-url=$(OIDC_ISSUER_URL)"
- "-oidc-scopes=$(OIDC_SCOPES)"
{{- end }}
{{- with .Values.config.baseURL }}
Expand Down
4 changes: 4 additions & 0 deletions charts/headlamp/tests/expected_templates/extra-args.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ spec:
app.kubernetes.io/instance: headlamp
---
# Source: headlamp/templates/deployment.yaml
# This block of code is used to extract the values from the env.
# This is done to check if the values are non-empty and if they are, they are used in the deployment.yaml.

apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -101,6 +104,7 @@ spec:
args:
- "-in-cluster"
- "-plugins-dir=/headlamp/plugins"
# Check if externalSecret is disabled
- -insecure-ssl
ports:
- name: http
Expand Down
153 changes: 153 additions & 0 deletions charts/headlamp/tests/expected_templates/oidc-create-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
---
# Source: headlamp/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: headlamp
labels:
helm.sh/chart: headlamp-0.21.0
app.kubernetes.io/name: headlamp
app.kubernetes.io/instance: headlamp
app.kubernetes.io/version: "0.23.2"
app.kubernetes.io/managed-by: Helm
---
# Source: headlamp/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: oidc
type: Opaque
data:
clientID: "dGVzdENsaWVudElk"
clientSecret: "dGVzdENsaWVudFNlY3JldA=="
issuerURL: "dGVzdElzc3VlclVSTA=="
scopes: "dGVzdFNjb3Bl"
---
# Source: headlamp/templates/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: headlamp-admin
labels:
helm.sh/chart: headlamp-0.21.0
app.kubernetes.io/name: headlamp
app.kubernetes.io/instance: headlamp
app.kubernetes.io/version: "0.23.2"
app.kubernetes.io/managed-by: Helm
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: headlamp
namespace: default
---
# Source: headlamp/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: headlamp
labels:
helm.sh/chart: headlamp-0.21.0
app.kubernetes.io/name: headlamp
app.kubernetes.io/instance: headlamp
app.kubernetes.io/version: "0.23.2"
app.kubernetes.io/managed-by: Helm
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: headlamp
app.kubernetes.io/instance: headlamp
---
# Source: headlamp/templates/deployment.yaml
# This block of code is used to extract the values from the env.
# This is done to check if the values are non-empty and if they are, they are used in the deployment.yaml.

apiVersion: apps/v1
kind: Deployment
metadata:
name: headlamp
labels:
helm.sh/chart: headlamp-0.21.0
app.kubernetes.io/name: headlamp
app.kubernetes.io/instance: headlamp
app.kubernetes.io/version: "0.23.2"
app.kubernetes.io/managed-by: Helm
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: headlamp
app.kubernetes.io/instance: headlamp
template:
metadata:
labels:
app.kubernetes.io/name: headlamp
app.kubernetes.io/instance: headlamp
spec:
serviceAccountName: headlamp
securityContext:
{}
containers:
- name: headlamp
securityContext:
privileged: false
runAsGroup: 101
runAsNonRoot: true
runAsUser: 100
image: "ghcr.io/headlamp-k8s/headlamp:v0.23.2"
imagePullPolicy: IfNotPresent

env:
- name: OIDC_CLIENT_ID
valueFrom:
secretKeyRef:
name: oidc
key: clientID
- name: OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: oidc
key: clientSecret
- name: OIDC_ISSUER_URL
valueFrom:
secretKeyRef:
name: oidc
key: issuerURL
- name: OIDC_SCOPES
valueFrom:
secretKeyRef:
name: oidc
key: scopes
args:
- "-in-cluster"
- "-plugins-dir=/headlamp/plugins"
# Check if externalSecret is disabled
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
# Check if clientSecret is non empty either from env or oidc.config
- "-oidc-client-secret=$(OIDC_CLIENT_SECRET)"
# Check if issuerURL is non empty either from env or oidc.config
- "-oidc-idp-issuer-url=$(OIDC_ISSUER_URL)"
# Check if scopes are non empty either from env or oidc.config
- "-oidc-scopes=$(OIDC_SCOPES)"
ports:
- name: http
containerPort: 4466
protocol: TCP
livenessProbe:
httpGet:
path: "/"
port: http
readinessProbe:
httpGet:
path: "/"
port: http
resources:
{}
Loading

0 comments on commit c49994a

Please sign in to comment.