Ansible Plugin

A collection of Ansible plugins that interact with your Keeper account and can be used in your automations.

Installation

Due to the flexibility of Ansible, where you install the plugins depends on your Ansible installation and playbook locations.

Install Keeper Ansible Module

The Ansible module for Keeper is installed with the command below. Make note of the location where the module is installed, as this will be needed in the Ansible playbook configuration.

$ pip3 install keeper_secrets_manager_ansible

Configure Location of Plugin Modules

The Keeper ansible plugins are installed in the site-packages directory of your version of Python or your current virtual environment. You can find the plugin locations usign the following command:

$ keeper_ansible --config
# Below are the directory paths to action and lookup plugins.
ANSIBLE_ACTION_PLUGINS=...site-packages/keeper_secrets_manager_ansible/plugins/action_plugins
ANSIBLE_LOOKUP_PLUGINS=...site-packages/keeper_secrets_manager_ansible/plugins/lookup_plugins

Those paths can be used in your ansible.cfg.

[defaults]
action_plugins = ...site-packages/keeper_secrets_manager_ansible/plugins/action_plugins
lookup_plugins = ...site-packages/keeper_secrets_manager_ansible/plugins/lookup_plugins

Generate a Config File

In order to use the Ansible plugin for Keeper Secrets Manager, a Keeper "config" file is required. Once you have a config file, the configuration values can be placed into Ansible variable files. These variable files can be encrypted with Ansible vault.

Generate a One Time Access Token from the Commander interface:

My Vault> secrets-manager client add --app MyApplication
------------------------------------------------------------------
One Time Access Token: XXXXXXXXXXX
------------------------------------------------------------------

If you have not configured any devices, make sure to check out the Quick Start Guide.

Using the Keeper Ansible module, generate a Configuration file using the provided One Time Access Token. For example:

$ keeper_ansible --keeper_token XXXXXXXXXXX
Config file create at location client-config.json

This will generate the Keeper JSON configuration file in the current directory.

If you added the module directory to your PYTHONPATH, you can create a config with the following command.

$ python3 -m keeper_secrets_manager_ansible --keeper_token XXXXXX
Config file create at location client-config.json

The default name for the JSON configuration file is client-config.json. The content of the file looks like the following:

{
"appKey" : "XXXXXXXX",
"clientId": "XXXXXXXX",
"clientKey": "XXXXXXXX",
"privateKey": "XXXXXXXX"
"serverPublicKeyId": "X"
}

This config file allows your Ansible playbook to authenticate and retrieve designated secrets from the vault.

Ansible Variables

Ansible can use the client-config.json config file directly. It can be specified in the Ansible variables using the keeper_config_file variable key.

---
keeper_config_file: /path/to/client-config.json

Another solution is to place the values in your client-config.json file into an Ansible variable file. For example, the values can be placed into the group_vars, host_vars, or in the task files:

---
keeper_app_key: XXXXX
keeper_client_id: XXXXX
keeper_token: XXXXX
keeper_private_key: XXXXX

For security, the group_vars or host_vars files can be encrypted with ansible-vault.

A list of valid Ansible Variables for the Keeper plugin are below:

Ansible Variable

JSON Key

Description

keeper_config_file

--

An alternative path and name for the JSON configuration file, if not current directory or named differently than client-config.json.

keeper_token

clientKey

The one time access token, also known as the client key.

keeper_client_id

clientId

The client id provided from Secrets Manager after the one time access token is used.

keeper_app_key

appKey

The app key provided from the secret management service after the one time access token is used.

keeper_private_key

privateKey

The private key provided from the secret management service after the one time access token is used.

keeper_server_public_key_id

serverPublicKeyId

Selects which public key to use when connecting to the server. If the server wants a different public key the SDK will handle switching.

keeper_hostname

hostname

The Secrets Manager backend hostname. Defaults to US. Supports "US", "EU", "AU" and "US_GOV" values depending on your Keeper data center location.

keeper_log_level

Set the log level of the SDK. Acceptable levels are DEBUG, INFO, WARNING, ERROR, and CRITICAL. Defaults to ERROR.

Command Line Variables

As an optional method, values can be passed in through the ansible-playbook command. Example:

$ ansible-playbook my_playbook.yml \
-e "keeper_app_key=XXXXX" \
-e "keeper_client_id=XXXXX" \
-e "keeper_token=XXXXX" \
-e "keeper_private_key=XXXXX"

Ansible Plugin Usage

There are three Keeper action plugins and one lookup plugin.

For all the plugins, the following arguments are used:

  • uid - The Record UID or title of the desired record (REQUIRED).

  • field - Retrieve the value with specified label from the record.

  • custom_field - Retrieve the value with the specific custom field name.

  • file - Retrieve the file with the specified name from the record.

The uid value is required, and you need either field or file populated.

To find out what fields and custom fields are available for a specific vault secret, use the Keeper Secrets Manager CLI "ksm secret get -u XXXX" command. More info here.

Plugin: keeper_copy

The plugin keeper_copy is an extension of the built-in copy plugin. Example:

