ansible-sign
ansible-sign is a utility for signing and verifying Ansible project directory contents using GPG. It generates checksum manifests of project files and signs them cryptographically, enabling downstream consumers (Ansible Automation Platform, AWX, CI/CD pipelines) to verify that content has not been tampered with since it was signed.
Installation
Section titled “Installation”# Via the full suite (recommended)pip install ansible-dev-tools
# Standalonepip install ansible-signVerify installation:
ansible-sign --versionCore concepts
Section titled “Core concepts”How signing works
Section titled “How signing works”- ansible-sign scans your project directory for tracked files
- It generates SHA-256 checksums for each file, creating a checksum manifest
- The manifest is signed with your GPG private key, producing a detached signature
- Both the manifest (
.ansible-sign/sha256sum.txt) and signature (.ansible-sign/sha256sum.txt.sig) are stored in the project
How verification works
Section titled “How verification works”- The verifier reads the signed manifest and signature
- GPG verifies the signature against the signer’s public key
- File checksums are recalculated and compared against the manifest
- Any modified, added, or removed files cause verification to fail
MANIFEST.in
Section titled “MANIFEST.in”The MANIFEST.in file controls which files are included in the checksum manifest. It uses Python’s distutils manifest template syntax:
include *.ymlinclude *.yamlrecursive-include roles *recursive-include playbooks *recursive-include inventory *recursive-include group_vars *recursive-include host_vars *exclude .git/*exclude .ansible-sign/*If no MANIFEST.in exists, ansible-sign defaults to including all files tracked by git (minus the .ansible-sign/ directory itself).
The .ansible-sign/ directory
Section titled “The .ansible-sign/ directory”After signing, your project contains:
.ansible-sign/├── sha256sum.txt # Checksum manifest└── sha256sum.txt.sig # GPG detached signatureThese files should be committed to version control so that consumers can verify the project.
CLI reference
Section titled “CLI reference”ansible-sign project gpg-sign
Section titled “ansible-sign project gpg-sign”Sign the current project:
# Sign with default GPG keyansible-sign project gpg-sign .
# Sign with a specific keyansible-sign project gpg-sign . --fingerprint ABCD1234...
# Sign a project at a specific pathansible-sign project gpg-sign /path/to/project
# Force re-sign (overwrite existing signature)ansible-sign project gpg-sign . --forceansible-sign project gpg-verify
Section titled “ansible-sign project gpg-verify”Verify a signed project:
# Verify the current directoryansible-sign project gpg-verify .
# Verify with a specific keyringansible-sign project gpg-verify . --keyring /path/to/keyring.gpg
# Verify a project at a specific pathansible-sign project gpg-verify /path/to/projectExit codes:
| Code | Meaning |
|---|---|
0 |
Verification successful — all files match |
1 |
Verification failed — signature invalid or files modified |
2 |
Error — missing signature, missing keyring, or other problem |
Global options
Section titled “Global options”| Flag | Description |
|---|---|
--debug |
Enable debug output |
--version |
Show version |
-h, --help |
Show help |
GPG key management
Section titled “GPG key management”Generating a key pair
Section titled “Generating a key pair”If you don’t have a GPG key:
gpg --full-generate-keyChoose RSA 4096-bit, set an appropriate expiration, and provide your name and email.
Listing keys
Section titled “Listing keys”# List public keysgpg --list-keys
# List private keys (for signing)gpg --list-secret-keysExporting for verification
Section titled “Exporting for verification”Export your public key for distribution to team members and automation platforms:
# Export as ASCII armorgpg --export --armor your.email@example.com > signing-key.pub
# Import on another machinegpg --import signing-key.pubWorkflow
Section titled “Workflow”Signing a project
Section titled “Signing a project”cd /path/to/ansible-project
# Create MANIFEST.in if you want to control which files are signedcat > MANIFEST.in << 'EOF'include *.ymlinclude *.yamlrecursive-include roles *recursive-include playbooks *recursive-include inventory *recursive-include group_vars *recursive-include host_vars *recursive-include collections *exclude .git/*EOF
# Sign the projectansible-sign project gpg-sign .
# Commit the signaturegit add .ansible-sign/ MANIFEST.ingit commit -m "Sign project content"git pushVerifying before deployment
Section titled “Verifying before deployment”# Clone or pull the projectgit clone git@github.com:myorg/ansible-project.gitcd ansible-project
# Verify signature before runningansible-sign project gpg-verify .if [ $? -eq 0 ]; then ansible-navigator run site.ymlelse echo "ERROR: Project signature verification failed!" exit 1fiAWX/Controller integration
Section titled “AWX/Controller integration”Ansible Automation Platform Controller (and AWX) supports automatic content verification on project sync. When configured:
- Controller syncs the project from SCM (git)
- Before making the content available for job execution, it runs
ansible-sign project gpg-verify - If verification fails, the project sync fails and jobs cannot run the unverified content
Configuring in Controller
Section titled “Configuring in Controller”- Upload the signing public key to Controller’s credential store as a GPG Public Key credential
- Attach the credential to the Project
- Enable “Content Signing Verification” on the Project settings
- On next sync, Controller automatically verifies the project signature
Configuring in AWX
Section titled “Configuring in AWX”The same workflow applies to AWX (the open-source upstream of Controller):
- Create a GPG Public Key credential
- Associate it with the project
- AWX verifies on every project update
CI/CD integration
Section titled “CI/CD integration”Signing in CI
Section titled “Signing in CI”Add signing as a step in your release pipeline:
# GitHub Actions example- name: Import GPG key run: echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --import
- name: Sign project run: | ansible-sign project gpg-sign . --fingerprint ${{ secrets.GPG_FINGERPRINT }} git add .ansible-sign/ git commit -m "Update project signature" git pushVerifying in CI
Section titled “Verifying in CI”Add verification as a gate before deployment:
- name: Import signing public key run: echo "${{ secrets.GPG_PUBLIC_KEY }}" | gpg --import
- name: Verify project signature run: ansible-sign project gpg-verify .Security considerations
Section titled “Security considerations”- Protect your private key: Store GPG private keys in secure credential stores (vault, CI secrets), never in the repository
- Key rotation: Establish a key rotation policy; update Controller/AWX credentials when rotating
- MANIFEST.in scope: Be deliberate about what files are covered — exclude generated files, caches, and editor artifacts
- Git integration: The default behavior (signing all git-tracked files) is the safest starting point
- Signature freshness: Re-sign after any content change; stale signatures will cause verification failures
Next steps
Section titled “Next steps”Your content is signed and ready for production. To see how all the tools fit together in a complete development cycle, read the end-to-end workflow guide.