Skip to content
This repository has been archived by the owner on May 16, 2023. It is now read-only.

Commit

Permalink
Hardening of the pod permissions.
Browse files Browse the repository at this point in the history
Role, role binding and service account can now be created by the Helm chart.
An external service account can also be referenced.

Adding support for pod security policy to either be referenced from an existing one or created by the helm chart.
  • Loading branch information
maximelenair committed Aug 24, 2019
1 parent 1ad3826 commit 93a1a23
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 0 deletions.
2 changes: 2 additions & 0 deletions elasticsearch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,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`<br>`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`<br>`name: ""`

## Try it out

Expand Down
28 changes: 28 additions & 0 deletions elasticsearch/templates/podsecuritypolicy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{{- 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:
allowPrivilegeEscalation: true
privileged: true
allowedCapabilities: ['*']
fsGroup:
rule: RunAsAny
runAsUser:
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- secret
- configMap
- persistentVolumeClaim
{{- end -}}
25 changes: 25 additions & 0 deletions elasticsearch/templates/role.yaml
Original file line number Diff line number Diff line change
@@ -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 -}}
24 changes: 24 additions & 0 deletions elasticsearch/templates/rolebinding.yaml
Original file line number Diff line number Diff line change
@@ -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 -}}
16 changes: 16 additions & 0 deletions elasticsearch/templates/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -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 -}}
5 changes: 5 additions & 0 deletions elasticsearch/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand Down
78 changes: 78 additions & 0 deletions elasticsearch/tests/elasticsearch_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
sys.path.insert(1, os.path.join(sys.path[0], '../../helpers'))
from helpers import helm_template
import yaml
import json

clusterName = 'elasticsearch'
nodeGroup = 'master'
Expand Down Expand Up @@ -899,3 +900,80 @@ def test_keystore_volumes():
}]
}
} in s['volumes']
def test_pod_security_policy():
## Make sure the default config is not creating any resources
config = '''
rbac:
create: false
serviceAccountName: ""
podSecurityPolicy:
create: false
name: ""
'''
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['allowPrivilegeEscalation'] is True
assert psp_spec['privileged'] is True
assert psp_spec['allowedCapabilities'] == ['*']


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
8 changes: 8 additions & 0 deletions elasticsearch/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ volumeClaimTemplate:
requests:
storage: 30Gi

rbac:
create: false
serviceAccountName: ""

podSecurityPolicy:
create: false
name: ""

persistence:
enabled: true
annotations: {}
Expand Down

0 comments on commit 93a1a23

Please sign in to comment.