Helm Security Challenges

Helm Security

Helm simplifies Kubernetes deployments but introduces security concerns: untrusted charts, unprotected secrets, and supply chain risks.

Chart Signing

Sign charts with GPG to verify authenticity:

Generate signing key

gpg --full-generate-key

gpg --list-secret-keys

Sign a chart

helm package mychart/

helm sign mychart-1.0.0.tgz --key "developer@example.com"

Verify a chart

helm verify mychart-1.0.0.tgz

With custom public key

gpg --export developer@example.com > pubkey.asc

helm verify mychart-1.0.0.tgz --keyring pubkey.asc

Provenance Files

Provenance files contain the chart hash and signature:

mychart-1.0.0.tgz.prov

apiVersion: v1

files:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- mychart-1.0.0.tgz

chart: |

sha256: a1b2c3d4...

signature: |

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\-----BEGIN PGP SIGNATURE-----

iQEzBAABCAAdFiEE...

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\-----END PGP SIGNATURE-----

Automated Verification in CI

CI pipeline chart verification

pipeline:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- name: verify-charts

commands:

Import trusted keys

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- gpg --import trusted-keys.asc

Verify all charts

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- for chart in charts/*.tgz; do

helm verify "$chart" --keyring trusted-keys.asc || exit 1

done

Scan for vulnerabilities

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- trivy fs charts/

Lint charts

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- helm lint charts/*

Check for deprecated APIs

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- pluto detect-files -d charts/

Secrets Management

Never store secrets in values files:

BAD: Secrets in values

apiKey: "sk-1234567890"

dbPassword: "password123"

GOOD: Reference external secret

apiKey: "{{ .Values.externalSecrets.apiKey }}"

dbPassword: "{{ .Values.externalSecrets.dbPassword }}"

Use external secrets operator:

apiVersion: external-secrets.io/v1beta1

kind: ExternalSecret

metadata:

name: app-secrets

spec:

refreshInterval: 1h

secretStoreRef:

name: vault-backend

kind: ClusterSecretStore

target:

name: app-secret

data:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- secretKey: api-key

remoteRef:

key: secret/data/app

property: api-key

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- secretKey: db-password

remoteRef:

key: secret/data/app

property: db-password

Values Security

Validate values with JSON Schema:

{

"$schema": "https://json-schema.org/draft-07/schema",

"type": "object",

"properties": {

"image": {

"type": "object",

"properties": {

"repository": { "type": "string" },

"tag": { "type": "string", "pattern": "^[a-zA-Z0-9._-]+$" },

"pullPolicy": {

"type": "string",

"enum": ["Always", "IfNotPresent", "Never"]

}

},

"required": ["repository"]

},

"securityContext": {

"type": "object",

"required": ["runAsNonRoot"],

"properties": {

"runAsNonRoot": { "type": "boolean", "const": true },

"runAsUser": { "type": "integer", "minimum": 1000 }

}

}

}

}

RBAC for Helm Operations

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

name: helm-deployer

rules:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- apiGroups: ["apps", "extensions"]

resources: ["deployments", "statefulsets"]

verbs: ["get", "list", "create", "update", "patch"]

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- apiGroups: [""]

resources: ["secrets", "configmaps"]

verbs: ["get", "list", "create"]

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- apiGroups: ["batch"]

resources: ["jobs"]

verbs: ["get", "create", "delete"]

Conclusion

Secure Helm deployments with chart signing and provenance verification. Use external secrets management instead of storing secrets in values files. Validate values with JSON Schema. Restrict Helm RBAC to specific operations. Scan charts for vulnerabilities before deployment. Always verify chart signatures from third-party repositories.