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.

conjur_appliance_url

URL of the running Conjur service

conjur_account

Conjur account name

conjur_host_factory_token

Host Factory token for layer enrollment. This should be specified in the environment on the Ansible controlling host.

conjur_host_name

Name of the host to create

conjur_ssl_certificate

Public SSL certificate of the Conjur endpoint

conjur_validate_certs

Boolean value to indicate if the Conjur endpoint should validate certificates

summon.version

Version of Summon to install. Default is 0.8.2.

summon_conjur.version

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.

conjur_appliance_url

URL of the running Conjur service

conjur_account

Conjur account name

conjur_host_factory_token

Host Factory token for layer enrollment. This should be specified in the environment on the Ansible controlling host.

conjur_host_name

(Optional) Name of the host to create

conjur_ssl_certificate

Public SSL certificate of the Conjur endpoint

conjur_validate_certs

Boolean value to indicate if the Conjur endpoint should validate certificates

summon.version

Version of Summon to install. Default is 0.8.2.

summon_conjur.version

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.

CONJUR_ACCOUNT

The Conjur account name

CONJUR_APPLIANCE_URL

URL of the running Conjur service

CONJUR_CERT_FILE

Path to the Conjur certificate file

CONJUR_AUTHN_LOGIN

A valid Conjur host username

CONJUR_AUTHN_API_KEY

The API key that corresponds to the Conjur host username

CONJUR_AUTHN_TOKEN_FILE

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') }}"