This guide covers how to structure CI/CD pipelines for Signotaur code signing and API key rotation. The core pattern is to separate signing from rotation into two distinct pipelines.
| Pipeline | Frequency | Purpose | Command |
|---|---|---|---|
| Build | Every commit | Sign artifacts with the current key | sign with --fail-if-expiring-within |
| Rotation | Monthly / Quarterly | Rotate the API key | rotate-key with appropriate overlap |
The two-pipeline approach keeps rotation separate from builds. If you prefer a simpler single-pipeline setup, see Rotate on Every Build below -- the --if-expiring-within option makes rotate-key safe to run on every build.
Key Principle: Regular builds consume the current key. Key rotation happens either in a separate scheduled job or conditionally within the build using --if-expiring-within.
Your build pipeline reads the current key, optionally checks its expiration, and signs artifacts. If the key is approaching expiration the build fails early, alerting your team to run the rotation pipeline before the key actually expires.
Example:
SignotaurTool sign --api-key-file %USERPROFILE%\.signotaur\api_key.txt --fail-if-expiring-within 7d -s https://signotaur.example.com --label production --fd SHA256 myapp.exe
See sign Command for all signing options and API key resolution details.
Create a dedicated scheduled or manual pipeline that runs monthly or quarterly. The rotate-key command creates a new key and keeps the old one valid during the overlap period so downstream systems can pick up the new key with no downtime.
Example:
SignotaurTool rotate-key --api-key-file %USERPROFILE%\.signotaur\api_key.txt -s https://signotaur.example.com --overlap-days 14 --write-key-file %USERPROFILE%\.signotaur\api_key.txt
If your CI server can capture command output, use --emit-secret with a built-in or custom template instead of --write-key-file to update CI server variables directly. For example, in Continua CI:
SignotaurTool rotate-key --api-key-file %USERPROFILE%\.signotaur\api_key.txt -s https://signotaur.example.com --overlap-days 14 --emit-secret "continua:serverVar=SignotaurApiKey"
See rotate-key Command for supported formats and template variables.
By default, rotate-key creates a new key that inherits the old key's expiry date -- rotation alone does not extend the key's lifetime. Add --renew to also extend the new key's expiry, so keys don't march toward the same fixed expiry date:
SignotaurTool rotate-key --api-key-file %USERPROFILE%\.signotaur\api_key.txt -s https://signotaur.example.com --overlap-days 14 --renew --write-key-file %USERPROFILE%\.signotaur\api_key.txt
Without --renew, repeated rotations eventually produce keys that are very close to expiry. With --renew, each rotation resets the expiry to the server default (90 days) or a custom duration specified with --renew <duration>.
If the renewal would result in a shorter validity than the current key (e.g., renewing for 7 days when the old key still has 90 days remaining), the server rejects the rotation. Add --allow-validity-reduction to permit this.
If you prefer not to maintain a separate rotation pipeline, use --if-expiring-within to make rotate-key safe to run on every build. The command checks the key's expiration date first and only performs a rotation when the key is approaching expiry -- otherwise it exits successfully with no action.
Combine with --ignore-already-rotated-error for full idempotency, so concurrent builds don't fail when one build has already rotated the key:
SignotaurTool rotate-key --api-key-file %USERPROFILE%\.signotaur\api_key.txt -s https://signotaur.example.com --if-expiring-within 14d --renew --ignore-already-rotated-error --write-key-file %USERPROFILE%\.signotaur\api_key.txt
This approach eliminates the need for a dedicated rotation pipeline at the cost of a lightweight server call on every build to check key expiry.
During the overlap period both old and new keys are valid, giving you time to propagate the new key to all systems. The server automatically revokes the old key when the overlap period expires.
Recommended overlap periods:
--fail-if-expiring-within in every build pipeline to get early warning of expiring keys--if-expiring-within to rotate conditionally on every build--no-auto-revoke if you have a manual process