diff --git a/filebeat/README.md b/filebeat/README.md index 47a98d47c..4e1d15883 100644 --- a/filebeat/README.md +++ b/filebeat/README.md @@ -121,6 +121,9 @@ as a reference. They are also used in the automated testing of this chart. | `terminationGracePeriod` | Termination period (in seconds) to wait before killing Filebeat pod process on pod shutdown | `30` | | `tolerations` | Configurable [tolerations][] | `[]` | | `updateStrategy` | The [updateStrategy][] for the `DaemonSet`. By default Kubernetes will kill and recreate pods on updates. Setting this to `OnDelete` will require that pods be deleted manually | `RollingUpdate` | +| `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: ""` | + ## FAQ diff --git a/filebeat/templates/podsecuritypolicy.yaml b/filebeat/templates/podsecuritypolicy.yaml new file mode 100644 index 000000000..86c74c213 --- /dev/null +++ b/filebeat/templates/podsecuritypolicy.yaml @@ -0,0 +1,14 @@ +{{- if .Values.podSecurityPolicy.create -}} +{{- $fullName := include "filebeat.fullname" . -}} +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/filebeat/templates/role.yaml b/filebeat/templates/role.yaml new file mode 100644 index 000000000..0a43af3d0 --- /dev/null +++ b/filebeat/templates/role.yaml @@ -0,0 +1,25 @@ +{{- if .Values.rbac.create -}} +{{- $fullName := include "filebeat.fullname" . -}} +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/filebeat/templates/rolebinding.yaml b/filebeat/templates/rolebinding.yaml new file mode 100644 index 000000000..537e8b6b4 --- /dev/null +++ b/filebeat/templates/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- if .Values.rbac.create -}} +{{- $fullName := include "filebeat.fullname" . -}} +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/filebeat/tests/filebeat_test.py b/filebeat/tests/filebeat_test.py index 7c8dc0ad0..507b35dca 100644 --- a/filebeat/tests/filebeat_test.py +++ b/filebeat/tests/filebeat_test.py @@ -400,3 +400,93 @@ def test_setting_fullnameOverride(): "type": "DirectoryOrCreate", }, } in 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["daemonset"][name]["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["daemonset"][name]["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"][name]["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/filebeat/values.yaml b/filebeat/values.yaml index e8c4ce22d..bc23fc3f3 100755 --- a/filebeat/values.yaml +++ b/filebeat/values.yaml @@ -110,6 +110,31 @@ resources: # Custom service account override that the pod will use serviceAccount: "" +rbac: + create: false + serviceAccountName: "" + +podSecurityPolicy: + create: false + name: "" + spec: + privileged: false + fsGroup: + rule: RunAsAny + runAsUser: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - secret + - configMap + - hostPath + allowedHostPaths: + - pathPrefix: "/var" + readOnly: false + # Annotations to add to the ServiceAccount that is created if the serviceAccount value isn't set. serviceAccountAnnotations: {} # eks.amazonaws.com/role-arn: arn:aws:iam::111111111111:role/k8s.clustername.namespace.serviceaccount