diff --git a/changelogs/fragments/9028-bitwarden-secrets-manager-syntax-fix.yml b/changelogs/fragments/9028-bitwarden-secrets-manager-syntax-fix.yml new file mode 100644 index 0000000000..d542692f45 --- /dev/null +++ b/changelogs/fragments/9028-bitwarden-secrets-manager-syntax-fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - "bitwarden lookup plugin - support BWS v0.3.0 syntax breaking change (https://github.com/ansible-collections/community.general/pull/9028)." \ No newline at end of file diff --git a/plugins/lookup/bitwarden_secrets_manager.py b/plugins/lookup/bitwarden_secrets_manager.py index 8cabc693ff..3d08067105 100644 --- a/plugins/lookup/bitwarden_secrets_manager.py +++ b/plugins/lookup/bitwarden_secrets_manager.py @@ -77,6 +77,8 @@ from ansible.module_utils.common.text.converters import to_text from ansible.parsing.ajson import AnsibleJSONDecoder from ansible.plugins.lookup import LookupBase +from ansible_collections.community.general.plugins.module_utils.version import LooseVersion + class BitwardenSecretsManagerException(AnsibleLookupError): pass @@ -114,6 +116,15 @@ class BitwardenSecretsManager(object): rc = p.wait() return to_text(out, errors='surrogate_or_strict'), to_text(err, errors='surrogate_or_strict'), rc + def get_bws_version(self): + """Get the version of the Bitwarden Secrets Manager CLI. + """ + out, err, rc = self._run(['--version']) + if rc != 0: + raise BitwardenSecretsManagerException(to_text(err)) + # strip the prefix and grab the last segment, the version number + return out.split()[-1] + def get_secret(self, secret_id, bws_access_token): """Get and return the secret with the given secret_id. """ @@ -122,10 +133,18 @@ class BitwardenSecretsManager(object): # Color output was not always disabled correctly with the default 'auto' setting so explicitly disable it. params = [ '--color', 'no', - '--access-token', bws_access_token, - 'get', 'secret', secret_id + '--access-token', bws_access_token ] + # bws version 0.3.0 introduced a breaking change in the command line syntax: + # pre-0.3.0: verb noun + # 0.3.0 and later: noun verb + bws_version = self.get_bws_version() + if LooseVersion(bws_version) < LooseVersion('0.3.0'): + params.extend(['get', 'secret', secret_id]) + else: + params.extend(['secret', 'get', secret_id]) + out, err, rc = self._run_with_retry(params) if rc != 0: raise BitwardenSecretsManagerException(to_text(err)) diff --git a/tests/unit/plugins/lookup/test_bitwarden_secrets_manager.py b/tests/unit/plugins/lookup/test_bitwarden_secrets_manager.py index aaeaf79eaf..5d2abeffa8 100644 --- a/tests/unit/plugins/lookup/test_bitwarden_secrets_manager.py +++ b/tests/unit/plugins/lookup/test_bitwarden_secrets_manager.py @@ -45,6 +45,10 @@ MOCK_SECRETS = [ class MockBitwardenSecretsManager(BitwardenSecretsManager): def _run(self, args, stdin=None): + # mock the --version call + if args[0] == "--version": + return "bws 1.0.0", "", 0 + # secret_id is the last argument passed to the bws CLI secret_id = args[-1] rc = 1