feat: fetch GPG passphrases from HashiCorp Vault - #71
Open
anfimovdm wants to merge 1 commit into
Open
Conversation
Adds a HashiCorp Vault KV v2 provider as an alternative to Bitwarden
for resolving GPG key passphrases at startup, so unattended restarts
do not fall back to an interactive prompt.
Passphrase resolution now goes through sign/pgp/secrets.py, which
picks the enabled provider and refuses to run with more than one
enabled: signing keys should have a single unambiguous source of
truth, so that is a configuration error rather than a fallback chain.
Each keyid maps to a secret at <mount>/<path_prefix>/<keyid> holding
the passphrase in a configurable field ('passphrase' by default).
Supports a static token (inline or from a file), AppRole, and the
VAULT_ADDR/VAULT_TOKEN environment variables for hosts already
running a Vault agent. hvac ships as a [vault] extra and is imported
lazily, so it is only needed when the provider is enabled.
Configurable via the YAML 'vault' section or SF_VAULT_* env vars.
Resolves: AlmaLinux/build-system#548
anfimovdm
force-pushed
the
feat/vault-passphrases
branch
from
August 25, 2026 15:34
7cc1c99 to
73fcbaa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a HashiCorp Vault KV v2 provider as an alternative to Bitwarden for resolving GPG key passphrases at startup, so unattended restarts don't fall back to an interactive prompt.
Resolves: AlmaLinux/build-system#548
Implements the sign-file half of that issue. The albs-sign-node half is AlmaLinux/albs-sign-node#184.
What changed
sign/pgp/vault.py— KV v2 fetcher. Static token (inline or from a file), AppRole, orVAULT_ADDR/VAULT_TOKENfrom the environment for hosts already running a Vault agent.hvacships as a[vault]extra and is imported lazily, so it's only needed when the provider is enabled.sign/pgp/secrets.py— provider resolver. Passphrase resolution for both Bitwarden and Vault now goes through here.sign/config.py— pydantic fields, a YAMLvault:section, and twelveSF_VAULT_*env overrides.sign/signing/backend.py— calls the resolver instead of Bitwarden directly.[vault]extra insetup.py.Secret layout
One secret per keyid at
<mount>/<path_prefix>/<keyid>, passphrase in thepassphrasefield:The field name is configurable via
vault.passphrase_field/SF_VAULT_PASSPHRASE_FIELDfor operators with an existing layout.Two design decisions worth reviewing
passphrase, notpassword. Bitwarden's wrapper hardcodes the item'spasswordfield; Vault has no such constraint, so the field name describes the value.vault.passphrase_fieldcovers anyone who wants literal parity.Out of scope
Storing the GPG private keys themselves in Vault, Vault Transit as a signing backend, and the
albs-deployAnsible wiring — all called out in the issue as follow-ups.Testing
Run in the CI Docker target (
sign-file-tests):vault_test.py,secrets_test.py), against a stubbedhvacclient.Settings, not only mocks: the YAMLvault:section maps through,SF_VAULT_MOUNTcorrectly overrides the YAML value, and enabling both providers raisesOnly one secret provider may be enabled at a time, but these are enabled: bitwarden, vault.pyproject.tomlconfig) and bandit-clean. Remaining pylint notes are the deliberate lazy imports (C0415) and the local count in a function with twelve config options (R0914).Note: the local dev
config.yamlis untracked in this repo, so the documentedvault:block for it isn't part of this PR — the README carries the YAML example instead.