NAME

regpg - safely store server secrets

SYNOPSIS

regpg help

regpg check [options] <cryptfile.asc>...

- keys:

regpg lskeys [options]

regpg addself [options]

regpg addkey [options] <keyname>...

regpg delkey [options] <keyname>...

regpg exportkey [options] [keyname]...

regpg importkey [options] [keyfile]...

- secrets:

regpg encrypt [options] [[clearfile] cryptfile.asc]

regpg decrypt [options] [cryptfile.asc [clearfile]]

regpg recrypt [options] <cryptfile.asc>...

- helpers:

regpg edit [options] <cryptfile.asc>

regpg pbcopy [options] [cryptfile.asc]

regpg pbpaste [options] [cryptfile.asc]

regpg shred [options] <clearfile>...

- generators:

regpg gencsrconf [options] [<certfile>|<hostname> [csr.conf]]

regpg gencsr [options] <private.asc> <csr.conf> [csr]

regpg genkey [options] <algorithm> <private.asc> [ssh.pub]

regpg genpwd [options] [cryptfile.asc]

- setup:

regpg init [options] [hook]...

regpg conv <command> [options] <args>...

DESCRIPTION

The regpg program is a thin wrapper around gpg for looking after secrets that need to be stored encrypted in a version control system and deployed to servers with a configuration management system.

You use the regpg *keys subcommands to maintain a gpg public key ring file (by default ./pubring.gpg) which lists the set of people who can decrypt the secrets.

You use the regpg *crypt subcommands to manage encrypted files. The encryption recipients are all the keys in the public key ring. Decryption is non-interactive, using gpg-agent.

You use the regpg gen* subcommands to create encrypted secrets.

The regpg check subcommand verifies that the encrypted files and public keyring are consistent with each other.

The regpg init subcommand helps you to hook up regpg with a few other utilities.

OPTIONS

The regpg subcommands all take the same options.

-k pubring.gpg

Specify the name of the public key ring file, to override the default ./pubring.gpg.

-n

Do nothing, but show what would have been done.

-r

For the addkey, delkey, and recrypt subcommands, recrypt all files found by the check subcommand.

-v

Verbose mode. This mainly prints the gpg commands.

SUBCOMMANDS

Several subcommands have abbreviated synonyms.

regpg help

Display this documentation.

regpg check <cryptfile.asc>...
regpg ck <cryptfile.asc>...

Check cryptfiles for consistency.

If no arguments are given, check recursively finds and lists all encrypted files. These are the files that are recryped by the -r option.

If a cryptfile has a .asc or a .gpg extension, and an adjacent file exists without the extension, it is called out as a potential cleartext file. You can use regpg shred to destroy cleartext files.

Keys that can decrypt a cryptfile but are not present in the -k pubring.gpg are listed in red with - markers.

Keys are present in the -k pubring.gpg but cannot decrypt a cryptfile are listed in green with + markers.

If one argument is given then key fingerprints are printed in full, otherwise the diffs just list bare key IDs.

These differences can be resolved by the recrypt subcommand.

Key management

The following subcommands manage the contents of the publig key ring file, by default pubring.gpg.

regpg lskeys
regpg ls

List the keys in the regpg keyring.

regpg addself

Add your own key(s) to the regpg keyring.

A key is "yours" if you have its secret key and it has an identity matching your login name.

It is a good idea to generate a new gpg key specifically for use with regpg. If you have multiple keys, addself will add them all. You can then use delkey to remove the unwanted ones.

If none of your keys were previously on the regpg keyring then you will not be able to recrypt the secrets. You will need to get one of the existing keyholders to do that for you.

regpg addkey <keyname>...
regpg add <keyname>...

Export keys from your default gpg public keyring, and import them into the regpg keyring.

A keyname can be a key fingerprint or ID or a person's email address.

If the -r option is given, all files are recrypted after the key is added.

regpg delkey <keyname>...
regpg del <keyname>...

Delete keys from the regpg keyring.

A keyname can be a key fingerprint or ID or a person's email address.

If the -r option is given, all files are recrypted after the key is added.

regpg exportkey [keyname]...
regpg export [keyname]...

Export keys from the regpg keyring.

If no keynames are given then all keys are exported.

regpg importkey [keyfile]...
regpg import [keyfile]...

Import keys into the regpg keyring that have previously been exported by gpg.

If no keyfiles are given then keys are read from stdin.

If the -r option is given, all files are recrypted after the key is added.

Secret management

The following are the core secret encryption and decryption subcommands.

