The Problem
When we integrate Red Hat Satellite with Ansible Tower we generally want to keep Red Hat Satellite as our single source of inventory data. How do we store sensitive data, such as passwords, in Red Hat Satellite, and ensure that it is available in the dynamic inventory for consumption in playbooks without exposing the data?
Red Hat Satellite does not support encrypted parameter values, only ‘hidden’ ones. These are less than useful as when accessed via an API script they are redacted. Ansible Tower does support encrypted variables, using Ansible Vault’s encrypt_string
feature, however this only works with variables that are statically declared in files and not with dynamic content.
An Example
Consider an Ansible playbook that is used for configuring the Red Hat High-Availability Add-on. Most of the fencing agents used by the STONITH fencing mechanism require a password used to access the fencing device. If we want to store this within Satellite we have a problem – in order for it to be consumed by the playbook that actually configures the cluster, it would need to be in plain text.
A Solution
The solution is to store an encrypted copy of the secret parameter in Satellite, and then decrypt it in the playbook, using a Custom Credential to store the encryption passphrase.
Creating the Custom Credential Type
First, I create a new custom credential type, called Foreman Parameter Encryption as show below:
The input configuration is as follows:
fields:
- secret: true
type: string
id: passphrase
label: Passphrase
required:
- passphrase
and the output configuration is:
extra_vars:
foreman_key: '{{ passphrase }}'
This creates a new credential type in which I can store passphrases. Any passphrase stored will me exposed at runtime into the playbook as a variable called foreman_key
.
Creating the Encryption Passphrase
I then decide on an encryption passphrase which I will use to encrypt and decrypt my sensitive data and store it in a credential of type Foreman Parameter Encryption
:
Encrypting Data
On the commandline, I then encrypt my sensitive data:
$ echo "my super secret stuff" | openssl enc -e -aes-256-cbc -a -salt
entering the passphrase when prompted.
I can then store this encrypted string as a Foreman parameter as shown below:
Accessing Secret Parameters from within a Playbook
At this point I know that I can securely store sensitive data in Satellite, and expose it, still in encrypted form, via the dynamic inventory to Ansible Tower. The last step is to decrypt it within a playbook for use.
I first need to add the credential containing the encryption passphrase that I saved earlier to the Job Template. This will expose the passphrase within the playbook as the variable foreman_key
. I can then decrypt foreman parameters with the following task:
- name: Decrypt my super secret stuff
shell: echo {{ foreman_params.my_secret_stuff }} | openssl enc -pass pass:{{ foreman_key }} -d -aes-256-cbc -a
register: decrypted_secret_stuff
no_log: true
Note the use of no_log: true
to ensure that decrypted variables are not reflected to the log – this should be specified in any task that consumed the decrypted_secret_stuff
variable.