Skip to content

Commit

Permalink
chore: add steps to validate pod templates (#59)
Browse files Browse the repository at this point in the history
* chore: add steps to validate pod templates

* remove pip cache

* add debug stmt

* use action_path

* rename values file

* update with sub-charts values
  • Loading branch information
ravisingal authored Oct 3, 2024
1 parent 84e5d5f commit 7fc8e2e
Show file tree
Hide file tree
Showing 3 changed files with 296 additions and 0 deletions.
23 changes: 23 additions & 0 deletions validate-charts/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ inputs:
description: 'Check no trailing spaces in helm template'
required: false
default: 'true'
check-pod-template:
description: 'Check labels, annotations and security context in a pod'
required: false
default: 'true'
runs:
using: "composite"
steps:
Expand All @@ -34,3 +38,22 @@ runs:
echo $output
exit 1
fi
- name: Setup python
if: inputs.check-pod-template == 'true'
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Install pyyaml
if: inputs.check-pod-template == 'true'
shell: bash
run: pip install pyyaml

- name: Check pod template
if: inputs.check-pod-template == 'true'
shell: bash
run: |
CHART_NAME=$(awk '/^name:/ {print $2}' ${{ inputs.chart-path }}/Chart.yaml)
helm template $CHART_NAME ${{ inputs.chart-path }} ${{ inputs.extra-args }} -f ${{ github.action_path }}/values.tpl > /tmp/${CHART_NAME}.yaml
python ${{ github.action_path }}/check.py /tmp/${CHART_NAME}.yaml
127 changes: 127 additions & 0 deletions validate-charts/check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import yaml
import sys

def check_pod_metadata(kind, name, template):
if not 'metadata' in template:
print(f'"metadata" is missing from {kind}/{name} template.')
return False
if not 'labels' in template['metadata']:
print(f'"labels" is missing from {kind}/{name} metadata.')
return False
if not 'applicationid' in template['metadata']['labels']:
print(f'commonPodLabels is missing from {kind}/{name} metadata.')
return False
if template['metadata']['labels']['applicationid'] != 'ABCD1234':
print(f'commonPodLabels is not matching {kind}/{name} metadata.')
return False
if not 'annotations' in template['metadata']:
print(f'"annotations" is missing from {kind}/{name} metadata.')
return False
if not 'traceable.ai/test' in template['metadata']['annotations']:
print(f'commonPodAnnotations is missing from {kind}/{name} metadata.')
return False
if template['metadata']['annotations']['traceable.ai/test'] != '1234567890':
print(f'commonPodAnnotations is not matching {kind}/{name} metadata.')
return False
return True

def check_pod_security_context(kind, name, template):
spec = template['spec']
if not 'securityContext' in spec:
print(f'Pod security context is missing from {kind}/{name} spec.')
return False
security_context = spec['securityContext']
# runAsUser
if not 'runAsUser' in security_context:
print(f'"runAsUser" is missing from {kind}/{name} pod security context.')
return False
if security_context['runAsUser'] != 55555:
print(f'"runAsUser" is not matching in {kind}/{name} pod security context.')
return False
# fsGroup
if not 'fsGroup' in security_context:
print(f'"fsGroup" is missing from {kind}/{name} pod security context.')
return False
if security_context['fsGroup'] != 44444:
print(f'"fsGroup" is not matching in {kind}/{name} pod security context.')
return False
# runAsNonRoot
if not 'runAsNonRoot' in security_context:
print(f'"runAsNonRoot" is missing from {kind}/{name} pod security context.')
return False
if security_context['runAsNonRoot'] != True:
print(f'"runAsNonRoot" is not matching in {kind}/{name} pod security context.')
return False
return True

def check_container_security_context(kind, name, container):
container_name = container['name']
if not 'securityContext' in container:
print(f'Container security context is missing from {kind}/{name}/{container_name} spec.')
return False
security_context = container['securityContext']
# runAsUser
if not 'runAsUser' in security_context:
print(f'"runAsUser" is missing from {kind}/{name}/{container_name} container security context.')
return False
if security_context['runAsUser'] != 22222:
print(f'"runAsUser" is not matching in {kind}/{name}/{container_name} container security context.')
return False
# runAsGroup
if not 'runAsGroup' in security_context:
print(f'"runAsGroup" is missing from {kind}/{name}/{container_name} container security context.')
return False
if security_context['runAsGroup'] != 333333:
print(f'"runAsGroup" is not matching in {kind}/{name}/{container_name} container security context.')
return False
# runAsNonRoot
if not 'runAsNonRoot' in security_context:
print(f'"runAsNonRoot" is missing from {kind}/{name}/{container_name} container security context.')
return False
if security_context['runAsNonRoot'] != True:
print(f'"runAsNonRoot" is not matching in {kind}/{name}/{container_name} container security context.')
return False
# allowPrivilegeEscalation
if not 'allowPrivilegeEscalation' in security_context:
print(f'"allowPrivilegeEscalation" is missing from {kind}/{name}/{container_name} container security context.')
return False
if security_context['allowPrivilegeEscalation'] != False:
print(f'"allowPrivilegeEscalation" is not matching in {kind}/{name}/{container_name} container security context.')
return False
return True

def check_helm_template(doc):
validated = True
kind = doc['kind']
name = doc['metadata']['name']
print(f'\nchecking {kind}/{name} template.')
if kind in ['Deployment', 'StatefulSet', 'Job']:
template = doc['spec']['template']
if kind in ['CronJob']:
template = doc['spec']['jobTemplate']['spec']['template']
if not check_pod_metadata(kind, name, template):
validated = False
if not check_pod_security_context(kind, name, template):
validated = False
containers = template['spec']['containers']
for container in containers:
if not check_container_security_context(kind, name, container):
validated = False
if 'initContainers' in template['spec']:
for container in template['spec']['initContainers']:
if not check_container_security_context(kind, name, container):
validated = False
print(f'validated: {validated}')
return validated

filepath = sys.argv[1]
validated = True
with open(filepath, 'r') as fd:
docs = yaml.safe_load_all(fd)
for doc in docs:
if doc['kind'] in ['Deployment', 'StatefulSet', 'Job', 'CronJob']:
if not check_helm_template(doc):
validated = False

if not validated:
sys.exit(1)
146 changes: 146 additions & 0 deletions validate-charts/values.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
commonPodAnnotations:
traceable.ai/test: "1234567890"

commonPodLabels:
applicationid: ABCD1234

containerSecurityContext:
runAsUser: 22222
runAsGroup: 333333
runAsNonRoot: true
allowPrivilegeEscalation: false

podSecurityContext:
runAsUser: 55555
fsGroup: 44444
runAsNonRoot: true

# sub-charts
kstreams-app-version-checker:
commonPodAnnotations:
traceable.ai/test: "1234567890"

commonPodLabels:
applicationid: ABCD1234

containerSecurityContext:
runAsUser: 22222
runAsGroup: 333333
runAsNonRoot: true
allowPrivilegeEscalation: false

podSecurityContext:
runAsUser: 55555
fsGroup: 44444
runAsNonRoot: true

hypertrace-pinot:
commonPodAnnotations:
traceable.ai/test: "1234567890"

commonPodLabels:
applicationid: ABCD1234

containerSecurityContext:
runAsUser: 22222
runAsGroup: 333333
runAsNonRoot: true
allowPrivilegeEscalation: false

podSecurityContext:
runAsUser: 55555
fsGroup: 44444
runAsNonRoot: true

config-bootstrapper:
commonPodAnnotations:
traceable.ai/test: "1234567890"

commonPodLabels:
applicationid: ABCD1234

containerSecurityContext:
runAsUser: 22222
runAsGroup: 333333
runAsNonRoot: true
allowPrivilegeEscalation: false

podSecurityContext:
runAsUser: 55555
fsGroup: 44444
runAsNonRoot: true

db-schema-manager:
enabled: false

redis:
master:
commonPodAnnotations:
traceable.ai/test: "1234567890"

commonPodLabels:
applicationid: ABCD1234

containerSecurityContext:
runAsUser: 22222
runAsGroup: 333333
runAsNonRoot: true
allowPrivilegeEscalation: false

podSecurityContext:
runAsUser: 55555
fsGroup: 44444
runAsNonRoot: true
metrics:
commonPodAnnotations:
traceable.ai/test: "1234567890"

commonPodLabels:
applicationid: ABCD1234

containerSecurityContext:
runAsUser: 22222
runAsGroup: 333333
runAsNonRoot: true
allowPrivilegeEscalation: false

podSecurityContext:
runAsUser: 55555
fsGroup: 44444
runAsNonRoot: true

postgresql:
primary:
commonPodAnnotations:
traceable.ai/test: "1234567890"

commonPodLabels:
applicationid: ABCD1234

containerSecurityContext:
runAsUser: 22222
runAsGroup: 333333
runAsNonRoot: true
allowPrivilegeEscalation: false

podSecurityContext:
runAsUser: 55555
fsGroup: 44444
runAsNonRoot: true
metrics:
commonPodAnnotations:
traceable.ai/test: "1234567890"

commonPodLabels:
applicationid: ABCD1234

containerSecurityContext:
runAsUser: 22222
runAsGroup: 333333
runAsNonRoot: true
allowPrivilegeEscalation: false

podSecurityContext:
runAsUser: 55555
fsGroup: 44444
runAsNonRoot: true

0 comments on commit 7fc8e2e

Please sign in to comment.