Ansible
Ansible is an automation language and automation engine that lets you describe end-to-end IT application environments with a playbook. Ansible's simple, human-readable language enables orchestration of your application lifecycle no matter where it's deployed.
See Secure Ansible Playbook Secrets with Conjur to use our fully-interactive tutorial on securing Ansible automation by keeping unsecured secrets out of playbooks with Conjur open source secrets management.
How Ansible works with Conjur
Instead of all secrets moving through the Ansible Controller, each Ansible-managed remote node is responsible for using its own identity to retrieve secrets from Conjur.
Grant a Conjur identity to Ansible hosts
You can use the Ansible role to configure a host with a Conjur machine identity. Using security policies, you can grant the Ansible host least-privilege access to securely retrieve only the secrets it needs. Restricting the secrets accessible to each Ansible host reduces the administrative power of each Ansible host and prevents the hosts from becoming high-value targets. Integrating with Conjur provides additional benefits, including enabling the storage of security policy as code and simplifying secret rotation.
Install the Conjur Ansible role
To grant your Ansible host a Conjur identity, you first must install the Conjur Ansible Role in your playbook directly. We recommend you install the Conjur Ansible collection, which includes both the Conjur Ansible role and the Conjur lookup plugin.
Install Conjur Ansible collection
$ ansible-galaxy collection install cyberark.conjur
Install standalone Conjur Ansible role
$ ansible-galaxy install cyberark.conjur-host-identityCode
Configure each Ansible node
After you install the Conjur Ansible role, configure each Ansible node with a Conjur identity by adding a section to your Ansible playbook based on the following playbook example:
Example playbook for Conjur Ansible collection
- hosts: servers
roles:
- role: cyberark.conjur.conjur-host-identity
conjur_appliance_url: 'https://conjur.myorg.com',
conjur_account: 'myorg',
conjur_host_factory_token: "{{ lookup('env', 'HFTOKEN') }}",
conjur_host_name: "{{ inventory_hostname }}"
conjur_ssl_certificate: "{{ lookup('file', '/path/to/conjur.pem') }}"
conjur_validate_certs: yes
Role variables
The role requires all variables to run with an HTTPS Conjur endpoint.
|
URL of the running Conjur service |
|
Conjur account name |
|
Host Factory token for layer enrollment. This should be specified in the environment on the Ansible controlling host. |
|
Name of the host to create |
|
Public SSL certificate of the Conjur endpoint |
|
Boolean value to indicate if the Conjur endpoint should validate certificates |
|
Version of Summon to install. Default is 0.8.2. |
|
Version of Summon-Conjur provider to install. Default is 0.5.3. |
Example playbook for the standalone Conjur Ansible role
- hosts: servers
roles:
- role: cyberark.conjur-host-identity
conjur_appliance_url: 'https://conjur.myorg.com',
conjur_account: 'myorg',
conjur_host_factory_token: "{{lookup('env', 'HFTOKEN')}}",
conjur_host_name: "{{inventory_hostname}}"
Role variables
The role requires all variables to run with an HTTPS Conjur endpoint.
|
URL of the running Conjur service |
|
Conjur account name |
|
Host Factory token for layer enrollment. This should be specified in the environment on the Ansible controlling host. |
|
(Optional) Name of the host to create |
|
Public SSL certificate of the Conjur endpoint |
|
Boolean value to indicate if the Conjur endpoint should validate certificates |
|
Version of Summon to install. Default is 0.8.2. |
|
Version of Summon-Conjur provider to install. Default is 0.5.3. |
This example:
-
Registers the host with Conjur, adding it into the layer specific to the provided host factory token.
-
Installs Summon with the Summon Conjur provider for secret retrieval from Conjur.
Retrieve secrets from Conjur
Use Summon to retrieve secrets
When you configure the Ansible node with a Conjur identity using the Ansible role, you also install Summon and the Summon-Conjur Provider on the Ansible host.
With Summon installed, using Conjur with a service manager (like SystemD
) is straightforward. Here's a simple example of a SystemD
file connecting to Conjur:
[Unit]
Description=DemoApp
After=network-online.target
[Service]
User=DemoUser
#Environment=CONJUR_MAJOR_VERSION=4
ExecStart=/usr/local/bin/summon --yaml 'DB_PASSWORD: !var staging/myapp/database/password' /usr/local/bin/myapp
When connecting to Conjur 4 (Conjur Enterprise), Summon requires the environment variable CONJUR_MAJOR_VERSION
set to 4
. You can provide the variable by removing the #
from the relevant line in the above example.
The above example uses Summon to retrieve the password stored in Conjur at staging/myapp/database/password
, set it to an environment variable DB_PASSWORD
, and provide it to the demo application process. Using Summon, the secret is kept off disk. If the service is restarted, Summon retrieves the password when the application is started.
Recommendations
-
Add
no_log: true
to each play that uses sensitive data, otherwise that data can be printed to the logs. -
Set the Ansible files to minimum permissions. Ansible uses the permissions of the user that runs it.
Use the Conjur Ansible lookup plugin to retrieve credentials
The Conjur Ansible lookup plugin is included when you install the Conjur Ansible collection. This plugin enables Ansible to retrieve credentials from Conjur using the controlling host's Conjur identity or environment variables.
The controlling host running Ansible must have a Conjur identity, provided by the Conjur Ansible role.
Environment variables
The lookup plugin uses the following environment variables, if present, to authenticate with the Conjur host.
|
The Conjur account name |
|
URL of the running Conjur service |
|
Path to the Conjur certificate file |
|
A valid Conjur host username |
|
The API key that corresponds to the Conjur host username |
|
Path to a file containing a valid Conjur authentication token |
Examples
Retrieve a secret in a playbook
---
- hosts: localhost
tasks:
- name: Lookup variable in Conjur
debug:
msg: "{{ lookup('cyberark.conjur.conjur_variable', '/path/to/secret') }}"
Retrieve a private key in an inventory file
---
ansible_host: <host>
ansible_ssh_private_key_file: "{{ lookup('cyberark.conjur.conjur_variable', 'path/to/secret-id', as_file=True) }}"
Using the as_file=True
condition, the private key is stored in a temporary file and its path is written in ansible_ssh_private_key_file
.
Use the conjur_variable
lookup plugin to retrieve secrets
When you install the Conjur Ansible Collection, you also install the conjur_variable
lookup plugin. You can use the lookup plugin to retrieve secrets from Conjur using the controlling host's Conjur identity or environment variables.
In general, lookup plugins enable Ansible to access data from outside sources. They can be used in a play, in a variables file, or in a Jinja2 template for the template module.
To invoke the conjur_variable
lookup plugin:
vars:
database_url: "{{ lookup('cyberark.conjur.conjur_variable', '/path/to/secret') }}"