Secure Pillar in SaltStack with GPG

Encrypting your Pillar data is recommended because it contains your most valuable information like passwords and keys used in your infrastructure. Pillar data is held by the Salt master and only send through an encrypted bus to Minions when used in a state file. Using Pillar makes sure that sensitive information is only available on the servers that need access. The weak spot here is the Salt master and all other places where your Pillar sls files are stored in plain text. You may for example use GitHub or another external code hosting service.

Encrypting your Pillar data can be done with GPG. This means that you encrypt the values with a public GPG key. This single public key is used by all the developers within your organization to encrypt sensitive information. The private key is only available on the Salt master (not the Minions!). Without the private key the encrypted data can not be decrypted.

Let’s go!

I assume that you are already running a Salt master and one or more Minions. We are first going to create a GPG key pair and than use it to encrypt some Pillar data.

Generate the key pair.

Create a directory named gpgkeys in the SaltStack configuration directory. Make sure nobody else has access to this folder and create the key pair.

mkdir -p /etc/salt/gpgkeys
chmod 0700 /etc/salt/gpgkeys
gpg --gen-key --homedir /etc/salt/gpgkeys

Export the public key

Export the public key and import it in your development environment.
I normally place the public key in the Salt configuration so if I switch my workplace or someone else is working on the project, he/she can use it as well.

gpg --export -a "salt-gpg" > salt-gpg-pub.key
gpg --import salt-gpg-pub.key

Start encrypting values

Encrypt values with the gpg command. Encrypting a complete file is possible as well. We can use it to encrypt SSL certificates for example.

echo -n "secret-value" | gpg --armor --batch --trust-model always --encrypt -r salt-master-gpg 
cat << EOF | gpg --armor --batch --trust-model always --encrypt -r salt-gpg 

Using encrypted values in Pillar

You can use the PGP messages in your Pillar files like bellow. Be sure to start with “#!yaml|gpg” and add a space and a vertical bar after every key name. Indenting is important as with all other files.

#!yaml|gpg
secret-key: |
  -----BEGIN PGP MESSAGE-----

  Version: GnuPG v1
  hQEMA6PfZaXaBkAuAQf/Sswb3Jmxal8BMzVWz3IsJsNlEWJ3SPApzb9LZMOW
  HaT6sVk9X3G6zGtUoWI6V/F/Rj9I6r3cUJhpNNBJAaZU/D45K0ERzT0pKaes
  OYCXtRzVRlmVUGkAbpnHxBEHO/OKU7Ps4i5tiqMPLbHS26lB1j7l7S+v+kQr
  kK6LUM6bo0r3FiLy0R5SjitbPw1/nFjhK/CB3wfCYoNqi4WJy3cRubBqvXgM
  zPA6lcZTHgU5XcCDw0iJzrrCVeJlIUsXH9hVdu6RmLUMk8gUj6tBAvY0hEhO
  pz/sI+3LL+Ag8G6ON/v7b0VRvtp2/lGU5MV2eYnuXNJHARhyN4/NFzdEZH1L
  uSw0VZdEDvlJJxzii5vStc66q1bItQ7zJ9vmNETvcvJ2H1+PdLB4yfegg6Az
  yUIeKEiNWpc=
  =GGPi
  -----END PGP MESSAGE-----
secret-key-2: |
  -----BEGIN PGP MESSAGE-----
...

Testing

A standard configured Salt master refreshes the Pillar data ones a minute. If you don’t have so much time, you can manually refresh it with:

salt '*' saltutil.refresh_pillar

Now requesting a Pillar item on the Salt master will show you the decrypted value.

gijs@Carbon:~$ sudo salt test-minion pillar.item secret-key
test-minion:
    secret-value

Pro tip!

I recommend to only encrypt sensitive data and to make sure that this data is replaceable. A users public SSH key does not have to be encrypted while your MySQL root password needs encryption. If you make sure that the values can be replaced easily. There is no need to backup you private key (and it’s extra secure 🙂 ). If the machine running your Salt master crashes you can generate a new GPG key pair and values.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s