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 2ead238 commit fc06f20
Show file tree
Hide file tree
Showing 8 changed files with 188 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 @@ -100,6 +100,8 @@ helm install --name elasticsearch elastic/elasticsearch --version 7.1.0 --set im
| `nodeSelector` | Configurable [nodeSelector](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) so that you can target specific nodes for your Elasticsearch cluster | `{}` |
| `tolerations` | Configurable [tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) | `[]` |
| `ingress` | Configurable [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) to expose the Elasticsearch service. See [`values.yaml`](./values.yaml) for an example | `enabled: false` |
| `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 @@ -47,6 +47,11 @@ spec:
spec:
securityContext:
fsGroup: {{ .Values.fsGroup }}
{{- 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
80 changes: 80 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 @@ -569,3 +570,82 @@ def test_priority_class_name():
r = helm_template(config)
priority_class_name = r['statefulset'][uname]['spec']['template']['spec']['priorityClassName']
assert priority_class_name == "highest"


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 @@ -75,6 +75,14 @@ volumeClaimTemplate:
requests:
storage: 30Gi

rbac:
create: false
serviceAccountName: ""

podSecurityPolicy:
create: false
name: ""

persistence:
enabled: true
annotations: {}
Expand Down

0 comments on commit fc06f20

Please sign in to comment.