diff --git a/elasticsearch/README.md b/elasticsearch/README.md
index e89f8a87b..a0d3ddb91 100644
--- a/elasticsearch/README.md
+++ b/elasticsearch/README.md
@@ -114,6 +114,8 @@ helm install --name elasticsearch elastic/elasticsearch --set imageTag=7.3.0
| `masterTerminationFix` | A workaround needed for Elasticsearch < 7.2 to prevent master status being lost during restarts [#63](https://github.com/elastic/helm-charts/issues/63) | `false` |
| `lifecycle` | Allows you to add lifecycle configuration. See [values.yaml](./values.yaml) for an example of the formatting. | `{}` |
| `keystore` | Allows you map Kubernetes secrets into the keystore. See the [config example](/elasticsearch/examples/config/values.yaml) and [how to use the keystore](#how-to-use-the-keystore) | `[]` |
+| `rbac` | Configuration for creating a role, role binding and service account as part of this helm chart with `create: true`. Also can be used to reference an external service account with `serviceAccountName: "externalServiceAccountName"`. | `create: false`
`serviceAccountName: ""` |
+| `podSecurityPolicy` | Configuration for create a pod security policy with minimal permissions to run this Helm chart with `create: true`. Also can be used to reference an external pod security policy with `name: "externalPodSecurityPolicy"` | `create: false`
`name: ""` |
## Try it out
diff --git a/elasticsearch/templates/podsecuritypolicy.yaml b/elasticsearch/templates/podsecuritypolicy.yaml
new file mode 100644
index 000000000..1e65b2864
--- /dev/null
+++ b/elasticsearch/templates/podsecuritypolicy.yaml
@@ -0,0 +1,14 @@
+{{- if .Values.podSecurityPolicy.create -}}
+{{- $fullName := include "uname" . -}}
+apiVersion: policy/v1beta1
+kind: PodSecurityPolicy
+metadata:
+ name: {{ default $fullName .Values.podSecurityPolicy.name | quote }}
+ labels:
+ heritage: {{ .Release.Service | quote }}
+ release: {{ .Release.Name | quote }}
+ chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
+ app: {{ $fullName | quote }}
+spec:
+{{ toYaml .Values.podSecurityPolicy.spec | indent 2 }}
+{{- end -}}
diff --git a/elasticsearch/templates/role.yaml b/elasticsearch/templates/role.yaml
new file mode 100644
index 000000000..d616e80d3
--- /dev/null
+++ b/elasticsearch/templates/role.yaml
@@ -0,0 +1,25 @@
+{{- if .Values.rbac.create -}}
+{{- $fullName := include "uname" . -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ $fullName | quote }}
+ labels:
+ heritage: {{ .Release.Service | quote }}
+ release: {{ .Release.Name | quote }}
+ chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
+ app: {{ $fullName | quote }}
+rules:
+ - apiGroups:
+ - extensions
+ resources:
+ - podsecuritypolicies
+ resourceNames:
+ {{- if eq .Values.podSecurityPolicy.name "" }}
+ - {{ $fullName | quote }}
+ {{- else }}
+ - {{ .Values.podSecurityPolicy.name | quote }}
+ {{- end }}
+ verbs:
+ - use
+{{- end -}}
diff --git a/elasticsearch/templates/rolebinding.yaml b/elasticsearch/templates/rolebinding.yaml
new file mode 100644
index 000000000..c2b6070a4
--- /dev/null
+++ b/elasticsearch/templates/rolebinding.yaml
@@ -0,0 +1,24 @@
+{{- if .Values.rbac.create -}}
+{{- $fullName := include "uname" . -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ $fullName | quote }}
+ labels:
+ heritage: {{ .Release.Service | quote }}
+ release: {{ .Release.Name | quote }}
+ chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
+ app: {{ $fullName | quote }}
+subjects:
+ - kind: ServiceAccount
+ {{- if eq .Values.rbac.serviceAccountName "" }}
+ name: {{ $fullName | quote }}
+ {{- else }}
+ name: {{ .Values.rbac.serviceAccountName | quote }}
+ {{- end }}
+ namespace: {{ .Release.Namespace | quote }}
+roleRef:
+ kind: Role
+ name: {{ $fullName | quote }}
+ apiGroup: rbac.authorization.k8s.io
+{{- end -}}
diff --git a/elasticsearch/templates/serviceaccount.yaml b/elasticsearch/templates/serviceaccount.yaml
new file mode 100644
index 000000000..59bbd5326
--- /dev/null
+++ b/elasticsearch/templates/serviceaccount.yaml
@@ -0,0 +1,16 @@
+{{- if .Values.rbac.create -}}
+{{- $fullName := include "uname" . -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ {{- if eq .Values.rbac.serviceAccountName "" }}
+ name: {{ $fullName | quote }}
+ {{- else }}
+ name: {{ .Values.rbac.serviceAccountName | quote }}
+ {{- end }}
+ labels:
+ heritage: {{ .Release.Service | quote }}
+ release: {{ .Release.Name | quote }}
+ chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
+ app: {{ $fullName | quote }}
+{{- end -}}
diff --git a/elasticsearch/templates/statefulset.yaml b/elasticsearch/templates/statefulset.yaml
index 5a545a0cb..2af675e61 100644
--- a/elasticsearch/templates/statefulset.yaml
+++ b/elasticsearch/templates/statefulset.yaml
@@ -58,6 +58,11 @@ spec:
{{- if .Values.fsGroup }}
fsGroup: {{ .Values.fsGroup }} # Deprecated value, please use .Values.podSecurityContext.fsGroup
{{- end }}
+ {{- if .Values.rbac.create }}
+ serviceAccountName: "{{ template "uname" . }}"
+ {{- else if not (eq .Values.rbac.serviceAccountName "") }}
+ serviceAccountName: {{ .Values.rbac.serviceAccountName | quote }}
+ {{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 6 }}
diff --git a/elasticsearch/tests/elasticsearch_test.py b/elasticsearch/tests/elasticsearch_test.py
index a4949eef9..c194c6a6b 100755
--- a/elasticsearch/tests/elasticsearch_test.py
+++ b/elasticsearch/tests/elasticsearch_test.py
@@ -899,3 +899,70 @@ def test_keystore_volumes():
}]
}
} in s['volumes']
+def test_pod_security_policy():
+ ## Make sure the default config is not creating any resources
+ config = ''
+ resources = ('role', 'rolebinding', 'serviceaccount', 'podsecuritypolicy')
+ r = helm_template(config)
+ for resource in resources:
+ assert resource not in r
+ assert 'serviceAccountName' not in r['statefulset'][uname]['spec']['template']['spec']
+
+ ## Make sure all the resources are created with default values
+ config = '''
+rbac:
+ create: true
+ serviceAccountName: ""
+
+podSecurityPolicy:
+ create: true
+ name: ""
+'''
+ r = helm_template(config)
+ for resource in resources:
+ assert resource in r
+ assert r['role'][uname]['rules'][0] == {"apiGroups": ["extensions"], "verbs": ["use"], "resources": ["podsecuritypolicies"], "resourceNames": [uname]}
+ assert r['rolebinding'][uname]['subjects'] == [{"kind": "ServiceAccount", "namespace": "default", "name": uname}]
+ assert r['rolebinding'][uname]['roleRef'] == {"apiGroup": "rbac.authorization.k8s.io", "kind": "Role", "name": uname}
+ assert r['statefulset'][uname]['spec']['template']['spec']['serviceAccountName'] == uname
+ psp_spec = r['podsecuritypolicy'][uname]['spec']
+ assert psp_spec['privileged'] is True
+
+
+def test_external_pod_security_policy():
+ ## Make sure we can use an externally defined pod security policy
+ config = '''
+rbac:
+ create: true
+ serviceAccountName: ""
+
+podSecurityPolicy:
+ create: false
+ name: "customPodSecurityPolicy"
+'''
+ resources = ('role', 'rolebinding')
+ r = helm_template(config)
+ for resource in resources:
+ assert resource in r
+
+ assert r['role'][uname]['rules'][0] == {"apiGroups": ["extensions"], "verbs": ["use"], "resources": ["podsecuritypolicies"], "resourceNames": ["customPodSecurityPolicy"]}
+
+
+def test_external_service_account():
+ ## Make sure we can use an externally defined service account
+ config = '''
+rbac:
+ create: false
+ serviceAccountName: "customServiceAccountName"
+
+podSecurityPolicy:
+ create: false
+ name: ""
+'''
+ resources = ('role', 'rolebinding', 'serviceaccount')
+ r = helm_template(config)
+
+ assert r['statefulset'][uname]['spec']['template']['spec']['serviceAccountName'] == "customServiceAccountName"
+ # When referencing an external service account we do not want any resources to be created.
+ for resource in resources:
+ assert resource not in r
diff --git a/elasticsearch/values.yaml b/elasticsearch/values.yaml
index 78f208849..575f2ce63 100755
--- a/elasticsearch/values.yaml
+++ b/elasticsearch/values.yaml
@@ -86,6 +86,28 @@ volumeClaimTemplate:
requests:
storage: 30Gi
+rbac:
+ create: false
+ serviceAccountName: ""
+
+podSecurityPolicy:
+ create: false
+ name: ""
+ spec:
+ privileged: true
+ fsGroup:
+ rule: RunAsAny
+ runAsUser:
+ rule: RunAsAny
+ seLinux:
+ rule: RunAsAny
+ supplementalGroups:
+ rule: RunAsAny
+ volumes:
+ - secret
+ - configMap
+ - persistentVolumeClaim
+
persistence:
enabled: true
annotations: {}