Security in the Drupal Operator
This document describes security-related aspects of the Drupal Operator and how you can configure or harden them.
It focuses on:
- Access control and RBAC
- Container security (securityContext, user IDs, capabilities)
- Secrets and sensitive data
- Network exposure (Services)
- Operational safety (CRDs and data deletion)
Access control and RBAC
The Drupal Operator installs RBAC roles and bindings that allow it to:
- Watch and reconcile
Drupalcustom resources - Create and manage:
- Deployments, StatefulSets, Jobs, CronJobs
- Services, ConfigMaps, Secrets, PVCs, Pods
- Status fields on custom resources
Key points:
- The operator runs as a cluster-wide controller.
- RBAC files are under
config/rbac/andinstall/rbac/install.yaml. -
The operator service account is typically:
ServiceAccount/drupal-operator (in your operator namespace)
Recommendations:
- Use a dedicated namespace for the operator (for example
drupal-operator-system). - Restrict who can create or modify
DrupalCRs; these are effectively “infrastructure as code” for entire sites. - If needed, review and tailor the RBAC manifests in
config/rbac/to your organization’s policies (for example, restricting namespaces).
Container security
The operator and the Drupal-related workloads follow best-effort hardening practices, which you can extend.
User and group IDs
Defaults in roles/setup/vars/main.yaml:
drupal_run_as_user:1000drupal_run_as_group:2000drupal_fsgroup:2000
These values are used to configure:
securityContext.runAsUsersecurityContext.runAsGroupsecurityContext.fsGroup
This ensures:
- The main Drupal container does not run as root by default.
- Volumes are accessible with the configured group.
You can change these IDs to match your cluster’s policy, PodSecurity standards, or existing conventions.
SecurityContext snippets
The operator defines securityContext snippets for PHP-FPM and Apache containers:
-
drupal_php_fpm_container_security_context:allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"]
-
drupal_apache_container_security_context:allowPrivilegeEscalation: false
These are applied in the templated manifests and provide:
- No privilege escalation
- Dropped Linux capabilities (for PHP-FPM)
- Read-only root filesystem (for PHP-FPM), where applicable
You can extend or override these snippets in your own overlays to:
- Add
seccompProfiledefinitions - Enforce
runAsNonRoot: true - Adjust filesystem or capability requirements
Sidecars and custom workloads
When you add sidecars via drupal_sidecars, those containers:
- Are not automatically hardened by the operator’s securityContext snippets, unless your templates explicitly apply them.
Recommendations:
- Always specify appropriate
securityContextfor each sidecar. - Run sidecars as non-root where possible.
- Drop unnecessary capabilities and set
readOnlyRootFilesystem: truewhen feasible.
Secrets and sensitive data
The Drupal Operator manages sensitive information primarily via Kubernetes Secrets:
- Database credentials (Drupal and MariaDB)
- Drupal admin user and password
- Backup credentials (via
drupal_backup_secret)
Relevant defaults:
drupal_backup_secret:"backup-secret"
The Ansible role roles/setup/tasks/main.yaml:
- Creates Secrets using templates:
templates/db-secrets.yaml.j2templates/drupal-secrets.yaml.j2- References them from Deployments and Jobs.
Recommendations:
- Use strong, unique values for:
drupal_db_passdrupal_password- Any credentials stored in
drupal_backup_secret - Store the backing values in a secure secret management solution or use sealed-secrets / external secret operators where appropriate.
- Ensure
kubectl/helmusers with permission to read these Secrets are limited.
Network exposure
By default, the operator can expose Drupal via:
- ClusterIP (default)
- NodePort Service (if
drupal_nodeport: true) - LoadBalancer Service (if
drupal_loadbalancer: true)
Example fields:
drupal_nodeport:true(default)drupal_loadbalancer:false(default)drupal_loadbalancer_port:80drupal_loadbalancer_target_port:80
Security considerations:
- A NodePort is reachable on every node in the cluster; ensure:
- Firewall rules or security groups around node ports are appropriate.
- A LoadBalancer may receive a public IP on cloud environments; ensure:
- TLS termination (via Ingress or other means).
- Proper WAF or reverse proxy rules, as needed.
Recommendations:
- For production, consider using:
- An Ingress controller and HTTPS.
- Locked-down firewall rules or private LoadBalancers.
- Limit the use of NodePort to development or internal clusters.
Data persistence and cleanup
The operator creates:
- PersistentVolumeClaims (PVCs) for:
- Database (
db_pvc,db_pvc_size) - Files (
files_pvc,files_pvc_size)
Deleting a Drupal resource:
- Will typically delete the Deployment/StatefulSet and some K8s resources.
- May or may not delete PVCs depending on the
reclaimPolicyof your StorageClass and how the templates are written.
You should:
- Understand your storage class behavior (Retain vs Delete).
- Treat PVCs as containing sensitive data (DB + file system).
- Apply appropriate storage encryption at rest where supported by your infrastructure (for example, encrypted volumes).
Operator uninstall and data loss
Running:
make uninstall
will:
- Remove the CRDs installed by the operator.
- Trigger Kubernetes garbage collection of all custom resources and any resources that depend on them, depending on ownerReferences.
The README and docs highlight:
- Never run
make uninstallon a live/production cluster.
Because:
- Removing CRDs makes all
Drupalresources and potentially associated Sites, Databases, and Jobs subject to deletion.
Recommendation:
- Only use
make uninstallin disposable or dedicated test clusters. - For production, remove individual
Drupalresources or namespaces, not the CRD itself.
Logging, auditing, and observability
For security investigations and auditing:
-
Operator logs:
kubectl logs -f deploy/drupal-operator-controller-manager -n drupal-operator-system
-
Resource events:
kubectl get events -A kubectl describe drupal
-n
Recommendations:
- Forward logs to a central logging solution (for example, EFK, Loki, or a cloud logging service).
- Enable audit logging on your Kubernetes cluster and restrict access to audit logs.
Summary checklist
- Run the operator in a dedicated namespace with least-privilege RBAC.
- Protect
DrupalCRs and Secrets via Kubernetes RBAC. - Use non-root containers and hardened
securityContextwhere possible. - Limit and secure external exposure (NodePort, LoadBalancer, Ingress).
- Understand storage retention and encryption for PVCs.
- Never use
make uninstallon a cluster with data you want to keep. - Collect and centralize logs for auditing and incident response.