--
- name: Keeper Copy
hosts: my_hosts
tasks:
- name: Copy a password
keeper_copy:
uid: MY UID OR RECORD TITLE
field: password
dest: /tmp/my_password
mode: "0600"
- name: Copy a file
keeper_copy:
uid: MY UID OR RECORD TITLE
file: my_cert_file.crt
dest: /etc/special.crt
owner: root
group: root
mode: "0644"
backup: yes

In the first task example from above, a "password" will be copied from the Keeper vault record and stored in the file /tmp/my_password on the remote system. It will use the built-in copy plugin's mode key/value to changed the permissions of the file.

The second task example from above, the file "my_cert_file.crt" will be coped from the Keeper vault record and stored at the location "/tmp/special.crt". Several of the built-in copy plugin functions will be applied to the file.

Plugin: keeper_get

The plugin keeper_get will retrieve a field or file from a Keeper vault record. Example:

---
- name: Keeper Get
hosts: my_hosts
tasks:
- name: Get login name
keeper_get:
uid: RECORD UID OR TITLE
field: login
register: my_login
- name: Print login name
debug:
var: my_login.value
verbosity: 0
- name: Make a sudoer
copy:
dest: "/etc/sudoers.d/{{ my_login.value }}"
content: |
# Auto added by Ansible
{{ my_login.value }} ALL=(ALL:ALL) ALL

The keeper_get plugin returns a dictionary. The key "value" in the dictionary will contain the desired field or file content. This plugin is normally paired with the Ansible register instruction and the return value is stored in memory so it can be accessed by other tasks.

In the example above, the first task gets the login field from the specified Vault record UID. It is then stored under the name my_login. The second task will print the login name to your console for debug purposes. The third task will add a sudoer file for the login name with ability to execute all applications.

Plugin: keeper_set

The keeper_set plugin has the ability to write a value into an existing Keeper vault record. Example:

___
- name: Keeper Set
hosts: my_hosts
tasks:
- name: Get login name
keeper_get:
uid: RECORD UID OR TITLE
field: login
register: my_login
- name: Add new user
user:
name: "{{ my_login.value }}"
comment: "User {{ my_login.value }}"
register: new_user
- name: Update record
keeper_set:
uid: RECORD UID OR TITLE
custom_field: my_home_directory
value: "{{ new_user.home }}"

In this example, the custom field "my_home_directory" in the specified Keeper vault record is updated with the given value.

Plugin: keeper_lookup

The keeper_lookup plugin retrieves a field from the Keeper vault record and inserts the value into a text string. Example:

---
- name: Keeper Lookup
hosts: my_hosts
tasks:
- name: Print my login
debug:
msg: "My login is {{ lookup('keeper', uid='RECORD UID', field='login') }}"

When using the lookup ability of Ansible, the module is called keeper. The Record UID or Title must be supplied. The field or custom_field can be.used to retrieve an individual field or file. The lookup will then insert the content of the field or file into the text string.

To find out what fields and custom fields are available for a specific vault secret, use the Keeper Secrets Manager CLI "ksm secret get -u XXXX" command. More info here.

Ansible Vault Password Retrieval

You can use the Keeper Secret Manager CLI ("ksm") to provide the decryption password for your Ansible vaults. This is done using the ANSIBLE_VAULT_PASSWORD_FILE environment variable or the vault_password_file in the ansible.cfg field to specify an executable file that will return a password.

A executable shell script can be created that returns the password using the "ksm" secret notation (learn more about ksm secret notation). For example, the below script will output a specific secret password for the given Record UID:

#!/bin/sh
ksm secret notation keeper://XXXX/field/password

Replace XXXX with the Vault Record UID. Running this script simply outputs the secret password.

To override the environmental variable "ANSIBLE_VAULT_PASSWORD_FILE", execute the following, replacing /path/to/script with the location of the above script.

$ ANSIBLE_VAULT_PASSWORD_FILE=/path/to/script.sh ansible-playbook playbook_with_vault.yml

Now, when Ansible needs to decrypt any vaults used by playbook_with_vault.yml, it will execute that shell script. The shell script will retrieve the password from the Keeper Vault.

Logging

By default, the Ansible plugins will only display errors. If you use the Ansible verbosity level, different SDK logging will be displayed. An Ansible verbosity level of -v will display any SDK messages INFO and higher, while a verbosity level of -vvv will display any SDK messages DEBUG and higher.

Troubleshooting

__NSPlaceholderDate in progress in another thread when fork() called error.

This appears to be specific to Ansible running on MacOS. While running a playbook you may get the following error:

objc[6763]: +[__NSPlaceholderDate initialize] may have been in progress in
another thread when fork() was called. We cannot safely call it or ignore
it in the fork() child process. Crashing instead. Set a breakpoint on
objc_initializeAfterForkError to debug

This is known problem with Ansible. This can be fixed with the following environmental variable.

OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ansible-playbook ...

Missing Configuration file

TASK [Copy file from Keeper into the file] ********************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: Exception: Keeper Ansible error: There is no config file and the Ansible variable contain no config keys. Will not be able to connect to the Keeper server.
fatal: [localhost]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}