ALTER USER myapp_user WITH PASSWORD 'new_strong_password';
ALTER USER myapp_user WITH PASSWORD 'new_strong_password';
ALTER USER myapp_user WITH PASSWORD 'new_strong_password';
# A snippet from .gitlab-ci.yml
deploy_production: stage: deploy script: - export NEW_API_KEY=$(generate_new_api_key_script) # Generate new key with custom script - sed -i "s/^API_KEY=.*$/API_KEY=${NEW_API_KEY}/g" .env.production - ssh user@prod-server "sudo systemctl reload myapp-backend.service" only: - master
# A snippet from .gitlab-ci.yml
deploy_production: stage: deploy script: - export NEW_API_KEY=$(generate_new_api_key_script) # Generate new key with custom script - sed -i "s/^API_KEY=.*$/API_KEY=${NEW_API_KEY}/g" .env.production - ssh user@prod-server "sudo systemctl reload myapp-backend.service" only: - master
# A snippet from .gitlab-ci.yml
deploy_production: stage: deploy script: - export NEW_API_KEY=$(generate_new_api_key_script) # Generate new key with custom script - sed -i "s/^API_KEY=.*$/API_KEY=${NEW_API_KEY}/g" .env.production - ssh user@prod-server "sudo systemctl reload myapp-backend.service" only: - master
# /etc/systemd/system/nginx-cert-rotate.service
[Unit]
Description=Nginx Certificate Rotation Script [Service]
Type=oneshot
ExecStart=/usr/local/bin/rotate_nginx_certs.sh
User=root # /etc/systemd/system/nginx-cert-rotate.timer
[Unit]
Description=Run Nginx Certificate Rotation Daily [Timer]
OnCalendar=daily
Persistent=true [Install]
WantedBy=timers.target
# /etc/systemd/system/nginx-cert-rotate.service
[Unit]
Description=Nginx Certificate Rotation Script [Service]
Type=oneshot
ExecStart=/usr/local/bin/rotate_nginx_certs.sh
User=root # /etc/systemd/system/nginx-cert-rotate.timer
[Unit]
Description=Run Nginx Certificate Rotation Daily [Timer]
OnCalendar=daily
Persistent=true [Install]
WantedBy=timers.target
# /etc/systemd/system/nginx-cert-rotate.service
[Unit]
Description=Nginx Certificate Rotation Script [Service]
Type=oneshot
ExecStart=/usr/local/bin/rotate_nginx_certs.sh
User=root # /etc/systemd/system/nginx-cert-rotate.timer
[Unit]
Description=Run Nginx Certificate Rotation Daily [Timer]
OnCalendar=daily
Persistent=true [Install]
WantedBy=timers.target - Creating a New User (Optional but Secure): If needed, creating a new user with the same privileges provides a safety net for rollback scenarios.
- Transition at the Application Layer: How applications manage database connection pools is critical. Many modern connection pools (e.g., HikariCP in Java, custom pools written with asyncpg in Python) can dynamically detect password changes or load new credentials with a reload command. If this feature isn't available, applications might need to be restarted sequentially.
- Two-Phase Rotation: In some cases, I implemented a transition strategy that allowed both the old and new passwords to be valid simultaneously for a period. For example, a new password is defined first, then applications are switched to the new password. Once all applications complete the transition, the old password is disabled. This is particularly useful for minimizing downtime in large and complex deployments.
- pg_hba.conf Management: Authentication methods are defined in the pg_hba.conf file. If IP-based restrictions or different authentication mechanisms are used here, these changes must also be included in the rotation plan. - Generate a new key via the service provider's API.
- Check the validity of the old key.
- Add the new key to the application's configuration file.
- Restart application services or reload the configuration.
- Deactivate the old key. - Phased Rollouts (Blue/Green or Canary Deployments): Deploying new service instances configured with new secrets and gradually shifting traffic to them.
- Two-Phase Secret Policy: Ensuring that both the old and new secrets are valid for a certain period. This allows applications to gradually transition to the new secret. For example, defining two different passwords for a database user or implementing a "continue to accept the old one" policy for an API key.
- Connection Pool Reload: Ensuring that application connection pools can dynamically reload secrets. If this isn't possible, ensure the application can pick up new secrets with a graceful restart. - Centralized Secret Management (SMT): Managing all secrets in one place makes it easier to track dependencies.
- Secret Mapping: Documenting which secret is used by which application or service and regularly reviewing it.
- Access Control and Auditing: SMTs typically log secret accesses. By analyzing these logs, we can see which services accessed which secrets and when. - Detailed Logging: Log secret rotation operations and related service secret access errors in detail. Error messages should be clear and understandable.
- Metrics and Alerts: Collect proactive metrics and set up alerts for secret access errors, connection errors, or service outages.
- Audit Logs: Maintain audit logs showing who rotated or accessed which secret and when.