Storing Sensitive Data in Git


Git is easily used as the one source of truth when it comes to configuration data, esp. in the world of infrastructure as code. A good way to include sensitive config info in a git repo is via the sops CLI.
Basically the workflow is like this (using AWS KMS for encryption; sops also supports GCP KMS, Azure Key Vault, age, and PGP):
  1. 1.
    someone creates an AWS KMS key and adds AWS users to it; this only needs to be done once
  2. 2.
    any one of those users encrypts the sensitive config file using sops CLI and the created AWS KMS key, and pushes it to git
  3. 3.
    any one of those users who has checked out the git repo uses sops to decrypt the file (this will fail if user does not have permission to use one of the keys mentioned in the encrypted file).
Sops puts the key reference in the encoded file, so decoding it is trivial, and safe: only users listed in the key (when the key was created) can use the key, so only they can decode it.
The sops CLI purposely encourages to decrypt to memory or stdout; you have to use extra arguments to encrypt to file. So it is very easy to see the content of the file, decrypted, without writing to disk, thus decreasing likelihood of leakage.
Several keys can be used in a key ring to encrypt, for redundancy (ie if an AWS region becomes unavailable, you can still decrypt if you used keys from several regions); sops will automatically try each key until one is found that works.
Any number of files can use the same KMS key.


Sops is easy to use with terraform thanks to the sops terraform provider which I have used quite a bit and is hugely popular.
The workflow of the preceding section has a different step 3:
3. someone configures the terraform code to use the sops provider and a data source that loads the file, pushes to git
4. some checks out the git repo
5. When terraform plan or apply is run, the sops provider automatically uses the KMS key referenced in the encrypted file to decode the file in memory; the tf code can use this info
This will fail if the user running terraform is not in the list of users of the key in AWS.
The decoded config file is never written to disk.