action #106925
closedopenQA Project - coordination #105624: [saga][epic] Reconsider how openQA handles secrets
[timeboxed:10h][research] What are best practices and options in the salt and GitLab community to handle secrets
Updated by jbaier_cz over 2 years ago
A side note from Ansible:
qa-maintenance/qamops uses
ansible-vault
which enables to encrypt variables or the whole yaml file (you will have strings like$ANSIBLE_VAULT;1.1;AES256
in the files); a variable containing the password is defined in for a Gitlab pipelines and the task is executed with--vault-password-file "$ANSIBLE_VAULT_PASS"
in another (personal) project, I am using
password-store
sub-repo and all sensitive settings are GPG encrypted and can be queried easily by executingpass <handle>
; the corresponding secret GPG key is again stored in a Gitlab variable and loaded in the keyring in a before_script of each stage
Updated by jbaier_cz over 2 years ago
- Status changed from New to In Progress
- Assignee set to jbaier_cz
Updated by nicksinger over 2 years ago
I can add my insights how it is done in salt: there is a "gpg renderer" which can decrypt data which is gpg encrypted. Of course we would need to store the secret key somewhere secure and on the host rendering our pillars (OSD). But everything else could be shared this way
Updated by jbaier_cz over 2 years ago
nicksinger wrote:
I can add my insights how it is done in salt: there is a "gpg renderer" which can decrypt data which is gpg encrypted. Of course we would need to store the secret key somewhere secure and on the host rendering our pillars (OSD). But everything else could be shared this way
Yep, from what I saw so far, the GPG renderer is one of the preferred ways. I also saw another approach via "SDB interface" and if I understood that correctly, this can be used with system keyring or other modules like Vault.
On the topic of storing the key to decrypt, Gitlab variables are probably a good place.
Updated by jbaier_cz over 2 years ago
Option 1: Simple and popular¶
Salt¶
Any key in the SLS file can be a GPG cipher and can be decrypted before passing to Salt by salt.renderers.gpg. This allows to safely store secrets in source control, only Salt master can decrypt and distribute the secrets to minions that need them.
To apply the renderer on a file-by-file basis add the following line to the top of any pillar with gpg data in it: #!yaml|gpg
The pillar data will look like:
#!yaml|gpg
a-secret: |
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
hQEMAweRHKaPCfNeAQf9GLTN16hCfXAbPwU6BbBK0unOc7i9/etGuVc5CyU9Q6um
QuetdvQVLFO/HkrC4lgeNQdM6D9E8PKonMlgJPyUvC8ggxhj0/IPFEKmrsnv2k6+
cnEfmVexS7o/U1VOVjoyUeliMCJlAz/30RXaME49Cpi6No2+vKD8a4q4nZN1UZcG
RhkhC0S22zNxOXQ38TBkmtJcqxnqT6YWKTUsjVubW3bVC+u2HGqJHu79wmwuN8tz
m4wBkfCAd8Eyo2jEnWQcM4TcXiF01XPL4z4g1/9AAxh+Q4d8RIRP4fbw7ct4nCJv
Gr9v2DTF7HNigIMl4ivMIn9fp+EZurJNiQskLgNbktJGAeEKYkqX5iCuB1b693hJ
FKlwHiJt5yA8X2dDtfk8/Ph1Jx2TwGS+lGjlZaNqp3R1xuAZzXzZMLyZDe5+i3RJ
skqmFTbOiA===Eqsm
-----END PGP MESSAGE-----
GitLab¶
In GitLab it is possible to use a file based variable for GPG key. File type variables are made available in jobs as environment variables, with the key as the environment variable name, the variable value is saved to a temporary file and the path to the temporary file is set as the environment variable value.
The GPG key can be imported into a gpg-agent inside the pipeline job and passed to the Salt master.
Option 2: More "cloud native"¶
The SDB interface is designed to store and retrieve data that, unlike pillars and grains, is not necessarily minion-specific. The initial design goal was to allow passwords to be stored in a secure database, such as one managed by the keyring package, rather than as plain-text files.
SDB is designed to make small database queries (hence the name, SDB) using a compact URL. This allows users to reference a database value quickly inside a number of Salt configuration areas, without a lot of overhead. The basic format of an SDB URI is: sdb://<profile>/<args>
One such module is salt.sdb.vault which allows access to Hashicorp Vault (secured storage and management system for sensitive data). Once configured the data can be accessed like:
password: sdb://myvault/secret/passwords/mypassword
To integrate Salt and Vault one need to create a vault policy and an access token for Salt. This token can be stored as a CI variable in GitLab. When presented to the vault, it will allow to query only the specified secrets (according to the policy in vault). The token can be made read-only and can be further limited by IP.
Option 3: Custom, but rare¶
The aforementioned SDB interface can be easily extended so one can write a custom SDB module. There is currently one function that MUST exist in any SDB module get()
, one that SHOULD exist set_()
and one that MAY exist delete()
. So it is entirely possible to use any other password storage (like pass
) or use another means of encrypting the secrets if GPG is not desired. More on that can be found in Extending SaltStack. The integration in GitLab in this case depends on the specific implementation, in most cases it could be done by a master password or secret key as a CI variable.
Updated by jbaier_cz over 2 years ago
- Status changed from In Progress to Feedback
It seems to me, that if we want bother ourselves with implementing a custom SDB module to suite our needs and if we do not require to have separate tokens for every developer and for the salt master; in other words if we are OK with having a single shared GPG key to encrypt/decrypt the salt variables, the option 1, as Nick already mentioned, is the way to go.
The only real challenge here is how to share that GPG key properly, however if we want to automate we need to have it somewhere anyway. As we already use different GitLab pipelines with secret variables, having one more will not hurt.