Centralizing Operational Secrets with Ansible
Centralizing Operational Secrets
Secrets are sensitive values, such as passwords, keys, and certificates, that must be shared across multiple systems—from applications to servers to build systems.
Some standard solutions to handle secrets are:
- Storing secrets within the CI/CD system: This approach stores the secrets in a secrets management solution within the CI/CD system - granting access only when performing builds and releases. Storing secrets in your CI/CD system requires any configuration be encrypted and stored in a secure location, which also risks these secrets being exposed via build logs as plaintext.
- Passworded / Encrypted Files: Stores secrets in an encrypted file is a default solution for many automation tools - for example Ansible’s Vault utilizes this approach. A major drawback is passwords are needed to decrypt these files,creating another set of challenges by needing to to protect, rotate, and share this password.
- Key Management Service (KMS): This approach connects systems to a KMS to enable safely retrieving secrets. KMSs secure the handling and management of the secrets although tend to be all-or-nothing when it comes to reading secrets, which risks exposing secrets to systems which should not have access. Keep in mind, KMS solutions require additional infrastructure and usage costs associated with them.
When asked to securely store, handle, access, and distribute secrets, existing solutions encounter problems. We want a solution that enables us to store a reference to the secret within our configuration or state files; easily distribute the secret across multiple systems and applications; restrict access to the secrets; and have the solution low cost.
To demonstrate how to solve this problem, we developed an Ansible Lookup Plugin. The Plugin stores a Basis Theory token within the Ansible configuration, allowing us to perform just-in-time lookups of the original secret value whenever we configure our systems.
Ansible Lookup Plugin
“ Ansible Lookup plugins retrieve data from outside sources, such as files, databases, key/value stores, APIs, and other services.”
The Basis Theory Ansible Lookup Plugin works against Basis Theory’s REST API to retrieve the data. Just want to dive right into the code? Check out the Ansible Lookup in our GitHub repo.
First thing we need to do is create the plugin. We do this using our Basis Theory Python SDK.
We configure the client configuration and connection:
# Defining client wide api_key
configuration = basistheory.Configuration(
host='https://api.basistheory.com',
api_key=os.environ.get('BT_API_KEY')
)
with basistheory.ApiClient(configuration) as api_client:
# Create an instance of the tokens API client
token_client = tokens_api.TokensApi(api_client)
)
Then we retrieve our tokens using the token_client with the get_by_id method.
response = token_client.get_by_id(id=term)
ret.append(response)
To use this in Ansible, we just call the lookup like any other lookup, and the simplest example is getting back a value, setting a variable, and then interpolating that variable in a file:
- name: Just in time configure local Server Fact Variable
set_fact:
my_api_key: ""
- name: Write Template File
template:
src: lookup_test.j2
dest: /tmp/lookup_test.cfg
And that’s it. With about a dozen lines of code and our Python SDK, we retrieved a secret directly from Basis Theory in our Ansible playbook.
Interested in trying Basis Theory? Simply register an account, name your first Tenant in our Web Portal, and create an application. Takes less than a minute and there’s no credit card required. Have questions? Contact us!