RFE: Add support for secrets in Remote Execution

Context
Currently there is no good way to pass secrets to a Remote Execution job. All the information that is passed as an input, or even rendered directly by the template can be read from Foreman’s UI.

Proposal
Add a new type for inputs to indicate that the input is a secret.
Values for those inputs would be encrypted before it’s stored.
They will be transferred to the Smart Proxy as encrypted and decrypted there.
The decrypted value would be injected as an ENV variable for both Ansible and Script job types.
Ideally the values would be encrypted with the relevant Smart Proxy public key, so only the proxy would be able to decrypt those values.

@Bernhard_Suttner Would be interesting to hear if this strategy (injecting ENV variables) will also work for Salt-based job types.

Very good idea. thank you very much.

Its possible to read salt environments: salt.modules.environ

The discussion has a slightly different target but there are some important notes: Storing secure information

  • like, how to store them - using encrypted with the system /etc/foreman/encryption_key.rb
  • use Encryptable module we have in core

It would be a bit more complicated than using the encrypted column, since we need to decrypt the value in the proxy (as opposed to decrypting it in the Foreman server process). Of course we can pass the decryption key to the proxy as a method parameter, but I find it less secure and prone to key exposure.

Would we? In my mind

  • the inputs would be encrypted using Encryptable
  • once proxy is selected, the inputs would be decrypted and then encrypted again for that single particular proxy

We cannot really encrypt them for a specific proxy before the job starts running because we don’t know in advance which proxy will be used for the job

Well in this case it would be actually both:

  1. encrypt them for storage (using Encryptable)
  2. Encrypt them for transport (proxy).

For 1 I suppose we will need to encrypt only parameters of a certain type, meaning Encryptable won’t fit, unless we extend it with a conditional option (which is not a bad thing).
As for transport - that would be yet another can of worms.

We already connect to proxies using HTTPS. In theory you could figure out the public key from the proxy, but that feels redundant.

Are env vars really a good idea? They often get dumped in process traces. https://www.redhat.com/sysadmin/ansible-playbooks-secrets describes passing them in an encrypted store. Not sure how much sense that makes, but it I’d lean to that.

Another aspect where I don’t know Ansible well enough, but in Puppet you have Sensitive as a type that shows up in logs as [redacted] and file diffs aren’t shown (because they can contain sensitive data). How does Ansible handle this?

Ansible’s concept is a bit different here as it does not protect the data itself but instead it protects the output of commands where possible the data are showing up (in the end it should be more or less the same for our use cases):
https://docs.ansible.com/ansible/latest/reference_appendices/logging.html#protecting-sensitive-data-with-no-log

If you would want to protect the data Ansible Vault would be the way to go as shown in the link you provided, but here is also the link to the official docs:
https://docs.ansible.com/ansible/latest/vault_guide/index.html