GPG Encrypt Pillar Data

/etc/salt/gpgkeys is a required hard-coded directory. Ensure only the salt-master user has access to this.

Note

salt-master requires no password for GPG decryption to work. Secure your certs. You may want to enforce expiration on certs as well.

If entropy generation is slow (typical on VM’s), install haveged to speed up entropy collection.

Generate GPG keys for salt-master encryption/decryption.
mkdir -p /etc/salt/gpgkeys
chmod 0700 /etc/salt/gpgkeys
gpg --gen-key --homedir /etc/salt/gpgkeys

Important

  • Default option (RSA and RSA).

  • 4096 bit key.

  • 0 (cert does not expire).

  • salty (salt@example.com).

  • NO password.

Export public key for signing data.
gpg --homedir /etc/salt/gpgkeys --armor --export > salty_public_key.gpg

salt_public_key.gpg is used by anyone on any system to create encrypted data that only the server can read.

Import the public key for signing (stored in ~/.gnupg).
gpg --import salt_public_key.gpg

Encrypting Data

Note

The entire PGP block should be added to Pillar; the blank vertical space can be removed. salty is the name of the recipient of the data.

Text.
echo -n "super_secret_server_stuff" | gpg --armor --batch --trust-model always --encrypt --recipient salty
Files.
gpg --armor --batch --trust-model always --encrypt --recipient salty {FILE}

Note

The contents of this file should be what is placed in Pillar. It will be written as {FILE}.asc. salty is the name of the recipient of the data (see Generate GPG keys for salt-master encryption/decryption.).

Warning

Binary data cannot be stored GPG encrypted in pillar for Python 3 versions of saltstack due to Python 3 strict handling of text vs. binary data type. This results in a binary data render error for GPG on salt. Binary support is being explicitly added.

Encrypt Shadow Passwords

The salt user state documentation recommends using openssl passwd -1 to generate a bash passwd hash. This only hashes MD5; modern distributuions of linux hash sha512. Use either the mkpasswd tool or the python script below to generate a salted, sha512 hash in the correct format for consumption in /etc/shadow. Then GPG encrypt the password when storing in Pillar.

Using mkpasswd.
apt install whois
mkpasswd -m sha-512
Python 3 version.
python3 -c "import crypt, getpass; print(crypt.crypt(getpass.getpass('password to hash: '), crypt.mksalt(crypt.METHOD_SHA512)))"

Add to Pillar

Prefix any Pillar file using GPG encryped data with #!yaml|gpg and insert the GPG message block as the value for a key. Use a pipe (|) to denote a GPG message. Blank lines between the begin/version and body can be removed. Standard YAML indentation rules for long text blocks apply.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#!yaml|gpg

secret-stuff: |
  -----BEGIN PGP MESSAGE-----
  Version: GnuPG v2.0.22 (GNU/Linux)
  hQEMA4Pr9QJhL3umAQgAnZtS7lTyDR3kjr+VjCIADutmxyjrxbyaNnPEs3eJRi9G
  N6LtiFlUt24Jgdgupu/CG2IS815V0Vx3EbBknpNNwq0Yrs2joMnm92ZRv4AI6ZTo
  yQqGICetmBOS+vGk4jS8mj9qRjLamvPDOBPyNpKiRCFqu1TPKYw0a8xssO/j/pzW
  TJ39WsHXjtOWLkfYOaf7SKffYL9EsdU5tqXASe5UvjR1Gbj7wdjPl+vMZxRhzfOn
  YQ3fq3wNrGkuz2PpE7n77mmvYGVlXemw4o6tITZMa3MIFZqGTPbCCnh4OubqWGqd
  MtMNgPD2EeZ6wfEWkf1LGrrFy9POmdpssiU92J5dsNJQAdTAZVP4gtoyjWRtHJQB
  3FNarZY210P1o16s1n05ZbkVnz2FeZW/ClB6FqiewDe2EoXcVbXT5WgSZTHFi3mJ
  dFXQZGtReJL4vt8Iq8jSwRI=
  =wJ+K
  -----END PGP MESSAGE-----

Refresh Pillar and Push Data

Regenerate cached Pillar data and push new values (e.g. updated GPG data) to minions if automatic refresh isn’t fast enough. Minions that have been given access to the specific pillar will be able to see the decrypted data.

Manual refresh of Pillar data.
salt '*' saltutil.refresh_pillar
salt pillar.items