AnsibleXXVII · Collections, Galaxy and Dependency TrustCollections and dependency trust
Checksums, GPG signatures and what they prove
What you'll learn
- Verify an installed collection against its manifest and against the published artefact
- Distinguish what --offline verification proves from what an online verification proves
- Configure GPG signature requirements for installs, and state their limits
- Explain precisely why integrity verification is not a safety judgement
Prerequisites
Verified against ansible-core 2.21.x · ansible (community package) 14.x · Python (controller) 3.12+ · ansible-lint 26.x · Molecule 26.x · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL / Rocky / AlmaLinux 9.x · 2026-08-11
Lesson 5 read a collection’s own claims about itself. This lesson checks a much narrower and much harder thing: that the bytes on your controller are the bytes somebody published.
That is a real and useful property. It is also, routinely, mistaken for a different and far larger one. A verified collection is not a safe collection. It is an unaltered one — which means the publisher’s code, exactly as the publisher wrote it, including anything they wrote badly or on purpose.
The two checksum files
Every collection installed from a Galaxy artefact carries two extra files that were not in the source tree:
$ ls -a collections/ansible_collections/example_corp/platform.
..
FILES.json
MANIFEST.json
README.md
docs
meta
plugins
rolesFILES.json holds a SHA-256 checksum for every file in the collection.
MANIFEST.json holds the collection metadata plus a checksum of
FILES.json. That is a two-level chain: verify MANIFEST.json, and it
vouches for FILES.json, which vouches for every file.
This is also the answer to the * version from lesson 3. A collection
checked out from git has neither file, so there is nothing to verify
against — which is the practical reason a production controller should
install artefacts rather than clone repositories.
Verifying, and watching it catch something
Verification against the local manifest, with no network:
$ ansible-galaxy collection verify example_corp.platform -p ./collections --offlineVerifying 'example_corp.platform:1.0.0'.
Installed collection found at '/home/opsuser/project/collections/ansible_collections/example_corp/platform'
MANIFEST.json hash: b7a3fc1e750306f07c857feb1f8fb374656e158fdf7101656503c9b03ba146df
Successfully verified that checksums for 'example_corp.platform:1.0.0' are internally consistent with its manifest.Read the wording carefully: internally consistent with its manifest. That phrasing is doing real work, and the next command shows why it is not a stronger claim.
Now append one line to a file in the installed collection — the sort of thing a “quick local fix” looks like — and verify again:
$ ansible-galaxy collection verify example_corp.platform -p ./collections --offline; echo "rc=$?"Verifying 'example_corp.platform:1.0.0'.
Installed collection found at '/home/opsuser/project/collections/ansible_collections/example_corp/platform'
MANIFEST.json hash: b7a3fc1e750306f07c857feb1f8fb374656e158fdf7101656503c9b03ba146df
Collection example_corp.platform contains modified content in the following files:
README.md
rc=1Named file, non-zero exit. That is a check you can put in CI and in a pre-change gate.
--offline versus online
Drop --offline and the command downloads the published artefact and
compares against that:
$ ansible-galaxy collection verify community.docker -p ./collectionsVerifying 'community.docker:4.7.0'.
Installed collection found at '/home/opsuser/project/collections/ansible_collections/community/docker'
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/community-docker-4.7.0.tar.gz to /home/opsuser/.ansible/tmp/ansible-local-162019a7u02r88/tmph1rz50he/community-docker-4.7.0-e9vko67e
MANIFEST.json hash: bedb151342e01b6945da014d533ef46128d1e82542722ddecc1f751a7b8fd2f6
Successfully verified that checksums for 'community.docker:4.7.0' match the remote collection.The closing line differs: match the remote collection, not internally consistent with its manifest. Two different claims:
| Mode | Compares | Catches | Misses |
|---|---|---|---|
--offline | Files on disk against the local MANIFEST.json/FILES.json | Local modification after install | A manifest that was itself replaced, and anything wrong upstream |
| online | Files on disk against the freshly downloaded artefact | Local modification, and a manifest replaced along with the files | Anything wrong upstream |
The --offline gap is real but narrow. An attacker who can rewrite
files in your collections directory can also rewrite MANIFEST.json
and FILES.json to match. Offline verification catches the careless
edit; it does not catch the deliberate one.
Both miss the same larger thing, which is the point of the whole lesson.
GPG signatures
Galaxy servers can serve detached GPG signatures for a collection’s
MANIFEST.json. ansible-galaxy will check them at install time if
you give it a keyring.
ansible-galaxy collection install -r requirements.yml \
-p ./collections \
--keyring ~/.ansible/galaxy-keyring.kbx \
--required-valid-signature-count +allThe options that matter:
--keyring <path>— the GPG keyring used for verification. Without it, signature verification does not happen; there is no default keyring and no implicit trust store.--signature <source>— an additional signature source, for a signature you obtained out of band rather than from the server. Repeatable. Only usable with a positional collection name, not with-r.--required-valid-signature-count <n>— how many signatures must verify. A positive integer, orall. Prefix with+to fail when no valid signatures are found at all —+allrather thanall.--ignore-signature-status-code <code>— tolerate specific GPG status codes such asNO_PUBKEYorEXPKEYSIG. Each one you add is a documented hole in the check.--disable-gpg-verify— turn it off entirely.
Knowledge check
Knowledge check · 4 questions
Q1. ansible-galaxy collection verify reports success. What has been established?
Q2. A pipeline installs collections with --required-valid-signature-count all and reports that signature verification is enforced. What is wrong?
Q3. Which are true of ansible-galaxy collection verify --offline? Select all that apply.
Q4. Requiring GPG signatures on installs from public Galaxy is a straightforward hardening step for most estates.
Passing score: 75%. Answers are checked in this browser.