fix(spiffe-oidc-discovery-provider): run under restricted PSA/SCC on OpenShift (#920)
* fix(spiffe-oidc-discovery-provider): run under restricted PSA/SCC on OpenShift The OIDC discovery provider does not require any elevated privileges: it runs fine under OpenShift's built-in restricted-v2 SCC (non-root, no privilege escalation, all capabilities dropped, RuntimeDefault seccomp, read-only root filesystem) and mounts only restricted-compatible volumes (csi, configMap, emptyDir, secret, projected, downwardAPI). Despite this, on OpenShift the chart: - downgraded the spire-server namespace from restricted to privileged PSA whenever the OIDC provider was enabled, and - created a fully privileged SecurityContextConstraints (host network/IPC/ PID, privileged container, hostPath, arbitrary seccomp, RunAsAny) bound to the provider's ServiceAccount. Both contradict the chart's own Namespaces documentation, which specifies restricted PSA for spire-server, and violate least privilege for an internet-facing OIDC endpoint. Remove the privileged PSA override for the OIDC provider (spire-server stays restricted; the scc.podSecurityLabelSync=false label is retained) and drop the privileged SCC so the provider falls through to restricted-v2. With spire-server enforcing restricted PSA, the inline-CSI PodSecurity check reads the cluster-scoped CSIDriver's security.openshift.io/csi-ephemeral-volume-profile label. If the CSIDriver is not committed before the spire-server StatefulSet (which mounts the inline upstream.csi.spiffe.io volume) is admitted, the profile defaults to privileged and admission is denied. Under ArgoCD the CSIDriver and the server StatefulSet can land in the same sync wave, racing admission. Annotate the CSIDriver with argocd.argoproj.io/sync-wave: "-1" (OpenShift only) so it is applied before the default-wave server workloads; the annotation is inert for plain helm installs. Signed-off-by: Michael Munch <[email protected]> * ✨ make CSIDriver sync-wave ordering configurable Add syncWave and csiDriverAnnotations values to the spiffe-csi-driver chart so the OpenShift argocd.argoproj.io/sync-wave annotation number can be overridden (e.g. when the chart is nested) and arbitrary annotations can be applied to the CSIDriver. Signed-off-by: Michael Munch <[email protected]> --------- Signed-off-by: Michael Munch <[email protected]> Co-authored-by: kfox1111 <[email protected]>
This commit is contained in:
co-authored by
kfox1111
parent
0726faa076
commit
ab5e5d8677
@@ -10,9 +10,6 @@
|
|||||||
{{- $labels = mergeOverwrite $labels (include "spire-lib.namespace.default_server_labels" . | fromYaml) }}
|
{{- $labels = mergeOverwrite $labels (include "spire-lib.namespace.default_server_labels" . | fromYaml) }}
|
||||||
{{- if (dig "openshift" false .Values.global) }}
|
{{- if (dig "openshift" false .Values.global) }}
|
||||||
{{- $_ := set $labels "security.openshift.io/scc.podSecurityLabelSync" "false" }}
|
{{- $_ := set $labels "security.openshift.io/scc.podSecurityLabelSync" "false" }}
|
||||||
{{- if (index .Values "spiffe-oidc-discovery-provider").enabled }}
|
|
||||||
{{- $_ := set $labels "pod-security.kubernetes.io/enforce" "privileged" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- $labels = mergeOverwrite $labels .Values.global.spire.namespaces.server.labels }}
|
{{- $labels = mergeOverwrite $labels .Values.global.spire.namespaces.server.labels }}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ A Helm chart to install the SPIFFE CSI driver.
|
|||||||
### SPIFFE CSI Driver Chart parameters
|
### SPIFFE CSI Driver Chart parameters
|
||||||
|
|
||||||
| Name | Description | Value |
|
| Name | Description | Value |
|
||||||
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------- |
|
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
||||||
| `pluginName` | Set the csi driver name deployed to Kubernetes. | `csi.spiffe.io` |
|
| `pluginName` | Set the csi driver name deployed to Kubernetes. | `csi.spiffe.io` |
|
||||||
| `image.registry` | The OCI registry to pull the image from | `ghcr.io` |
|
| `image.registry` | The OCI registry to pull the image from | `ghcr.io` |
|
||||||
| `image.repository` | The repository within the registry | `spiffe/spiffe-csi-driver` |
|
| `image.repository` | The repository within the registry | `spiffe/spiffe-csi-driver` |
|
||||||
@@ -46,6 +46,8 @@ A Helm chart to install the SPIFFE CSI driver.
|
|||||||
| `validatingAdmissionPolicy.enabled` | When set to auto, the validatingAdmissionPolicy will be enabled when the pluginName == "upstream.csi.spiffe.io" and k8s >= 1.30.0. Valid options are [auto, true, false] | `auto` |
|
| `validatingAdmissionPolicy.enabled` | When set to auto, the validatingAdmissionPolicy will be enabled when the pluginName == "upstream.csi.spiffe.io" and k8s >= 1.30.0. Valid options are [auto, true, false] | `auto` |
|
||||||
| `fullnameOverride` | Full name override for spiffe-csi-driver | `""` |
|
| `fullnameOverride` | Full name override for spiffe-csi-driver | `""` |
|
||||||
| `csiDriverLabels` | Labels to apply to the CSIDriver | `{}` |
|
| `csiDriverLabels` | Labels to apply to the CSIDriver | `{}` |
|
||||||
|
| `csiDriverAnnotations` | Annotations to apply to the CSIDriver | `{}` |
|
||||||
|
| `syncWave` | The argocd.argoproj.io/sync-wave value applied to the CSIDriver on OpenShift, ensuring the CSI driver reconciles before workloads that depend on its csi-ephemeral-volume-profile label | `-1` |
|
||||||
| `initContainers` | Init Containers to apply to the CSI Driver DaemonSet | `[]` |
|
| `initContainers` | Init Containers to apply to the CSI Driver DaemonSet | `[]` |
|
||||||
| `serviceAccount.create` | Specifies whether a service account should be created | `true` |
|
| `serviceAccount.create` | Specifies whether a service account should be created | `true` |
|
||||||
| `serviceAccount.annotations` | Annotations to add to the service account | `{}` |
|
| `serviceAccount.annotations` | Annotations to add to the service account | `{}` |
|
||||||
|
|||||||
@@ -3,10 +3,19 @@
|
|||||||
{{- $_ := set $labels "security.openshift.io/csi-ephemeral-volume-profile" "restricted" }}
|
{{- $_ := set $labels "security.openshift.io/csi-ephemeral-volume-profile" "restricted" }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- $labels = mergeOverwrite $labels .Values.csiDriverLabels }}
|
{{- $labels = mergeOverwrite $labels .Values.csiDriverLabels }}
|
||||||
|
{{- $annotations := dict }}
|
||||||
|
{{- if (dig "openshift" false .Values.global) }}
|
||||||
|
{{- $_ := set $annotations "argocd.argoproj.io/sync-wave" (toString .Values.syncWave) }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $annotations = mergeOverwrite $annotations .Values.csiDriverAnnotations }}
|
||||||
apiVersion: storage.k8s.io/v1
|
apiVersion: storage.k8s.io/v1
|
||||||
kind: CSIDriver
|
kind: CSIDriver
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ .Values.pluginName | quote }}
|
name: {{ .Values.pluginName | quote }}
|
||||||
|
{{- with $annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
{{- with $labels }}
|
{{- with $labels }}
|
||||||
labels:
|
labels:
|
||||||
{{- toYaml . | nindent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
|
|||||||
@@ -76,6 +76,12 @@ fullnameOverride: ""
|
|||||||
## @param csiDriverLabels Labels to apply to the CSIDriver
|
## @param csiDriverLabels Labels to apply to the CSIDriver
|
||||||
csiDriverLabels: {}
|
csiDriverLabels: {}
|
||||||
|
|
||||||
|
## @param csiDriverAnnotations Annotations to apply to the CSIDriver
|
||||||
|
csiDriverAnnotations: {}
|
||||||
|
|
||||||
|
## @param syncWave The argocd.argoproj.io/sync-wave value applied to the CSIDriver on OpenShift, ensuring the CSI driver reconciles before workloads that depend on its csi-ephemeral-volume-profile label
|
||||||
|
syncWave: -1
|
||||||
|
|
||||||
## @param initContainers Init Containers to apply to the CSI Driver DaemonSet
|
## @param initContainers Init Containers to apply to the CSI Driver DaemonSet
|
||||||
initContainers: []
|
initContainers: []
|
||||||
|
|
||||||
|
|||||||
-42
@@ -1,42 +0,0 @@
|
|||||||
{{- if eq (.Values.global.openshift | toString) "true" }}
|
|
||||||
apiVersion: security.openshift.io/v1
|
|
||||||
kind: SecurityContextConstraints
|
|
||||||
metadata:
|
|
||||||
name: {{ include "spiffe-oidc-discovery-provider.fullname" . }}
|
|
||||||
readOnlyRootFilesystem: true
|
|
||||||
runAsUser:
|
|
||||||
type: RunAsAny
|
|
||||||
seLinuxContext:
|
|
||||||
type: RunAsAny
|
|
||||||
supplementalGroups:
|
|
||||||
type: RunAsAny
|
|
||||||
users:
|
|
||||||
- system:serviceaccount:{{ include "spiffe-oidc-discovery-provider.namespace" . }}:{{ include "spiffe-oidc-discovery-provider.serviceAccountName" . }}
|
|
||||||
- system:serviceaccount:{{ include "spiffe-oidc-discovery-provider.namespace" . }}:{{ include "spiffe-oidc-discovery-provider.serviceAccountName" . }}-pre-delete
|
|
||||||
volumes:
|
|
||||||
- configMap
|
|
||||||
- csi
|
|
||||||
- downwardAPI
|
|
||||||
- emptyDir
|
|
||||||
- ephemeral
|
|
||||||
- hostPath
|
|
||||||
- projected
|
|
||||||
- secret
|
|
||||||
allowedCapabilities: null
|
|
||||||
allowHostDirVolumePlugin: true
|
|
||||||
allowHostIPC: true
|
|
||||||
allowHostNetwork: true
|
|
||||||
allowHostPID: true
|
|
||||||
allowHostPorts: true
|
|
||||||
allowPrivilegeEscalation: true
|
|
||||||
allowPrivilegedContainer: true
|
|
||||||
defaultAddCapabilities: null
|
|
||||||
fsGroup:
|
|
||||||
type: RunAsAny
|
|
||||||
groups: []
|
|
||||||
priority: null
|
|
||||||
requiredDropCapabilities: null
|
|
||||||
seccompProfiles:
|
|
||||||
- '*'
|
|
||||||
|
|
||||||
{{ end }}
|
|
||||||
@@ -349,6 +349,43 @@ spire-server:
|
|||||||
Expect(objs[serverTmpl]).Should(ContainSubstring("init-jwt-svid-exec"))
|
Expect(objs[serverTmpl]).Should(ContainSubstring("init-jwt-svid-exec"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Describe("spiffe-csi-driver.syncWave", func() {
|
||||||
|
csiTmpl := "spire/charts/spiffe-csi-driver/templates/spiffe-csi-driver.yaml"
|
||||||
|
It("renders the default sync-wave annotation on OpenShift", func() {
|
||||||
|
objs, err := ValueStringRender(chart, `
|
||||||
|
global:
|
||||||
|
openshift: true
|
||||||
|
`)
|
||||||
|
Expect(err).Should(Succeed())
|
||||||
|
Expect(objs[csiTmpl]).Should(ContainSubstring(`argocd.argoproj.io/sync-wave: "-1"`))
|
||||||
|
})
|
||||||
|
It("allows overriding the sync-wave number", func() {
|
||||||
|
objs, err := ValueStringRender(chart, `
|
||||||
|
global:
|
||||||
|
openshift: true
|
||||||
|
spiffe-csi-driver:
|
||||||
|
syncWave: -2
|
||||||
|
`)
|
||||||
|
Expect(err).Should(Succeed())
|
||||||
|
Expect(objs[csiTmpl]).Should(ContainSubstring(`argocd.argoproj.io/sync-wave: "-2"`))
|
||||||
|
})
|
||||||
|
It("allows overriding the annotation via csiDriverAnnotations", func() {
|
||||||
|
objs, err := ValueStringRender(chart, `
|
||||||
|
global:
|
||||||
|
openshift: true
|
||||||
|
spiffe-csi-driver:
|
||||||
|
csiDriverAnnotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "-5"
|
||||||
|
`)
|
||||||
|
Expect(err).Should(Succeed())
|
||||||
|
Expect(objs[csiTmpl]).Should(ContainSubstring(`argocd.argoproj.io/sync-wave: "-5"`))
|
||||||
|
})
|
||||||
|
It("does not render the sync-wave annotation when not on OpenShift", func() {
|
||||||
|
objs, err := ValueStringRender(chart, ``)
|
||||||
|
Expect(err).Should(Succeed())
|
||||||
|
Expect(objs[csiTmpl]).ShouldNot(ContainSubstring("argocd.argoproj.io/sync-wave"))
|
||||||
|
})
|
||||||
|
})
|
||||||
Describe("spire-server.externalServerSubject", func() {
|
Describe("spire-server.externalServerSubject", func() {
|
||||||
It("binds the external server's downstream RBAC to a ServiceAccount subject", func() {
|
It("binds the external server's downstream RBAC to a ServiceAccount subject", func() {
|
||||||
objs, err := ValueStringRender(chart, `
|
objs, err := ValueStringRender(chart, `
|
||||||
|
|||||||
Reference in New Issue
Block a user