Skip to content

mandx/privie

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔐 Privie 🔐

An experimental (and opinionated, and probably over-engineered) CLI utility to manage secrets as part of code, managed with your source control system. This utility is heavily inspired by ejson, and so, it strives to keep all of its benefits, which are:

  • Secrets can be safely stored in a git repo.
  • Changes to secrets are auditable on a line-by-line basis with git blame.
  • Anyone with git commit access has access to write new secrets.
  • Decryption access can easily be locked down to production servers only.
  • Secrets change synchronously with application source (as opposed to secrets provisioned by Configuration Management).

There are also a couple more (opinionated) improvements:

  • Keyrings are a single JSON file, instead of files named with random hashes. Now there's a single file with an explicit name to be added to .gitignore.
  • By default keyrings are looked up in the current directory, so no need to modify your own system using sudo on /opt/ or whatever.
  • Full support for stdin/stdout, plus explicit CLI flags to specify the input and output files.
  • Handy subcommand to add and encrypt secrets to an existing secrets file; less hand editing files.
  • Public keys are embedded in the encrypted secrets themselves, instead of a single public key shared for all the secrets in the document. This allows for two things:
  • JSON documents can now have an arbitrary structure, now there's no requirement for them to be an object. We could have a JSON document containing an array of strings, the individual strings inside the array can be encrypted too.
  • We can construct an encrypted secrets file in which each secret can have independent public keys, so, when decoding, only the keys in the keyring with a corresponding secret key will be decrypted; the rest of the secrets (those that couldn't be decrypted) will be left as-is in the output.

Caveats (or, why you shouldn't use this)

Unfortunately, at this moment, Privie can not be recommended for production environments, mainly because:

  • I'm not cryptography expert! (Help is welcomed)
  • The cryptographic libraries used provide a good API, however they haven't been (yet) properly audited.

Usage

Keyrings

A keyring is a JSON document with a mapping of public keys and (optionally) their corresponding secret keys. We only need a public key to encrypt a secret, but we do need its corresponding secret key to decrypt that encrypted secret.

A keyring can be generated like this:

$ privie generate-keyring > my-keyring.json
# or
$ privie generate-keyring --output=my-keyring.json

By default generated keyrings are dumped to stdout, so we can use shell redirections (>) or the explicit --output parameter.

Now we have a keyring file that looks like this:

cat my-keyring.json
{"17EV2Rohy...Th0tJF36qfAw=":"hy9ZzHBn...8dpiqdIBxck8="}

Keyrings contain the secret keys required for decryption, so it's very important we keep these safe. DO NOT commit these to any code repository!.

Encrypting

Assuming we have a file called my-secrets.json with this content:

{
   "mongodb": "mongodb://m-user:m-pass@some-server.mlab.com:23022/someDb",
   "redis": "redis://r-user:r-pass@some-server.cloud.redislab.com:12345/1"
}

We can encrypt it using the keyring from the previous example:

$ privie encrypt --keyring=my-keyring.json --input=my-secrets.json --output=my-encrypted-secrets.json
We can also use `stdin` and/or `stdout` instead of `--input` and/or `--ouput`

For example, this command is equivalent to the previous one:

$ privie encrypt --keyring=my-keyring.json < my-secrets.json > my-encrypted-secrets.json

Now we have a my-encrypted-secrets.json file that looks something like this:

$ cat my-encrypted-secrets.json
{
  "mongodb": "17EV2Rohy...Th0tJF36qfAw=:qeGq09vNaBoDda8RWnmnT2zxF/B5jIeEtQ894Uy4...g9zBE2BPa08DVzt1sjHJxe",
  "redis": "17EV2Rohy...Th0tJF36qfAw=:cDbrdgVu446IA475Hq8HTDJb7FMKGXtlG8YAgGCbr1...7Cq0FXl+O41kKRSfEix3f70pJDK1K"
}

Now our secrets are encrypted and can be committed to our repository:

$ git add my-encrypted-secrets.json
$ git commit -m 'Add encrypted secrets file'

Decrypting

$ privie decrypt --keyring=my-keyring.json --input=my-encrypted-secrets.json --output=my-decrypted-secrets.json

Similar to when decrypting; we use the decrypt subcommand instead of encrypt and reverse the --input and --output params. Now we have a my-decrypted-secrets.json file which is "equivalent" to the initial my-secrets.json file we had at the beginning. (They won't be exactly equal, since most formatting will be lost every time a JSON document is read and written).

Sharing the keyring

This is where is up to the team to decide where to keep this file, and also, how to make it available in CI. For example, its possible to paste the content of the keyring as a Github secret, and write it to a file just before invoking privie:

      - name: Decrypt the secrets file
        env:
          KEYRING_CONTENTS: ${{ secrets.KEYRING_CONTENTS }}
        run: |
          echo $KEYRING_CONTENTS > my-keyring.json
          privie decrypt --keyring=my-keyring.json --input=my-encrypted-secrets.json --output=my-decrypted-secrets.json

You can also have the keyring's content piped in via stdin, like so:

$ echo $KEYRING_CONTENTS | privie decrypt --keyring=- --input=my-encrypted-secrets.json --output=my-decrypted-secrets.json

Most commands with a --keyring argument will allow using - to denote to read from stdin, the limitation being that it won't be possible then to use stdin for the --input argument.

// TODO: Add more examples

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages