From 25e80762aae4373cebd171da671fa793af8424bd Mon Sep 17 00:00:00 2001 From: "RevBits, LLC" <74629760+RevBits@users.noreply.github.com> Date: Mon, 22 Nov 2021 07:49:51 -0500 Subject: [PATCH] RevBits PAM Secret Server Plugin (#3405) * RevBits PAM Secret Server Plugin * Update revbitspss.py * Update plugins/lookup/revbitspss.py Co-authored-by: Felix Fontein * Update plugins/lookup/revbitspss.py Co-authored-by: Felix Fontein * Update plugins/lookup/revbitspss.py Co-authored-by: Felix Fontein * Update plugins/lookup/revbitspss.py Co-authored-by: Felix Fontein * Update plugins/lookup/revbitspss.py Co-authored-by: Felix Fontein * Update plugins/lookup/revbitspss.py Co-authored-by: Felix Fontein * Fixes based on feedback from Ansible * Fixes for auto tests * module updated * f string changed * maintainer added * maintainer added * maintainer added * review updates * test added * test added * test added * revisions updtes * revisions updtes * revisions updtes * file removed * unit test added * suggestions updated * suggestions updated * Update plugins/lookup/revbitspss.py * Update plugins/lookup/revbitspss.py * Update plugins/lookup/revbitspss.py Co-authored-by: Felix Fontein Co-authored-by: Zubair Hassan Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> --- .github/BOTMETA.yml | 2 + plugins/lookup/revbitspss.py | 107 +++++++++++++++++++ tests/unit/plugins/lookup/test_revbitspss.py | 44 ++++++++ 3 files changed, 153 insertions(+) create mode 100644 plugins/lookup/revbitspss.py create mode 100644 tests/unit/plugins/lookup/test_revbitspss.py diff --git a/.github/BOTMETA.yml b/.github/BOTMETA.yml index 6847d690f8..caa0981958 100644 --- a/.github/BOTMETA.yml +++ b/.github/BOTMETA.yml @@ -225,6 +225,8 @@ files: maintainers: konstruktoid $lookups/redis.py: maintainers: $team_ansible_core jpmens + $lookups/revbitspss.py: + maintainers: RevBits $lookups/shelvefile.py: {} $lookups/tss.py: maintainers: amigus endlesstrax diff --git a/plugins/lookup/revbitspss.py b/plugins/lookup/revbitspss.py new file mode 100644 index 0000000000..b5be15f7a6 --- /dev/null +++ b/plugins/lookup/revbitspss.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +# Copyright: (c) 2021, RevBits +# GNU General Public License v3.0+ (see COPYING or +# https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = r""" +name: revbitspss +author: RevBits (@RevBits) +short_description: Get secrets from RevBits PAM server +version_added: 4.1.0 +description: + - Uses the revbits_ansible Python SDK to get Secrets from RevBits PAM + Server using API key authentication with the REST API. +requirements: + - revbits_ansible - U(https://pypi.org/project/revbits_ansible/) +options: + _terms: + description: + - This will be an array of keys for secrets which you want to fetch from RevBits PAM. + required: true + type: list + elements: string + base_url: + description: + - This will be the base URL of the server, for example C(https://server-url-here). + required: true + type: string + api_key: + description: + - This will be the API key for authentication. You can get it from the RevBits PAM secret manager module. + required: true + type: string +""" + +RETURN = r""" +_list: + description: + - The JSON responses which you can access with defined keys. + - If you are fetching secrets named as UUID, PASSWORD it will gives you the dict of all secrets. + type: list + elements: dict +""" + +EXAMPLES = r""" +- hosts: localhost + vars: + secret: >- + {{ + lookup( + 'community.general.revbitspss', + 'UUIDPAM', 'DB_PASS', + base_url='https://server-url-here', + api_key='API_KEY_GOES_HERE' + ) + }} + tasks: + - ansible.builtin.debug: + msg: > + UUIDPAM is {{ (secret['UUIDPAM']) }} and DB_PASS is {{ (secret['DB_PASS']) }} +""" + +from ansible.plugins.lookup import LookupBase +from ansible.utils.display import Display +from ansible.errors import AnsibleError +from ansible.module_utils.six import raise_from + +try: + from pam.revbits_ansible.server import SecretServer +except ImportError as imp_exc: + ANOTHER_LIBRARY_IMPORT_ERROR = imp_exc +else: + ANOTHER_LIBRARY_IMPORT_ERROR = None + + +display = Display() + + +class LookupModule(LookupBase): + + @staticmethod + def Client(server_parameters): + return SecretServer(**server_parameters) + + def run(self, terms, variables, **kwargs): + if ANOTHER_LIBRARY_IMPORT_ERROR: + raise_from( + AnsibleError('revbits_ansible must be installed to use this plugin'), + ANOTHER_LIBRARY_IMPORT_ERROR + ) + self.set_options(var_options=variables, direct=kwargs) + secret_server = LookupModule.Client( + { + "base_url": self.get_option('base_url'), + "api_key": self.get_option('api_key'), + } + ) + result = [] + for term in terms: + try: + display.vvv(u"Secret Server lookup of Secret with ID %s" % term) + result.append({term: secret_server.get_pam_secret(term)}) + except Exception as error: + raise AnsibleError("Secret Server lookup failure: %s" % error.message) + return result diff --git a/tests/unit/plugins/lookup/test_revbitspss.py b/tests/unit/plugins/lookup/test_revbitspss.py new file mode 100644 index 0000000000..352e61d0fa --- /dev/null +++ b/tests/unit/plugins/lookup/test_revbitspss.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright: (c) 2021, RevBits +# GNU General Public License v3.0+ (see COPYING or +# https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from ansible_collections.community.general.tests.unit.compat.unittest import TestCase +from ansible_collections.community.general.tests.unit.compat.mock import ( + patch, + MagicMock, +) +from ansible_collections.community.general.plugins.lookup import revbitspss +from ansible.plugins.loader import lookup_loader + + +class MockPamSecrets(MagicMock): + RESPONSE = 'dummy value' + + def get_pam_secret(self, path): + return self.RESPONSE + + +class TestLookupModule(TestCase): + def setUp(self): + revbitspss.ANOTHER_LIBRARY_IMPORT_ERROR = None + self.lookup = lookup_loader.get("community.general.revbitspss") + + @patch( + "ansible_collections.community.general.plugins.lookup.revbitspss.LookupModule.Client", + MockPamSecrets(), + ) + def test_get_pam_secret(self): + terms = ['dummy secret'] + variables = [] + kwargs = { + "base_url": 'https://dummy.url', + "api_key": 'dummy' + } + self.assertListEqual( + [{'dummy secret': 'dummy value'}], + self.lookup.run(terms, variables, **kwargs) + )