Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lookup plugin option (file_mode) to store secret in a file #51

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- The [Conjur Ansible role](https://galaxy.ansible.com/cyberark/conjur-host-identity) has been
migrated to this collection, where it will be maintained moving forward.
[cyberark/ansible-conjur-host-identity#30](https://github.com/cyberark/ansible-conjur-host-identity/issues/30)
- Add `as_file` boolean option to store the secret as a temporary file and returns its path.
[Cyberark Commons post #1070](https://discuss.cyberarkcommons.org/t/conjur-ansible-lookup-plugin-and-ssh-key-file/1070)

## [1.0.7] - 2020-08-20

Expand Down
32 changes: 31 additions & 1 deletion plugins/lookup/conjur_variable.py
Expand Up @@ -31,6 +31,12 @@
description: Flag to control SSL certificate validation
type: boolean
default: True
as_file:
description: >
Store lookup result in a temporary file and returns the file path. Thus allowing it to be consumed as an ansible file parameter
(eg ansible_ssh_private_key_file).
type: boolean
default: False
identity_file:
description: Path to the Conjur identity file. The identity file follows the netrc file format convention.
type: path
Expand Down Expand Up @@ -88,6 +94,8 @@
from os import environ
from time import time
from ansible.module_utils.six.moves.urllib.parse import quote
from stat import S_IRUSR, S_IWUSR
from tempfile import gettempdir, NamedTemporaryFile
import yaml

from ansible.module_utils.urls import open_url
Expand Down Expand Up @@ -203,12 +211,29 @@ def _fetch_conjur_variable(conjur_variable, token, conjur_url, account, validate
return {}


def _default_tmp_path():
if os.access("/dev/shm", os.W_OK):
return "/dev/shm"

return gettempdir()


def _store_secret_in_file(value):
secrets_file = NamedTemporaryFile(mode='w', dir=_default_tmp_path(), delete=False)
os.chmod(secrets_file.name, S_IRUSR | S_IWUSR)
secrets_file.write(value[0])

return [secrets_file.name]


class LookupModule(LookupBase):

def run(self, terms, variables=None, **kwargs):
self.set_options(direct=kwargs)
validate_certs = self.get_option('validate_certs')
conf_file = self.get_option('config_file')
as_file = self.get_option('as_file')

conf = _merge_dictionaries(
_load_conf_from_file(conf_file),
{
Expand Down Expand Up @@ -277,11 +302,16 @@ def run(self, terms, variables=None, **kwargs):
with open(conf['authn_token_file'], 'rb') as f:
token = f.read()

return _fetch_conjur_variable(
conjur_variable = _fetch_conjur_variable(
terms[0],
token,
conf['appliance_url'],
conf['account'],
validate_certs,
cert_file
)

if as_file:
return _store_secret_in_file(conjur_variable)

return conjur_variable
1 change: 1 addition & 0 deletions tests/conjur_variable/policy/root.yml
Expand Up @@ -12,6 +12,7 @@

- &variables
- !variable test-secret
- !variable test-secret-in-file
- !variable var with spaces

- !permit
Expand Down
1 change: 1 addition & 0 deletions tests/conjur_variable/test.sh
Expand Up @@ -66,6 +66,7 @@ function setup_conjur {
docker-compose exec -T conjur_cli bash -c '
conjur policy load root /policy/root.yml
conjur variable values add ansible/test-secret test_secret_password
conjur variable values add ansible/test-secret-in-file test_secret_in_file_password
conjur variable values add "ansible/var with spaces" var_with_spaces_secret_password
'
}
Expand Down
@@ -0,0 +1 @@
export CONJUR_CERT_FILE=./conjur.pem
@@ -0,0 +1,14 @@
---
- name: Retrieve Conjur variable into file
hosts: localhost
connection: local
tasks:
- name: Clean artifact path
file:
state: absent
path: /conjur_secret_path.txt

- name: Retrieve Conjur variable into file using as_file option
vars:
secret_path: "{{lookup('conjur_variable', 'ansible/test-secret-in-file', as_file=True)}}"
shell: echo "{{secret_path}}" > /conjur_secret_path.txt
@@ -0,0 +1,21 @@
from __future__ import (absolute_import, division, print_function)

__metaclass__ = type

import os
import testinfra.utils.ansible_runner

testinfra_hosts = [os.environ['COMPOSE_PROJECT_NAME'] + '_ansible_1']


def test_retrieved_secret(host):
secret_path_file = host.file('/conjur_secret_path.txt')
assert secret_path_file.exists

secret_path = host.check_output("cat /conjur_secret_path.txt", shell=True)
secret_file = host.file(secret_path)
assert secret_file.exists
assert secret_file.mode == 0o600

secret = host.check_output("cat {0}".format(secret_path), shell=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jcosteatcyberark, just for my own understanding... Can you explain what this line is doing? I know it's doing a level of indirection (taking secret_path and cating the file that it points to), but I'd like to understand better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @diverdane, the test playbook stores the lookup output in /conjur_secret_path.txt. This file contains the path to the file that contains the secret (secret_path).
To resume this test asserts that cat (cat /conjur_secret_path) = secret

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since it wasn't clear to Dane from the code, is it worth writing this in a more-verbose-but-more-clear way or at least adding a code comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @izgeri I cleaned up the code and commented. It should be easier to understand now.

assert secret == "test_secret_in_file_password"