podsec context with some todo's to check

This commit is contained in:
Stavros kois
2023-02-08 18:52:15 +02:00
parent 1188aa4d54
commit 9042ebfb9b
6 changed files with 297 additions and 45 deletions
@@ -1,4 +1,4 @@
suite: pod hostname name test
suite: pod hostname test
templates:
- common.yaml
tests:
@@ -0,0 +1,236 @@
suite: pod securityContext test
templates:
- common.yaml
tests:
- it: should pass with securityContext from "global"
set:
securityContext:
pod:
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
supplementalGroups:
- 1000
- 1001
sysctls:
- name: net.ipv4.ip_forward
value: "1"
- name: net.ipv4.ping_group_range
value: "0 65535"
workload:
workload-name1:
enabled: true
primary: true
type: StatefulSet
podSpec: {}
asserts:
- documentIndex: &statefulSetDoc 0
isKind:
of: StatefulSet
- documentIndex: *statefulSetDoc
equal:
path: spec.template.spec.securityContext
value:
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
supplementalGroups:
- 1000
- 1001
sysctls:
- name: net.ipv4.ip_forward
value: "1"
- name: net.ipv4.ping_group_range
value: "0 65535"
- it: should pass with securityContext from "global" and partial override with "pod"
set:
securityContext:
pod:
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
supplementalGroups:
- 1000
- 1001
sysctls:
- name: net.ipv4.ip_forward
value: "1"
- name: net.ipv4.ping_group_range
value: "0 65535"
workload:
workload-name1:
enabled: true
primary: true
type: StatefulSet
podSpec:
securityContext:
fsGroup: 1001
asserts:
- documentIndex: &statefulSetDoc 0
isKind:
of: StatefulSet
- documentIndex: *statefulSetDoc
equal:
path: spec.template.spec.securityContext
value:
fsGroup: 1001
fsGroupChangePolicy: OnRootMismatch
supplementalGroups:
- 1000
- 1001
sysctls:
- name: net.ipv4.ip_forward
value: "1"
- name: net.ipv4.ping_group_range
value: "0 65535"
- it: should pass with securityContext from "global" and full override with "pod"
set:
some_sysctl_name: net.ipv4.ip_forward
some_sysctl_value: 2
securityContext:
pod:
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
supplementalGroups:
- 1000
- 1001
sysctls:
- name: net.ipv4.ip_forward
value: "1"
- name: net.ipv4.ping_group_range
value: "0 65535"
workload:
workload-name1:
enabled: true
primary: true
type: StatefulSet
podSpec:
securityContext:
fsGroup: 1001
fsGroupChangePolicy: Always
supplementalGroups:
- 1002
- 1003
sysctls:
- name: "{{ .Values.some_sysctl_name }}"
value: "{{ .Values.some_sysctl_value }}"
- name: net.ipv4.ping_group_range
value: "1 65534"
asserts:
- documentIndex: &statefulSetDoc 0
isKind:
of: StatefulSet
- documentIndex: *statefulSetDoc
equal:
path: spec.template.spec.securityContext
value:
fsGroup: 1001
fsGroupChangePolicy: Always
supplementalGroups:
- 1002
- 1003
sysctls:
- name: net.ipv4.ip_forward
value: "2"
- name: net.ipv4.ping_group_range
value: "1 65534"
# Failures
- it: should fail with empty securityContext from "global"
set:
securityContext:
pod: null
workload:
workload-name1:
enabled: true
primary: true
type: StatefulSet
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Pod - Expected non-empty <.Values.securityContext.pod>
- it: should fail with empty fsGroup
set:
securityContext:
pod:
fsGroup: ""
workload:
workload-name1:
enabled: true
primary: true
type: StatefulSet
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Pod - Expected non-empty <fsGroup>
- it: should fail with empty fsGroupChangePolicy
set:
securityContext:
pod:
fsGroup: 568
fsGroupChangePolicy: ""
workload:
workload-name1:
enabled: true
primary: true
type: StatefulSet
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Pod - Expected non-empty <fsGroupChangePolicy>
- it: should fail with invalid fsGroupChangePolicy
set:
securityContext:
pod:
fsGroup: 568
fsGroupChangePolicy: invalid
workload:
workload-name1:
enabled: true
primary: true
type: StatefulSet
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Pod - Expected <fsGroupChangePolicy> to be one of [Always, OnRootMismatch], but got [invalid]
- it: should fail with empty name in sysctls
set:
securityContext:
pod:
fsGroup: 568
fsGroupChangePolicy: OnRootMismatch
sysctls:
- name: ""
value: "1"
workload:
workload-name1:
enabled: true
primary: true
type: StatefulSet
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Pod - Expected non-empty <name> in <sysctls>
- it: should fail with empty value in sysctls
set:
securityContext:
pod:
fsGroup: 568
fsGroupChangePolicy: OnRootMismatch
sysctls:
- name: net.ipv4.ip_forward
value: ""
workload:
workload-name1:
enabled: true
primary: true
type: StatefulSet
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Pod - Expected non-empty <value> in <sysctls>
+48 -33
View File
@@ -1,38 +1,45 @@
# workload
| Key | Type | Required | Helm Template | Default | Description |
| :----------------------------------------------------------------- | :-------: | :------: | :----------------: | :-------------------------------------------------------------: | :--------------------------------------------------------------------------------- |
| workload | `dict` | ❌ | ❌ | `{}` | Define the workload as dicts |
| workload.[workload-name] | `dict` | ✅ | ❌ | `{}` | Holds workload definition |
| workload.[workload-name].enabled | `boolean` | ✅ | ❌ | `false` | Enables or Disables the workload |
| workload.[workload-name].primary | `boolean` | ✅ | ❌ | `false` | Sets the workload as primary |
| workload.[workload-name].labels | `dict` | ❌ | ✅ (On value only) | `{}` | Additional labels for workload |
| workload.[workload-name].annotations | `dict` | ❌ | ✅ (On value only) | `{}` | Additional annotations for workload |
| workload.[workload-name].type | `string` | ✅ | ❌ | `""` | Define the kind of the workload (Deployment, DaemonSet, StatefulSet, CronJob, Job) |
| workload.[workload-name].podSpec | `dict` | ✅ | ❌ | `{}` | Holds the pod definition |
| workload.[workload-name].podSpec.labels | `dict` | ❌ | ✅ (On value only) | `{}` | Additional Pod Labels |
| workload.[workload-name].podSpec.annotations | `dict` | ❌ | ✅ (On value only) | `{}` | Pod Annotations |
| workload.[workload-name].podSpec.automountServiceAccountToken | `boolean` | ❌ | ❌ | `{{ .Values.podOptions.automountServiceAccoutnToken }}` (false) | Pod's automountServiceAccountToken |
| workload.[workload-name].podSpec.hostNetwork | `boolean` | ❌ | ❌ | `{{ .Values.podOptions.hostNetwork }}` (false) | Pod's hostNetwork |
| workload.[workload-name].podSpec.enableServiceLinks | `boolean` | ❌ | ❌ | `{{ .Values.podOptions.enableServiceLinks }}` (false) | Pod's enableServiceLinks |
| workload.[workload-name].podSpec.restartPolicy | `string` | ❌ | ✅ | `{{ .Values.podOptions.restartPolicy }}` (Always) | Pod's restartPolicy. (Always, Never, OnFailure) |
| workload.[workload-name].podSpec.schedulerName | `string` | ❌ | ✅ | `{{ .Values.podOptions.schedulerName }}` ("") | Pod's schedulerName |
| workload.[workload-name].podSpec.priorityClassName | `string` | ❌ | ✅ | `{{ .Values.podOptions.priorityClassName }}` ("") | Pod's priorityClassName |
| workload.[workload-name].podSpec.hostname | `string` | ❌ | ✅ | `""` | Pod's hostname |
| workload.[workload-name].podSpec.terminationGracePeriodSeconds | `int` | ❌ | ✅ | `{{ .Values.podOptions.terminationGracePeriodSeconds }}` (120) | Pod's terminationGracePeriodSeconds |
| workload.[workload-name].podSpec.nodeSelector | `dict` | ❌ | ✅ (On value only) | `{{ .Values.podOptions.nodeSelector }}` ({}) | Pod's nodeSelector |
| workload.[workload-name].podSpec.hostAliases | `list` | ❌ | ❌ | | Pod's host aliases |
| workload.[workload-name].podSpec.hostAliases.ip | `string` | ❌ | ✅ | | Value for `ip` in hosts aliases |
| workload.[workload-name].podSpec.hostAliases.hostnames | `list` | ❌ | ❌ | | Hostnames for the `ip` in hosts aliases |
| workload.[workload-name].podSpec.hostAliases.hostnames.[host-name] | `string` | ❌ | ✅ | | [Value] for `hostnames` for the `ip` in hosts aliases |
| workload.[workload-name].podSpec.dnsPolicy | `string` | ❌ | ✅ | `{{ .Values.podOptions.dnsPolicy }}` (ClusterFirst) | Pod's DNS Policy (ClusterFirst, ClusterFirstWithHostNet, Default, None). |
| workload.[workload-name].podSpec.tolerations | `list` | ❌ | ❌ | `{{ .Values.podOptions.tolerations }}` ([]) | Pod's Tolerations |
| workload.[workload-name].podSpec.tolerations.operator | `string` | ✅ | ✅ | | Toleration's `operator` (Equal, Exists) |
| workload.[workload-name].podSpec.tolerations.key | `string` | ❌/✅ | ✅ | | Toleration's `key`. Required only when `operator` = `Equal` |
| workload.[workload-name].podSpec.tolerations.value | `string` | ❌/✅ | ✅ | | Toleration's `value`. Required only when `operator` = `Equal` |
| workload.[workload-name].podSpec.tolerations.effect | `string` | ❌ | ✅ | | Toleration's `effect`.(NoExecute, NoSchedule, PreferNoSchedule) |
| workload.[workload-name].podSpec.tolerations.tolerationSeconds | `int` | ❌ | ❌ | | Toleration's `tolerationSeconds`. |
| workload.[workload-name].podSpec.runtimeClassName | `string` | | | `{{ .Values.podOptions.runtimeClassName }}` ("") | Pod's runtimeClassName |
| Key | Type | Required | Helm Template | Default | Description |
| :------------------------------------------------------------------- | :-------: | :------: | :----------------: | :-------------------------------------------------------------: | :--------------------------------------------------------------------------------- |
| workload | `dict` | ❌ | ❌ | `{}` | Define the workload as dicts |
| workload.[workload-name] | `dict` | ✅ | ❌ | `{}` | Holds workload definition |
| workload.[workload-name].enabled | `boolean` | ✅ | ❌ | `false` | Enables or Disables the workload |
| workload.[workload-name].primary | `boolean` | ✅ | ❌ | `false` | Sets the workload as primary |
| workload.[workload-name].labels | `dict` | ❌ | ✅ (On value only) | `{}` | Additional labels for workload |
| workload.[workload-name].annotations | `dict` | ❌ | ✅ (On value only) | `{}` | Additional annotations for workload |
| workload.[workload-name].type | `string` | ✅ | ❌ | `""` | Define the kind of the workload (Deployment, DaemonSet, StatefulSet, CronJob, Job) |
| workload.[workload-name].podSpec | `dict` | ✅ | ❌ | `{}` | Holds the pod definition |
| workload.[workload-name].podSpec.labels | `dict` | ❌ | ✅ (On value only) | `{}` | Additional Pod Labels |
| workload.[workload-name].podSpec.annotations | `dict` | ❌ | ✅ (On value only) | `{}` | Pod Annotations |
| workload.[workload-name].podSpec.automountServiceAccountToken | `boolean` | ❌ | ❌ | `{{ .Values.podOptions.automountServiceAccoutnToken }}` (false) | Pod's automountServiceAccountToken |
| workload.[workload-name].podSpec.hostNetwork | `boolean` | ❌ | ❌ | `{{ .Values.podOptions.hostNetwork }}` (false) | Pod's hostNetwork |
| workload.[workload-name].podSpec.enableServiceLinks | `boolean` | ❌ | ❌ | `{{ .Values.podOptions.enableServiceLinks }}` (false) | Pod's enableServiceLinks |
| workload.[workload-name].podSpec.restartPolicy | `string` | ❌ | ✅ | `{{ .Values.podOptions.restartPolicy }}` (Always) | Pod's restartPolicy. (Always, Never, OnFailure) |
| workload.[workload-name].podSpec.schedulerName | `string` | ❌ | ✅ | `{{ .Values.podOptions.schedulerName }}` ("") | Pod's schedulerName |
| workload.[workload-name].podSpec.priorityClassName | `string` | ❌ | ✅ | `{{ .Values.podOptions.priorityClassName }}` ("") | Pod's priorityClassName |
| workload.[workload-name].podSpec.hostname | `string` | ❌ | ✅ | `""` | Pod's hostname |
| workload.[workload-name].podSpec.terminationGracePeriodSeconds | `int` | ❌ | ✅ | `{{ .Values.podOptions.terminationGracePeriodSeconds }}` (120) | Pod's terminationGracePeriodSeconds |
| workload.[workload-name].podSpec.nodeSelector | `dict` | ❌ | ✅ (On value only) | `{{ .Values.podOptions.nodeSelector }}` ({}) | Pod's nodeSelector |
| workload.[workload-name].podSpec.hostAliases | `list` | ❌ | ❌ | | Pod's host aliases |
| workload.[workload-name].podSpec.hostAliases.ip | `string` | ❌ | ✅ | | Value for `ip` in hosts aliases |
| workload.[workload-name].podSpec.hostAliases.hostnames | `list` | ❌ | ❌ | | Hostnames for the `ip` in hosts aliases |
| workload.[workload-name].podSpec.hostAliases.hostnames.[host-name] | `string` | ❌ | ✅ | | [Value] for `hostnames` for the `ip` in hosts aliases |
| workload.[workload-name].podSpec.dnsPolicy | `string` | ❌ | ✅ | `{{ .Values.podOptions.dnsPolicy }}` (ClusterFirst) | Pod's DNS Policy (ClusterFirst, ClusterFirstWithHostNet, Default, None). |
| workload.[workload-name].podSpec.tolerations | `list` | ❌ | ❌ | `{{ .Values.podOptions.tolerations }}` ([]) | Pod's Tolerations |
| workload.[workload-name].podSpec.tolerations.operator | `string` | ✅ | ✅ | | Toleration's `operator` (Equal, Exists) |
| workload.[workload-name].podSpec.tolerations.key | `string` | ❌/✅ | ✅ | | Toleration's `key`. Required only when `operator` = `Equal` |
| workload.[workload-name].podSpec.tolerations.value | `string` | ❌/✅ | ✅ | | Toleration's `value`. Required only when `operator` = `Equal` |
| workload.[workload-name].podSpec.tolerations.effect | `string` | ❌ | ✅ | | Toleration's `effect`.(NoExecute, NoSchedule, PreferNoSchedule) |
| workload.[workload-name].podSpec.tolerations.tolerationSeconds | `int` | ❌ | ❌ | | Toleration's `tolerationSeconds`. |
| workload.[workload-name].podSpec.runtimeClassName | `string` | | | `{{ .Values.podOptions.runtimeClassName }}` ("") | Pod's runtimeClassName |
| workload.[workload-name].podSpec.securityContext | `dict` | ❌ | ❌ | `{{ .Values.securityContext.pod }}` | Pod's securityContext |
| workload.[workload-name].podSpec.securityContext.fsGroup | `int` | ❌ | ❌ | `568` | Pod's fsGroup |
| workload.[workload-name].podSpec.securityContext.fsGroupChangePolicy | `string` | ❌ | ❌ | `OnRootMismatch` | Pod's fsGroupChangePolicy (Always, OnRootMismatch) |
| workload.[workload-name].podSpec.securityContext.supplementalGroups | `list` | ❌ | ❌ | `[]` | Pod's supplementalGroups (list of `int`) |
| workload.[workload-name].podSpec.securityContext.sysctls | `list` | ❌ | ❌ | `[]` | Pod's sysctls |
| workload.[workload-name].podSpec.securityContext.sysctls.name | `string` | ✅ | ✅ | `""` | `name` of the sysctl |
| workload.[workload-name].podSpec.securityContext.sysctls.value | `string` | ✅ | ✅ | `""` | `value` of the sysctl |
---
@@ -119,4 +126,12 @@ workload:
effect: NoExecute
tolerationSeconds: 3600
runtimeClassName: some-runtime-class
securityContext:
fsGroup: 568
fsGroupChangePolicy: OnRootMismatch
supplementalGroups:
- 568
sysctls:
- name: net.ipv4.ip_local_port_range
value: 1024 65535
```
@@ -8,12 +8,12 @@ objectData: The object data to be used to render the Pod.
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- $secContext := dict -}}
{{- if not $rootCtx.Values.securityContext.pod -}}
{{- fail "Pod - Expected non-empty <.Values.securityContext.pod>" -}}
{{- end -}}
{{/* Initialize from the "global" option */}}
{{- with $rootCtx.Values.securityContext.pod -}}
{{- $secContext = (mustDeepCopy .) -}}
{{- end -}}
{{- $secContext := mustDeepCopy $rootCtx.Values.securityContext.pod -}}
{{/* Override with pod's option */}}
{{- with $objectData.podSpec.securityContext -}}
@@ -26,6 +26,7 @@ objectData: The object data to be used to render the Pod.
{{/* TODO: Add sysctls
net.ipv4.ip_unprivileged_port_start: (Set to the lowest port on the pod's containers)
net.ipv4.ping_group_range: (Set to the lowest port and highest port on the pod's containers)
TODO: Unit Test the above cases
*/}}
{{- if not $secContext.fsGroup -}}
@@ -52,15 +53,15 @@ supplementalGroups: []
{{- end -}}
{{- with $secContext.sysctls }}
sysctls:
{{- range $name, $value := . }}
{{- if not $name -}}
{{- range . }}
{{- if not .name -}}
{{- fail "Pod - Expected non-empty <name> in <sysctls>" -}}
{{- end -}}
{{- if not $value -}}
{{- if not .value -}}
{{- fail "Pod - Expected non-empty <value> in <sysctls>" -}}
{{- end }}
- name: {{ $name }}
value: {{ $value }}
- name: {{ tpl .name $rootCtx | quote }}
value: {{ tpl .value $rootCtx | quote }}
{{- end -}}
{{- else }}
sysctls: []
@@ -42,7 +42,7 @@ terminationGracePeriodSeconds: {{ . }}
tolerations:
{{- . | nindent 2 }}
{{- end }}
securityContext: {{/* TODO: Unit Tests */}}
securityContext:
{{- include "ix.v1.common.lib.pod.securityContext" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 2 }}
#TODO:containers:
#TODO:initContainers:
+1 -1
View File
@@ -75,7 +75,7 @@ securityContext:
fsGroup: 568
fsGroupChangePolicy: OnRootMismatch
supplementalGroups: []
sysctls: {}
sysctls: []
# -- Resources
# Can be overruled per container