Protects SPIRE Agent's Chart Against YAML Template Injection (#450)

* protects agent's chart against template injection

Signed-off-by: Nico Weisenauer <[email protected]>

* removes unnecessary braces and whitespace

Signed-off-by: Nico Weisenauer <[email protected]>

* Removes int type validation via cast

Signed-off-by: Nico Weisenauer <[email protected]>

---------

Signed-off-by: Nico Weisenauer <[email protected]>
This commit is contained in:
nweisenauer
2024-09-16 06:23:01 -07:00
committed by GitHub
parent ea710023f4
commit 8832da39b4
8 changed files with 61 additions and 53 deletions
@@ -75,20 +75,20 @@ Create chart name and version as used by the chart label.
Common labels
*/}}
{{- define "spire-agent.labels" -}}
helm.sh/chart: {{ include "spire-agent.chart" . }}
helm.sh/chart: {{ include "spire-agent.chart" . | quote }}
{{ include "spire-agent.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "spire-agent.selectorLabels" -}}
app.kubernetes.io/name: {{ include "spire-agent.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/name: {{ include "spire-agent.name" . | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
{{- end }}
{{/*
@@ -53,7 +53,7 @@ agent:
default_svid_name: {{ .Values.sds.defaultSvidName | quote }}
default_bundle_name: {{ .Values.sds.defaultBundleName | quote }}
default_all_bundles_name: {{ .Values.sds.defaultAllBundlesName | quote }}
disable_spiffe_cert_validation: {{ .Values.sds.disableSpiffeCertValidation }}
disable_spiffe_cert_validation: {{ eq .Values.sds.disableSpiffeCertValidation true }}
{{- end }}
{{- with .Values.experimental }}
@@ -97,7 +97,7 @@ plugins:
{{- if eq (.enabled | toString) "true" }}
tpm:
plugin_cmd: "/tpm/tpm_attestor_agent"
plugin_checksum: {{ .plugin.checksum }}
plugin_checksum: {{ .plugin.checksum | quote }}
plugin_data: {}
{{- $nodeAttestorUsed = add1 $nodeAttestorUsed }}
{{- end }}
@@ -126,9 +126,9 @@ plugins:
kubelet_ca_path: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
{{- end }}
skip_kubelet_verification: {{ eq .Values.workloadAttestors.k8s.verification.type "skip" }}
disable_container_selectors: {{ .Values.workloadAttestors.k8s.disableContainerSelectors }}
use_new_container_locator: {{ .Values.workloadAttestors.k8s.useNewContainerLocator }}
verbose_container_locator_logs: {{ .Values.workloadAttestors.k8s.verboseContainerLocatorLogs }}
disable_container_selectors: {{ eq .Values.workloadAttestors.k8s.disableContainerSelectors true}}
use_new_container_locator: {{ eq .Values.workloadAttestors.k8s.useNewContainerLocator true }}
verbose_container_locator_logs: {{ eq .Values.workloadAttestors.k8s.verboseContainerLocatorLogs true }}
{{- if eq (include "spire-agent.connect-by-hostname" .) "true" }}
node_name_env: "MY_NODE_NAME"
{{- end }}
@@ -168,8 +168,8 @@ telemetry:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "spire-agent.fullname" . }}{{ $nameSuffix }}
namespace: {{ include "spire-agent.namespace" . }}
name: {{ printf "%s%s" (include "spire-agent.fullname" .) $nameSuffix | quote }}
namespace: {{ include "spire-agent.namespace" . | quote }}
{{- with .Values.configMap.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
@@ -22,16 +22,16 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: {{ include "spire-agent.fullname" . }}{{ $nameSuffix }}
namespace: {{ include "spire-agent.namespace" . }}
name: {{ printf "%s%s" (include "spire-agent.fullname" .) $nameSuffix | quote }}
namespace: {{ include "spire-agent.namespace" . | quote}}
labels:
{{- include "spire-agent.labels" . | nindent 4 }}
app.kubernetes.io/component: {{ $name }}
app.kubernetes.io/component: {{ $name | quote }}
spec:
selector:
matchLabels:
{{- include "spire-agent.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: {{ $name }}
app.kubernetes.io/component: {{ $name | quote }}
{{- with .Values.updateStrategy }}
updateStrategy:
{{- if not (has .type (list "RollingUpdate" "OnDelete")) }}
@@ -47,13 +47,13 @@ spec:
metadata:
annotations:
kubectl.kubernetes.io/default-container: spire-agent
checksum/config: {{ $configSum }}
checksum/config: {{ $configSum | quote }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "spire-agent.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: {{ $name }}
app.kubernetes.io/component: {{ $name | quote }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
@@ -65,7 +65,7 @@ spec:
hostPID: true
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
serviceAccountName: {{ include "spire-agent.serviceAccountName" . }}
serviceAccountName: {{ include "spire-agent.serviceAccountName" . | quote }}
securityContext:
{{- toYaml $podSecurityContext | nindent 8 }}
{{- include "spire-lib.default_node_priority_class_name" . | nindent 6 }}
@@ -79,17 +79,17 @@ spec:
securityContext:
{{- $mainSecurityContext | toYaml | nindent 12 }}
image: {{ template "spire-lib.image" (dict "image" .Values.hostCert.image "global" .Values.global) }}
imagePullPolicy: {{ .Values.hostCert.image.pullPolicy }}
imagePullPolicy: {{ .Values.hostCert.image.pullPolicy | quote }}
command: ["bash", "-xc"]
args:
- |
{{- if ne .Values.workloadAttestors.k8s.verification.hostCert.fileName "" }}
openssl x509 -in "{{ .Values.workloadAttestors.k8s.verification.hostCert.basePath }}/{{ .Values.workloadAttestors.k8s.verification.hostCert.fileName }}" -out /hostCert/kubelet.crt
openssl x509 -in {{ printf "%s/%s" .Values.workloadAttestors.k8s.verification.hostCert.basePath .Values.workloadAttestors.k8s.verification.hostCert.fileName | quote }} -out /hostCert/kubelet.crt
{{- else }}
if [ -f "{{ .Values.workloadAttestors.k8s.verification.hostCert.basePath }}/kubelet-server-current.pem" ]; then
openssl x509 -in "{{ .Values.workloadAttestors.k8s.verification.hostCert.basePath }}/kubelet-server-current.pem" -out /hostCert/kubelet.crt
openssl x509 -in {{ printf "%s/kubelet-server-current.pem" .Values.workloadAttestors.k8s.verification.hostCert.basePath | quote }} -out /hostCert/kubelet.crt
elif [ -f "{{ .Values.workloadAttestors.k8s.verification.hostCert.basePath }}/kubelet.crt" ]; then
openssl x509 -in "{{ .Values.workloadAttestors.k8s.verification.hostCert.basePath }}/kubelet.crt" -out /hostCert/kubelet.crt
openssl x509 -in {{ printf "%s/kubelet.crt" .Values.workloadAttestors.k8s.verification.hostCert.basePath | quote }} -out /hostCert/kubelet.crt
else
{{- if eq .Values.workloadAttestors.k8s.verification.type "auto" }}
{{- if $cbh }}
@@ -150,7 +150,7 @@ spec:
readOnly: true
- name: kmsg
mountPath: /dev/kmsg
imagePullPolicy: {{ .Values.nodeAttestor.tpmDirect.pubHash.image.pullPolicy }}
imagePullPolicy: {{ .Values.nodeAttestor.tpmDirect.pubHash.image.pullPolicy | quote }}
{{- end }}
- name: init-tpm-direct
securityContext:
@@ -161,16 +161,16 @@ spec:
- -ec
- |
# SPIRE must be able to fork the plugin directly within its container. Copy the plugin into a volume that can be mounted where SPIRE can execute it.
cp -a {{ .Values.nodeAttestor.tpmDirect.plugin.path }} /tpm/tpm_attestor_agent
cp -a {{ .Values.nodeAttestor.tpmDirect.plugin.path | quote }} /tpm/tpm_attestor_agent
volumeMounts:
- name: tpm-direct
mountPath: /tpm
imagePullPolicy: {{ .Values.nodeAttestor.tpmDirect.plugin.image.pullPolicy }}
imagePullPolicy: {{ .Values.nodeAttestor.tpmDirect.plugin.image.pullPolicy | quote }}
{{- end }}
{{- if gt (len $socketAlternateNames) 0 }}
- name: ensure-alternate-names
image: {{ template "spire-lib.image" (dict "image" .Values.socketAlternate.image "global" .Values.global) }}
imagePullPolicy: {{ .Values.socketAlternate.image.pullPolicy }}
imagePullPolicy: {{ .Values.socketAlternate.image.pullPolicy | quote }}
command: ["bash", "-xc"]
{{- /* 1. Look for symlinks pointing at the wrong place and remove them. 2. Make symlinks that don't exist. 3. If new socket is pointing at an existing symlink, remove old symlink. */}}
args:
@@ -195,12 +195,12 @@ spec:
{{- if gt (int (dig "fsGroup" 0 $podSecurityContext)) 0 }}
- name: fsgroupfix
image: {{ template "spire-lib.image" (dict "image" .Values.fsGroupFix.image "global" .Values.global) }}
imagePullPolicy: {{ .Values.fsGroupFix.image.pullPolicy }}
imagePullPolicy: {{ .Values.fsGroupFix.image.pullPolicy | quote }}
command: ["bash", "-c"]
args:
- |
chown -R {{ $podSecurityContext.runAsUser }}:{{ $podSecurityContext.fsGroup }} {{ $socketPath | dir }} /tmp/spire-agent/private
chown -R {{ $podSecurityContext.runAsUser }}:{{ $podSecurityContext.fsGroup }} /var/lib/spire
chown -R {{ printf "%v:%v" $podSecurityContext.runAsUser $podSecurityContext.fsGroup | quote }} {{ $socketPath | dir }} /tmp/spire-agent/private
chown -R {{ printf "%v:%v" $podSecurityContext.runAsUser $podSecurityContext.fsGroup | quote }} /var/lib/spire
resources:
{{- toYaml .Values.fsGroupFix.resources | nindent 12 }}
volumeMounts:
@@ -218,9 +218,9 @@ spec:
{{- toYaml .Values.initContainers | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
- name: {{ .Chart.Name | quote }}
image: {{ template "spire-lib.image" (dict "appVersion" $.Chart.AppVersion "image" .Values.image "global" .Values.global) }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
args: ["-config", "/opt/spire/conf/agent/agent.conf"]
securityContext:
{{- $mainSecurityContext | toYaml | nindent 12 }}
@@ -314,7 +314,11 @@ spec:
{{- if .Values.sockets.admin.mountOnHost }}
- name: spire-agent-admin-socket-dir
hostPath:
path: {{ .Values.sockets.hostBasePath }}/{{ if .Values.upstream }}upstream.csi.spiffe.io{{ else }}csi.spiffe.io{{ end }}/admin
{{- if .Values.upstream }}
path: {{ printf "%s/upstream.csi.spiffe.io/admin" .Values.sockets.hostBasePath | quote }}
{{- else }}
path: {{ printf "%s/csi.spiffe.io/admin" .Values.sockets.hostBasePath | quote }}
{{- end }}
type: DirectoryOrCreate
{{- else }}
- name: spire-agent-admin-socket-dir
@@ -323,7 +327,11 @@ spec:
{{- if eq .Values.persistence.type "hostPath" }}
- name: spire-agent-persistence
hostPath:
path: {{ .Values.persistence.hostPath }}/{{ if .Values.upstream }}upstream.csi.spiffe.io{{ else }}csi.spiffe.io{{ end }}
{{- if .Values.upstream }}
path: {{ printf "%s/upstream.csi.spiffe.io" .Values.persistence.hostPath | quote }}
{{- else }}
path: {{ printf "%s/csi.spiffe.io" .Values.persistence.hostPath | quote }}
{{- end }}
type: DirectoryOrCreate
{{- else }}
- name: spire-agent-persistence
@@ -332,7 +340,7 @@ spec:
{{- if eq (len .Values.trustBundleURL) 0 }}
- name: spire-bundle
configMap:
name: {{ include "spire-lib.bundle-configmap" . }}{{ $nameSuffix }}
name: {{ printf "%s%s" (include "spire-lib.bundle-configmap" .) $nameSuffix | quote }}
{{- end }}
{{- if .Values.nodeAttestor.tpmDirect.enabled }}
- name: tpm-direct
@@ -364,7 +372,7 @@ spec:
emptyDir: {}
- name: host-cert
hostPath:
path: {{ .Values.workloadAttestors.k8s.verification.hostCert.basePath }}
path: {{ .Values.workloadAttestors.k8s.verification.hostCert.basePath | quote }}
{{- end }}
{{- if gt (len .Values.extraVolumes) 0 }}
{{- toYaml .Values.extraVolumes | nindent 8 }}
@@ -5,7 +5,7 @@ apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: {{ include "spire-agent.fullname" . }}
namespace: {{ $namespace }}
namespace: {{ $namespace | quote }}
labels:
{{- include "spire-agent.labels" . | nindent 4 }}
{{- if ne (len (dig "telemetry" "prometheus" "podMonitor" "labels" (dict) .Values.global)) 0 }}
@@ -22,6 +22,6 @@ spec:
- port: prom
{{- if ne $namespace $podNamespace }}
namespaceSelector:
kubernetes.io/metadata.name: {{ $podNamespace }}
kubernetes.io/metadata.name: {{ $podNamespace | quote }}
{{- end }}
{{- end }}
@@ -2,7 +2,7 @@
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "spire-agent.fullname" . }}
name: {{ include "spire-agent.fullname" . | quote }}
rules:
- apiGroups: [""]
resources:
@@ -15,12 +15,12 @@ rules:
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "spire-agent.fullname" . }}
name: {{ include "spire-agent.fullname" . | quote }}
subjects:
- kind: ServiceAccount
name: {{ include "spire-agent.serviceAccountName" . }}
namespace: {{ include "spire-agent.namespace" . }}
name: {{ include "spire-agent.serviceAccountName" . | quote }}
namespace: {{ include "spire-agent.namespace" . | quote }}
roleRef:
kind: ClusterRole
name: {{ include "spire-agent.fullname" . }}
name: {{ include "spire-agent.fullname" . | quote }}
apiGroup: rbac.authorization.k8s.io
@@ -2,7 +2,7 @@
apiVersion: security.openshift.io/v1
kind: SecurityContextConstraints
metadata:
name: {{ include "spire-agent.fullname" . }}
name: {{ include "spire-agent.fullname" . | quote }}
readOnlyRootFilesystem: true
runAsUser:
type: RunAsAny
@@ -11,7 +11,7 @@ seLinuxContext:
supplementalGroups:
type: RunAsAny
users:
- system:serviceaccount:{{ include "spire-agent.namespace" . }}:{{ include "spire-agent.serviceAccountName" . }}
- {{ printf "system:serviceaccount:%s:%s" (include "spire-agent.namespace" .) (include "spire-agent.serviceAccountName" .) | quote }}
volumes:
- configMap
- hostPath
@@ -2,8 +2,8 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "spire-agent.serviceAccountName" . }}
namespace: {{ include "spire-agent.namespace" . }}
name: {{ include "spire-agent.serviceAccountName" . | quote }}
namespace: {{ include "spire-agent.namespace" . | quote }}
labels:
{{- include "spire-agent.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
@@ -53,17 +53,17 @@
{{- $repo := .image.repository }}
{{- $tag := .image.tag | toString }}
{{- if eq (substr 0 7 $tag) "sha256:" }}
{{- printf "%s/%s@%s" $registry $repo $tag }}
{{- printf "%s/%s@%s" $registry $repo $tag | quote }}
{{- else if .appVersion }}
{{- $appVersion := .appVersion }}
{{- if and (hasKey . "ubi") (dig "openshift" false .global) }}
{{- $appVersion = printf "ubi-%s" $appVersion }}
{{- end }}
{{- printf "%s%s:%s" $registry $repo (default $appVersion $tag) }}
{{- printf "%s%s:%s" $registry $repo (default $appVersion $tag) | quote }}
{{- else if $tag }}
{{- printf "%s%s:%s" $registry $repo $tag }}
{{- printf "%s%s:%s" $registry $repo $tag | quote }}
{{- else }}
{{- printf "%s%s" $registry $repo }}
{{- printf "%s%s" $registry $repo | quote }}
{{- end }}
{{- end }}
@@ -309,7 +309,7 @@ securityContext - the subbranch of values that contains the securityContext to m
{{- define "spire-lib.default_node_priority_class_name" }}
{{- if .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName | quote }}
{{- else if and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "priorityClassName" true .Values.global) }}
priorityClassName: system-node-critical
{{- end }}
@@ -317,7 +317,7 @@ priorityClassName: system-node-critical
{{- define "spire-lib.default_cluster_priority_class_name" }}
{{- if .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName | quote }}
{{- else if and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "priorityClassName" true .Values.global) }}
priorityClassName: system-cluster-critical
{{- end }}