Helm Chart Security: Securing Kubernetes Package Management

Helm is the de facto package manager for Kubernetes, but Helm charts can introduce security vulnerabilities if not properly vetted and configured. This guide covers securing Helm deployments from chart development to production deployment.

Helm chart security encompasses chart provenance, secure defaults, secrets management, and runtime security configurations. Understanding these aspects is essential for maintaining secure Kubernetes deployments.

Chart Provenance and Signing

# Sign a Helm chart
helm package --sign --key mykey --keyring ~/.gnupg/secring.gpg mychart/

# Verify chart signature
helm verify mychart-1.0.0.tgz

# Install with verification
helm install myrelease mychart-1.0.0.tgz --verify

Secure Values Configuration

# values.yaml with security defaults
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  capabilities:
    drop:
      - ALL

resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 100m
    memory: 128Mi

networkPolicy:
  enabled: true

Secrets Management

# Use External Secrets Operator
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secrets
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: SecretStore
  target:
    name: app-secrets
  data:
    - secretKey: database-password
      remoteRef:
        key: production/database
        property: password

Chart Security Scanning

# Scan with Checkov
checkov -d mychart/ --framework helm

# Scan with Kubesec
helm template mychart/ | kubesec scan -

# Scan with Trivy
trivy config mychart/

Pod Security in Templates

# deployment.yaml template
spec:
  template:
    spec:
      securityContext:
        {{- toYaml .Values.podSecurityContext | nindent 8 }}
      containers:
        - name: {{ .Chart.Name }}
          securityContext:
            {{- toYaml .Values.securityContext | nindent 12 }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: Always

Network Policies

{{- if .Values.networkPolicy.enabled }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: {{ include "mychart.fullname" . }}
spec:
  podSelector:
    matchLabels:
      {{- include "mychart.selectorLabels" . | nindent 6 }}
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - port: 8080
{{- end }}

Best Practices

  • Sign and verify all charts
  • Use secure defaults in values.yaml
  • Never store secrets in charts
  • Scan charts before deployment
  • Pin image tags with digests
  • Enable network policies by default
  • Use read-only root filesystem
  • Drop all capabilities
  • Set resource limits
  • Review third-party charts carefully

Conclusion

Helm chart security requires attention from development through deployment. By implementing chart signing, secure defaults, and proper secrets management, you can ensure your Kubernetes applications are deployed securely.