diff options
Diffstat (limited to 'ansible_collections/cyberark/conjur/plugins')
-rw-r--r-- | ansible_collections/cyberark/conjur/plugins/lookup/conjur_variable.py | 164 |
1 files changed, 126 insertions, 38 deletions
diff --git a/ansible_collections/cyberark/conjur/plugins/lookup/conjur_variable.py b/ansible_collections/cyberark/conjur/plugins/lookup/conjur_variable.py index db3d209e4..fd3bf5c28 100644 --- a/ansible_collections/cyberark/conjur/plugins/lookup/conjur_variable.py +++ b/ansible_collections/cyberark/conjur/plugins/lookup/conjur_variable.py @@ -15,9 +15,10 @@ DOCUMENTATION = """ author: - CyberArk BizDev (@cyberark-bizdev) description: - Retrieves credentials from Conjur using the controlling host's Conjur identity - or environment variables. + Retrieves credentials from Conjur using the controlling host's Conjur identity, + environment variables, or extra-vars. Environment variables could be CONJUR_ACCOUNT, CONJUR_APPLIANCE_URL, CONJUR_CERT_FILE, CONJUR_AUTHN_LOGIN, CONJUR_AUTHN_API_KEY, CONJUR_AUTHN_TOKEN_FILE + Extra-vars could be conjur_account, conjur_appliance_url, conjur_cert_file, conjur_authn_login, conjur_authn_api_key, conjur_authn_token_file Conjur info - U(https://www.conjur.org/). requirements: - 'The controlling host running Ansible has a Conjur identity. @@ -46,16 +47,6 @@ DOCUMENTATION = """ key: identity_file_path env: - name: CONJUR_IDENTITY_FILE - authn_token_file: - description: Path to the access token file. - type: path - default: /var/run/conjur/access-token - required: False - ini: - - section: conjur, - key: authn_token_file - env: - - name: CONJUR_AUTHN_TOKEN_FILE config_file: description: Path to the Conjur configuration file. The configuration file is a YAML file. type: path @@ -66,6 +57,72 @@ DOCUMENTATION = """ key: config_file_path env: - name: CONJUR_CONFIG_FILE + conjur_appliance_url: + description: Conjur appliance url + type: string + required: False + ini: + - section: conjur, + key: appliance_url + vars: + - name: conjur_appliance_url + env: + - name: CONJUR_APPLIANCE_URL + conjur_authn_login: + description: Conjur authn login + type: string + required: False + ini: + - section: conjur, + key: authn_login + vars: + - name: conjur_authn_login + env: + - name: CONJUR_AUTHN_LOGIN + conjur_account: + description: Conjur account + type: string + required: False + ini: + - section: conjur, + key: account + vars: + - name: conjur_account + env: + - name: CONJUR_ACCOUNT + conjur_authn_api_key: + description: Conjur authn api key + type: string + required: False + ini: + - section: conjur, + key: authn_api_key + vars: + - name: conjur_authn_api_key + env: + - name: CONJUR_AUTHN_API_KEY + conjur_cert_file: + description: Path to the Conjur cert file + type: path + required: False + ini: + - section: conjur, + key: cert_file + vars: + - name: conjur_cert_file + env: + - name: CONJUR_CERT_FILE + conjur_authn_token_file: + description: Path to the access token file + type: path + required: False + ini: + - section: conjur, + key: authn_token_file + vars: + - name: conjur_authn_token_file + env: + - name: CONJUR_AUTHN_TOKEN_FILE """ EXAMPLES = """ @@ -87,14 +144,13 @@ RETURN = """ import os.path import socket +import ansible.module_utils.six.moves.urllib.error as urllib_error from ansible.errors import AnsibleError from ansible.plugins.lookup import LookupBase from base64 import b64encode from netrc import netrc -from os import environ from time import sleep from ansible.module_utils.six.moves.urllib.parse import quote -from ansible.module_utils.urls import urllib_error from stat import S_IRUSR, S_IWUSR from tempfile import gettempdir, NamedTemporaryFile import yaml @@ -272,7 +328,25 @@ class LookupModule(LookupBase): elif not terms[0] or terms[0].isspace(): raise AnsibleError("Invalid secret path: empty secret path not accepted.") - self.set_options(direct=kwargs) + # We should register the variables as LookupModule options. + # + # Doing this has some nice advantages if we're considering supporting + # a set of Ansible variables that could sometimes replace environment + # variables. + # + # Registering the variables as options forces them to adhere to the + # behavior described in the DOCUMENTATION variable. An option can have + # both a Ansible variable and environment variable source, which means + # Ansible will do some juggling on our behalf. + self.set_options(var_options=variables, direct=kwargs) + + appliance_url = self.get_var_value("conjur_appliance_url") + account = self.get_var_value("conjur_account") + authn_login = self.get_var_value("conjur_authn_login") + authn_api_key = self.get_var_value("conjur_authn_api_key") + cert_file = self.get_var_value("conjur_cert_file") + authn_token_file = self.get_var_value("conjur_authn_token_file") + validate_certs = self.get_option('validate_certs') conf_file = self.get_option('config_file') as_file = self.get_option('as_file') @@ -280,53 +354,59 @@ class LookupModule(LookupBase): if validate_certs is False: display.warning('Certificate validation has been disabled. Please enable with validate_certs option.') - if 'http://' in str(environ.get("CONJUR_APPLIANCE_URL")): + if 'http://' in str(appliance_url): raise AnsibleError(('[WARNING]: Conjur URL uses insecure connection. Please consider using HTTPS.')) conf = _merge_dictionaries( _load_conf_from_file(conf_file), { - "account": environ.get('CONJUR_ACCOUNT'), - "appliance_url": environ.get("CONJUR_APPLIANCE_URL") + "account": account, + "appliance_url": appliance_url } if ( - environ.get('CONJUR_ACCOUNT') is not None - and environ.get('CONJUR_APPLIANCE_URL') is not None + account is not None + and appliance_url is not None ) else {}, { - "cert_file": environ.get('CONJUR_CERT_FILE') - } if (environ.get('CONJUR_CERT_FILE') is not None) + "cert_file": cert_file + } if (cert_file is not None) else {}, { - "authn_token_file": environ.get('CONJUR_AUTHN_TOKEN_FILE') - } if (environ.get('CONJUR_AUTHN_TOKEN_FILE') is not None) + "authn_token_file": authn_token_file + } if authn_token_file is not None else {} ) + if 'account' not in conf or 'appliance_url' not in conf: + raise AnsibleError( + """Configuration must define options `conjur_account` and `conjur_appliance_url`. + This config can be set by any of the following methods, listed in order of priority: + - Ansible variables of the same name, set either in the parent playbook or passed to + the ansible-playbook command with the --extra-vars flag + - Environment variables `CONJUR_ACCOUNT` and `CONJUR_APPLIANCE_URL` + - A configuration file on the controlling host with fields `account` and `appliance_url`""" + ) + if 'authn_token_file' not in conf: identity_file = self.get_option('identity_file') identity = _merge_dictionaries( _load_identity_from_file(identity_file, conf['appliance_url']), { - "id": environ.get('CONJUR_AUTHN_LOGIN'), - "api_key": environ.get('CONJUR_AUTHN_API_KEY') - } if (environ.get('CONJUR_AUTHN_LOGIN') is not None - and environ.get('CONJUR_AUTHN_API_KEY') is not None) + "id": authn_login, + "api_key": authn_api_key + } if authn_login is not None + and authn_api_key is not None else {} ) - if 'account' not in conf or 'appliance_url' not in conf: - raise AnsibleError( - ("Configuration file on the controlling host must " - "define `account` and `appliance_url`" - "entries or they should be environment variables") - ) - if 'id' not in identity or 'api_key' not in identity: raise AnsibleError( - ("Identity file on the controlling host must contain " - "`login` and `password` entries for Conjur appliance" - " URL or they should be environment variables") + """Configuration must define options `conjur_authn_login` and `conjur_authn_api_key`. + This config can be set by any of the following methods, listed in order of priority: + - Ansible variables of the same name, set either in the parent playbook or passed to + the ansible-playbook command with the --extra-vars flag + - Environment variables `CONJUR_AUTHN_LOGIN` and `CONJUR_AUTHN_API_KEY` + - An identity file on the controlling host with the fields `login` and `password`""" ) cert_file = None @@ -364,3 +444,11 @@ class LookupModule(LookupBase): return _store_secret_in_file(conjur_variable) return conjur_variable + + def get_var_value(self, key): + try: + variable_value = self.get_option(key) + except KeyError: + raise AnsibleError("{0} was not defined in configuration".format(key)) + + return variable_value |