Unconditional⋆ pre-commit
hook to encrypt sensitive files using ansible-vault
tl;dr git hook to encrypt terraform
's tfstate
files on commit using ansible-vault
. Could be used for other file types as well and as a standalone script.
- Dependencies
bash
yq
ansible-vault
- Add to
.pre-commit-config.yaml
in your git repo:
- repo: https://github.com/thekondor/pre-commit-hook-ensure-ansiblevaulted
rev: v0.1.4 # or other specific tag
hooks:
- id: ensure-ansiblevaulted
- Define settings in
.ensure-ansiblevaulted.yml
:
# Optional. Default: vault-encrypted
# The suffix to be added to an encrypted file created with `ansible-vault`
encrypted-suffix: vault
# Optional. Default: .with-error
# Should files to encrypted listed in `files` (see below) be checked against `.gitignore`:
# - `.with-error` fails the hook once a file to process is not added (as a pattern or as a filename) to `.gitignore`.
# Highly recommended to prevent accidental snitching of these files to a git history.
# - `.with-warning` is similar to `.with-error` but raises a warning message instead and continues the hook's flow.
track-git-ignored: .with-warning
# Required. The value is passed "as is" to `ansible-vault`; so it could be an executable script as well.
vault-password-file: path/to/ansible-vault-password
# Required
files:
- "*.ext"
- "*.*another-ext"
Once the hook activated, all files across the repo matching either against *.ext
or *.*another-ext
to be encrypted using ansible-vault
to ones *.ext.vault
or *.*another-ext.vault
and staged for a commit.
The files before being encrypted, firstly checked for a difference against an encrypted copy. Once they differ, they are re-encrypted using ansible-vault edit
, otherwise skipped.
- Highly recommended: add the patterns from the previous step to
.gitignore
to avoid any accidental commit to git. Files withencrypted-suffix
are subject for adding to git only.
While occasionally playing around with a homelab, I faced with a necessity having encrypted terraform
's state files before pushing them to a git. Encryption of these files are must since they can (and they do) contain sensitive data. Alternative options would be either using a remote (cloud) backend with encryption support or some other sophisticated one; for homelab that is an overkill, vendor lock or another extra dependency. Using ansible-vault
already I want to leverage it for this use-case as well to keep everything more or less consistent way.
Hashicorp hasn't invested in a local tfstate
encryption so far (e.g. proposal; there are some more). PR for contribution seems would not be worth the efforts.
On of the common patterns to deal with use-cases like this one, is to leverage either git-encrypt
or local git filters. I prefer to have something more simple and more transparent (w/o being worried that the file is pushed unencrypted because of misconfiguration). That's the reason why git's builtin pre-commit
(as a concept) hook came to rescue.
- ⋆Unconditional - the hook is always applied independently whether files to "protect" were changed/staged or not;
- On fresh repo checkout, the files remain encrypted, so they are subject for manual decryption first;
- Files to "protect" (specified in
.ensure-ansiblevaulted.yml
):- have to be added manually to
.gitignore
to avoid any accidental stage (seetrack-git-ignored
); - are limited with
find
glob-patterns;
- have to be added manually to
- Each file is encrypted to a separate file-based artefact (though e.g. they all could be stored to a single
yml
-based vault).
Since this implementation is a part of my homelab, it has never been prepared for public distribution and further public support. Though the code suits the needs well, there is no guarantee that it will work for you or will work ever properly. You apply it on your own responsibility. Bug reports, suggestions & pull requests are welcome anyway.