summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/hashi_vault/plugins/modules
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
commit7fec0b69a082aaeec72fee0612766aa42f6b1b4d (patch)
treeefb569b86ca4da888717f5433e757145fa322e08 /ansible_collections/community/hashi_vault/plugins/modules
parentReleasing progress-linux version 7.7.0+dfsg-3~progress7.99u1. (diff)
downloadansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.tar.xz
ansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.zip
Merging upstream version 9.4.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/hashi_vault/plugins/modules')
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_configure.py193
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_delete.py146
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_read.py162
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_reset.py145
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_connections_list.py176
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_create.py207
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_delete.py146
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_read.py175
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_roles_list.py173
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_rotate_root_credentials.py150
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_create.py188
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_get_credentials.py167
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_read.py171
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_rotate_credentials.py152
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_roles_list.py174
-rw-r--r--ansible_collections/community/hashi_vault/plugins/modules/vault_write.py19
16 files changed, 2540 insertions, 4 deletions
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_configure.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_configure.py
new file mode 100644
index 000000000..035f2c4f5
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_configure.py
@@ -0,0 +1,193 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_connection_configure
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Configures the database engine
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - Creates a L(new database connection for a database secrets engine,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#configuration),
+ identified by its O(engine_mount_point) in HashiCorp Vault.
+notes:
+ - The database needs to be created and available to connect before you can configure the database secrets engine using the above configure method.
+ - This module always reports C(changed) status because it cannot guarantee idempotence.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+attributes:
+ check_mode:
+ support: partial
+ details:
+ - In check mode, a sample response will be returned, but the create / update will not be performed in Hashicorp Vault.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ connection_name:
+ description: Name of the database connection.
+ type: str
+ required: True
+ plugin_name:
+ description: Plugin name used to connect to the database
+ type: str
+ required: True
+ allowed_roles:
+ description: Allowed roles
+ type: list
+ elements: str
+ required: True
+ connection_url:
+ description: Connection URL to the database
+ type: str
+ required: True
+ connection_username:
+ description: Username to connect to the database
+ type: str
+ required: True
+ connection_password:
+ description: Password to connect to the database
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Create a new Database Connection with the default mount point
+ community.hashi_vault.vault_database_connection_configure:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ connection_name: MyName
+ plugin_name: postgresql-database-plugin
+ connection_url: postgresql://{{'{{username}}'}}:{{'{{password}}'}}@postgres:5432/postgres?sslmode=disable
+ connection_username: SomeUser
+ connection_password: SomePass
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+
+- name: Create a new Database Connection with a custom mount point
+ community.hashi_vault.vault_database_connection_configure:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ connection_name: MyName
+ plugin_name: postgresql-database-plugin
+ connection_url: postgresql://{{'{{username}}'}}:{{'{{password}}'}}@postgres:5432/postgres?sslmode=disable
+ connection_username: SomeUser
+ connection_password: SomePass
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r""""""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ plugin_name=dict(type="str", required=True),
+ allowed_roles=dict(type="list", required=True, elements="str"),
+ connection_name=dict(type="str", required=True),
+ connection_url=dict(type="str", required=True),
+ connection_username=dict(type="str", required=True),
+ connection_password=dict(type="str", required=True, no_log=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ if module.check_mode is True:
+ module.exit_json(changed=True)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["plugin_name"] = module.params.get("plugin_name")
+ parameters["allowed_roles"] = module.params.get("allowed_roles")
+ parameters["connection_url"] = module.params.get("connection_url")
+ parameters["name"] = module.params.get("connection_name")
+ parameters["username"] = module.params.get("connection_username")
+ parameters["password"] = module.params.get("connection_password")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ client.secrets.database.configure(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/config/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidRequest as e:
+ module.fail_json(
+ msg="Error creating database connection ['%s/config/%s']. Please analyze the traceback for further details."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ else:
+ module.exit_json(changed=True)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_delete.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_delete.py
new file mode 100644
index 000000000..4579d15f8
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_delete.py
@@ -0,0 +1,146 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_connection_delete
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Delete a Database Connection
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - Deletes a L(Database Connection,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#delete-connection),
+ identified by its O(connection_name) from HashiCorp Vault.
+notes:
+ - This module always reports C(changed) status because it cannot guarantee idempotence.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+attributes:
+ check_mode:
+ support: partial
+ details:
+ - In check mode, a sample response will be returned, but the deletion will not be performed in Hashicorp Vault.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ connection_name:
+ description: The connection name to be deleted.
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Delete a Database Connection with the default mount point
+ community.hashi_vault.vault_database_connection_delete:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ connection_name: SomeName
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Delete a Database Connection with a custom mount point
+ community.hashi_vault.vault_database_connection_delete:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ connection_name: SomeName
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r""""""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ connection_name=dict(type="str", required=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ if module.check_mode is True:
+ module.exit_json(changed=True)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["name"] = module.params.get("connection_name")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ client.secrets.database.delete_connection(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/config/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ else:
+ module.exit_json(changed=True)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_read.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_read.py
new file mode 100644
index 000000000..4d4fdb0f5
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_read.py
@@ -0,0 +1,162 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_connection_read
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Returns the configuration settings for a O(connection_name)
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - L(Reads a Database Connection,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#read-configuration),
+ identified by its O(connection_name) from Hashcorp Vault.
+notes:
+ - This module always reports C(changed) as False as it is a read operation that doesn't modify data.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.attributes.check_mode_read_only
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ connection_name:
+ description: The connection name to be read.
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Read a Database Connection with the default mount point
+ community.hashi_vault.vault_database_connection_read:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ connection_name: SomeName
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Read a Database Connection with a custom mount point
+ community.hashi_vault.vault_database_connection_read:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r"""
+data: &data
+ description: The C(data) field of the RV(raw) result. This can also be accessed via RV(raw.data).
+ returned: success
+ type: dict
+ sample: &data_sample
+ allowed_roles: []
+ connection_details:
+ connection_url: "postgresql://{{username}}:{{password}}@postgres:5432/postgres?sslmode=disable"
+ username: "UserName"
+ password_policy": ""
+ plugin_name": "postgresql-database-plugin"
+ plugin_version": ""
+ root_credentials_rotate_statements": []
+raw:
+ description: The raw result of the operation
+ returned: success
+ type: dict
+ contains:
+ data: *data
+ sample:
+ auth: null,
+ data: *data_sample
+"""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ connection_name=dict(type="str", required=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["name"] = module.params.get("connection_name")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ raw = client.secrets.database.read_connection(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/config/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+
+ data = raw["data"]
+ module.exit_json(raw=raw, data=data, changed=False)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_reset.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_reset.py
new file mode 100644
index 000000000..858fdfc7f
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connection_reset.py
@@ -0,0 +1,145 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_connection_reset
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Closes a O(connection_name) and its underlying plugin and restarts it with the configuration stored
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - L(Resets a Database Connection,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#reset-connection).
+notes:
+ - This module always reports C(changed) status because it cannot guarantee idempotence.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+attributes:
+ check_mode:
+ support: partial
+ details:
+ - In check mode, a sample response will be returned, but the reset will not be performed in Hashicorp Vault.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ connection_name:
+ description: The connection name to be resetted.
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Reset a Database Connection with the default mount point
+ community.hashi_vault.vault_database_connection_reset:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ connection_name: SomeName
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Reset a Database Connection with a custom mount point
+ community.hashi_vault.vault_database_connection_reset:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ connection_name: SomeName
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r""""""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ connection_name=dict(type="str", required=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ if module.check_mode is True:
+ module.exit_json(changed=True)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["name"] = module.params.get("connection_name")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ client.secrets.database.reset_connection(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/reset/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ else:
+ module.exit_json(changed=True)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connections_list.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connections_list.py
new file mode 100644
index 000000000..f570947d5
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_connections_list.py
@@ -0,0 +1,176 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_connections_list
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Returns a list of available connections
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - L(List Database Connections,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#list-connections).
+notes:
+ - This module always reports C(changed) as False as it is a read operation that doesn't modify data.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.attributes.check_mode_read_only
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+"""
+
+EXAMPLES = r"""
+- name: List Database Connections with the default mount point
+ community.hashi_vault.vault_database_connections_list:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: List Database Connections with a custom mount point
+ community.hashi_vault.vault_database_connections_list:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r"""
+data:
+ description: The C(data) field of raw result. This can also be accessed via RV(raw.data).
+ returned: success
+ type: dict
+ contains: &data_contains
+ keys:
+ description: The list of database connections.
+ returned: success
+ type: list
+ elements: str
+ sample: &sample_connections ["role1", "role2", "role3"]
+ sample:
+ keys: *sample_connections
+connections:
+ description: The list of database connections or en empty list. This can also be accessed via RV(data.keys) or RV(raw.data.keys).
+ returned: success
+ type: list
+ elements: str
+ sample: *sample_connections
+raw:
+ description: The raw result of the operation.
+ returned: success
+ type: dict
+ contains:
+ data:
+ description: The data field of the API response.
+ returned: success
+ type: dict
+ contains: *data_contains
+ sample:
+ auth: null
+ data:
+ keys: *sample_connections
+ lease_duration": 0
+ lease_id: ""
+ renewable: false
+ request_id: "123456"
+ warnings: null
+ wrap_info: null
+"""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ raw = client.secrets.database.list_connections(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/config']."
+ % (engine_mount_point or "database"),
+ exception=traceback.format_exc(),
+ )
+
+ data = raw.get("data", {"keys": []})
+ connections = data["keys"]
+ module.exit_json(
+ raw=raw,
+ connections=connections,
+ data=data,
+ changed=False,
+ )
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_create.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_create.py
new file mode 100644
index 000000000..c005e27e7
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_create.py
@@ -0,0 +1,207 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_role_create
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Creates or updates a (dynamic) role definition
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - L(Creates or updates a dynamic role definition,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#create-static-role).
+notes:
+ - This module always reports C(changed) status because it cannot guarantee idempotence.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+attributes:
+ check_mode:
+ support: partial
+ details:
+ - In check mode, a sample response will be returned, but the role creation will not be performed in Hashicorp Vault.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ connection_name:
+ description: The connection name under which the role should be created.
+ type: str
+ required: True
+ role_name:
+ description: The name of the role that should be created.
+ type: str
+ required: True
+ creation_statements:
+ description: Specifies the database statements executed to create and configure a user.
+ type: list
+ required: True
+ elements: str
+ revocation_statements:
+ description: Specifies the database statements to be executed to revoke a user.
+ type: list
+ required: False
+ elements: str
+ rollback_statements:
+ description: Specifies the database statements to be executed to rollback a create operation in the event of an error.
+ type: list
+ required: False
+ elements: str
+ renew_statements:
+ description: Specifies the database statements to be executed to renew a user
+ type: list
+ required: False
+ elements: str
+ default_ttl:
+ description: Default TTL for the role.
+ type: int
+ required: False
+ default: 3600
+ max_ttl:
+ description: Max TTL for the role.
+ type: int
+ required: False
+ default: 86400
+"""
+
+EXAMPLES = r"""
+- name: Generate creation statement
+ ansible.builtin.set_fact:
+ creation_statements = [
+ "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';",
+ "GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"
+ ]
+
+- name: Create / update Role with the default mount point
+ community.hashi_vault.vault_database_role_create:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ connection_name: SomeConnection
+ role_name: SomeRole
+ db_username: '{{ db_username}}'
+ creation_statements: '{{ creation_statements }}'
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Create / update Role with a custom mount point
+ community.hashi_vault.vault_database_role_create:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ connection_name: SomeConnection
+ role_name: SomeRole
+ db_username: '{{ db_username}}'
+ creation_statements: '{{ creation_statements }}'
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r""""""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ connection_name=dict(type="str", required=True),
+ role_name=dict(type="str", required=True),
+ creation_statements=dict(type="list", required=True, elements="str"),
+ revocation_statements=dict(type="list", required=False, elements="str"),
+ rollback_statements=dict(type="list", required=False, elements="str"),
+ renew_statements=dict(type="list", required=False, elements="str"),
+ default_ttl=dict(type="int", required=False, default=3600),
+ max_ttl=dict(type="int", required=False, default=86400),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ if module.check_mode is True:
+ module.exit_json(changed=True)
+
+ parameters = {
+ "name": module.params.get("role_name"),
+ "db_name": module.params.get("connection_name"),
+ "creation_statements": module.params.get("creation_statements"),
+ "revocation_statements": module.params.get("revocation_statements"),
+ "rollback_statements": module.params.get("rollback_statements"),
+ "renew_statements": module.params.get("renew_statements"),
+ "default_ttl": module.params.get("default_ttl"),
+ "max_ttl": module.params.get("max_ttl"),
+ }
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ client.secrets.database.create_role(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/roles/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ else:
+ module.exit_json(changed=True)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_delete.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_delete.py
new file mode 100644
index 000000000..7f20e3bba
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_delete.py
@@ -0,0 +1,146 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_role_delete
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Delete a role definition
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - L(Delete a role definition,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#delete-a-role).
+notes:
+ - Applies to both static and dynamic roles.
+ - This module always reports C(changed) status because it cannot guarantee idempotence.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+attributes:
+ check_mode:
+ support: partial
+ details:
+ - In check mode, a sample response will be returned, but the deletion will not be performed in Hashicorp Vault.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ role_name:
+ description: The name of the role to rotate credentials for.
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Delete a Role with the default mount point
+ community.hashi_vault.vault_database_role_delete:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Delete a Role with a custom mount point
+ community.hashi_vault.vault_database_role_delete:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_path: db1
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r""""""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ role_name=dict(type="str", required=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ if module.check_mode is True:
+ module.exit_json(changed=True)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["name"] = module.params.get("role_name")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ client.secrets.database.delete_role(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/roles/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ else:
+ module.exit_json(changed=True)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_read.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_read.py
new file mode 100644
index 000000000..68157dce1
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_role_read.py
@@ -0,0 +1,175 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_role_read
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Queries a dynamic role definition
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - L(Queries a role definition,L(reads a static role,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#read-a-role),
+ identified by its O(role_name).
+notes:
+ - This module always reports C(changed) as False as it is a read operation that doesn't modify data.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.attributes.check_mode_read_only
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ role_name:
+ description: The role name to be read from Hashicorp Vault.
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Read Role with a default mount point
+ community.hashi_vault.vault_database_role_read:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Read Static Role with a custom moint point
+ community.hashi_vault.vault_database_role_read:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+"""
+
+RETURN = r"""
+data: &data
+ description: The C(data) field of raw result. This can also be accessed via RV(raw.data).
+ returned: success
+ type: dict
+ sample: &data_sample
+ creation_statements: [
+ "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';",
+ "GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"
+ ]
+ credential_type: "password"
+ db_name: "database"
+ default_ttl: 3600
+ max_ttl: 86400
+ renew_statements: []
+ revocation_statements: []
+ rollback_statements: []
+raw:
+ description: The raw result of the operation.
+ returned: success
+ type: dict
+ contains:
+ data: *data
+ sample:
+ auth: null
+ data: *data_sample
+ username: "SomeUser"
+ lease_duration": 0
+ lease_id: ""
+ renewable: false
+ request_id: "123456"
+ warnings: null
+ wrap_info: null
+"""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ role_name=dict(type="str", required=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["name"] = module.params.get("role_name")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ raw = client.secrets.database.read_role(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/roles/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+
+ data = raw["data"]
+
+ module.exit_json(data=data, raw=raw, changed=False)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_roles_list.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_roles_list.py
new file mode 100644
index 000000000..a0dc7e472
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_roles_list.py
@@ -0,0 +1,173 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_roles_list
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Returns a list of available (dynamic) roles
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - Returns a list of available (dynamic) roles.
+notes:
+ - This API returns a member named C(keys).
+ - In Ansible, accessing RV(data.keys) or RV(raw.data.keys) will not work because the dict object contains a method named C(keys).
+ - Instead, use RV(roles) to access the list of roles, or use the syntax C(data["keys"]) or C(raw.data["keys"]) to access the list via dict member.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.attributes.check_mode_read_only
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+"""
+
+EXAMPLES = r"""
+- name: List all roles with the default mount point
+ community.hashi_vault.vault_database_roles_list:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: List all roles with a custom mount point
+ community.hashi_vault.vault_database_roles_list:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r"""
+data:
+ description: The C(data) field of raw result. This can also be accessed via RV(raw.data).
+ returned: success
+ type: dict
+ contains: &data_contains
+ keys:
+ description: The list of dynamic role names.
+ returned: success
+ type: list
+ elements: str
+ sample: &sample_roles ["dyn_role1", "dyn_role2", "dyn_role3"]
+ sample:
+ keys: *sample_roles
+roles:
+ description: The list of dynamic roles or en empty list. This can also be accessed via RV(data.keys) or RV(raw.data.keys).
+ returned: success
+ type: list
+ elements: str
+ sample: *sample_roles
+raw:
+ description: The raw result of the operation.
+ returned: success
+ type: dict
+ contains:
+ data:
+ description: The data field of the API response.
+ returned: success
+ type: dict
+ contains: *data_contains
+ sample:
+ auth: null
+ data:
+ keys: *sample_roles
+ username: "SomeUser"
+ lease_duration": 0
+ lease_id: ""
+ renewable: false
+ request_id: "123456"
+ warnings: null
+ wrap_info: null
+"""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ raw = client.secrets.database.list_roles(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/roles']."
+ % (engine_mount_point or "database"),
+ exception=traceback.format_exc(),
+ )
+
+ data = raw.get("data", {"keys": []})
+ roles = data["keys"]
+
+ module.exit_json(data=data, roles=roles, raw=raw, changed=False)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_rotate_root_credentials.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_rotate_root_credentials.py
new file mode 100644
index 000000000..f5b58de1e
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_rotate_root_credentials.py
@@ -0,0 +1,150 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_rotate_root_credentials
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Rotates the root credentials stored for the database connection. This user must have permissions to update its own password.
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html)) >= 2.0.0
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - Trigger L(root credential rotation,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#rotate-root-credentials)
+ of a Database Connection identified by its O(connection_name).
+notes:
+ - This module always reports C(changed) status because it cannot guarantee idempotence.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+attributes:
+ check_mode:
+ support: partial
+ details:
+ - In check mode, a sample response will be returned, but the credential rotation will not be performed in Hashicorp Vault.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ connection_name:
+ description: The connection name where the root credential rotation should be triggered.
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Trigger root credentiaL rotation with the default mount point
+ community.hashi_vault.vault_database_rotate_root_credentials:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ connection_name: SomeName
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Trigger root credential rotation with the default mount point
+ community.hashi_vault.vault_database_rotate_root_credentials:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ connection_name: SomeName
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r""""""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ connection_name=dict(type="str", required=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ if module.check_mode is True:
+ module.exit_json(changed=True)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["name"] = module.params.get("connection_name")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ client.secrets.database.rotate_root_credentials(**parameters)
+ except AttributeError as e:
+ module.fail_json(
+ msg="hvac>=2.0.0 is required", exception=traceback.format_exc()
+ )
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/rotate-root/%s']"
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ else:
+ module.exit_json(changed=True)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_create.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_create.py
new file mode 100644
index 000000000..5dd57ccae
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_create.py
@@ -0,0 +1,188 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_static_role_create
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Create or update a static role
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - L(Creates a new or updates an existing static role,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#create-static-role).
+notes:
+ - This module always reports C(changed) status because it cannot guarantee idempotence.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+attributes:
+ check_mode:
+ support: partial
+ details:
+ - In check mode, a sample response will be returned, but the role creation will not be performed in Hashicorp Vault.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ connection_name:
+ description: The connection name under which the role should be created.
+ type: str
+ required: True
+ role_name:
+ description: The name of the role that should be created.
+ type: str
+ required: True
+ db_username:
+ description: The database username - Note that the user must exist in the target database!
+ type: str
+ required: True
+ rotation_statements:
+ description: SQL statements to rotate the password for the given O(db_username)
+ type: list
+ required: True
+ elements: str
+ rotation_period:
+ description: Password rotation period in seconds (defaults to 24hs)
+ type: int
+ required: False
+ default: 86400
+"""
+
+EXAMPLES = r"""
+- name: Generate rotation statement
+ ansible.builtin.set_fact:
+ rotation_statements = ["ALTER USER \"{{name}}\" WITH PASSWORD '{{password}}';"]
+
+- name: Create / update Static Role with the default mount point
+ community.hashi_vault.vault_database_static_role_create:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ connection_name: SomeConnection
+ role_name: SomeRole
+ db_username: '{{ db_username}}'
+ rotation_statements: '{{ rotation_statements }}'
+ register: response
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Create / update Static Role with a custom mount point
+ community.hashi_vault.vault_database_static_role_create:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ connection_name: SomeConnection
+ role_name: SomeRole
+ db_username: '{{ db_username}}'
+ rotation_statements: '{{ rotation_statements }}'
+ register: response
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r""""""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ connection_name=dict(type="str", required=True),
+ role_name=dict(type="str", required=True),
+ db_username=dict(type="str", required=True),
+ rotation_statements=dict(type="list", required=True, elements="str"),
+ rotation_period=dict(type="int", required=False, default=86400),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ if module.check_mode is True:
+ module.exit_json(changed=True)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["db_name"] = module.params.get("connection_name")
+ parameters["name"] = module.params.get("role_name")
+ parameters["username"] = module.params.get("db_username")
+ parameters["rotation_statements"] = module.params.get("rotation_statements")
+ rotation_period = module.params.get("rotation_period", None)
+ parameters["rotation_period"] = rotation_period
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ client.secrets.database.create_static_role(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/static-roles/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidRequest as e:
+ module.fail_json(
+ msg="Cannot update static role ['%s/static-roles/%s']. Please verify that the user exists on the database."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ else:
+ module.exit_json(changed=True)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_get_credentials.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_get_credentials.py
new file mode 100644
index 000000000..a8a5cc9cc
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_get_credentials.py
@@ -0,0 +1,167 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_static_role_get_credentials
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Returns the current credentials based on the named static role
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - Returns the
+ L(current credentials based of the named static role,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#get-static-credentials),
+ identified by its O(role_name).
+notes:
+ - This module always reports C(changed) as False as it is a read operation that doesn't modify data.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.attributes.check_mode_read_only
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ role_name:
+ description: The role name from which the credentials should be retrieved.
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Returns the current credentials based on the named static role with the default mount point
+ community.hashi_vault.vault_database_static_role_read:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Returns the current credentials based on the named static role with a custom mount point
+ community.hashi_vault.vault_database_static_role_read:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r"""
+data: &data
+ description: The C(data) field of raw result. This can also be accessed via RV(raw.data).
+ returned: success
+ type: dict
+ sample: &data_sample
+ last_vault_rotation": "2024-01-01T09:00:00+01:00"
+ password": "Th3_$3cr3t_P@ss!"
+ rotation_period": 86400
+ ttl": 123456
+ username: "SomeUser"
+raw:
+ description: The raw result of the operation.
+ returned: success
+ type: dict
+ contains:
+ data: *data
+ sample:
+ auth: null,
+ data: *data_sample
+ lease_duration: 0
+ lease_id: ""
+ renewable: false
+ request_id: "123456"
+ warnings: null,
+ wrap_info: null
+"""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ role_name=dict(type="str", required=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["name"] = module.params.get("role_name")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ raw = client.secrets.database.get_static_credentials(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point,
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/static-creds/%s']"
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+
+ data = raw["data"]
+
+ module.exit_json(data=data, raw=raw, changed=False)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_read.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_read.py
new file mode 100644
index 000000000..f2ad972b6
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_read.py
@@ -0,0 +1,171 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_static_role_read
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Queries a static role definition
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - L(Queries a static role definition,L(reads a static role,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#read-static-role),
+ - identified by its O(role_name)
+notes:
+ - This module always reports C(changed) as False as it is a read operation that doesn't modify data.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.attributes.check_mode_read_only
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ role_name:
+ description: The role name to be read from Hashicorp Vault.
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Read Static Role with a default mount point
+ community.hashi_vault.vault_database_static_role_read:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Read Static Role with a custom moint point
+ community.hashi_vault.vault_database_static_role_read:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+"""
+
+RETURN = r"""
+data: &data
+ description: The C(data) field of raw result. This can also be accessed via RV(raw.data).
+ returned: success
+ type: dict
+ sample: &data_sample
+ credential_type: "password"
+ db_name: "SomeConnection"
+ last_vault_rotation": "2024-01-01T09:00:00 +01:00"
+ rotation_period": 86400
+ rotation_statements": [
+ "ALTER USER \"{{name}}\" WITH PASSWORD '{{password}}';"
+ ]
+raw:
+ description: The raw result of the operation.
+ returned: success
+ type: dict
+ contains:
+ data: *data
+ sample:
+ auth: null
+ data: *data_sample
+ username: "SomeUser"
+ lease_duration": 0
+ lease_id: ""
+ renewable: false
+ request_id: "123456"
+ warnings: null
+ wrap_info: null
+"""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ role_name=dict(type="str", required=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["name"] = module.params.get("role_name")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ raw = client.secrets.database.read_static_role(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/static-roles/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+
+ data = raw["data"]
+
+ module.exit_json(data=data, raw=raw, changed=False)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_rotate_credentials.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_rotate_credentials.py
new file mode 100644
index 000000000..660725b0b
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_role_rotate_credentials.py
@@ -0,0 +1,152 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_static_role_rotate_credentials
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Trigger the credential rotation for a static role
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html)) >= 2.0.0
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - This endpoint is used to
+ - L(rotate the Static Role credentials,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#rotate-static-role-credentials)
+ - stored for a given role name. While Static Roles are rotated automatically by Vault at configured rotation periods,
+ - users can use this endpoint to manually trigger a rotation to change the stored password and reset the TTL of the Static Role's password.
+notes:
+ - This module always reports C(changed) status because it cannot guarantee idempotence.
+ - Use C(changed_when) to control that in cases where the operation is known to not change state.
+attributes:
+ check_mode:
+ support: partial
+ details:
+ - In check mode, a sample response will be returned, but the credential rotation will not be performed in Hashicorp Vault.
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+options:
+ role_name:
+ description: The name of the role to rotate credentials for.
+ type: str
+ required: True
+"""
+
+EXAMPLES = r"""
+- name: Rotate credentials of a static role with the default mount point
+ community.hashi_vault.vault_database_static_role_rotate_credentials:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+
+- name: Rotate credentials of a static role with a custom mount point
+ community.hashi_vault.vault_database_static_role_rotate_credentials:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ role_name: SomeRole
+ register: result
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ result }}"
+"""
+
+RETURN = r""""""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ role_name=dict(type="str", required=True),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ if module.check_mode is True:
+ module.exit_json(changed=True)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+ parameters["name"] = module.params.get("role_name")
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ raw = client.secrets.database.rotate_static_role_credentials(**parameters)
+ except AttributeError as e:
+ module.fail_json(
+ msg="hvac>=2.0.0 is required", exception=traceback.format_exc()
+ )
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/rotate-role/%s']."
+ % (engine_mount_point or "database", parameters["name"]),
+ exception=traceback.format_exc(),
+ )
+ else:
+ module.exit_json(changed=True)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_roles_list.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_roles_list.py
new file mode 100644
index 000000000..36a35337e
--- /dev/null
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_database_static_roles_list.py
@@ -0,0 +1,174 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# (c) 2024, Martin Chmielewski (@M4rt1nCh)
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: vault_database_static_roles_list
+version_added: 6.2.0
+author:
+ - Martin Chmielewski (@M4rt1nCh)
+short_description: Returns a list of available static roles
+requirements:
+ - C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/overview.html))
+ - For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
+description:
+ - L(Returns a list of available static roles,https://hvac.readthedocs.io/en/stable/usage/secrets_engines/database.html#list-static-roles).
+extends_documentation_fragment:
+ - community.hashi_vault.attributes
+ - community.hashi_vault.attributes.action_group
+ - community.hashi_vault.attributes.check_mode_read_only
+ - community.hashi_vault.connection
+ - community.hashi_vault.auth
+ - community.hashi_vault.engine_mount
+notes:
+ - This API returns a member named C(keys).
+ - In Ansible, accessing RV(data.keys) or RV(raw.data.keys) will not work because the dict object contains a method named C(keys).
+ - Instead, use RV(roles) to access the list of roles, or use the syntax C(data["keys"]) or C(raw.data["keys"]) to access the list via dict member.
+"""
+
+EXAMPLES = r"""
+- name: List static roles with the default mount point
+ community.hashi_vault.vault_database_static_roles_list:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ register: response
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ response }}"
+
+- name: List static roles with a custom mount point
+ community.hashi_vault.vault_database_static_roles_list:
+ url: https://vault:8201
+ auth_method: userpass
+ username: '{{ user }}'
+ password: '{{ passwd }}'
+ engine_mount_point: db1
+ register: response
+
+- name: Display the result of the operation
+ ansible.builtin.debug:
+ msg: "{{ response }}"
+"""
+
+RETURN = r"""
+data:
+ description: The C(data) field of raw result. This can also be accessed via RV(raw.data).
+ returned: success
+ type: dict
+ contains: &data_contains
+ keys:
+ description: The list of role names.
+ returned: success
+ type: list
+ elements: str
+ sample: &sample_roles ["role1", "role2", "role3"]
+ sample:
+ keys: *sample_roles
+roles:
+ description: The list of roles or en empty list. This can also be accessed via RV(data.keys) or RV(raw.data.keys).
+ returned: success
+ type: list
+ elements: str
+ sample: *sample_roles
+raw:
+ description: The raw result of the operation.
+ returned: success
+ type: dict
+ contains:
+ data:
+ description: The data field of the API response.
+ returned: success
+ type: dict
+ contains: *data_contains
+ sample:
+ auth: null
+ data:
+ keys: *sample_roles
+ username: "SomeUser"
+ lease_duration": 0
+ lease_id: ""
+ renewable: false
+ request_id: "123456"
+ warnings: null
+ wrap_info: null
+"""
+
+import traceback
+
+from ansible.module_utils._text import to_native
+from ansible.module_utils.basic import missing_required_lib
+
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
+
+try:
+ import hvac
+except ImportError:
+ HAS_HVAC = False
+ HVAC_IMPORT_ERROR = traceback.format_exc()
+else:
+ HVAC_IMPORT_ERROR = None
+ HAS_HVAC = True
+
+
+def run_module():
+ argspec = HashiVaultModule.generate_argspec(
+ engine_mount_point=dict(type="str", required=False),
+ )
+
+ module = HashiVaultModule(argument_spec=argspec, supports_check_mode=True)
+
+ if not HAS_HVAC:
+ module.fail_json(msg=missing_required_lib("hvac"), exception=HVAC_IMPORT_ERROR)
+
+ parameters = {}
+ engine_mount_point = module.params.get("engine_mount_point", None)
+ if engine_mount_point is not None:
+ parameters["mount_point"] = engine_mount_point
+
+ module.connection_options.process_connection_options()
+ client_args = module.connection_options.get_hvac_connection_options()
+ client = module.helper.get_vault_client(**client_args)
+
+ try:
+ module.authenticator.validate()
+ module.authenticator.authenticate(client)
+ except (NotImplementedError, HashiVaultValueError) as e:
+ module.fail_json(msg=to_native(e), exception=traceback.format_exc())
+
+ try:
+ raw = client.secrets.database.list_static_roles(**parameters)
+ except hvac.exceptions.Forbidden as e:
+ module.fail_json(
+ msg="Forbidden: Permission Denied to path ['%s']." % engine_mount_point
+ or "database",
+ exception=traceback.format_exc(),
+ )
+ except hvac.exceptions.InvalidPath as e:
+ module.fail_json(
+ msg="Invalid or missing path ['%s/static-roles']."
+ % (engine_mount_point or "database"),
+ exception=traceback.format_exc(),
+ )
+
+ data = raw.get("data", {"keys": []})
+ roles = data["keys"]
+
+ module.exit_json(data=data, roles=roles, raw=raw, changed=False)
+
+
+def main():
+ run_module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/community/hashi_vault/plugins/modules/vault_write.py b/ansible_collections/community/hashi_vault/plugins/modules/vault_write.py
index 35c7fcb60..76cf4f8e9 100644
--- a/ansible_collections/community/hashi_vault/plugins/modules/vault_write.py
+++ b/ansible_collections/community/hashi_vault/plugins/modules/vault_write.py
@@ -46,7 +46,9 @@ DOCUMENTATION = """
type: str
required: True
data:
- description: A dictionary to be serialized to JSON and then sent as the request body.
+ description:
+ - A dictionary to be serialized to JSON and then sent as the request body.
+ - If the dictionary contains keys named C(path) or C(wrap_ttl), the call will fail with C(hvac<1.2).
type: dict
required: false
default: {}
@@ -108,8 +110,8 @@ import traceback
from ansible.module_utils._text import to_native
from ansible.module_utils.basic import missing_required_lib
-from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_module import HashiVaultModule
-from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
+from ..module_utils._hashi_vault_module import HashiVaultModule
+from ..module_utils._hashi_vault_common import HashiVaultValueError
try:
import hvac
@@ -157,7 +159,16 @@ def run_module():
if module.check_mode:
response = {}
else:
- response = client.write(path=path, wrap_ttl=wrap_ttl, **data)
+ try:
+ # TODO: write_data will eventually turn back into write
+ # see: https://github.com/hvac/hvac/issues/1034
+ response = client.write_data(path=path, wrap_ttl=wrap_ttl, data=data)
+ except AttributeError:
+ # https://github.com/ansible-collections/community.hashi_vault/issues/389
+ if "path" in data or "wrap_ttl" in data:
+ module.fail_json("To use 'path' or 'wrap_ttl' as data keys, use hvac >= 1.2")
+ else:
+ response = client.write(path=path, wrap_ttl=wrap_ttl, **data)
except hvac.exceptions.Forbidden:
module.fail_json(msg="Forbidden: Permission Denied to path '%s'." % path, exception=traceback.format_exc())
except hvac.exceptions.InvalidPath: