This document outlines the security features and best practices for deploying the Prowler Helm Chart.
- Security Features
- Security Best Practices
- Secrets Management
- Network Security
- RBAC Configuration
- Pod Security
- Security Checklist
- Reporting Vulnerabilities
The chart automatically generates Django secret keys during installation using a pre-install Job. This ensures:
- No hardcoded secrets in version control
- Unique keys per installation
- Secure key generation using OpenSSL
Keys are stored in a Kubernetes Secret and include:
DJANGO_TOKEN_SIGNING_KEY- RSA private key for JWT signingDJANGO_TOKEN_VERIFYING_KEY- RSA public key for JWT verificationDJANGO_SECRETS_ENCRYPTION_KEY- Encryption key for sensitive data
All pods run with restrictive security contexts:
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false # Required for application writes
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALLNetwork policies can be enabled to restrict pod-to-pod communication:
api:
networkPolicy:
enabled: trueWhen enabled, the following policies are applied:
- UI: Can communicate with API only
- API: Can communicate with PostgreSQL, Valkey, and Kubernetes API
- Workers: Can communicate with API, PostgreSQL, Valkey, and cloud provider APIs
- Beat Worker: Can communicate with PostgreSQL and Valkey
The chart creates a ClusterRole with minimal read-only permissions for Kubernetes scanning:
- Core resources: pods, configmaps, nodes, namespaces, services, serviceaccounts
- RBAC resources: roles, rolebindings, clusterroles, clusterrolebindings
- Apps resources: deployments, daemonsets, statefulsets, replicasets
- Networking resources: networkpolicies, ingresses
- Policy resources: podsecuritypolicies, poddisruptionbudgets
You can disable Kubernetes scanning RBAC if not needed:
api:
rbac:
create: falseAll pods are labeled for Pod Security Standards compliance:
pod-security.kubernetes.io/enforce: restrictedPods also include seccomp annotations for additional protection.
For production deployments, use external managed databases instead of the bundled PostgreSQL and Valkey:
postgresql:
enabled: false
valkey:
enabled: falseThen create secrets with connection details to your external databases.
Enable network policies to restrict pod-to-pod communication:
api:
networkPolicy:
enabled: trueNote: Ensure your Kubernetes cluster has a network plugin that supports NetworkPolicy (e.g., Calico, Cilium, Weave Net).
Set appropriate resource limits to prevent resource exhaustion:
api:
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 500m
memory: 512Mi
worker:
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 500m
memory: 512MiConfigure TLS certificates for the UI and API ingresses:
ui:
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: prowler-ui.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: prowler-ui-tls
hosts:
- prowler-ui.example.com
api:
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: prowler-api.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: prowler-api-tls
hosts:
- prowler-api.example.comKeep the Prowler chart and application updated:
helm repo update
helm upgrade prowler prowler-app/prowlerEnable audit logging in your Kubernetes cluster to track access to Prowler resources.
Deploy Prowler in a dedicated namespace with appropriate RBAC:
kubectl create namespace prowler
helm install prowler prowler-app/prowler -n prowlerBy default, Django secrets are generated automatically. If you need to provide your own secrets:
- Set
api.djangoConfigKeys.create: false - Create a secret manually:
# Generate keys
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
ENCRYPTION_KEY=$(openssl rand -base64 32)
# Create secret
kubectl create secret generic my-release-api-django-config-keys \
--from-file=DJANGO_TOKEN_SIGNING_KEY=private.pem \
--from-file=DJANGO_TOKEN_VERIFYING_KEY=public.pem \
--from-literal=DJANGO_SECRETS_ENCRYPTION_KEY=$ENCRYPTION_KEYFor production, consider using external secret management:
- AWS Secrets Manager: Use External Secrets Operator
- HashiCorp Vault: Use Vault Secrets Operator
- Azure Key Vault: Use Azure Key Vault Provider
- Google Secret Manager: Use External Secrets Operator
To rotate Django secrets:
-
Delete the existing secret:
kubectl delete secret my-release-api-django-config-keys
-
Upgrade the release to regenerate:
helm upgrade prowler prowler-app/prowler
-
Restart all pods:
kubectl rollout restart deployment -l app.kubernetes.io/instance=prowler
Note: Rotating secrets will invalidate all existing JWT tokens.
To use network policies, your cluster must have a CNI plugin that supports them:
- Calico
- Cilium
- Weave Net
- Azure CNI (with Azure Network Policy Manager)
- GKE (with Network Policy enabled)
By default, workers need egress access to:
- Cloud provider APIs (AWS, Azure, GCP) on port 443
- Kubernetes API on port 443/6443
- PostgreSQL on port 5432
- Valkey on port 6379
If you have strict egress requirements, configure additional egress rules:
api:
networkPolicy:
enabled: true
egress:
# Allow specific cloud provider endpoints
- to:
- podSelector: {}
ports:
- protocol: TCP
port: 443The chart creates a ClusterRole with minimal permissions for Kubernetes scanning. If you need to reduce permissions further:
api:
rbac:
create: true
rules:
# Add only the resources you want to scan
- apiGroups: [""]
resources: ["pods", "namespaces"]
verbs: ["get", "list"]If you don't plan to scan Kubernetes resources:
api:
rbac:
create: falseWorkers don't need cluster-wide permissions by default. If you need workers to have Kubernetes access, configure accordingly.
All pods comply with the restricted Pod Security Standard:
- Run as non-root user
- Drop all capabilities
- Use seccomp profile
- No privilege escalation
- Read-only root filesystem (where possible)
If your cluster uses Pod Security Admission, label your namespace:
kubectl label namespace prowler \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restrictedFor additional security, configure AppArmor or SELinux profiles:
api:
podAnnotations:
container.apparmor.security.beta.kubernetes.io/api: runtime/default
worker:
podAnnotations:
container.apparmor.security.beta.kubernetes.io/worker: runtime/defaultBefore deploying to production:
- Use external managed databases (PostgreSQL and Valkey/Redis)
- Enable network policies
- Configure resource limits for all components
- Enable TLS for ingresses
- Configure authentication (OAuth, SAML, etc.)
- Set up backup and disaster recovery
- Enable audit logging
- Review and configure RBAC permissions
- Implement secret rotation policy
- Configure monitoring and alerting
- Perform security scanning of container images
- Review and test disaster recovery procedures
- Document security configurations
If you discover a security vulnerability in the Prowler Helm Chart, please report it to:
- Chart Issues: GitHub Issues
- Prowler Application: Prowler Security Policy
Please do not disclose security vulnerabilities publicly until they have been addressed.