From 17ef6c54ff61400e8a6f52aed91efb600ce35d09 Mon Sep 17 00:00:00 2001 From: Pooja Gangwar Date: Fri, 18 Nov 2022 12:48:54 +0530 Subject: [PATCH 1/3] testing --- plugins/lookup/conjur_variable.py | 60 ++++++++++++------- .../plugins/lookup/test_conjur_variable.py | 32 +++++++++- 2 files changed, 69 insertions(+), 23 deletions(-) diff --git a/plugins/lookup/conjur_variable.py b/plugins/lookup/conjur_variable.py index 8b523c6c..6410b752 100644 --- a/plugins/lookup/conjur_variable.py +++ b/plugins/lookup/conjur_variable.py @@ -102,6 +102,7 @@ from ansible.module_utils.urls import open_url from ansible.utils.display import Display import ssl +from pathlib import Path display = Display() @@ -163,26 +164,6 @@ def _encode_str(input_str): return quote(input_str, safe='') -# Use credentials to retrieve temporary authorization token -def _fetch_conjur_token(conjur_url, account, username, api_key, validate_certs, cert_file): - conjur_url = '{0}/authn/{1}/{2}/authenticate'.format(conjur_url, account, _encode_str(username)) - display.vvvv('Authentication request to Conjur at: {0}, with user: {1}'.format( - conjur_url, - _encode_str(username))) - - response = open_url(conjur_url, - data=api_key, - method='POST', - validate_certs=validate_certs, - ca_path=cert_file) - code = response.getcode() - if code != 200: - raise AnsibleError('Failed to authenticate as \'{0}\' (got {1} response)' - .format(username, code)) - - return response.read() - - def retry(retries, retry_interval): """ Custom retry decorator @@ -212,6 +193,44 @@ def decorator(*args, **kwargs): return parameters_wrapper +# Use credentials to retrieve temporary authorization token +def _fetch_conjur_token(conjur_url, account, username, api_key, validate_certs, cert_file): + conjur_url = '{0}/authn/{1}/{2}/authenticate'.format(conjur_url, account, _encode_str(username)) + display.vvvv('Authentication request to Conjur at: {0}, with user: {1}'.format( + conjur_url, + _encode_str(username))) + + response = open_url(conjur_url, + data=api_key, + method='POST', + validate_certs=validate_certs, + ca_path=cert_file) + code = response.getcode() + if response.getcode() == 200: + display.vvvv('Conjur token was successfully retrieved and authorized with {0} code and {1} username '.format(code, username)) + return response.read() + if response.getcode() == 401: + raise AnsibleError('Conjur request has invalid authorization credentials as {0} and {1} response'.format(code, username)) + if response.getcode() == 403: + raise AnsibleError('The controlling host\'s Conjur identity does not have authorization as \'{0}\' (got {1} response)' + .format(username, code)) + if response.getcode() == 404: + raise AnsibleError('The token does not exist with {0} response '.format(code)) + if response.getcode() == 500: + raise AnsibleError('Internal Server Error with {0} response'.format(code)) + + return response.read() + + +@retry(retries=5, retry_interval=10) +def _open_url(conjur_url, api_key=None, method=None, validate_certs=True, cert_file=None): + return open_url(conjur_url, + data=api_key, + method=method, + validate_certs=validate_certs, + ca_path=cert_file) + + @retry(retries=5, retry_interval=10) def _repeat_open_url(url, headers=None, method=None, validate_certs=True, ca_path=None): return open_url(url, @@ -351,7 +370,6 @@ def run(self, terms, variables=None, **kwargs): .format(conf['authn_token_file'])) with open(conf['authn_token_file'], 'rb') as f: token = f.read() - conjur_variable = _fetch_conjur_variable( terms[0], token, diff --git a/tests/unit/plugins/lookup/test_conjur_variable.py b/tests/unit/plugins/lookup/test_conjur_variable.py index 7a0db1e1..6c87b0a8 100644 --- a/tests/unit/plugins/lookup/test_conjur_variable.py +++ b/tests/unit/plugins/lookup/test_conjur_variable.py @@ -51,6 +51,34 @@ def test_fetch_conjur_token(self, mock_open_url): ca_path="cert_file") self.assertEquals("response body", result) + @patch('ansible_collections.cyberark.conjur.plugins.lookup.conjur_variable.open_url') + def test_fetch_conjur_token_401(self, mock_open_url): + mock_response = MagicMock() + mock_response.getcode.return_value == 401 + mock_response.read.return_value = "Conjur request has invalid authorization credentials" + mock_open_url.return_value = mock_response + result = _fetch_conjur_token("url", "account", "username1", "api_key", True, "cert_file") + mock_open_url.assert_called_with("url/authn/account/username1/authenticate", + data="api_key", + method="POST", + validate_certs=True, + ca_path="cert_file") + self.assertEquals("Conjur request has invalid authorization credentials", result) + + @patch('ansible_collections.cyberark.conjur.plugins.lookup.conjur_variable.open_url') + def test_fetch_conjur_token_500(self, mock_open_url): + mock_response = MagicMock() + mock_response.getcode.return_value == 500 + mock_response.read.return_value = "Internal Server Error" + mock_open_url.return_value = mock_response + result = _fetch_conjur_token("url", "account", "username1", "api_key", True, "cert_file") + mock_open_url.assert_called_with("url/authn/account/username1/authenticate", + data="api_key", + method="POST", + validate_certs=True, + ca_path="cert_file") + self.assertEquals("Internal Server Error", result) + @patch('ansible_collections.cyberark.conjur.plugins.lookup.conjur_variable._repeat_open_url') def test_fetch_conjur_variable(self, mock_repeat_open_url): mock_response = MagicMock() @@ -69,7 +97,7 @@ def test_fetch_conjur_variable(self, mock_repeat_open_url): @patch('ansible_collections.cyberark.conjur.plugins.lookup.conjur_variable._fetch_conjur_token') @patch('ansible_collections.cyberark.conjur.plugins.lookup.conjur_variable._merge_dictionaries') def test_run(self, mock_merge_dictionaries, mock_fetch_conjur_token, mock_fetch_conjur_variable): - mock_fetch_conjur_token.return_value = "token" + mock_fetch_conjur_token.return_value = b'token' mock_fetch_conjur_variable.return_value = ["conjur_variable"] mock_merge_dictionaries.side_effect = [ {'account': 'fakeaccount', 'appliance_url': 'https://conjur-fake', 'cert_file': './conjurfake.pem'}, @@ -86,7 +114,7 @@ def test_run(self, mock_merge_dictionaries, mock_fetch_conjur_token, mock_fetch_ @patch('ansible_collections.cyberark.conjur.plugins.lookup.conjur_variable._fetch_conjur_token') @patch('ansible_collections.cyberark.conjur.plugins.lookup.conjur_variable._merge_dictionaries') def test_retrieve_to_file(self, mock_merge_dictionaries, mock_fetch_conjur_token, mock_fetch_conjur_variable): - mock_fetch_conjur_token.return_value = "token" + mock_fetch_conjur_token.return_value = b'token' mock_fetch_conjur_variable.return_value = ["conjur_variable"] mock_merge_dictionaries.side_effect = [ {'account': 'fakeaccount', 'appliance_url': 'https://conjur-fake', 'cert_file': './conjurfake.pem'}, From 889eb245306024fb526a7e6606f8f5841a8f8940 Mon Sep 17 00:00:00 2001 From: Pooja Gangwar Date: Fri, 18 Nov 2022 12:53:04 +0530 Subject: [PATCH 2/3] testing --- .github/workflows/ansible-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 27d35235..2693e6f5 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -34,7 +34,7 @@ jobs: - stable-2.10 - stable-2.11 - stable-2.12 - - devel + # - devel python: - 3.9 runs-on: ubuntu-latest From 6bc6bcb472a912b9b5f36e52f97169b5246be46f Mon Sep 17 00:00:00 2001 From: Pooja Gangwar <56577577+Pooja-Gangwar@users.noreply.github.com> Date: Tue, 20 Dec 2022 15:32:13 +0530 Subject: [PATCH 3/3] Update conjur_variable.py --- plugins/lookup/conjur_variable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/lookup/conjur_variable.py b/plugins/lookup/conjur_variable.py index 6410b752..cec858c4 100644 --- a/plugins/lookup/conjur_variable.py +++ b/plugins/lookup/conjur_variable.py @@ -129,7 +129,7 @@ def _load_identity_from_file(identity_path, appliance_url): if not os.path.exists(identity_path): return {} # raise AnsibleError('Conjur identity file `{0}` was not found on the controlling host' - # .format(identity_path)) + # .format(identity_path)) display.vvvv('Loading identity from: {0} for {1}'.format(identity_path, appliance_url))