feat: fetch GPG passphrases from HashiCorp Vault - #184
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_node/utils/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 is imported lazily so it is only needed
when the provider is enabled.
Passphrases are read once at startup, so a short-lived token is
enough and no Vault session is renewed while the node runs.
Resolves: AlmaLinux/build-system#548
anfimovdm
force-pushed
the
feat/vault-passphrases
branch
from
August 25, 2026 15:34
fe6fba1 to
ff96348
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-node half of that issue. The albs-sign-file half is AlmaLinux/albs-sign-file#71.
What changed
sign_node/utils/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.hvacis imported lazily, so it's only needed when the provider is enabled.sign_node/utils/secrets.py— provider resolver. Passphrase resolution for both Bitwarden and Vault now goes through here.sign_node/config.py— twelvevault_*keys plus cerberus schema entries.almalinux_sign_node.py— calls the resolver instead of Bitwarden directly.node-config/sign_node.yml,hvac==2.4.0inrequirements.txt.Secret layout
One secret per keyid at
<vault_mount>/<vault_path_prefix>/<keyid>, passphrase in thepassphrasefield:The field name is configurable via
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-node-tests), since building pycurl locally needs system libs:test_vault.py,test_secrets.py), against a stubbedhvacclient.SignNodeConfigobjects, not only mocks: defaults load correctly, and enabling both providers raisesOnly one secret provider may be enabled at a time, but these are enabled: bitwarden, vault.C0415) and the local count in a function with twelve config options (R0914). Pre-existing black violations inconfig.pyandalmalinux_sign_node.pywere left alone — both were already non-clean atmaster.