Secrets Management Best Practices¶
This page provides recommendations for using Zaita's Secrets Management securely and operationally. These practices apply whether you are managing a handful of secrets for a single application or operating a large multi-team secrets estate.
Locker Organisation¶
Organise Lockers by application or service, not by secret type. A Locker called payment-service-production that contains all credentials the payment service needs is easier to manage and audit than a Locker called database-passwords shared across multiple services.
Separate environments. Create distinct Lockers for production, staging, and development. This prevents a credential for a lower environment from inadvertently being delivered to production, and allows you to grant access to lower-environment Lockers more broadly.
Use descriptive names. Locker and secret names should be immediately meaningful to someone reading the audit log six months from now. Prefer payments-api-stripe-live-key over key1.
Use the description field. The secret description is a good place to record what the value is used for, when it was last rotated, and who is responsible for it. This information is visible in the portal and aids in operational management.
Access Control¶
Apply least privilege. Grant each Courier, Bridge, and Workload access only to the Lockers it genuinely needs. A CI/CD pipeline Courier does not need access to the same Locker as a production application.
Review access regularly. As applications are decommissioned or refactored, revoke access grants that are no longer needed. The Locker's Courier Access, Bridge Cache, and Workload Access tabs provide a full view of who has access.
Prefer Workload identity over client secrets. Where your environment supports it, use credential-less Workload authentication methods (azure_jwt, spiffe_spire, oidc_oauth2) rather than client_secret. Credential-less authentication eliminates the need to rotate the Workload's own credentials and removes a class of secret management overhead.
Use Service Accounts with narrow scopes. When using the Service Account API to automate Locker or Secret management, grant only the scopes required (lockers:write for locker management, secrets:write for secret rotation). Do not use a Super Administrator account for programmatic access.
Choosing a Delivery Method¶
| Delivery Method | Best For | Avoid When |
|---|---|---|
| Courier | Scheduled jobs, cron-driven services, CI/CD pipelines, startup-time injection into .env files |
Runtime secret access or dynamic rotation needed mid-process |
| Bridge | On-premises environments, high-availability requirements, multiple local consumers | Cloud-native apps with direct platform connectivity |
| Workload | Cloud-native apps, services with SPIFFE/SPIRE or managed identity, dynamic runtime access | Environments without an OIDC-compatible identity provider or where file-based delivery is simpler |
| Service Account API | Infrastructure-as-code, automated secret rotation scripts, CI/CD pipelines that manage secrets | Delivering secrets to applications (use Courier or Workload instead) |
Secret Rotation¶
Zaita does not generate new secret values automatically. Rotation is performed by the operator or automation tooling — via the REST API (Service Account API) or by updating the secret value directly in the portal. Once the new value is stored in the Locker, the Courier or Bridge delivers it to consuming workloads on their next run.
Rotate secrets on a defined schedule. Even if no compromise is suspected, rotating credentials limits the window of exposure from an undetected breach. Common rotation intervals are 90 days for API keys and service tokens, and 30 days for database passwords in high-sensitivity environments.
Automate rotation with the Service Account API. Use a Service Account with secrets:write scope to script rotation from any automation tooling — Ansible playbooks, Terraform, CI/CD pipelines, or custom scripts. The recommended pattern:
- Create the new secret value in the Locker under a temporary name (for example,
DB_PASSWORD_NEW). - Update the consuming service to use the new value.
- Verify the service is operating correctly.
- Delete the old secret and rename the new one.
A minimal Ansible example using the Zaita REST API:
- name: Rotate database password
uri:
url: "https://your-tenant.zaita.io/api/v1/lockers/{{ locker_uuid }}/secrets/{{ secret_uuid }}"
method: PUT
headers:
Authorization: "Bearer {{ zaita_service_account_token }}"
body_format: json
body:
value: "{{ new_db_password }}"
Use the on_success hook in Couriers to reload services after a secrets file is refreshed. This ensures the new credentials are picked up without requiring manual intervention or a service restart.
secrets:
locker_uuid: "..."
output_file: /etc/myapp/secrets.env
output_format: env_file
on_success: "systemctl reload myapp"
Do not version secrets in the Locker. A Locker is not a version history — it is a snapshot of the current valid credentials. Maintain only one live value per secret. If you need rollback capability, keep the previous value temporarily under a secondary name until the rotation is confirmed.
Courier Scheduling¶
Set the Courier schedule to match your rotation frequency. If secrets are rotated every 90 days, a daily Courier run is sufficient. If secrets may be rotated at any time in response to a security event, run the Courier more frequently (for example, every 15 minutes).
Set the on_failure hook to alert. A Courier failure may indicate a connectivity problem, a revoked access grant, or a key rotation issue. Configure on_failure to send an alert so failures are investigated promptly.
Write secrets to a dedicated directory. Use a directory that is owned by the application user and not readable by other processes (for example, /etc/myapp/secrets/ with mode 0700). The Courier writes files with mode 0600, but the parent directory permissions provide an additional layer of containment.
Bridge Deployment¶
Use Bridges for on-premises environments. The Bridge's in-memory cache means secrets remain available to local processes even if the connection to the Zaita platform is temporarily interrupted. This is particularly valuable in environments with less reliable connectivity.
Assign only the Lockers a Bridge needs. A Bridge that caches five Lockers has more secret material in memory than one that caches two. Scope assignments carefully.
Monitor Bridge connectivity. The Bridge's heartbeat mechanism keeps it synchronised with the platform. If the Bridge loses connectivity for an extended period, its cache may become stale. Monitor Bridge health through the platform's Bridge management page and set up alerting on heartbeat failures.
Monitoring and Audit¶
Monitor for unauthorised access attempts. The audit log records every secrets download attempt, including failures and unauthorised attempts. Query for courier.download_locker.unauthorised and workload.locker.download.unauthorised events regularly, and alert on unexpected patterns.
Review audit logs after credential rotation. After rotating a secret, review the audit log to confirm that the old credential is no longer being used and that consuming services have picked up the new value.
Export audit logs to your SIEM. Secrets management operations are high-value audit events. Integrate them into your centralised security monitoring to enable correlation with other security signals. See SIEM Integration for configuration options.
Next Steps¶
- Managing Lockers and Secrets — create and manage Lockers and Secrets through the portal.
- Workloads — register applications and select the appropriate authentication method.
- Delivering Secrets with Couriers — configure Couriers for file-based secrets delivery.
- Caching Secrets on Bridges — cache Lockers on-premises for high availability.
- Service Account API — automate secrets management with the API.