regpg encrypt [[clearfile] cryptfile.asc]
regpg en [[clearfile] [<cryptfile.asc>]

Encrypt clearfile to produce cryptfile.asc. The encryption recipients are all the keys in the public key ring.

If clearfile is - or there is one argument then the cleartext is read from stdin.

If cryptfile is - or there are no arguments then the ciphertext is written to stdout.

Note: conventionally the cryptfile has a .asc (for ASCII-armored) or .gpg extension.

regpg decrypt [cryptfile.asc [clearfile]]

Decrypt cryptfile.asc to produce clearfile. You must be running gpg-agent which will be used to gain access to your private key for decryption.

If cryptfile is - or there are no arguments then the ciphertext is read from stdin.

If clearfile is - or there is one argument then the cleartext is written to stdout.

Note: You can also just use gpg --decrypt. The regpg decrypt subcommand requires the GPG agent so it has consistent behaviour in bulk operations such as regpg recrypt -r.

regpg recrypt <cryptfile.asc>...
regpg re <cryptfile.asc>...

Decrypt and re-encrypt cryptfiles. If the -r option is given, all files are re-encrypted.

You should use this after using addkey or delkey, if you did not pass the -r option.

Higher-level helpers

The following subcommands provide more convenient access to secrets, at the cost of some safety.

regpg edit <cryptfile.asc>

Decrypt cryptfile.asc (if it exists) and run $EDITOR on the cleartext file. The cleartext is placed on a tmpfs in RAM when possible. When you have finished editing, the file is re-encrypted and the cleartext is shredded.

regpg pbcopy [cryptfile.asc]

Decrypt cryptfile.asc and copy the cleartext to the clipboard. When you have used the secret, press ^C and regpg will clear the clipboard.

This uses pbcopy on macOS or xclip on X11.

If cryptfile is missing or - then it is read from stdin.

regpg pbpaste [cryptfile.asc]

Encrypt the contents of the clipboard and paste the ciphertext into cryptfile.asc. The clipboard is cleared afterwards.

This uses pbpaste on macOS or xclip on X11.

If cryptfile is missing or - then it is written to stdout.

regpg shred <clearfile>...

Destroy cleartext files and any related editor backup files. If shred(1) is not available, the files are just deleted.

If the -r option is given, all cleartext files found by regpg check are shredded.

Note: You might want to test shred with the -n option first!

Secret generators

The following subcommands combine the core regpg encrypt / decrypt subcommands with secret handling tools from OpenSSL and OpenSSH, etc.

regpg gencsrconf [<certfile>|<hostname> [csr.conf]]

Convert an X.509 certificate into an openssl req configuration file which can be used with regpg gencsr.

You can use gencsrconf with an existing certificate file certfile to help with renewals, or you can fetch a web server's certificate from hostname to create an example configuration to adapt for a new certificate request. See the "EXAMPLES" below.

If certfile is - or there are no arguments then it is read from stdin.

If csr.conf is - or there is one argument then it is written to stdout.

regpg gencsr <private.asc> <csr.conf> [csr]

Generate an X.509 certificate signing request for an encrypted private key.

The CSR parameters (distinguished name, subjectAltName, etc) are given in the OpenSSL configuration file csr.conf. (See the req(1ssl) man page for details.)

The private key private.asc should have been generated with regpg genkey rsa.

If csr is - or is omitted then it is written to stdout.

As well as being written to csr, the CSR is printed in text form if you give the -v option.

regpg genkey <algorithm> <private.asc> [ssh.pub]

Generate a cryptographic key pair, for use with OpenSSL or OpenSSH. The PEM private key is encrypted and written to the file private.asc. If an ssh.pub filename is given, an ssh public key is written there.

The algorithm can be one of:

dsa - 1024 bit DSA
ec256 - 256 bit ECDSA (prime256v1)
ec384 - 384 bit ECDSA (secp384r1)
ec521 - 521 bit ECDSA (secp521r1)
ecdsa - same as ec256
rsa - 2048 bit RSA

regpg genpwd [cryptfile.asc]

Generate a 20 character password, encrypt it, and store it in cryptfile.asc.

If cryptfile is missing or - then it is written to stdout.

Initial setup

regpg init [hook]...

Easy initialization of regpg and its hooks for other utilities. It is safe to re-run regpg init since it is idempotent.

Every init run ensures the regpg public keyring exists. If it doesn't, the keyring is created using regpg addself.

The hooks can be zero or more of:

git
ansible
ansible-vault

regpg init git

Configure git to provide human-readable diffs of the regpg public keyring.

Note: You must have run git init first. The git diff configuration is not propagated with the contents of the repository, so you need to re-run regpg init git in each fresh clone.

Note: this does not provide human-readable diffs of the cleartext contents of encrypted files, because that would expose secrets dangerously.

regpg init ansible

Configure Ansible for use with regpg. An ansible.cfg file is created if necessary.

This installs an Ansible Jinja2 filter plugin called gpg_d that decrypts secrets for deployment on servers. It can be used in templates, including the content: option to Ansible's copy module.

It also creates a gpg-preload.yml playbook, which you can use to get gpg-agent ready right at the start of a playbook run.

See the "EXAMPLES" below for how to use this setup.

Note: these Ansible hooks only use gpg, so you don't need regpg to run your playbooks. You only need regpg for altering the public keyring and encrypted files.

regpg init ansible-vault

Configure Ansible Vault for use with regpg. An ansible.cfg file is created if necessary.

This creates an encrypted vault password vault.pwd.asc and a wrapper script vault.open to decrypt the password using gpg.

You can then use ansible-vault as usual, and when it needs the vault password it will be automatically decrypted.

Note: the decryption script only uses gpg, so you don't need regpg to run ansible-playbook nor ansible-vault. You only need regpg for altering the public keyring.

Converting to regpg

The conv subcommand has a number of sub-sub-commands which help you convert from other setups to regpg.

regpg conv ansible-gpg

Convert an ansible-gpg setup for use with regpg, as if you had used regpg init ansible-vault.

This copies the keys from .ansible-gpg/pubring.gpg into the regpg keyring, renames .ansible-gpg/vault_passphrase.gpg to vault.pwd.gpg, reconfigures Ansible, and finally removes the remaining ansible-gpg files.

regpg conv ansible-vault [<vaultfile> [cryptfile.asc]]

Decrypt vaultfile using ansible-vault and re-encrypt the cleartext using regpg.

If cryptfile is - or omitted then the ciphertext is written to stdout.

If both arguments are omitted then regpg searches for ansible-vault files that may need conversion.

regpg conv stgza [<member> [cryptfile.asc]]

Convert from a symmetrically-encrypted secrets.tar.gz.asc using its regpg-encrypted passphrase from secrets.pwd.asc. (These filenames are hard-coded to match old tooling.)

The member is the name of a file inside secrets.tar.gz.asc to extract and re-encrypt with regpg.

If cryptfile is - or omitted then the ciphertext is written to stdout.

With no argument, regpg lists the contents of secrets.tar.gz.asc.

EXAMPLES

TLS preparation

Get a template OpenSSL CSR configuration file based on a certificate similar to the one you want. This example gets the request details from the certificate for dotat.at:

    $ regpg gencsrconf dotat.at tls.csr.conf

Edit tls.csr.conf to the correct details for your server, then you can generate a key and CSR:

    $ regpg genkey rsa tls.pem.asc
    $ regpg gencsr tls.pem.asc tls.csr.conf tls.csr

Ansible without Vault

After running regpg init ansible, here are a couple of ways you can use gpg in your Ansible playbooks.

This Ansible task installs ssh host private keys that have been encrypted with regpg. The private key file content= is generated from a Jinja2 template that uses the gpg_d filter plugin. The with_fileglob: loop translates relative filenames to absolute filenames according to Ansible's search path, so with_fileglob: is useful with gpg_d even when a task is decrypting only one file. The when: condition on the last line allows you to avoid decrypting secrets except when necessary.

    - name: install ssh host keys
      copy:
        content="{{ item | gpg_d }}"
        dest="/etc/ssh/{{ item | basename | replace('.asc','') }}"
        mode=0600
      with_fileglob:
        - ssh_host_*_key.asc
      when: secrets | default(all) | default()

There can be a problem when Ansible invokes gpg_d multiple times concurrently, that you may be asked to enter your passphrase more than once. You can avoid this by forcing Ansible to preload gpg-agent immediately at startup. Do this by including gpg-preload.yml at the start of your main playbook:

    ---
    - include: gpg-preload.yml
      when: secrets | default(all) | default()
    # etc...

VERSION

  This is regpg-0.91.X <https://dotat.at/prog/regpg/>

  Written by Tony Finch <fanf2@cam.ac.uk> <dot@dotat.at>
  at Cambridge University Information Services.
  You may do anything with this. It has no warranty.
  <https://creativecommons.org/publicdomain/zero/1.0/>

ACKNOWLEDGMENTS

Thanks to Jon Warbrick who gave me the idea for regpg's key management, and David McBride for helpful discussions.

SEE ALSO

gpg(1), gpg-agent(1), ansible(1), git(1), openssl(1), shred(1), ssh-keygen(1)