Skip to content

Commit

Permalink
Add CSI secrets store provider (#461)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhjp authored Mar 19, 2021
1 parent ff73577 commit 4c1d79f
Show file tree
Hide file tree
Showing 14 changed files with 847 additions and 0 deletions.
55 changes: 55 additions & 0 deletions templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,61 @@ Sets the container resources if the user has set any.
{{ end }}
{{- end -}}

{{/*
Sets the container resources if the user has set any.
*/}}
{{- define "csi.resources" -}}
{{- if .Values.csi.resources -}}
resources:
{{ toYaml .Values.csi.resources | indent 12}}
{{ end }}
{{- end -}}

{{/*
Sets extra CSI daemonset annotations
*/}}
{{- define "csi.daemonSet.annotations" -}}
{{- if .Values.csi.daemonSet.annotations }}
annotations:
{{- $tp := typeOf .Values.csi.daemonSet.annotations }}
{{- if eq $tp "string" }}
{{- tpl .Values.csi.daemonSet.annotations . | nindent 4 }}
{{- else }}
{{- toYaml .Values.csi.daemonSet.annotations | nindent 4 }}
{{- end }}
{{- end }}
{{- end -}}

{{/*
Sets extra CSI provider pod annotations
*/}}
{{- define "csi.pod.annotations" -}}
{{- if .Values.csi.pod.annotations }}
annotations:
{{- $tp := typeOf .Values.csi.pod.annotations }}
{{- if eq $tp "string" }}
{{- tpl .Values.csi.pod.annotations . | nindent 8 }}
{{- else }}
{{- toYaml .Values.csi.pod.annotations | nindent 8 }}
{{- end }}
{{- end }}
{{- end -}}

{{/*
Sets extra CSI service account annotations
*/}}
{{- define "csi.serviceAccount.annotations" -}}
{{- if .Values.csi.serviceAccount.annotations }}
annotations:
{{- $tp := typeOf .Values.csi.serviceAccount.annotations }}
{{- if eq $tp "string" }}
{{- tpl .Values.csi.serviceAccount.annotations . | nindent 4 }}
{{- else }}
{{- toYaml .Values.csi.serviceAccount.annotations | nindent 4 }}
{{- end }}
{{- end }}
{{- end -}}

{{/*
Inject extra environment vars in the format key:value, if populated
*/}}
Expand Down
17 changes: 17 additions & 0 deletions templates/csi-clusterrole.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{- if and (eq (.Values.csi.enabled | toString) "true" ) (eq (.Values.global.enabled | toString) "true") }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "vault.name" . }}-csi-provider-clusterrole
labels:
app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
rules:
- apiGroups:
- ""
resources:
- serviceaccounts/token
verbs:
- create
{{- end }}
18 changes: 18 additions & 0 deletions templates/csi-clusterrolebinding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{{- if and (eq (.Values.csi.enabled | toString) "true" ) (eq (.Values.global.enabled | toString) "true") }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "vault.fullname" . }}-csi-provider-clusterrolebinding
labels:
app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "vault.fullname" . }}-csi-provider-clusterrole
subjects:
- kind: ServiceAccount
name: {{ template "vault.fullname" . }}-csi-provider
namespace: {{ .Release.Namespace }}
{{- end }}
89 changes: 89 additions & 0 deletions templates/csi-daemonset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{{- if and (eq (.Values.csi.enabled | toString) "true" ) (eq (.Values.global.enabled | toString) "true") }}
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: {{ template "vault.fullname" . }}-csi-provider
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{ template "csi.daemonSet.annotations" . }}
spec:
updateStrategy:
type: {{ .Values.csi.daemonSet.updateStrategy.type }}
{{- if .Values.csi.daemonSet.updateStrategy.maxUnavailable }}
rollingUpdate:
maxUnavailable: {{ .Values.csi.daemonSet.updateStrategy.maxUnavailable }}
{{- end }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ template "vault.name" . }}-csi-provider
app.kubernetes.io/instance: {{ .Release.Name }}
{{ template "csi.pod.annotations" . }}
spec:
serviceAccountName: {{ include "vault.name" . }}-csi-provider
containers:
- name: {{ include "vault.name" . }}-csi-provider
{{ template "csi.resources" . }}
image: "{{ .Values.csi.image.repository }}:{{ .Values.csi.image.tag }}"
imagePullPolicy: {{ .Values.csi.image.pullPolicy }}
args:
- --endpoint=/provider/vault.sock
- --debug={{ .Values.csi.debug }}
volumeMounts:
- name: providervol
mountPath: "/provider"
- name: mountpoint-dir
mountPath: /var/lib/kubelet/pods
mountPropagation: HostToContainer
{{- range .Values.csi.extraVolumes }}
- name: userconfig-{{ .name }}
mountPath: {{ .path | default "/vault/userconfig" }}/{{ .name }}
readOnly: true
{{- end }}
{{- if .Values.csi.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: /health/ready
port: 8080
failureThreshold: {{ .Values.csi.livenessProbe.failureThreshold }}
initialDelaySeconds: {{ .Values.csi.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.csi.livenessProbe.periodSeconds }}
successThreshold: {{ .Values.csi.livenessProbe.successThreshold }}
timeoutSeconds: {{ .Values.csi.livenessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.csi.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: /health/ready
port: 8080
failureThreshold: {{ .Values.csi.readinessProbe.failureThreshold }}
initialDelaySeconds: {{ .Values.csi.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.csi.readinessProbe.periodSeconds }}
successThreshold: {{ .Values.csi.readinessProbe.successThreshold }}
timeoutSeconds: {{ .Values.csi.readinessProbe.timeoutSeconds }}
{{- end }}
volumes:
- name: providervol
hostPath:
path: "/etc/kubernetes/secrets-store-csi-providers"
- name: mountpoint-dir
hostPath:
path: /var/lib/kubelet/pods
{{- range .Values.csi.extraVolumes }}
- name: userconfig-{{ .name }}
{{ .type }}:
{{- if (eq .type "configMap") }}
name: {{ .name }}
{{- else if (eq .type "secret") }}
secretName: {{ .name }}
{{- end }}
defaultMode: {{ .defaultMode | default 420 }}
{{- end }}
{{- end }}
12 changes: 12 additions & 0 deletions templates/csi-serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{- if and (eq (.Values.csi.enabled | toString) "true" ) (eq (.Values.global.enabled | toString) "true") }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "vault.fullname" . }}-csi-provider
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{ template "csi.serviceAccount.annotations" . }}
{{- end }}
26 changes: 26 additions & 0 deletions test/acceptance/csi-test/nginx.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx
---
kind: Pod
apiVersion: v1
metadata:
name: nginx
spec:
terminationGracePeriodSeconds: 0
containers:
- image: docker.mirror.hashicorp.services/nginx
name: nginx
volumeMounts:
- name: secrets-store-inline
mountPath: "/mnt/secrets-store"
readOnly: true
volumes:
- name: secrets-store-inline
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-kv"
15 changes: 15 additions & 0 deletions test/acceptance/csi-test/vault-kv-secretproviderclass.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# The "Hello World" Vault SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
name: vault-kv
spec:
provider: vault
parameters:
roleName: "kv-role"
vaultAddress: http://vault:8200
objects: |
array:
- |
objectName: "bar1"
objectPath: "v1/secret/kv1"
7 changes: 7 additions & 0 deletions test/acceptance/csi-test/vault-policy.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
path "sys/mounts" {
capabilities = ["read"]
}

path "secret/*" {
capabilities = ["read"]
}
59 changes: 59 additions & 0 deletions test/acceptance/csi.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env bats

load _helpers

@test "csi: testing deployment" {
cd `chart_dir`

kubectl delete namespace acceptance --ignore-not-found=true
kubectl create namespace acceptance

# Install Secrets Store CSI driver
helm install secrets-store-csi-driver https://github.com/kubernetes-sigs/secrets-store-csi-driver/blob/master/charts/secrets-store-csi-driver-0.0.19.tgz?raw=true \
--wait --timeout=5m \
--namespace=acceptance \
--set linux.image.pullPolicy="IfNotPresent" \
--set grpcSupportedProviders="azure;gcp;vault"
# Install Vault and Vault provider
helm install vault \
--wait --timeout=5m \
--namespace=acceptance \
--set="server.dev.enabled=true" \
--set="csi.enabled=true" \
--set="injector.enabled=false" .
kubectl --namespace=acceptance wait --for=condition=Ready --timeout=5m pod -l app.kubernetes.io/name=vault
kubectl --namespace=acceptance wait --for=condition=Ready --timeout=5m pod -l app.kubernetes.io/name=vault-csi-provider

# Set up k8s auth and a kv secret.
cat ./test/acceptance/csi-test/vault-policy.hcl | kubectl --namespace=acceptance exec -i vault-0 -- vault policy write kv-policy -
kubectl --namespace=acceptance exec vault-0 -- vault auth enable kubernetes
kubectl --namespace=acceptance exec vault-0 -- sh -c 'vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'
kubectl --namespace=acceptance exec vault-0 -- vault write auth/kubernetes/role/kv-role \
bound_service_account_names=vault-csi-provider \
bound_service_account_namespaces=acceptance \
policies=kv-policy \
ttl=20m
kubectl --namespace=acceptance exec vault-0 -- vault kv put secret/kv1 bar1=hello1

kubectl --namespace=acceptance apply -f ./test/acceptance/csi-test/vault-kv-secretproviderclass.yaml
kubectl --namespace=acceptance apply -f ./test/acceptance/csi-test/nginx.yaml
kubectl --namespace=acceptance wait --for=condition=Ready --timeout=5m pod nginx

result=$(kubectl --namespace=acceptance exec nginx -- cat /mnt/secrets-store/bar1)
[[ "$result" == "hello1" ]]
}

# Clean up
teardown() {
if [[ ${CLEANUP:-true} == "true" ]]
then
echo "helm/pvc teardown"
helm --namespace=acceptance delete vault
helm --namespace=acceptance delete secrets-store-csi-driver
kubectl delete --all pvc
kubectl delete namespace acceptance
fi
}
22 changes: 22 additions & 0 deletions test/unit/csi-clusterrole.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bats

load _helpers

@test "csi/ClusterRole: disabled by default" {
cd `chart_dir`
local actual=$( (helm template \
--show-only templates/csi-clusterrole.yaml \
. || echo "---") | tee /dev/stderr |
yq 'length > 0' | tee /dev/stderr)
[ "${actual}" = "false" ]
}

@test "csi/ClusterRole: enabled with csi.enabled" {
cd `chart_dir`
local actual=$(helm template \
--show-only templates/csi-clusterrole.yaml \
--set 'csi.enabled=true' \
. | tee /dev/stderr |
yq 'length > 0' | tee /dev/stderr)
[ "${actual}" = "true" ]
}
22 changes: 22 additions & 0 deletions test/unit/csi-clusterrolebinding.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bats

load _helpers

@test "csi/ClusterRoleBinding: disabled by default" {
cd `chart_dir`
local actual=$( (helm template \
--show-only templates/csi-clusterrolebinding.yaml \
. || echo "---")| tee /dev/stderr |
yq 'length > 0' | tee /dev/stderr)
[ "${actual}" = "false" ]
}

@test "csi/ClusterRoleBinding: enabled with csi.enabled" {
cd `chart_dir`
local actual=$(helm template \
--show-only templates/csi-clusterrolebinding.yaml \
--set 'csi.enabled=true' \
. | tee /dev/stderr |
yq 'length > 0' | tee /dev/stderr)
[ "${actual}" = "true" ]
}
Loading

0 comments on commit 4c1d79f

Please sign in to comment.