Init: mediaserver

This commit is contained in:
2023-02-08 12:13:28 +01:00
parent 848bc9739c
commit f7c23d4ba9
31914 changed files with 6175775 additions and 0 deletions

View File

@@ -0,0 +1,573 @@
===================================
community.hashi_vault Release Notes
===================================
.. contents:: Topics
v4.1.0
======
Release Summary
---------------
This release brings new generic ``vault_list`` plugins from a new contributor!
There are also some deprecation notices for the next major version, and some updates to documentation attributes.
Deprecated Features
-------------------
- ansible-core - support for ``ansible-core`` versions ``2.11`` and ``2.12`` will be dropped in collection version ``5.0.0``, making ``2.13`` the minimum supported version of ``ansible-core`` (https://github.com/ansible-collections/community.hashi_vault/issues/340).
- hvac - the minimum version of ``hvac`` to be supported in collection version ``5.0.0`` will be at least ``1.0.2``; this minimum may be raised before ``5.0.0`` is released, so please subscribe to the linked issue and look out for new notices in the changelog (https://github.com/ansible-collections/community.hashi_vault/issues/324).
New Plugins
-----------
Lookup
~~~~~~
- vault_list - Perform a list operation against HashiCorp Vault
New Modules
-----------
- vault_list - Perform a list operation against HashiCorp Vault
v4.0.0
======
Release Summary
---------------
The next major version of the collection includes previously announced breaking changes to some default values, and improvements to module documentation with attributes that describe the use of action groups and check mode support.
Minor Changes
-------------
- modules - all modules now document their action group and support for check mode in their attributes documentation (https://github.com/ansible-collections/community.hashi_vault/issues/197).
Breaking Changes / Porting Guide
--------------------------------
- auth - the default value for ``token_validate`` has changed from ``true`` to ``false``, as previously announced (https://github.com/ansible-collections/community.hashi_vault/issues/248).
- vault_kv2_get lookup - as previously announced, the default value for ``engine_mount_point`` in the ``vault_kv2_get`` lookup has changed from ``kv`` to ``secret`` (https://github.com/ansible-collections/community.hashi_vault/issues/279).
v3.4.0
======
Release Summary
---------------
This release includes a new module, fixes (another) ``requests`` header issue, and updates some inaccurate documentation.
This is the last planned release before v4.0.0.
Minor Changes
-------------
- vault_pki_generate_certificate - the documentation has been updated to match the argspec for the default values of options ``alt_names``, ``ip_sans``, ``other_sans``, and ``uri_sans`` (https://github.com/ansible-collections/community.hashi_vault/pull/318).
Bugfixes
--------
- connection options - the ``namespace`` connection option will be forced into a string to ensure cmpatibility with recent ``requests`` versions (https://github.com/ansible-collections/community.hashi_vault/issues/309).
New Modules
-----------
- vault_kv2_delete - Delete one or more versions of a secret from HashiCorp Vault's KV version 2 secret store
v3.3.1
======
Release Summary
---------------
No functional changes in this release, this provides updated filter documentation for the public docsite.
v3.3.0
======
Release Summary
---------------
With the release of ``hvac`` version ``1.0.0``, we needed to update ``vault_token_create``'s support for orphan tokens.
The collection's changelog is now viewable in the Ansible documentation site.
Minor Changes
-------------
- vault_token_create - creation or orphan tokens uses ``hvac``'s new v1 method for creating orphans, or falls back to the v0 method if needed (https://github.com/ansible-collections/community.hashi_vault/issues/301).
v3.2.0
======
Release Summary
---------------
This release brings support for the ``azure`` auth method, adds ``412`` to the default list of HTTP status codes to be retried, and fixes a bug that causes failures in token auth with ``requests>=2.28.0``.
Minor Changes
-------------
- community.hashi_vault collection - add support for ``azure`` auth method, for Azure service principal, managed identity, or plain JWT access token (https://github.com/ansible-collections/community.hashi_vault/issues/293).
- community.hashi_vault retries - `HTTP status code 412 <https://www.vaultproject.io/api-docs#412>`__ has been added to the default list of codes to be retried, for the new `Server Side Consistent Token feature <https://www.vaultproject.io/docs/faq/ssct#q-is-there-anything-else-i-need-to-consider-to-achieve-consistency-besides-upgrading-to-vault-1-10>`__ in Vault Enterprise (https://github.com/ansible-collections/community.hashi_vault/issues/290).
Bugfixes
--------
- community.hashi_vault plugins - tokens will be cast to a string type before being sent to ``hvac`` to prevent errors in ``requests`` when values are ``AnsibleUnsafe`` (https://github.com/ansible-collections/community.hashi_vault/issues/289).
- modules - fix a "variable used before assignment" that cannot be reached but causes sanity test failures (https://github.com/ansible-collections/community.hashi_vault/issues/296).
v3.1.0
======
Release Summary
---------------
A default value that was set incorrectly will be corrected in ``4.0.0``.
A deprecation warning will be shown until then if the value is not specified explicitly.
This version also includes some fixes and improvements to the licensing in the collection, which does not affect any functionality.
Deprecated Features
-------------------
- vault_kv2_get lookup - the ``engine_mount_point option`` in the ``vault_kv2_get`` lookup only will change its default from ``kv`` to ``secret`` in community.hashi_vault version 4.0.0 (https://github.com/ansible-collections/community.hashi_vault/issues/279).
Bugfixes
--------
- Add SPDX license headers to individual files (https://github.com/ansible-collections/community.hashi_vault/pull/282).
- Add missing ``BSD-2-Clause.txt`` file for BSD licensed content (https://github.com/ansible-collections/community.hashi_vault/issues/275).
- Use the correct GPL license for plugin_utils (https://github.com/ansible-collections/community.hashi_vault/issues/276).
v3.0.0
======
Release Summary
---------------
Version 3.0.0 of ``community.hashi_vault`` drops support for Ansible 2.9 and ansible-base 2.10.
Several deprecated features have been removed. See the changelog for the full list.
Deprecated Features
-------------------
- token_validate options - the shared auth option ``token_validate`` will change its default from ``true`` to ``false`` in community.hashi_vault version 4.0.0. The ``vault_login`` lookup and module will keep the default value of ``true`` (https://github.com/ansible-collections/community.hashi_vault/issues/248).
Removed Features (previously deprecated)
----------------------------------------
- aws_iam auth - the deprecated alias ``aws_iam_login`` for the ``aws_iam`` value of the ``auth_method`` option has been removed (https://github.com/ansible-collections/community.hashi_vault/issues/194).
- community.hashi_vault collection - support for Ansible 2.9 and ansible-base 2.10 has been removed (https://github.com/ansible-collections/community.hashi_vault/issues/189).
- hashi_vault lookup - the deprecated ``[lookup_hashi_vault]`` INI config section has been removed in favor of the collection-wide ``[hashi_vault_collection]`` section (https://github.com/ansible-collections/community.hashi_vault/issues/179).
v2.5.0
======
Release Summary
---------------
This release finally contains dedicated KV plugins and modules, and an exciting new lookup to help use plugin values in module calls.
With that, we also have a guide in the collection docsite for migrating away from the ``hashi_vault`` lookup toward dedicated content.
We are also announcing that the ``token_validate`` option will change its default value in version 4.0.0.
This is the last planned release before 3.0.0. See the porting guide for breaking changes and removed features in the next version.
Minor Changes
-------------
- vault_login module & lookup - no friendly error message was given when ``hvac`` was missing (https://github.com/ansible-collections/community.hashi_vault/issues/257).
- vault_pki_certificate - add ``vault_pki_certificate`` to the ``community.hashi_vault.vault`` action group (https://github.com/ansible-collections/community.hashi_vault/issues/251).
- vault_read module & lookup - no friendly error message was given when ``hvac`` was missing (https://github.com/ansible-collections/community.hashi_vault/issues/257).
- vault_token_create - add ``vault_token_create`` to the ``community.hashi_vault.vault`` action group (https://github.com/ansible-collections/community.hashi_vault/issues/251).
- vault_token_create module & lookup - no friendly error message was given when ``hvac`` was missing (https://github.com/ansible-collections/community.hashi_vault/issues/257).
- vault_write - add ``vault_write`` to the ``community.hashi_vault.vault`` action group (https://github.com/ansible-collections/community.hashi_vault/issues/251).
Deprecated Features
-------------------
- token_validate options - the shared auth option ``token_validate`` will change its default from ``True`` to ``False`` in community.hashi_vault version 4.0.0. The ``vault_login`` lookup and module will keep the default value of ``True`` (https://github.com/ansible-collections/community.hashi_vault/issues/248).
New Plugins
-----------
Lookup
~~~~~~
- vault_ansible_settings - Returns plugin settings (options)
- vault_kv1_get - Get a secret from HashiCorp Vault's KV version 1 secret store
- vault_kv2_get - Get a secret from HashiCorp Vault's KV version 2 secret store
New Modules
-----------
- vault_kv1_get - Get a secret from HashiCorp Vault's KV version 1 secret store
- vault_kv2_get - Get a secret from HashiCorp Vault's KV version 2 secret store
v2.4.0
======
Release Summary
---------------
Our first content for writing to Vault is now live.
New Plugins
-----------
Lookup
~~~~~~
- vault_write - Perform a write operation against HashiCorp Vault
New Modules
-----------
- vault_write - Perform a write operation against HashiCorp Vault
v2.3.0
======
Release Summary
---------------
This release contains new plugins and modules for creating tokens and for generating certificates with Vault's PKI secrets engine.
New Plugins
-----------
Lookup
~~~~~~
- vault_token_create - Create a HashiCorp Vault token
New Modules
-----------
- vault_pki_generate_certificate - Generates a new set of credentials (private key and certificate) using HashiCorp Vault PKI
- vault_token_create - Create a HashiCorp Vault token
v2.2.0
======
Release Summary
---------------
This release contains a new lookup/module combo for logging in to Vault, and includes our first filter plugin.
Minor Changes
-------------
- The Filter guide has been added to the collection's docsite.
New Plugins
-----------
Filter
~~~~~~
- vault_login_token - Extracts the client token from a Vault login response
Lookup
~~~~~~
- vault_login - Perform a login operation against HashiCorp Vault
New Modules
-----------
- vault_login - Perform a login operation against HashiCorp Vault
v2.1.0
======
Release Summary
---------------
The most important change in this release is renaming the ``aws_iam_login`` auth method to ``aws_iam`` and deprecating the old name. This release also announces the deprecation of Ansible 2.9 and ansible-base 2.10 support in 3.0.0.
Deprecated Features
-------------------
- Support for Ansible 2.9 and ansible-base 2.10 is deprecated, and will be removed in the next major release (community.hashi_vault 3.0.0) next spring (https://github.com/ansible-community/community-topics/issues/50, https://github.com/ansible-collections/community.hashi_vault/issues/189).
- aws_iam_login auth method - the ``aws_iam_login`` method has been renamed to ``aws_iam``. The old name will be removed in collection version ``3.0.0``. Until then both names will work, and a warning will be displayed when using the old name (https://github.com/ansible-collections/community.hashi_vault/pull/193).
Removed Features (previously deprecated)
----------------------------------------
- the "legacy" integration test setup has been removed; this does not affect end users and is only relevant to contributors (https://github.com/ansible-collections/community.hashi_vault/pull/191).
v2.0.0
======
Release Summary
---------------
Version 2.0.0 of the collection drops support for Python 2 & Python 3.5, making Python 3.6 the minimum supported version.
Some deprecated features and settings have been removed as well.
Breaking Changes / Porting Guide
--------------------------------
- connection options - there is no longer a default value for the ``url`` option (the Vault address), so a value must be supplied (https://github.com/ansible-collections/community.hashi_vault/issues/83).
Removed Features (previously deprecated)
----------------------------------------
- drop support for Python 2 and Python 3.5 (https://github.com/ansible-collections/community.hashi_vault/issues/81).
- support for the following deprecated environment variables has been removed: ``VAULT_AUTH_METHOD``, ``VAULT_TOKEN_PATH``, ``VAULT_TOKEN_FILE``, ``VAULT_ROLE_ID``, ``VAULT_SECRET_ID`` (https://github.com/ansible-collections/community.hashi_vault/pull/173).
v1.5.0
======
Release Summary
---------------
This release includes a new action group for use with ``module_defaults``, and additional ways of specifying the ``mount_point`` option for plugins.
This will be the last ``1.x`` release.
Minor Changes
-------------
- add the ``community.hashi_vault.vault`` action group (https://github.com/ansible-collections/community.hashi_vault/pull/172).
- auth methods - Add support for configuring the ``mount_point`` auth method option in plugins via the ``ANSIBLE_HASHI_VAULT_MOUNT_POINT`` environment variable, ``ansible_hashi_vault_mount_point`` ansible variable, or ``mount_point`` INI section (https://github.com/ansible-collections/community.hashi_vault/pull/171).
v1.4.1
======
Release Summary
---------------
This release contains a bugfix for ``aws_iam_login`` authentication.
Bugfixes
--------
- aws_iam_login auth method - fix incorrect use of ``boto3``/``botocore`` that prevented proper loading of AWS IAM role credentials (https://github.com/ansible-collections/community.hashi_vault/issues/167).
v1.4.0
======
Release Summary
---------------
This release includes bugfixes, a new auth method (``cert``), and the first new content since the collection's formation, the ``vault_read`` module and lookup plugin.
We're also announcing the deprecation of the ``[lookup_hashi_vault]`` INI section (which will continue working up until its removal only for the ``hashi_vault`` lookup), to be replaced by the ``[hashi_vault_collection]`` section that will apply to all plugins in the collection.
Minor Changes
-------------
- community.hashi_vault collection - add cert auth method (https://github.com/ansible-collections/community.hashi_vault/pull/159).
Deprecated Features
-------------------
- lookup hashi_vault - the ``[lookup_hashi_vault]`` section in the ``ansible.cfg`` file is deprecated and will be removed in collection version ``3.0.0``. Instead, the section ``[hashi_vault_collection]`` can be used, which will apply to all plugins in the collection going forward (https://github.com/ansible-collections/community.hashi_vault/pull/144).
Bugfixes
--------
- aws_iam_login auth - the ``aws_security_token`` option was not used, causing assumed role credentials to fail (https://github.com/ansible-collections/community.hashi_vault/issues/160).
- hashi_vault collection - a fallback import supporting the ``retries`` option for ``urllib3`` via ``requests.packages.urllib3`` was not correctly formed (https://github.com/ansible-collections/community.hashi_vault/issues/116).
- hashi_vault collection - unhandled exception with ``token`` auth when ``token_file`` exists but is a directory (https://github.com/ansible-collections/community.hashi_vault/issues/152).
New Plugins
-----------
Lookup
~~~~~~
- vault_read - Perform a read operation against HashiCorp Vault
New Modules
-----------
- vault_read - Perform a read operation against HashiCorp Vault
v1.3.2
======
Release Summary
---------------
This release adds requirements detection support for Ansible Execution Environments. It also updates and adds new guides in our `collection docsite <https://docs.ansible.com/ansible/devel/collections/community/hashi_vault>`_.
This release also announces the dropping of Python 3.5 support in version ``2.0.0`` of the collection, alongside the previous announcement dropping Python 2.x in ``2.0.0``.
Minor Changes
-------------
- hashi_vault collection - add ``execution-environment.yml`` and a python requirements file to better support ``ansible-builder`` (https://github.com/ansible-collections/community.hashi_vault/pull/105).
Deprecated Features
-------------------
- hashi_vault collection - support for Python 3.5 will be dropped in version ``2.0.0`` of ``community.hashi_vault`` (https://github.com/ansible-collections/community.hashi_vault/issues/81).
v1.3.1
======
Release Summary
---------------
This release fixes an error in the documentation. No functionality is changed so it's not necessary to upgrade from ``1.3.0``.
v1.3.0
======
Release Summary
---------------
This release adds two connection-based options for controlling timeouts and retrying failed Vault requests.
Minor Changes
-------------
- hashi_vault lookup - add ``retries`` and ``retry_action`` to enable built-in retry on failure (https://github.com/ansible-collections/community.hashi_vault/pull/71).
- hashi_vault lookup - add ``timeout`` option to control connection timeouts (https://github.com/ansible-collections/community.hashi_vault/pull/100).
v1.2.0
======
Release Summary
---------------
This release brings several new ways of accessing options, like using Ansible vars, and addng new environment variables and INI config entries.
A special ``none`` auth type is also added, for working with certain Vault Agent configurations.
This release also announces the deprecation of Python 2 support in version ``2.0.0`` of the collection.
Minor Changes
-------------
- hashi_vault lookup - add ``ANSIBLE_HASHI_VAULT_CA_CERT`` env var (with ``VAULT_CACERT`` low-precedence fallback) for ``ca_cert`` option (https://github.com/ansible-collections/community.hashi_vault/pull/97).
- hashi_vault lookup - add ``ANSIBLE_HASHI_VAULT_PASSWORD`` env var and ``ansible_hashi_vault_password`` ansible var for ``password`` option (https://github.com/ansible-collections/community.hashi_vault/pull/96).
- hashi_vault lookup - add ``ANSIBLE_HASHI_VAULT_USERNAME`` env var and ``ansible_hashi_vault_username`` ansible var for ``username`` option (https://github.com/ansible-collections/community.hashi_vault/pull/96).
- hashi_vault lookup - add ``ansible_hashi_vault_auth_method`` Ansible vars entry to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_ca_cert`` ansible var for ``ca_cert`` option (https://github.com/ansible-collections/community.hashi_vault/pull/97).
- hashi_vault lookup - add ``ansible_hashi_vault_namespace`` Ansible vars entry to the ``namespace`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_proxies`` Ansible vars entry to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_role_id`` Ansible vars entry to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_secret_id`` Ansible vars entry to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_token_file`` Ansible vars entry to the ``token_file`` option (https://github.com/ansible-collections/community.hashi_vault/pull/95).
- hashi_vault lookup - add ``ansible_hashi_vault_token_path`` Ansible vars entry to the ``token_path`` option (https://github.com/ansible-collections/community.hashi_vault/pull/95).
- hashi_vault lookup - add ``ansible_hashi_vault_token_validate`` Ansible vars entry to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_token`` Ansible vars entry to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_url`` and ``ansible_hashi_vault_addr`` Ansible vars entries to the ``url`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_validate_certs`` Ansible vars entry to the ``validate_certs`` option (https://github.com/ansible-collections/community.hashi_vault/pull/95).
- hashi_vault lookup - add ``ca_cert`` INI config file key ``ca_cert`` option (https://github.com/ansible-collections/community.hashi_vault/pull/97).
- hashi_vault lookup - add ``none`` auth type which allows for passive auth via a Vault agent (https://github.com/ansible-collections/community.hashi_vault/pull/80).
Deprecated Features
-------------------
- hashi_vault collection - support for Python 2 will be dropped in version ``2.0.0`` of ``community.hashi_vault`` (https://github.com/ansible-collections/community.hashi_vault/issues/81).
v1.1.3
======
Release Summary
---------------
This release fixes a bug with ``userpass`` authentication and ``hvac`` versions 0.9.6 and higher.
Bugfixes
--------
- hashi_vault - userpass authentication did not work with hvac 0.9.6 or higher (https://github.com/ansible-collections/community.hashi_vault/pull/68).
v1.1.2
======
Release Summary
---------------
This release contains the same functionality as 1.1.1. The only change is to mark some code as internal to the collection. If you are already using 1.1.1 as an end user you do not need to update.
v1.1.1
======
Release Summary
---------------
This bugfix release restores the use of the ``VAULT_ADDR`` environment variable for setting the ``url`` option.
See the PR linked from the changelog entry for details and workarounds if you cannot upgrade.
Bugfixes
--------
- hashi_vault - restore use of ``VAULT_ADDR`` environment variable as a low preference env var (https://github.com/ansible-collections/community.hashi_vault/pull/61).
v1.1.0
======
Release Summary
---------------
This release contains a new ``proxies`` option for the ``hashi_vault`` lookup.
Minor Changes
-------------
- hashi_vault - add ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/50).
v1.0.0
======
Release Summary
---------------
Our first major release contains a single breaking change that will affect only a small subset of users. No functionality is removed. See the details in the changelog to determine if you're affected and if so how to transition to remediate.
Breaking Changes / Porting Guide
--------------------------------
- hashi_vault - the ``VAULT_ADDR`` environment variable is now checked last for the ``url`` parameter. For details on which use cases are impacted, see (https://github.com/ansible-collections/community.hashi_vault/issues/8).
v0.2.0
======
Release Summary
---------------
Several backwards-compatible bugfixes and enhancements in this release.
Some environment variables are deprecated and have standardized replacements.
Minor Changes
-------------
- Add optional ``aws_iam_server_id`` parameter as the value for ``X-Vault-AWS-IAM-Server-ID`` header (https://github.com/ansible-collections/community.hashi_vault/pull/27).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_ADDR`` environment variable added for option ``url`` (https://github.com/ansible-collections/community.hashi_vault/issues/8).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_AUTH_METHOD`` environment variable added for option ``auth_method`` (https://github.com/ansible-collections/community.hashi_vault/issues/17).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_ROLE_ID`` environment variable added for option ``role_id`` (https://github.com/ansible-collections/community.hashi_vault/issues/20).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_SECRET_ID`` environment variable added for option ``secret_id`` (https://github.com/ansible-collections/community.hashi_vault/issues/20).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_TOKEN_FILE`` environment variable added for option ``token_file`` (https://github.com/ansible-collections/community.hashi_vault/issues/15).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_TOKEN_PATH`` environment variable added for option ``token_path`` (https://github.com/ansible-collections/community.hashi_vault/issues/15).
- hashi_vault - ``namespace`` parameter can be specified in INI or via env vars ``ANSIBLE_HASHI_VAULT_NAMESPACE`` (new) and ``VAULT_NAMESPACE`` (lower preference) (https://github.com/ansible-collections/community.hashi_vault/issues/14).
- hashi_vault - ``token`` parameter can now be specified via ``ANSIBLE_HASHI_VAULT_TOKEN`` as well as via ``VAULT_TOKEN`` (the latter with lower preference) (https://github.com/ansible-collections/community.hashi_vault/issues/16).
- hashi_vault - add ``token_validate`` option to control token validation (https://github.com/ansible-collections/community.hashi_vault/pull/24).
- hashi_vault - uses new AppRole method in hvac 0.10.6 with fallback to deprecated method with warning (https://github.com/ansible-collections/community.hashi_vault/pull/33).
Deprecated Features
-------------------
- hashi_vault - ``VAULT_ADDR`` environment variable for option ``url`` will have its precedence lowered in 1.0.0; use ``ANSIBLE_HASHI_VAULT_ADDR`` to intentionally override a config value (https://github.com/ansible-collections/community.hashi_vault/issues/8).
- hashi_vault - ``VAULT_AUTH_METHOD`` environment variable for option ``auth_method`` will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_AUTH_METHOD`` instead (https://github.com/ansible-collections/community.hashi_vault/issues/17).
- hashi_vault - ``VAULT_ROLE_ID`` environment variable for option ``role_id`` will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_ROLE_ID`` instead (https://github.com/ansible-collections/community.hashi_vault/issues/20).
- hashi_vault - ``VAULT_SECRET_ID`` environment variable for option ``secret_id`` will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_SECRET_ID`` instead (https://github.com/ansible-collections/community.hashi_vault/issues/20).
- hashi_vault - ``VAULT_TOKEN_FILE`` environment variable for option ``token_file`` will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_TOKEN_FILE`` instead (https://github.com/ansible-collections/community.hashi_vault/issues/15).
- hashi_vault - ``VAULT_TOKEN_PATH`` environment variable for option ``token_path`` will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_TOKEN_PATH`` instead (https://github.com/ansible-collections/community.hashi_vault/issues/15).
Bugfixes
--------
- hashi_vault - ``mount_point`` parameter did not work with ``aws_iam_login`` auth method (https://github.com/ansible-collections/community.hashi_vault/issues/7)
- hashi_vault - fallback logic for handling deprecated style of auth in hvac was not implemented correctly (https://github.com/ansible-collections/community.hashi_vault/pull/33).
- hashi_vault - parameter ``mount_point`` does not work with JWT auth (https://github.com/ansible-collections/community.hashi_vault/issues/29).
- hashi_vault - tokens without ``lookup-self`` ability can't be used because of validation (https://github.com/ansible-collections/community.hashi_vault/issues/18).
v0.1.0
======
Release Summary
---------------
Our first release matches the ``hashi_vault`` lookup functionality provided by ``community.general`` version ``1.3.0``.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,7 @@
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,39 @@
{
"collection_info": {
"namespace": "community",
"name": "hashi_vault",
"version": "4.1.0",
"authors": [
"Julie Davila (@juliedavila) <julie(at)davila.io>",
"Brian Scholer (@briantist)"
],
"readme": "README.md",
"tags": [
"vault",
"hashicorp",
"secret",
"secrets",
"password",
"passwords"
],
"description": "Plugins related to HashiCorp Vault",
"license": [
"GPL-3.0-or-later",
"BSD-2-Clause"
],
"license_file": null,
"dependencies": {},
"repository": "https://github.com/ansible-collections/community.hashi_vault",
"documentation": "https://docs.ansible.com/ansible/devel/collections/community/hashi_vault",
"homepage": "https://github.com/ansible-collections/community.hashi_vault",
"issues": "https://github.com/ansible-collections/community.hashi_vault/issues"
},
"file_manifest_file": {
"name": "FILES.json",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "1351b3e0f894ac04833663995ed2b44aba0e4601ad2bf7e8796d2cb36dd47b16",
"format": 1
},
"format": 1
}

View File

@@ -0,0 +1,128 @@
# community.hashi_vault Collection
<!-- Add CI and code coverage badges here. Samples included below. -->
[![CI](https://github.com/ansible-collections/community.hashi_vault/workflows/CI/badge.svg?event=push)](https://github.com/ansible-collections/community.hashi_vault/actions) [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.hashi_vault)](https://codecov.io/gh/ansible-collections/community.hashi_vault)
<!-- Describe the collection and why a user would want to use it. What does the collection do? -->
## Collection Documentation
Browsing the [**latest** collection documentation](https://docs.ansible.com/ansible/latest/collections/community/hashi_vault) will show docs for the _latest version released in the Ansible package_ not the latest version of the collection released on Galaxy.
Browsing the [**devel** collection documentation](https://docs.ansible.com/ansible/devel/collections/community/hashi_vault) shows docs for the _latest version released on Galaxy_.
We also separately publish [**latest commit** collection documentation](https://ansible-collections.github.io/community.hashi_vault/branch/main/) which shows docs for the _latest commit in the `main` branch_.
If you use the Ansible package and don't update collections independently, use **latest**, if you install or update this collection directly from Galaxy, use **devel**. If you are looking to contribute, use **latest commit**.
## Tested with Ansible
* 2.11
* 2.12
* 2.13
* 2.14
* devel (latest development commit)
See [the CI configuration](https://github.com/ansible-collections/community.hashi_vault/blob/main/.github/workflows/ansible-test.yml) for the most accurate testing information.
<!-- List the versions of Ansible the collection has been tested with. Must match what is in galaxy.yml. -->
## Tested with Vault
We currently test against the latest patch version within the latest two minor versions of the latest major version of Vault. Put another way, we test against version `Z.{Z|Y}.Z`. For example as of this writing, Vault is on major version `1`, with the latest two minors being `8` and `7`. So we'll test Vault `1.8.Z` and `1.7.Z` where `Z` is the latest patch within those versions.
We do not test against any versions of Vault with major version `0` or against pre-release/release candidate (RC) versions.
If/when a new major version of Vault is released, we'll revisit which and how many versions to test against.
The decision of which version(s) of Vault to test against is still somewhat in flux, as we try to balance wide testing with CI execution time and resources.
See [the CI configuration](https://github.com/ansible-collections/community.hashi_vault/blob/main/.github/workflows/ansible-test.yml) for the most accurate testing information.
## Python Requirements
**Python 2.6, 2.7, and 3.5 are not supported in version `2.0.0` or later of the collection.**
Currently we support and test against Python versions:
* 3.6
* 3.7
* 3.8
* 3.9
* 3.10
Note that for controller-side plugins, only the Python versions supported by the Ansible controller are supported (for example, you cannot use Python 3.7 with Ansible core 2.12).
## External requirements
The `hvac` Python library is required for this collection. [For full requirements and details, see the collection's User Guide](https://docs.ansible.com/ansible/devel/collections/community/hashi_vault/docsite/user_guide.html#requirements).
## Included content
[See the list of included content in the docsite](https://docs.ansible.com/ansible/devel/collections/community/hashi_vault/#plugin-index).
## Using this collection
<!--Include some quick examples that cover the most common use cases for your collection content. -->
See [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details.
## Contributing to this collection
See the contributor guide in the [**devel** collection documentation](https://docs.ansible.com/ansible/devel/collections/community/hashi_vault).
<!--Describe how the community can contribute to your collection. At a minimum, include how and where users can create issues to report problems or request features for this collection. List contribution requirements, including preferred workflows and necessary testing, so you can benefit from community PRs. If you are following general Ansible contributor guidelines, you can link to - [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html). -->
## Releasing this collection (for maintainers)
[Follow the instructions for releasing small collections in the Ansible community wiki](https://github.com/ansible/community/wiki/ReleasingCollections#releasing-without-release-branches-for-smaller-collections).
Once the new collection is published and the Zuul job is finished, add a release in GitHub by [manually running the `GitHub Release` workflow](https://github.com/ansible-collections/community.hashi_vault/actions/workflows/github-release.yml). You'll need to enter the version number, which should exactly match the tag used to release the collection.
## Release notes
See the [rendered changelog](https://ansible-collections.github.io/community.hashi_vault/branch/main/collections/community/hashi_vault/docsite/CHANGELOG.html) or the [raw generated changelog](https://github.com/ansible-collections/community.hashi_vault/tree/main/CHANGELOG.rst).
## FAQ
### **Q:** Why not have a single collection of HashiCorp products instead of one just for Vault?
**A:** This was considered when the `hashi_vault` plugin was first moved from `community.general` to this collection. There are several reasons behind this:
* The other known HashiCorp content at that time (covering Consul, Nomad, Terraform, etc.) does not share implementation or testing with Vault content.
* The maintainers are also different. This being a community supported collection means separate maintainers are more likely to focus on goals that make sense for their particular plugins and user base.
* The HashiCorp products serve different goals, and even when used together, they have their own APIs and interfaces that don't really have anything in common from the point of view of the Ansible codebase as a consumer.
* It would complicate testing. One of the primary goals of moving to a new collection was the ability to increase the scope of Vault-focused testing without having to balance the impact to unrelated components.
* It makes for a smaller package for consumers, that can hopefully release more quickly.
### **Q:** Why is the collection named `community.hashi_vault` instead of `community.vault` or `community.hashicorp_vault` or `hashicorp.vault` or any number of other names?
**A:** This too was considered during formation. In the end, `hashi_vault` is a compromise of various concerns.
* `hashicorp.vault` looks great, but implies the collection is supported by HashiCorp (which it is not). That doesn't follow the convention of denoting community supported namespaces with `community.`
* `community.vault` looks great at first, but "Vault" is a very general and overloaded term, and in Ansible the first "Vault" one thinks of is [Ansible Vault](https://docs.ansible.com/ansible/latest/user_guide/vault.html). So in the naming, and even in the future of this collection and its content, we have to be mindful of avoiding and removing ambiguities between these products (and other Vaults out there).
* `community.hashicorp_vault` is descriptive and unambiguous but is unfortunately quite long.
* `community.hashicorp` would be good for a collection that aims to contain community-supported content related to all HashiCorp products, but this collection is only focused on Vault (see above question).
* `community.hashicorp.vault` (or any other 3-component name): not supported (also long).
* `community.hashi_vault` isn't perfect, but has an established convention in the existing plugin name and isn't as long as `hashicorp_vault`.
## Roadmap
<!-- Optional. Include the roadmap for this collection, and the proposed release/versioning strategy so users can anticipate the upgrade/update cycle. -->
## More information
<!-- List out where the user can find additional information, such as working group meeting times, slack/IRC channels, or documentation for the product this collection automates. At a minimum, link to: -->
- [Ansible Collection overview](https://github.com/ansible-collections/overview)
- [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html)
- [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html)
- [Ansible Collections Checklist](https://github.com/ansible-collections/overview/blob/master/collection_requirements.rst)
- [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html)
- [The Bullhorn (the Ansible Contributor newsletter)](https://us19.campaign-archive.com/home/?u=56d874e027110e35dea0e03c1&id=d6635f5420)
- [Changes impacting Contributors](https://github.com/ansible-collections/overview/issues/45)
## Licensing
<!-- Include the appropriate license information here and a pointer to the full licensing details. If the collection contains modules migrated from the ansible/ansible repo, you must use the same license that existed in the ansible/ansible repo. See the GNU license example below. -->
GNU General Public License v3.0 or later.
See [LICENSE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text.
Parts of the collection are licensed under the [BSD-2-Clause](https://opensource.org/licenses/BSD-2-Clause) license.

View File

@@ -0,0 +1,621 @@
ancestor: null
releases:
0.1.0:
changes:
release_summary: 'Our first release matches the ``hashi_vault`` lookup functionality
provided by ``community.general`` version ``1.3.0``.
'
fragments:
- 0.1.0.yml
release_date: '2020-12-02'
0.2.0:
changes:
bugfixes:
- hashi_vault - ``mount_point`` parameter did not work with ``aws_iam_login``
auth method (https://github.com/ansible-collections/community.hashi_vault/issues/7)
- hashi_vault - fallback logic for handling deprecated style of auth in hvac
was not implemented correctly (https://github.com/ansible-collections/community.hashi_vault/pull/33).
- hashi_vault - parameter ``mount_point`` does not work with JWT auth (https://github.com/ansible-collections/community.hashi_vault/issues/29).
- hashi_vault - tokens without ``lookup-self`` ability can't be used because
of validation (https://github.com/ansible-collections/community.hashi_vault/issues/18).
deprecated_features:
- hashi_vault - ``VAULT_ADDR`` environment variable for option ``url`` will
have its precedence lowered in 1.0.0; use ``ANSIBLE_HASHI_VAULT_ADDR`` to
intentionally override a config value (https://github.com/ansible-collections/community.hashi_vault/issues/8).
- hashi_vault - ``VAULT_AUTH_METHOD`` environment variable for option ``auth_method``
will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_AUTH_METHOD`` instead
(https://github.com/ansible-collections/community.hashi_vault/issues/17).
- hashi_vault - ``VAULT_ROLE_ID`` environment variable for option ``role_id``
will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_ROLE_ID`` instead (https://github.com/ansible-collections/community.hashi_vault/issues/20).
- hashi_vault - ``VAULT_SECRET_ID`` environment variable for option ``secret_id``
will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_SECRET_ID`` instead (https://github.com/ansible-collections/community.hashi_vault/issues/20).
- hashi_vault - ``VAULT_TOKEN_FILE`` environment variable for option ``token_file``
will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_TOKEN_FILE`` instead (https://github.com/ansible-collections/community.hashi_vault/issues/15).
- hashi_vault - ``VAULT_TOKEN_PATH`` environment variable for option ``token_path``
will be removed in 2.0.0, use ``ANSIBLE_HASHI_VAULT_TOKEN_PATH`` instead (https://github.com/ansible-collections/community.hashi_vault/issues/15).
minor_changes:
- Add optional ``aws_iam_server_id`` parameter as the value for ``X-Vault-AWS-IAM-Server-ID``
header (https://github.com/ansible-collections/community.hashi_vault/pull/27).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_ADDR`` environment variable added for
option ``url`` (https://github.com/ansible-collections/community.hashi_vault/issues/8).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_AUTH_METHOD`` environment variable added
for option ``auth_method`` (https://github.com/ansible-collections/community.hashi_vault/issues/17).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_ROLE_ID`` environment variable added for
option ``role_id`` (https://github.com/ansible-collections/community.hashi_vault/issues/20).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_SECRET_ID`` environment variable added
for option ``secret_id`` (https://github.com/ansible-collections/community.hashi_vault/issues/20).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_TOKEN_FILE`` environment variable added
for option ``token_file`` (https://github.com/ansible-collections/community.hashi_vault/issues/15).
- hashi_vault - ``ANSIBLE_HASHI_VAULT_TOKEN_PATH`` environment variable added
for option ``token_path`` (https://github.com/ansible-collections/community.hashi_vault/issues/15).
- hashi_vault - ``namespace`` parameter can be specified in INI or via env vars
``ANSIBLE_HASHI_VAULT_NAMESPACE`` (new) and ``VAULT_NAMESPACE`` (lower preference) (https://github.com/ansible-collections/community.hashi_vault/issues/14).
- hashi_vault - ``token`` parameter can now be specified via ``ANSIBLE_HASHI_VAULT_TOKEN``
as well as via ``VAULT_TOKEN`` (the latter with lower preference) (https://github.com/ansible-collections/community.hashi_vault/issues/16).
- hashi_vault - add ``token_validate`` option to control token validation (https://github.com/ansible-collections/community.hashi_vault/pull/24).
- hashi_vault - uses new AppRole method in hvac 0.10.6 with fallback to deprecated
method with warning (https://github.com/ansible-collections/community.hashi_vault/pull/33).
release_summary: 'Several backwards-compatible bugfixes and enhancements in
this release.
Some environment variables are deprecated and have standardized replacements.'
fragments:
- 0.2.0.yml
- 22-hashi_vault-aws_iam_login-mount_point.yml
- 24-hashi_vault-token_validation.yml
- 25-non-breaking-env-parameter-changes.yml
- 27-add-hashi_vault-header_value-param.yml
- 31-jwt-mount_point.yml
- 33-approle-deprecation.yml
- 35-env-var-deprecations.yml
release_date: '2020-12-24'
1.0.0:
changes:
breaking_changes:
- hashi_vault - the ``VAULT_ADDR`` environment variable is now checked last
for the ``url`` parameter. For details on which use cases are impacted, see
(https://github.com/ansible-collections/community.hashi_vault/issues/8).
release_summary: Our first major release contains a single breaking change that
will affect only a small subset of users. No functionality is removed. See
the details in the changelog to determine if you're affected and if so how
to transition to remediate.
fragments:
- 1.0.0.yml
- 41-lower-url-env-precedence.yml
release_date: '2020-12-30'
1.1.0:
changes:
minor_changes:
- hashi_vault - add ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/50).
release_summary: This release contains a new ``proxies`` option for the ``hashi_vault``
lookup.
fragments:
- 1.1.0.yml
- 50-add-proxies-option.yml
release_date: '2021-02-08'
1.1.1:
changes:
bugfixes:
- hashi_vault - restore use of ``VAULT_ADDR`` environment variable as a low
preference env var (https://github.com/ansible-collections/community.hashi_vault/pull/61).
release_summary: 'This bugfix release restores the use of the ``VAULT_ADDR``
environment variable for setting the ``url`` option.
See the PR linked from the changelog entry for details and workarounds if
you cannot upgrade.'
fragments:
- 1.1.1.yml
- 41-fix-vault-addr.yml
release_date: '2021-02-24'
1.1.2:
changes:
release_summary: This release contains the same functionality as 1.1.1. The
only change is to mark some code as internal to the collection. If you are
already using 1.1.1 as an end user you do not need to update.
fragments:
- 1.1.2.yml
release_date: '2021-03-02'
1.1.3:
changes:
bugfixes:
- hashi_vault - userpass authentication did not work with hvac 0.9.6 or higher
(https://github.com/ansible-collections/community.hashi_vault/pull/68).
release_summary: This release fixes a bug with ``userpass`` authentication and
``hvac`` versions 0.9.6 and higher.
fragments:
- 1.1.3.yml
- 68-fix-userpass-auth.yml
release_date: '2021-03-19'
1.2.0:
changes:
deprecated_features:
- hashi_vault collection - support for Python 2 will be dropped in version ``2.0.0``
of ``community.hashi_vault`` (https://github.com/ansible-collections/community.hashi_vault/issues/81).
minor_changes:
- hashi_vault lookup - add ``ANSIBLE_HASHI_VAULT_CA_CERT`` env var (with ``VAULT_CACERT``
low-precedence fallback) for ``ca_cert`` option (https://github.com/ansible-collections/community.hashi_vault/pull/97).
- hashi_vault lookup - add ``ANSIBLE_HASHI_VAULT_PASSWORD`` env var and ``ansible_hashi_vault_password``
ansible var for ``password`` option (https://github.com/ansible-collections/community.hashi_vault/pull/96).
- hashi_vault lookup - add ``ANSIBLE_HASHI_VAULT_USERNAME`` env var and ``ansible_hashi_vault_username``
ansible var for ``username`` option (https://github.com/ansible-collections/community.hashi_vault/pull/96).
- hashi_vault lookup - add ``ansible_hashi_vault_auth_method`` Ansible vars
entry to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_ca_cert`` ansible var for ``ca_cert``
option (https://github.com/ansible-collections/community.hashi_vault/pull/97).
- hashi_vault lookup - add ``ansible_hashi_vault_namespace`` Ansible vars entry
to the ``namespace`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_proxies`` Ansible vars entry
to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_role_id`` Ansible vars entry
to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_secret_id`` Ansible vars entry
to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_token_file`` Ansible vars entry
to the ``token_file`` option (https://github.com/ansible-collections/community.hashi_vault/pull/95).
- hashi_vault lookup - add ``ansible_hashi_vault_token_path`` Ansible vars entry
to the ``token_path`` option (https://github.com/ansible-collections/community.hashi_vault/pull/95).
- hashi_vault lookup - add ``ansible_hashi_vault_token_validate`` Ansible vars
entry to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_token`` Ansible vars entry
to the ``proxies`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_url`` and ``ansible_hashi_vault_addr``
Ansible vars entries to the ``url`` option (https://github.com/ansible-collections/community.hashi_vault/pull/86).
- hashi_vault lookup - add ``ansible_hashi_vault_validate_certs`` Ansible vars
entry to the ``validate_certs`` option (https://github.com/ansible-collections/community.hashi_vault/pull/95).
- hashi_vault lookup - add ``ca_cert`` INI config file key ``ca_cert`` option
(https://github.com/ansible-collections/community.hashi_vault/pull/97).
- hashi_vault lookup - add ``none`` auth type which allows for passive auth
via a Vault agent (https://github.com/ansible-collections/community.hashi_vault/pull/80).
release_summary: 'This release brings several new ways of accessing options,
like using Ansible vars, and addng new environment variables and INI config
entries.
A special ``none`` auth type is also added, for working with certain Vault
Agent configurations.
This release also announces the deprecation of Python 2 support in version
``2.0.0`` of the collection.'
fragments:
- 1.2.0.yml
- 80-add-none-auth-type.yml
- 81-deprecating-python2.yml
- 86-add-vars-options.yml
- 95-more-vars-options.yml
- 96-userpass-vars-env.yml
- 97-ca_cert-env-and-vars.yml
release_date: '2021-06-19'
1.3.0:
changes:
minor_changes:
- hashi_vault lookup - add ``retries`` and ``retry_action`` to enable built-in
retry on failure (https://github.com/ansible-collections/community.hashi_vault/pull/71).
- hashi_vault lookup - add ``timeout`` option to control connection timeouts
(https://github.com/ansible-collections/community.hashi_vault/pull/100).
release_summary: This release adds two connection-based options for controlling
timeouts and retrying failed Vault requests.
fragments:
- 1.3.0.yml
- 100-add-timeout-option.yml
- 71-add-retries.yml
release_date: '2021-06-28'
1.3.1:
changes:
release_summary: This release fixes an error in the documentation. No functionality
is changed so it's not necessary to upgrade from ``1.3.0``.
fragments:
- 1.3.1.yml
release_date: '2021-06-30'
1.3.2:
changes:
deprecated_features:
- hashi_vault collection - support for Python 3.5 will be dropped in version
``2.0.0`` of ``community.hashi_vault`` (https://github.com/ansible-collections/community.hashi_vault/issues/81).
minor_changes:
- hashi_vault collection - add ``execution-environment.yml`` and a python requirements
file to better support ``ansible-builder`` (https://github.com/ansible-collections/community.hashi_vault/pull/105).
release_summary: 'This release adds requirements detection support for Ansible
Execution Environments. It also updates and adds new guides in our `collection
docsite <https://docs.ansible.com/ansible/devel/collections/community/hashi_vault>`_.
This release also announces the dropping of Python 3.5 support in version
``2.0.0`` of the collection, alongside the previous announcement dropping
Python 2.x in ``2.0.0``.'
fragments:
- 1.3.2.yml
- 105-support-ansible-builder.yml
- 107-deprecating-python-35.yml
release_date: '2021-07-20'
1.4.0:
changes:
bugfixes:
- aws_iam_login auth - the ``aws_security_token`` option was not used, causing
assumed role credentials to fail (https://github.com/ansible-collections/community.hashi_vault/issues/160).
- hashi_vault collection - a fallback import supporting the ``retries`` option
for ``urllib3`` via ``requests.packages.urllib3`` was not correctly formed
(https://github.com/ansible-collections/community.hashi_vault/issues/116).
- hashi_vault collection - unhandled exception with ``token`` auth when ``token_file``
exists but is a directory (https://github.com/ansible-collections/community.hashi_vault/issues/152).
deprecated_features:
- lookup hashi_vault - the ``[lookup_hashi_vault]`` section in the ``ansible.cfg``
file is deprecated and will be removed in collection version ``3.0.0``. Instead,
the section ``[hashi_vault_collection]`` can be used, which will apply to
all plugins in the collection going forward (https://github.com/ansible-collections/community.hashi_vault/pull/144).
minor_changes:
- community.hashi_vault collection - add cert auth method (https://github.com/ansible-collections/community.hashi_vault/pull/159).
release_summary: 'This release includes bugfixes, a new auth method (``cert``),
and the first new content since the collection''s formation, the ``vault_read``
module and lookup plugin.
We''re also announcing the deprecation of the ``[lookup_hashi_vault]`` INI
section (which will continue working up until its removal only for the ``hashi_vault``
lookup), to be replaced by the ``[hashi_vault_collection]`` section that will
apply to all plugins in the collection.'
fragments:
- 1.4.0.yml
- 113-retry-fallback.yml
- 144-deprecate-lookup-ini.yml
- 154-token_file must be a file.yml
- 159-add-cert-auth.yml
- 161-aws-sts-token.yml
modules:
- description: Perform a read operation against HashiCorp Vault
name: vault_read
namespace: ''
plugins:
lookup:
- description: Perform a read operation against HashiCorp Vault
name: vault_read
namespace: null
release_date: '2021-10-25'
1.4.1:
changes:
bugfixes:
- aws_iam_login auth method - fix incorrect use of ``boto3``/``botocore`` that
prevented proper loading of AWS IAM role credentials (https://github.com/ansible-collections/community.hashi_vault/issues/167).
release_summary: This release contains a bugfix for ``aws_iam_login`` authentication.
fragments:
- 1.4.1.yml
- 168-aws_auth-boto-bug.yml
release_date: '2021-10-28'
1.5.0:
changes:
minor_changes:
- add the ``community.hashi_vault.vault`` action group (https://github.com/ansible-collections/community.hashi_vault/pull/172).
- auth methods - Add support for configuring the ``mount_point`` auth method
option in plugins via the ``ANSIBLE_HASHI_VAULT_MOUNT_POINT`` environment
variable, ``ansible_hashi_vault_mount_point`` ansible variable, or ``mount_point``
INI section (https://github.com/ansible-collections/community.hashi_vault/pull/171).
release_summary: 'This release includes a new action group for use with ``module_defaults``,
and additional ways of specifying the ``mount_point`` option for plugins.
This will be the last ``1.x`` release.'
fragments:
- 1.5.0.yml
- 172-action_group.yml
- pr-171-envvar-for-mount-point.yaml
release_date: '2021-11-05'
2.0.0:
changes:
breaking_changes:
- connection options - there is no longer a default value for the ``url`` option
(the Vault address), so a value must be supplied (https://github.com/ansible-collections/community.hashi_vault/issues/83).
release_summary: 'Version 2.0.0 of the collection drops support for Python 2
& Python 3.5, making Python 3.6 the minimum supported version.
Some deprecated features and settings have been removed as well.'
removed_features:
- drop support for Python 2 and Python 3.5 (https://github.com/ansible-collections/community.hashi_vault/issues/81).
- 'support for the following deprecated environment variables has been removed:
``VAULT_AUTH_METHOD``, ``VAULT_TOKEN_PATH``, ``VAULT_TOKEN_FILE``, ``VAULT_ROLE_ID``,
``VAULT_SECRET_ID`` (https://github.com/ansible-collections/community.hashi_vault/pull/173).'
fragments:
- 173-deprecated-env-vars.yml
- 176-url-is-required.yml
- 177-drop-py2-3.5.yml
- 2.0.0.yml
release_date: '2021-11-06'
2.1.0:
changes:
deprecated_features:
- Support for Ansible 2.9 and ansible-base 2.10 is deprecated, and will be removed
in the next major release (community.hashi_vault 3.0.0) next spring (https://github.com/ansible-community/community-topics/issues/50,
https://github.com/ansible-collections/community.hashi_vault/issues/189).
- aws_iam_login auth method - the ``aws_iam_login`` method has been renamed
to ``aws_iam``. The old name will be removed in collection version ``3.0.0``.
Until then both names will work, and a warning will be displayed when using
the old name (https://github.com/ansible-collections/community.hashi_vault/pull/193).
release_summary: The most important change in this release is renaming the ``aws_iam_login``
auth method to ``aws_iam`` and deprecating the old name. This release also
announces the deprecation of Ansible 2.9 and ansible-base 2.10 support in
3.0.0.
removed_features:
- the "legacy" integration test setup has been removed; this does not affect
end users and is only relevant to contributors (https://github.com/ansible-collections/community.hashi_vault/pull/191).
fragments:
- 190-deprecate-ansible-2.9-2.10.yml
- 191-remove-legacy-integration.yml
- 193-rename-aws-iam-auth.yml
- 2.1.0.yml
release_date: '2021-12-03'
2.2.0:
changes:
minor_changes:
- The Filter guide has been added to the collection's docsite.
release_summary: This release contains a new lookup/module combo for logging
in to Vault, and includes our first filter plugin.
fragments:
- 199-vault_login-vault_login_token.yml
- 2.2.0.yml
modules:
- description: Perform a login operation against HashiCorp Vault
name: vault_login
namespace: ''
plugins:
filter:
- description: Extracts the client token from a Vault login response
name: vault_login_token
namespace: null
lookup:
- description: Perform a login operation against HashiCorp Vault
name: vault_login
namespace: null
release_date: '2022-01-05'
2.3.0:
changes:
release_summary: This release contains new plugins and modules for creating
tokens and for generating certificates with Vault's PKI secrets engine.
fragments:
- 2.3.0.yml
modules:
- description: Generates a new set of credentials (private key and certificate)
using HashiCorp Vault PKI
name: vault_pki_generate_certificate
namespace: ''
- description: Create a HashiCorp Vault token
name: vault_token_create
namespace: ''
plugins:
lookup:
- description: Create a HashiCorp Vault token
name: vault_token_create
namespace: null
release_date: '2022-02-15'
2.4.0:
changes:
release_summary: Our first content for writing to Vault is now live.
fragments:
- 2.4.0.yml
modules:
- description: Perform a write operation against HashiCorp Vault
name: vault_write
namespace: ''
plugins:
lookup:
- description: Perform a write operation against HashiCorp Vault
name: vault_write
namespace: null
release_date: '2022-03-31'
2.5.0:
changes:
deprecated_features:
- token_validate options - the shared auth option ``token_validate`` will change
its default from ``True`` to ``False`` in community.hashi_vault version 4.0.0.
The ``vault_login`` lookup and module will keep the default value of ``True``
(https://github.com/ansible-collections/community.hashi_vault/issues/248).
minor_changes:
- vault_login module & lookup - no friendly error message was given when ``hvac``
was missing (https://github.com/ansible-collections/community.hashi_vault/issues/257).
- vault_pki_certificate - add ``vault_pki_certificate`` to the ``community.hashi_vault.vault``
action group (https://github.com/ansible-collections/community.hashi_vault/issues/251).
- vault_read module & lookup - no friendly error message was given when ``hvac``
was missing (https://github.com/ansible-collections/community.hashi_vault/issues/257).
- vault_token_create - add ``vault_token_create`` to the ``community.hashi_vault.vault``
action group (https://github.com/ansible-collections/community.hashi_vault/issues/251).
- vault_token_create module & lookup - no friendly error message was given when
``hvac`` was missing (https://github.com/ansible-collections/community.hashi_vault/issues/257).
- vault_write - add ``vault_write`` to the ``community.hashi_vault.vault`` action
group (https://github.com/ansible-collections/community.hashi_vault/issues/251).
release_summary: 'This release finally contains dedicated KV plugins and modules,
and an exciting new lookup to help use plugin values in module calls.
With that, we also have a guide in the collection docsite for migrating away
from the ``hashi_vault`` lookup toward dedicated content.
We are also announcing that the ``token_validate`` option will change its
default value in version 4.0.0.
This is the last planned release before 3.0.0. See the porting guide for breaking
changes and removed features in the next version.'
fragments:
- 2.5.0.yml
- 246-action_group.yml
- 258-token_validate-default.yml
- 259-hvac-checks.yml
modules:
- description: Get a secret from HashiCorp Vault's KV version 1 secret store
name: vault_kv1_get
namespace: ''
- description: Get a secret from HashiCorp Vault's KV version 2 secret store
name: vault_kv2_get
namespace: ''
plugins:
lookup:
- description: Returns plugin settings (options)
name: vault_ansible_settings
namespace: null
- description: Get a secret from HashiCorp Vault's KV version 1 secret store
name: vault_kv1_get
namespace: null
- description: Get a secret from HashiCorp Vault's KV version 2 secret store
name: vault_kv2_get
namespace: null
release_date: '2022-05-11'
3.0.0:
changes:
deprecated_features:
- token_validate options - the shared auth option ``token_validate`` will change
its default from ``true`` to ``false`` in community.hashi_vault version 4.0.0.
The ``vault_login`` lookup and module will keep the default value of ``true``
(https://github.com/ansible-collections/community.hashi_vault/issues/248).
release_summary: 'Version 3.0.0 of ``community.hashi_vault`` drops support for
Ansible 2.9 and ansible-base 2.10.
Several deprecated features have been removed. See the changelog for the full
list.'
removed_features:
- aws_iam auth - the deprecated alias ``aws_iam_login`` for the ``aws_iam``
value of the ``auth_method`` option has been removed (https://github.com/ansible-collections/community.hashi_vault/issues/194).
- community.hashi_vault collection - support for Ansible 2.9 and ansible-base
2.10 has been removed (https://github.com/ansible-collections/community.hashi_vault/issues/189).
- hashi_vault lookup - the deprecated ``[lookup_hashi_vault]`` INI config section
has been removed in favor of the collection-wide ``[hashi_vault_collection]``
section (https://github.com/ansible-collections/community.hashi_vault/issues/179).
fragments:
- 179-remove-lookup_hashi_vault-ini.yml
- 189-remove-ansible-2_9-2_10-support.yml
- 194-remove-aws_iam_login.yml
- 248-token_validate-change-default.yml
- 3.0.0.yml
release_date: '2022-05-21'
3.1.0:
changes:
bugfixes:
- Add SPDX license headers to individual files (https://github.com/ansible-collections/community.hashi_vault/pull/282).
- Add missing ``BSD-2-Clause.txt`` file for BSD licensed content (https://github.com/ansible-collections/community.hashi_vault/issues/275).
- Use the correct GPL license for plugin_utils (https://github.com/ansible-collections/community.hashi_vault/issues/276).
deprecated_features:
- vault_kv2_get lookup - the ``engine_mount_point option`` in the ``vault_kv2_get``
lookup only will change its default from ``kv`` to ``secret`` in community.hashi_vault
version 4.0.0 (https://github.com/ansible-collections/community.hashi_vault/issues/279).
release_summary: 'A default value that was set incorrectly will be corrected
in ``4.0.0``.
A deprecation warning will be shown until then if the value is not specified
explicitly.
This version also includes some fixes and improvements to the licensing in
the collection, which does not affect any functionality.'
fragments:
- 279-incorrect-kv2-lookup-default.yml
- 3.1.0.yml
- licensing.yml
release_date: '2022-07-17'
3.2.0:
changes:
bugfixes:
- community.hashi_vault plugins - tokens will be cast to a string type before
being sent to ``hvac`` to prevent errors in ``requests`` when values are ``AnsibleUnsafe``
(https://github.com/ansible-collections/community.hashi_vault/issues/289).
- modules - fix a "variable used before assignment" that cannot be reached but
causes sanity test failures (https://github.com/ansible-collections/community.hashi_vault/issues/296).
minor_changes:
- community.hashi_vault collection - add support for ``azure`` auth method,
for Azure service principal, managed identity, or plain JWT access token (https://github.com/ansible-collections/community.hashi_vault/issues/293).
- community.hashi_vault retries - `HTTP status code 412 <https://www.vaultproject.io/api-docs#412>`__
has been added to the default list of codes to be retried, for the new `Server
Side Consistent Token feature <https://www.vaultproject.io/docs/faq/ssct#q-is-there-anything-else-i-need-to-consider-to-achieve-consistency-besides-upgrading-to-vault-1-10>`__
in Vault Enterprise (https://github.com/ansible-collections/community.hashi_vault/issues/290).
release_summary: This release brings support for the ``azure`` auth method,
adds ``412`` to the default list of HTTP status codes to be retried, and fixes
a bug that causes failures in token auth with ``requests>=2.28.0``.
fragments:
- 289-handle-unsafe-strings.yml
- 290-retry-http-412.yml
- 293-support-azure-auth-method.yml
- 296-use-before-assignment.yml
- 3.2.0.yml
release_date: '2022-08-21'
3.3.0:
changes:
minor_changes:
- vault_token_create - creation or orphan tokens uses ``hvac``'s new v1 method
for creating orphans, or falls back to the v0 method if needed (https://github.com/ansible-collections/community.hashi_vault/issues/301).
release_summary: 'With the release of ``hvac`` version ``1.0.0``, we needed
to update ``vault_token_create``''s support for orphan tokens.
The collection''s changelog is now viewable in the Ansible documentation site.'
fragments:
- 3.3.0.yml
- 301-orphan-token-handling.yml
release_date: '2022-09-19'
3.3.1:
changes:
release_summary: No functional changes in this release, this provides updated
filter documentation for the public docsite.
fragments:
- 3.3.1.yml
release_date: '2022-09-25'
3.4.0:
changes:
bugfixes:
- connection options - the ``namespace`` connection option will be forced into
a string to ensure cmpatibility with recent ``requests`` versions (https://github.com/ansible-collections/community.hashi_vault/issues/309).
minor_changes:
- vault_pki_generate_certificate - the documentation has been updated to match
the argspec for the default values of options ``alt_names``, ``ip_sans``,
``other_sans``, and ``uri_sans`` (https://github.com/ansible-collections/community.hashi_vault/pull/318).
release_summary: 'This release includes a new module, fixes (another) ``requests``
header issue, and updates some inaccurate documentation.
This is the last planned release before v4.0.0.'
fragments:
- 3.4.0.yml
- 309-stringify-namespace.yml
- 318-pki-argspec-doc-mismatch.yml
modules:
- description: Delete one or more versions of a secret from HashiCorp Vault's
KV version 2 secret store
name: vault_kv2_delete
namespace: ''
release_date: '2022-11-03'
4.0.0:
changes:
breaking_changes:
- auth - the default value for ``token_validate`` has changed from ``true``
to ``false``, as previously announced (https://github.com/ansible-collections/community.hashi_vault/issues/248).
- vault_kv2_get lookup - as previously announced, the default value for ``engine_mount_point``
in the ``vault_kv2_get`` lookup has changed from ``kv`` to ``secret`` (https://github.com/ansible-collections/community.hashi_vault/issues/279).
minor_changes:
- modules - all modules now document their action group and support for check
mode in their attributes documentation (https://github.com/ansible-collections/community.hashi_vault/issues/197).
release_summary: The next major version of the collection includes previously
announced breaking changes to some default values, and improvements to module
documentation with attributes that describe the use of action groups and check
mode support.
fragments:
- 197-module-attributes.yml
- 248-token_validate-default.yml
- 279-vault_kv2_get-lookup-mount-default.yml
- 4.0.0.yml
release_date: '2022-11-05'
4.1.0:
changes:
deprecated_features:
- ansible-core - support for ``ansible-core`` versions ``2.11`` and ``2.12``
will be dropped in collection version ``5.0.0``, making ``2.13`` the minimum
supported version of ``ansible-core`` (https://github.com/ansible-collections/community.hashi_vault/issues/340).
- hvac - the minimum version of ``hvac`` to be supported in collection version
``5.0.0`` will be at least ``1.0.2``; this minimum may be raised before ``5.0.0``
is released, so please subscribe to the linked issue and look out for new
notices in the changelog (https://github.com/ansible-collections/community.hashi_vault/issues/324).
release_summary: 'This release brings new generic ``vault_list`` plugins from
a new contributor!
There are also some deprecation notices for the next major version, and some
updates to documentation attributes.'
fragments:
- 324-deprecate-hvac.yml
- 325-fix attributes.yml
- 340-deprecate-core-211-212.yml
- 4.1.0.yml
modules:
- description: Perform a list operation against HashiCorp Vault
name: vault_list
namespace: ''
plugins:
lookup:
- description: Perform a list operation against HashiCorp Vault
name: vault_list
namespace: null
release_date: '2023-01-18'

View File

@@ -0,0 +1,29 @@
changelog_filename_template: ../CHANGELOG.rst
changelog_filename_version_depth: 0
changes_file: changelog.yaml
changes_format: combined
keep_fragments: false
mention_ancestor: true
new_plugins_after_name: removed_features
notesdir: fragments
prelude_section_name: release_summary
prelude_section_title: Release Summary
sections:
- - major_changes
- Major Changes
- - minor_changes
- Minor Changes
- - breaking_changes
- Breaking Changes / Porting Guide
- - deprecated_features
- Deprecated Features
- - removed_features
- Removed Features (previously deprecated)
- - security_fixes
- Security Fixes
- - bugfixes
- Bugfixes
- - known_issues
- Known Issues
title: community.hashi_vault
trivial_section_name: trivial

View File

@@ -0,0 +1,109 @@
---
ignore:
- tests/unit/compat/*
- tests/unit/**/conftest.py
- tests/unit/conftest.py
fixes:
- "ansible_collections/community/hashi_vault/::"
flags:
target_filter_vault_login_token:
paths:
- plugins/filter/vault_login_token.py
target_module_vault_kv1_get:
paths:
- plugins/modules/vault_kv1_get.py
target_module_vault_kv2_get:
paths:
- plugins/modules/vault_kv2_get.py
target_module_vault_list:
paths:
- plugins/modules/vault_list.py
target_module_vault_login:
paths:
- plugins/modules/vault_login.py
target_module_vault_read:
paths:
- plugins/modules/vault_read.py
target_module_vault_token_create:
paths:
- plugins/modules/vault_token_create.py
target_module_vault_pki_generate_certificate:
paths:
- plugins/modules/vault_pki_generate_certificate
target_lookup_vault_kv1_get:
paths:
- plugins/lookup/vault_kv1_get.py
target_lookup_vault_kv2_get:
paths:
- plugins/lookup/vault_kv2_get.py
target_lookup_vault_list:
paths:
- plugins/lookup/vault_list.py
target_lookup_vault_login:
paths:
- plugins/lookup/vault_login.py
target_lookup_vault_read:
paths:
- plugins/lookup/vault_read.py
target_lookup_vault_token_create:
paths:
- plugins/lookup/vault_token_create.py
target_lookup_hashi_vault:
paths:
- plugins/lookup/hashi_vault.py
target_auth_approle:
paths:
- plugins/module_utils/_auth_method_approle.py
target_auth_aws_iam:
paths:
- plugins/module_utils/_auth_method_aws_iam.py
target_auth_azure:
paths:
- plugins/module_utils/_auth_method_azure.py
target_auth_cert:
paths:
- plugins/module_utils/_auth_method_cert.py
target_auth_jwt:
paths:
- plugins/module_utils/_auth_method_jwt.py
target_auth_ldap:
paths:
- plugins/module_utils/_auth_method_ldap.py
target_auth_none:
paths:
- plugins/module_utils/_auth_method_none.py
target_auth_token:
paths:
- plugins/module_utils/_auth_method_token.py
target_auth_userpass:
paths:
- plugins/module_utils/_auth_method_userpass.py
target_connection_options:
paths:
- plugins/module_utils/_connection_options.py

View File

@@ -0,0 +1,9 @@
# ansible-builder doesn't seem to properly handle "; python_version" type of constraints
# requirements here are assuming python 3.6 or higher
hvac >=0.10.6
urllib3 >= 1.15
boto3 # these are only needed if inferring AWS credentials or
botocore # using a boto profile; including for completeness
azure-identity # only needed when using a servide principal or managed identity

View File

@@ -0,0 +1,4 @@
---
version: 1
dependencies:
python: meta/ee-requirements.txt

View File

@@ -0,0 +1,14 @@
---
requires_ansible: '>=2.11.0'
action_groups:
# let's keep this in alphabetical order
vault:
- vault_kv1_get
- vault_kv2_delete
- vault_kv2_get
- vault_list
- vault_login
- vault_pki_generate_certificate
- vault_read
- vault_token_create
- vault_write

View File

@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2022, Brian Scholer (@briantist)
# 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
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options: {}
attributes:
check_mode:
description: Can run in C(check_mode) and return changed status prediction without modifying target.
'''
ACTION_GROUP = r'''
options: {}
attributes:
action_group:
description: Use C(group/community.hashi_vault.vault) in C(module_defaults) to set defaults for this module.
support: full
membership:
- community.hashi_vault.vault
'''
# Should be used together with the standard fragment
CHECK_MODE_READ_ONLY = r'''
options: {}
attributes:
check_mode:
support: full
details:
- This module is "read only" and operates the same regardless of check mode.
'''

View File

@@ -0,0 +1,308 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Brian Scholer (@briantist)
# 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
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options:
auth_method:
description:
- Authentication method to be used.
- C(none) auth method was added in collection version C(1.2.0).
- C(cert) auth method was added in collection version C(1.4.0).
- C(aws_iam_login) was renamed C(aws_iam) in collection version C(2.1.0) and was removed in C(3.0.0).
- C(azure) auth method was added in collection version C(3.2.0).
choices:
- token
- userpass
- ldap
- approle
- aws_iam
- azure
- jwt
- cert
- none
default: token
type: str
mount_point:
description:
- Vault mount point.
- If not specified, the default mount point for a given auth method is used.
- Does not apply to token authentication.
type: str
token:
description:
- Vault token. Token may be specified explicitly, through the listed [env] vars, and also through the C(VAULT_TOKEN) env var.
- If no token is supplied, explicitly or through env, then the plugin will check for a token file, as determined by I(token_path) and I(token_file).
- The order of token loading (first found wins) is C(token param -> ansible var -> ANSIBLE_HASHI_VAULT_TOKEN -> VAULT_TOKEN -> token file).
type: str
token_path:
description: If no token is specified, will try to read the I(token_file) from this path.
type: str
token_file:
description: If no token is specified, will try to read the token from this file in I(token_path).
default: '.vault-token'
type: str
token_validate:
description:
- For token auth, will perform a C(lookup-self) operation to determine the token's validity before using it.
- Disable if your token does not have the C(lookup-self) capability.
type: bool
default: false
version_added: 0.2.0
username:
description: Authentication user name.
type: str
password:
description: Authentication password.
type: str
role_id:
description:
- Vault Role ID or name. Used in C(approle), C(aws_iam), C(azure) and C(cert) auth methods.
- For C(cert) auth, if no I(role_id) is supplied, the default behavior is to try all certificate roles and return any one that matches.
- For C(azure) auth, I(role_id) is required.
type: str
secret_id:
description: Secret ID to be used for Vault AppRole authentication.
type: str
jwt:
description: The JSON Web Token (JWT) to use for JWT authentication to Vault.
type: str
aws_profile:
description: The AWS profile
type: str
aliases: [ boto_profile ]
aws_access_key:
description: The AWS access key to use.
type: str
aliases: [ aws_access_key_id ]
aws_secret_key:
description: The AWS secret key that corresponds to the access key.
type: str
aliases: [ aws_secret_access_key ]
aws_security_token:
description: The AWS security token if using temporary access and secret keys.
type: str
region:
description: The AWS region for which to create the connection.
type: str
aws_iam_server_id:
description: If specified, sets the value to use for the C(X-Vault-AWS-IAM-Server-ID) header as part of C(GetCallerIdentity) request.
required: False
type: str
version_added: '0.2.0'
azure_tenant_id:
description:
- The Azure Active Directory Tenant ID (also known as the Directory ID) of the service principal. Should be a UUID.
- >-
Required when using a service principal to authenticate to Vault,
e.g. required when both I(azure_client_id) and I(azure_client_secret) are specified.
- Optional when using managed identity to authenticate to Vault.
required: False
type: str
version_added: '3.2.0'
azure_client_id:
description:
- The client ID (also known as application ID) of the Azure AD service principal or managed identity. Should be a UUID.
- If not specified, will use the system assigned managed identity.
required: False
type: str
version_added: '3.2.0'
azure_client_secret:
description: The client secret of the Azure AD service principal.
required: False
type: str
version_added: '3.2.0'
azure_resource:
description: The resource URL for the application registered in Azure Active Directory. Usually should not be changed from the default.
required: False
type: str
default: https://management.azure.com/
version_added: '3.2.0'
cert_auth_public_key:
description: For C(cert) auth, path to the certificate file to authenticate with, in PEM format.
type: path
version_added: 1.4.0
cert_auth_private_key:
description: For C(cert) auth, path to the private key file to authenticate with, in PEM format.
type: path
version_added: 1.4.0
'''
PLUGINS = r'''
options:
auth_method:
env:
- name: ANSIBLE_HASHI_VAULT_AUTH_METHOD
version_added: 0.2.0
ini:
- section: hashi_vault_collection
key: auth_method
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_auth_method
version_added: 1.2.0
mount_point:
env:
- name: ANSIBLE_HASHI_VAULT_MOUNT_POINT
version_added: 1.5.0
ini:
- section: hashi_vault_collection
key: mount_point
version_added: 1.5.0
vars:
- name: ansible_hashi_vault_mount_point
version_added: 1.5.0
token:
env:
- name: ANSIBLE_HASHI_VAULT_TOKEN
version_added: 0.2.0
vars:
- name: ansible_hashi_vault_token
version_added: 1.2.0
token_path:
env:
- name: ANSIBLE_HASHI_VAULT_TOKEN_PATH
version_added: 0.2.0
ini:
- section: hashi_vault_collection
key: token_path
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_token_path
version_added: 1.2.0
token_file:
env:
- name: ANSIBLE_HASHI_VAULT_TOKEN_FILE
version_added: 0.2.0
ini:
- section: hashi_vault_collection
key: token_file
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_token_file
version_added: 1.2.0
token_validate:
env:
- name: ANSIBLE_HASHI_VAULT_TOKEN_VALIDATE
ini:
- section: hashi_vault_collection
key: token_validate
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_token_validate
version_added: 1.2.0
username:
env:
- name: ANSIBLE_HASHI_VAULT_USERNAME
version_added: '1.2.0'
vars:
- name: ansible_hashi_vault_username
version_added: '1.2.0'
password:
env:
- name: ANSIBLE_HASHI_VAULT_PASSWORD
version_added: '1.2.0'
vars:
- name: ansible_hashi_vault_password
version_added: '1.2.0'
role_id:
env:
- name: ANSIBLE_HASHI_VAULT_ROLE_ID
version_added: 0.2.0
ini:
- section: hashi_vault_collection
key: role_id
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_role_id
version_added: 1.2.0
secret_id:
env:
- name: ANSIBLE_HASHI_VAULT_SECRET_ID
version_added: 0.2.0
vars:
- name: ansible_hashi_vault_secret_id
version_added: 1.2.0
jwt:
env:
- name: ANSIBLE_HASHI_VAULT_JWT
aws_profile:
env:
- name: AWS_DEFAULT_PROFILE
- name: AWS_PROFILE
aws_access_key:
env:
- name: EC2_ACCESS_KEY
- name: AWS_ACCESS_KEY
- name: AWS_ACCESS_KEY_ID
aws_secret_key:
env:
- name: EC2_SECRET_KEY
- name: AWS_SECRET_KEY
- name: AWS_SECRET_ACCESS_KEY
aws_security_token:
env:
- name: EC2_SECURITY_TOKEN
- name: AWS_SESSION_TOKEN
- name: AWS_SECURITY_TOKEN
region:
env:
- name: EC2_REGION
- name: AWS_REGION
aws_iam_server_id:
env:
- name: ANSIBLE_HASHI_VAULT_AWS_IAM_SERVER_ID
ini:
- section: hashi_vault_collection
key: aws_iam_server_id
version_added: 1.4.0
azure_tenant_id:
env:
- name: ANSIBLE_HASHI_VAULT_AZURE_TENANT_ID
ini:
- section: hashi_vault_collection
key: azure_tenant_id
vars:
- name: ansible_hashi_vault_azure_tenant_id
azure_client_id:
env:
- name: ANSIBLE_HASHI_VAULT_AZURE_CLIENT_ID
ini:
- section: hashi_vault_collection
key: azure_client_id
vars:
- name: ansible_hashi_vault_azure_client_id
azure_client_secret:
env:
- name: ANSIBLE_HASHI_VAULT_AZURE_CLIENT_SECRET
vars:
- name: ansible_hashi_vault_azure_client_secret
azure_resource:
env:
- name: ANSIBLE_HASHI_VAULT_AZURE_RESOURCE
ini:
- section: hashi_vault_collection
key: azure_resource
vars:
- name: ansible_hashi_vault_azure_resource
cert_auth_public_key:
env:
- name: ANSIBLE_HASHI_VAULT_CERT_AUTH_PUBLIC_KEY
ini:
- section: hashi_vault_collection
key: cert_auth_public_key
cert_auth_private_key:
env:
- name: ANSIBLE_HASHI_VAULT_CERT_AUTH_PRIVATE_KEY
ini:
- section: hashi_vault_collection
key: cert_auth_private_key
'''

View File

@@ -0,0 +1,161 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Brian Scholer (@briantist)
# 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
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options:
url:
description:
- URL to the Vault service.
- If not specified by any other means, the value of the C(VAULT_ADDR) environment variable will be used.
- If C(VAULT_ADDR) is also not defined then an error will be raised.
type: str
proxies:
description:
- URL(s) to the proxies used to access the Vault service.
- It can be a string or a dict.
- If it's a dict, provide the scheme (eg. C(http) or C(https)) as the key, and the URL as the value.
- If it's a string, provide a single URL that will be used as the proxy for both C(http) and C(https) schemes.
- A string that can be interpreted as a dictionary will be converted to one (see examples).
- You can specify a different proxy for HTTP and HTTPS resources.
- If not specified, L(environment variables from the Requests library,https://requests.readthedocs.io/en/master/user/advanced/#proxies) are used.
type: raw
version_added: 1.1.0
ca_cert:
description:
- Path to certificate to use for authentication.
- If not specified by any other means, the C(VAULT_CACERT) environment variable will be used.
aliases: [ cacert ]
type: str
validate_certs:
description:
- Controls verification and validation of SSL certificates, mostly you only want to turn off with self signed ones.
- Will be populated with the inverse of C(VAULT_SKIP_VERIFY) if that is set and I(validate_certs) is not explicitly provided.
- Will default to C(true) if neither I(validate_certs) or C(VAULT_SKIP_VERIFY) are set.
type: bool
namespace:
description:
- Vault namespace where secrets reside. This option requires HVAC 0.7.0+ and Vault 0.11+.
- Optionally, this may be achieved by prefixing the authentication mount point and/or secret path with the namespace
(e.g C(mynamespace/secret/mysecret)).
- If environment variable C(VAULT_NAMESPACE) is set, its value will be used last among all ways to specify I(namespace).
type: str
timeout:
description:
- Sets the connection timeout in seconds.
- If not set, then the C(hvac) library's default is used.
type: int
version_added: 1.3.0
retries:
description:
- "Allows for retrying on errors, based on
the L(Retry class in the urllib3 library,https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html#urllib3.util.Retry)."
- This collection defines recommended defaults for retrying connections to Vault.
- This option can be specified as a positive number (integer) or dictionary.
- If this option is not specified or the number is C(0), then retries are disabled.
- A number sets the total number of retries, and uses collection defaults for the other settings.
- A dictionary value is used directly to initialize the C(Retry) class, so it can be used to fully customize retries.
- For detailed information on retries, see the collection User Guide.
type: raw
version_added: 1.3.0
retry_action:
description:
- Controls whether and how to show messages on I(retries).
- This has no effect if a request is not retried.
type: str
choices:
- ignore
- warn
default: warn
version_added: 1.3.0
'''
PLUGINS = r'''
options:
url:
env:
- name: ANSIBLE_HASHI_VAULT_ADDR
version_added: 0.2.0
ini:
- section: hashi_vault_collection
key: url
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_url
version_added: 1.2.0
- name: ansible_hashi_vault_addr
version_added: 1.2.0
proxies:
env:
- name: ANSIBLE_HASHI_VAULT_PROXIES
ini:
- section: hashi_vault_collection
key: proxies
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_proxies
version_added: 1.2.0
type: raw
version_added: 1.1.0
ca_cert:
env:
- name: ANSIBLE_HASHI_VAULT_CA_CERT
version_added: 1.2.0
ini:
- section: hashi_vault_collection
key: ca_cert
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_ca_cert
version_added: 1.2.0
validate_certs:
vars:
- name: ansible_hashi_vault_validate_certs
version_added: 1.2.0
namespace:
env:
- name: ANSIBLE_HASHI_VAULT_NAMESPACE
version_added: 0.2.0
ini:
- section: hashi_vault_collection
key: namespace
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_namespace
version_added: 1.2.0
timeout:
env:
- name: ANSIBLE_HASHI_VAULT_TIMEOUT
ini:
- section: hashi_vault_collection
key: timeout
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_timeout
retries:
env:
- name: ANSIBLE_HASHI_VAULT_RETRIES
ini:
- section: hashi_vault_collection
key: retries
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_retries
retry_action:
env:
- name: ANSIBLE_HASHI_VAULT_RETRY_ACTION
ini:
- section: hashi_vault_collection
key: retry_action
version_added: 1.4.0
vars:
- name: ansible_hashi_vault_retry_action
'''

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2022, Brian Scholer (@briantist)
# 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
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options:
engine_mount_point:
description: The path where the secret backend is mounted.
type: str
'''
PLUGINS = r'''
options:
engine_mount_point:
vars:
- name: ansible_hashi_vault_engine_mount_point
'''

View File

@@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2022, Brian Scholer (@briantist)
# 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
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options:
orphan:
description:
- When C(true), uses the C(/create-orphan) API endpoint, which requires C(sudo) (but not C(root)) to create an orphan.
- With C(hvac>=1.0.0), requires collection version C(>=3.3.0).
type: bool
default: false
no_parent:
description:
- This option only has effect if used by a C(root) or C(sudo) caller and only when I(orphan=false).
- When C(true), the token created will not have a parent.
type: bool
no_default_policy:
description:
- If C(true) the default policy will not be contained in this token's policy set.
- If the token will be used with this collection, set I(token_validate=false).
type: bool
policies:
description:
- A list of policies for the token. This must be a subset of the policies belonging to the token making the request, unless root.
- If not specified, defaults to all the policies of the calling token.
type: list
elements: str
id:
description:
- The ID of the client token. Can only be specified by a root token.
- The ID provided may not contain a C(.) character.
- Otherwise, the token ID is a randomly generated value.
type: str
role_name:
description:
- The name of the token role. If used, the token will be created against the specified role name which may override options set during this call.
type: str
meta:
description: A dict of string to string valued metadata. This is passed through to the audit devices.
type: dict
renewable:
description:
- Set to C(false) to disable the ability of the token to be renewed past its initial TTL.
- Setting the value to C(true) will allow the token to be renewable up to the system/mount maximum TTL.
type: bool
ttl:
description:
- The TTL period of the token, provided as C(1h) for example, where hour is the largest suffix.
- If not provided, the token is valid for the default lease TTL, or indefinitely if the root policy is used.
type: str
type:
description: The token type. The default is determined by the role configuration specified by I(role_name).
type: str
choices:
- batch
- service
explicit_max_ttl:
description:
- If set, the token will have an explicit max TTL set upon it.
- This maximum token TTL cannot be changed later,
and unlike with normal tokens, updates to the system/mount max TTL value will have no effect at renewal time.
- The token will never be able to be renewed or used past the value set at issue time.
type: str
display_name:
description: The display name of the token.
type: str
num_uses:
description:
- The maximum uses for the given token. This can be used to create a one-time-token or limited use token.
- The value of C(0) has no limit to the number of uses.
type: int
period:
description:
- If specified, the token will be periodic.
- It will have no maximum TTL (unless an I(explicit_max_ttl) is also set) but every renewal will use the given period.
- Requires a root token or one with the C(sudo) capability.
type: str
entity_alias:
description:
- Name of the entity alias to associate with during token creation.
- Only works in combination with I(role_name) option and used entity alias must be listed in C(allowed_entity_aliases).
- If this has been specified, the entity will not be inherited from the parent.
type: str
'''

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2022, Brian Scholer (@briantist)
# 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
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options:
wrap_ttl:
description: Specifies response wrapping token creation with duration. For example C(15s), C(20m), C(25h).
type: str
'''
PLUGINS = r'''
options:
wrap_ttl:
vars:
- name: ansible_hashi_vault_wrap_ttl
'''

View File

@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# (c) 2021, Brian Scholer (@briantist)
# 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
from ansible.errors import AnsibleError
def vault_login_token(login_response, optional_field='login'):
'''Extracts the token value from a Vault login response.
Meant to be used with the vault_login module and lookup plugin.
'''
try:
deref = login_response[optional_field]
except TypeError:
raise AnsibleError("The 'vault_login_token' filter expects a dictionary.")
except KeyError:
deref = login_response
try:
token = deref['auth']['client_token']
except KeyError:
raise AnsibleError("Could not find 'auth' or 'auth.client_token' fields. Input may not be a Vault login response.")
return token
class FilterModule(object):
'''Ansible jinja2 filters'''
def filters(self):
return {
'vault_login_token': vault_login_token,
}

View File

@@ -0,0 +1,98 @@
# (c) 2022, Brian Scholer (@briantist)
# 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
---
DOCUMENTATION:
name: vault_login_token
short_description: Extracts the Vault token from a login or token creation
version_added: 2.2.0
description:
- Extracts the token value from the structure returned by a Vault token creation operation.
seealso:
- module: community.hashi_vault.vault_login
- module: community.hashi_vault.vault_token_create
- plugin: community.hashi_vault.vault_login
plugin_type: lookup
- plugin: community.hashi_vault.vault_token_create
plugin_type: lookup
- ref: Filter Guide <ansible_collections.community.hashi_vault.docsite.filter_guide.vault_login_token>
description: The C(community.hashi_vault) Filter Guide
notes:
- >-
This filter is the same as reading into the I(_input) dictionary directly,
but it provides semantic meaning and automatically works with the differing output of the modules and lookups.
See the Filter guide for more information.
options:
_input:
description:
- A dictionary matching the structure returned by a login or token creation.
type: dict
required: true
optional_field:
description:
- >-
If this field exists in the input dictionary, then the value of that field is used as the I(_input) value.
- >-
The default value deals with the difference between the output of lookup plugins,
and does not need to be changed in most cases.
- See the examples or the Filter guide for more information.
type: string
default: login
author:
- Brian Scholer (@briantist)
EXAMPLES: |
- name: Set defaults
vars:
ansible_hashi_vault_url: https://vault:9801/
ansible_hashi_vault_auth_method: userpass
ansible_hashi_vault_username: user
ansible_hashi_vault_password: "{{ lookup('env', 'MY_SECRET_PASSWORD') }}"
module_defaults:
community.hashi_vault.vault_login:
url: '{{ ansible_hashi_vault_url }}'
auth_method: '{{ ansible_hashi_vault_auth_method }}'
username: '{{ ansible_hashi_vault_username }}'
password: '{{ ansible_hashi_vault_password }}'
block:
- name: Perform a login with a lookup and display the token
vars:
login_response: "{{ lookup('community.hashi_vault.vault_login') }}"
debug:
msg: "The token is {{ login_response | community.hashi_vault.vault_login_token }}"
- name: Perform a login with a module
community.hashi_vault.vault_login:
register: login_response
- name: Display the token
debug:
msg: "The token is {{ login_response | community.hashi_vault.vault_login_token }}"
- name: Use of optional_field
vars:
lookup_login_response: "{{ lookup('community.hashi_vault.vault_login') }}"
my_data:
something: somedata
vault_login: "{{ lookup_login_response }}"
token_from_param: "{{ my_data | community.hashi_vault.vault_login_token(optional_field='vault_login') }}"
token_from_deref: "{{ my_data['vault_login'] | community.hashi_vault.vault_login_token }}"
# if the optional field doesn't exist, the dictionary itself is still checked
unused_optional: "{{ my_data['vault_login'] | community.hashi_vault.vault_login_token(optional_field='missing') }}"
block:
- name: Display the variables
ansible.builtin.debug:
var: '{{ item }}'
loop:
- my_data
- token_from_param
- token_from_deref
- unused_optional
RETURN:
_value:
description: The token value.
returned: always
sample: s.nnrpog4i5gjizr6b8g1inwj3
type: string

View File

@@ -0,0 +1,349 @@
# (c) 2020, Brian Scholer (@briantist)
# (c) 2015, Julie Davila (@juliedavila) <julie(at)davila.io>
# (c) 2017 Ansible Project
# 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 = """
name: hashi_vault
author:
- Julie Davila (@juliedavila) <julie(at)davila.io>
- Brian Scholer (@briantist)
short_description: Retrieve secrets from HashiCorp's Vault
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:
- Retrieve secrets from HashiCorp's Vault.
- Consider R(migrating to other plugins in the collection,ansible_collections.community.hashi_vault.docsite.migration_hashi_vault_lookup).
seealso:
- ref: community.hashi_vault.hashi_vault Migration Guide <ansible_collections.community.hashi_vault.docsite.migration_hashi_vault_lookup>
description: Migrating from the C(hashi_vault) lookup.
- ref: About the community.hashi_vault.hashi_vault lookup <ansible_collections.community.hashi_vault.docsite.about_hashi_vault_lookup>
description: The past, present, and future of the C(hashi_vault) lookup.
- ref: community.hashi_vault.vault_read lookup <ansible_collections.community.hashi_vault.vault_read_lookup>
description: The official documentation for the C(community.hashi_vault.vault_read) lookup plugin.
- module: community.hashi_vault.vault_read
- ref: community.hashi_vault.vault_kv2_get lookup <ansible_collections.community.hashi_vault.vault_kv2_get_lookup>
description: The official documentation for the C(community.hashi_vault.vault_kv2_get) lookup plugin.
- module: community.hashi_vault.vault_kv2_get
- ref: community.hashi_vault.vault_kv1_get lookup <ansible_collections.community.hashi_vault.vault_kv1_get_lookup>
description: The official documentation for the C(community.hashi_vault.vault_kv1_get) lookup plugin.
- module: community.hashi_vault.vault_kv1_get
- ref: community.hashi_vault Lookup Guide <ansible_collections.community.hashi_vault.docsite.lookup_guide>
description: Guidance on using lookups in C(community.hashi_vault).
notes:
- Due to a current limitation in the HVAC library there won't necessarily be an error if a bad endpoint is specified.
- As of community.hashi_vault 0.1.0, only the latest version of a secret is returned when specifying a KV v2 path.
- As of community.hashi_vault 0.1.0, all options can be supplied via term string (space delimited key=value pairs) or by parameters (see examples).
- As of community.hashi_vault 0.1.0, when I(secret) is the first option in the term string, C(secret=) is not required (see examples).
extends_documentation_fragment:
- community.hashi_vault.connection
- community.hashi_vault.connection.plugins
- community.hashi_vault.auth
- community.hashi_vault.auth.plugins
options:
secret:
description: Vault path to the secret being requested in the format C(path[:field]).
required: True
return_format:
description:
- Controls how multiple key/value pairs in a path are treated on return.
- C(dict) returns a single dict containing the key/value pairs.
- C(values) returns a list of all the values only. Use when you don't care about the keys.
- C(raw) returns the actual API result (deserialized), which includes metadata and may have the data nested in other keys.
choices:
- dict
- values
- raw
default: dict
aliases: [ as ]
"""
EXAMPLES = """
- ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/hello:value token=c975b780-d1be-8016-866b-01d0f9b688a5 url=http://myvault:8200') }}"
- name: Return all secrets from a path
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/hello token=c975b780-d1be-8016-866b-01d0f9b688a5 url=http://myvault:8200') }}"
- name: Vault that requires authentication via LDAP
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/hello:value auth_method=ldap mount_point=ldap username=myuser password=mypas') }}"
- name: Vault that requires authentication via username and password
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/hola:val auth_method=userpass username=myuser password=psw url=http://vault:8200') }}"
- name: Connect to Vault using TLS
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/hola:value token=c975b780-d1be-8016-866b-01d0f9b688a5 validate_certs=False') }}"
- name: using certificate auth
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/hi:val token=xxxx url=https://vault:8200 validate_certs=True cacert=/cacert/path/ca.pem') }}"
- name: Authenticate with a Vault app role
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/hello:value auth_method=approle role_id=myroleid secret_id=mysecretid') }}"
- name: Return all secrets from a path in a namespace
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/hello token=c975b780-d1be-8016-866b-01d0f9b688a5 namespace=teama/admins') }}"
# When using KV v2 the PATH should include "data" between the secret engine mount and path (e.g. "secret/data/:path")
# see: https://www.vaultproject.io/api/secret/kv/kv-v2.html#read-secret-version
- name: Return latest KV v2 secret from path
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/data/hello token=my_vault_token url=http://myvault_url:8200') }}"
# The following examples show more modern syntax, with parameters specified separately from the term string.
- name: secret= is not required if secret is first
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/data/hello token=<token> url=http://myvault_url:8200') }}"
- name: options can be specified as parameters rather than put in term string
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/data/hello', token=my_token_var, url='http://myvault_url:8200') }}"
# return_format (or its alias 'as') can control how secrets are returned to you
- name: return secrets as a dict (default)
ansible.builtin.set_fact:
my_secrets: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/data/manysecrets', token=my_token_var, url='http://myvault_url:8200') }}"
- ansible.builtin.debug:
msg: "{{ my_secrets['secret_key'] }}"
- ansible.builtin.debug:
msg: "Secret '{{ item.key }}' has value '{{ item.value }}'"
loop: "{{ my_secrets | dict2items }}"
- name: return secrets as values only
ansible.builtin.debug:
msg: "A secret value: {{ item }}"
loop: "{{ query('community.hashi_vault.hashi_vault', 'secret/data/manysecrets', token=my_token_var, url='http://vault_url:8200', return_format='values') }}"
- name: return raw secret from API, including metadata
ansible.builtin.set_fact:
my_secret: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/data/hello:value', token=my_token_var, url='http://myvault_url:8200', as='raw') }}"
- ansible.builtin.debug:
msg: "This is version {{ my_secret['metadata']['version'] }} of hello:value. The secret data is {{ my_secret['data']['data']['value'] }}"
# AWS IAM authentication method
# uses Ansible standard AWS options
- name: authenticate with aws_iam
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/hello:value', auth_method='aws_iam', role_id='myroleid', profile=my_boto_profile) }}"
# JWT auth
- name: Authenticate with a JWT
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/hola:val', auth_method='jwt', role_id='myroleid', jwt='myjwt', url='https://vault:8200') }}"
# Disabling Token Validation
# Use this when your token does not have the lookup-self capability. Usually this is applied to all tokens via the default policy.
# However you can choose to create tokens without applying the default policy, or you can modify your default policy not to include it.
# When disabled, your invalid or expired token will be indistinguishable from insufficent permissions.
- name: authenticate without token validation
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/hello:value', token=my_token, token_validate=False) }}"
# "none" auth method does no authentication and does not send a token to the Vault address.
# One example of where this could be used is with a Vault agent where the agent will handle authentication to Vault.
# https://www.vaultproject.io/docs/agent
- name: authenticate with vault agent
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/hello:value', auth_method='none', url='http://127.0.0.1:8100') }}"
# Use a proxy
- name: use a proxy with login/password
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=... token=... url=https://... proxies=https://user:pass@myproxy:8080') }}"
- name: 'use a socks proxy (need some additional dependencies, see: https://requests.readthedocs.io/en/master/user/advanced/#socks )'
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=... token=... url=https://... proxies=socks5://myproxy:1080') }}"
- name: use proxies with a dict (as param)
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', '...', proxies={'http': 'http://myproxy1', 'https': 'http://myproxy2'}) }}"
- name: use proxies with a dict (as param, pre-defined var)
vars:
prox:
http: http://myproxy1
https: https://myproxy2
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', '...', proxies=prox }}"
- name: use proxies with a dict (as direct ansible var)
vars:
ansible_hashi_vault_proxies:
http: http://myproxy1
https: https://myproxy2
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', '...' }}"
- name: use proxies with a dict (in the term string, JSON syntax)
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', '... proxies={\\"http\\":\\"http://myproxy1\\",\\"https\\":\\"http://myproxy2\\"}') }}"
- name: use ansible vars to supply some options
vars:
ansible_hashi_vault_url: 'https://myvault:8282'
ansible_hashi_vault_auth_method: token
set_fact:
secret1: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/data/secret1') }}"
secret2: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/data/secret2') }}"
- name: use a custom timeout
debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/data/secret1', timeout=120) }}"
- name: use a custom timeout and retry on failure 3 times (with collection retry defaults)
vars:
ansible_hashi_vault_timeout: 5
ansible_hashi_vault_retries: 3
debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/data/secret1') }}"
- name: retry on failure (with custom retry settings and no warnings)
vars:
ansible_hashi_vault_retries:
total: 6
backoff_factor: 0.9
status_forcelist: [500, 502]
allowed_methods:
- GET
- PUT
debug:
msg: "{{ lookup('community.hashi_vault.hashi_vault', 'secret/data/secret1', retry_action='warn') }}"
"""
RETURN = """
_raw:
description:
- secrets(s) requested
type: list
elements: dict
"""
from ansible.errors import AnsibleError
from ansible.utils.display import Display
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_lookup_base import HashiVaultLookupBase
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
display = Display()
HAS_HVAC = False
try:
import hvac
HAS_HVAC = True
except ImportError:
HAS_HVAC = False
class LookupModule(HashiVaultLookupBase):
def run(self, terms, variables=None, **kwargs):
if not HAS_HVAC:
raise AnsibleError("Please pip install hvac to use the hashi_vault lookup module.")
ret = []
for term in terms:
opts = kwargs.copy()
opts.update(self.parse_kev_term(term, first_unqualified='secret', plugin_name='hashi_vault'))
self.set_options(direct=opts, var_options=variables)
# TODO: remove process_deprecations() if backported fix is available (see method definition)
self.process_deprecations()
self.process_options()
client_args = self.connection_options.get_hvac_connection_options()
self.client = self.helper.get_vault_client(**client_args)
try:
self.authenticator.authenticate(self.client)
except (NotImplementedError, HashiVaultValueError) as e:
raise AnsibleError(e)
ret.extend(self.get())
return ret
def process_options(self):
'''performs deep validation and value loading for options'''
# process connection options
self.connection_options.process_connection_options()
try:
self.authenticator.validate()
except (NotImplementedError, HashiVaultValueError) as e:
raise AnsibleError(e)
# secret field splitter
self.field_ops()
# begin options processing methods
def field_ops(self):
# split secret and field
secret = self.get_option('secret')
s_f = secret.rsplit(':', 1)
self.set_option('secret', s_f[0])
if len(s_f) >= 2:
field = s_f[1]
else:
field = None
self.set_option('secret_field', field)
def get(self):
'''gets a secret. should always return a list'''
secret = self.get_option('secret')
field = self.get_option('secret_field')
return_as = self.get_option('return_format')
try:
data = self.client.read(secret)
except hvac.exceptions.Forbidden:
raise AnsibleError("Forbidden: Permission Denied to secret '%s'." % secret)
if data is None:
raise AnsibleError("The secret '%s' doesn't seem to exist." % secret)
if return_as == 'raw':
return [data]
# Check response for KV v2 fields and flatten nested secret data.
# https://vaultproject.io/api/secret/kv/kv-v2.html#sample-response-1
try:
# sentinel field checks
check_dd = data['data']['data']
check_md = data['data']['metadata']
# unwrap nested data
data = data['data']
except KeyError:
pass
if return_as == 'values':
return list(data['data'].values())
# everything after here implements return_as == 'dict'
if not field:
return [data['data']]
if field not in data['data']:
raise AnsibleError("The secret %s does not contain the field '%s'. for hashi_vault lookup" % (secret, field))
return [data['data'][field]]

View File

@@ -0,0 +1,337 @@
# (c) 2022, Brian Scholer (@briantist)
# 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'''
name: vault_ansible_settings
version_added: 2.5.0
author:
- Brian Scholer (@briantist)
short_description: Returns plugin settings (options)
description:
- Returns a dictionary of options and their values for a given plugin.
- This is most useful for using plugin settings in modules and C(module_defaults),
especially when common settings are set in C(ansible.cfg), in Ansible vars, or via environment variables on the controller.
- Options can be filtered by name, and can include or exclude defaults, unset options, and private options.
seealso:
- ref: Module defaults <module_defaults>
description: Using the C(module_defaults) keyword.
notes:
- This collection supports some "low precedence" environment variables that get loaded after all other sources, such as C(VAULT_ADDR).
- These environment variables B(are not supported) with this plugin.
- If you wish to use them, use the R(ansible.builtin.env lookup,ansible_collections.ansible.builtin.env_lookup) to
load them directly when calling a module or setting C(module_defaults).
- Similarly, any options that rely on additional processing to fill in their values will not have that done.
- For example, tokens will not be loaded from the token sink file, auth methods will not have their C(validate) methods called.
- See the examples for workarounds, but consider using Ansible-specific ways of setting these values instead.
options:
_terms:
description:
- The names of the options to load.
- Supports C(fnmatch) L(style wildcards,https://docs.python.org/3/library/fnmatch.html).
- Prepend any name or pattern with C(!) to invert the match.
type: list
elements: str
required: false
default: ['*']
plugin:
description:
- The name of the plugin whose options will be returned.
- Only lookups are supported.
- Short names (without a dot C(.)) will be fully qualified with C(community.hashi_vault).
type: str
default: community.hashi_vault.vault_login
include_private:
description: Include options that begin with underscore C(_).
type: bool
default: false
include_none:
description: Include options whose value is C(None) (this usually means they are unset).
type: bool
default: false
include_default:
description: Include options whose value comes from a default.
type: bool
default: false
'''
EXAMPLES = r'''
### In these examples, we assume an ansible.cfg like this:
# [hashi_vault_collection]
# url = https://config-based-vault.example.com
# retries = 5
### end ansible.cfg
### We assume some environment variables set as well
# ANSIBLE_HASHI_VAULT_URL: https://env-based-vault.example.com
# ANSIBLE_HASHI_VAULT_TOKEN: s.123456789
### end environment variables
# playbook - ansible-core 2.12 and higher
## set defaults for the collection group
- hosts: all
vars:
ansible_hashi_vault_auth_method: token
module_defaults:
group/community.hashi_vault.vault: "{{ lookup('community.hashi_vault.vault_ansible_settings') }}"
tasks:
- name: Get a secret from the remote host with settings from the controller
community.hashi_vault.vault_kv2_get:
path: app/some/secret
######
# playbook - ansible any version
## set defaults for a specific module
- hosts: all
vars:
ansible_hashi_vault_auth_method: token
module_defaults:
community.hashi_vault.vault_kv2_get: "{{ lookup('community.hashi_vault.vault_ansible_settings') }}"
tasks:
- name: Get a secret from the remote host with settings from the controller
community.hashi_vault.vault_kv2_get:
path: app/some/secret
######
# playbook - ansible any version
## set defaults for several modules
## do not use controller's auth
- hosts: all
vars:
ansible_hashi_vault_auth_method: aws_iam
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', '*', '!*token*') }}"
module_defaults:
community.hashi_vault.vault_kv2_get: '{{ settings }}'
community.hashi_vault.vault_kv1_get: '{{ settings }}'
tasks:
- name: Get a secret from the remote host with some settings from the controller, auth from remote
community.hashi_vault.vault_kv2_get:
path: app/some/secret
- name: Same with kv1
community.hashi_vault.vault_kv1_get:
path: app/some/secret
######
# playbook - ansible any version
## set defaults for several modules
## do not use controller's auth
## override returned settings
- hosts: all
vars:
ansible_hashi_vault_auth_method: userpass
plugin_settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', '*', '!*token*') }}"
overrides:
auth_method: aws_iam
retries: '{{ (plugin_settings.retries | int) + 2 }}'
settings: >-
{{
plugin_settings
| combine(overrides)
}}
module_defaults:
community.hashi_vault.vault_kv2_get: '{{ settings }}'
community.hashi_vault.vault_kv1_get: '{{ settings }}'
tasks:
- name: Get a secret from the remote host with some settings from the controller, auth from remote
community.hashi_vault.vault_kv2_get:
path: app/some/secret
- name: Same with kv1
community.hashi_vault.vault_kv1_get:
path: app/some/secret
######
# using a block is similar
- name: Settings
vars:
ansible_hashi_vault_auth_method: aws_iam
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', '*', '!*token*') }}"
module_defaults:
community.hashi_vault.vault_kv2_get: '{{ settings }}'
community.hashi_vault.vault_kv1_get: '{{ settings }}'
block:
- name: Get a secret from the remote host with some settings from the controller, auth from remote
community.hashi_vault.vault_kv2_get:
path: app/some/secret
- name: Same with kv1
community.hashi_vault.vault_kv1_get:
path: app/some/secret
#####
# use settings from a different plugin
## when you need settings that are not in the default plugin (vault_login)
- name: Settings
vars:
ansible_hashi_vault_engine_mount_point: dept-secrets
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', plugin='community.hashi_vault.vault_kv2_get') }}"
module_defaults:
community.hashi_vault.vault_kv2_get: '{{ settings }}'
block:
- name: Get a secret from the remote host with some settings from the controller, auth from remote
community.hashi_vault.vault_kv2_get:
path: app/some/secret
#####
# use settings from a different plugin (on an indivdual call)
## short names assume community.hashi_vault
- name: Settings
vars:
ansible_hashi_vault_engine_mount_point: dept-secrets
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings') }}"
module_defaults:
community.hashi_vault.vault_kv2_get: '{{ settings }}'
block:
- name: Get a secret from the remote host with some settings from the controller, auth from remote
community.hashi_vault.vault_kv2_get:
engine_mount_point: "{{ lookup('community.hashi_vault.vault_ansible_settings', plugin='vault_kv2_get') }}"
path: app/some/secret
#####
# normally, options with default values are not returned, but can be
- name: Settings
vars:
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings') }}"
module_defaults:
# we usually want to use the remote host's IAM auth
community.hashi_vault.vault_kv2_get: >-
{{
settings
| combine({'auth_method': aws_iam})
}}
block:
- name: Use the plugin auth method instead, even if it is the default method
community.hashi_vault.vault_kv2_get:
auth_method: "{{ lookup('community.hashi_vault.vault_ansible_settings', 'auth_method', include_default=True) }}"
path: app/some/secret
#####
# normally, options with None/null values are not returned,
# nor are private options (names begin with underscore _),
# but they can be returned too if desired
- name: Show all plugin settings
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_ansible_settings', include_none=True, include_private=True, include_default=True) }}"
#####
# dealing with low-precedence env vars and token sink loading
## here, VAULT_ADDR is usually used with plugins, but that will not work with vault_ansible_settings.
## additionally, the CLI `vault login` is used before running Ansible, so the token sink is usually used, which also will not work.
- hosts: all
vars:
plugin_settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', 'url', 'token*', include_default=True) }}"
overrides:
url: "{{ plugin_settings.url | default(lookup('ansible.builtin.env', 'VAULT_ADDR')) }}"
token: >-
{{
plugin_settings.token
| default(
lookup(
'ansible.builtin.file',
(
plugin_settings.token_path | default(lookup('ansible.builtin.env', 'HOME')),
plugin_settings.token_file
) | path_join
)
)
}}
auth_method: token
settings: >-
{{
plugin_settings
| combine(overrides)
}}
module_defaults:
community.hashi_vault.vault_kv2_get: "{{ lookup('community.hashi_vault.vault_ansible_settings') }}"
tasks:
- name: Get a secret from the remote host with settings from the controller
community.hashi_vault.vault_kv2_get:
path: app/some/secret
#####
'''
RETURN = r'''
_raw:
description:
- A dictionary of the options and their values.
- Only a single dictionary will be returned, even with multiple terms.
type: dict
sample:
retries: 5
timeout: 20
token: s.jRHAoqElnJDx6J5ExYelCDYR
url: https://vault.example.com
'''
from fnmatch import fnmatchcase
from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase
from ansible import constants as C
from ansible.plugins.loader import lookup_loader
from ansible.utils.display import Display
display = Display()
class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs):
self.set_options(direct=kwargs, var_options=variables)
include_private = self.get_option('include_private')
include_none = self.get_option('include_none')
include_default = self.get_option('include_default')
plugin = self.get_option('plugin')
if '.' not in plugin:
plugin = 'community.hashi_vault.' + plugin
if not terms:
terms = ['*']
opts = {}
try:
# ansible-core 2.10 or later
p = lookup_loader.find_plugin_with_context(plugin)
loadname = p.plugin_resolved_name
resolved = p.resolved
except AttributeError:
# ansible 2.9
p = lookup_loader.find_plugin_with_name(plugin)
loadname = p[0]
resolved = loadname is not None
if not resolved:
raise AnsibleError("'%s' plugin not found." % plugin)
# Loading ensures that the options are initialized in ConfigManager
lookup_loader.get(plugin, class_only=True)
pluginget = C.config.get_configuration_definitions('lookup', loadname)
for option in pluginget.keys():
if not include_private and option.startswith('_'):
continue
keep = False
for pattern in terms:
if pattern.startswith('!'):
if keep and fnmatchcase(option, pattern[1:]):
keep = False
else:
keep = keep or fnmatchcase(option, pattern)
if not keep:
continue
value, origin = C.config.get_config_value_and_origin(option, None, 'lookup', loadname, None, variables=variables)
if (include_none or value is not None) and (include_default or origin != 'default'):
opts[option] = value
return [opts]

View File

@@ -0,0 +1,220 @@
# (c) 2022, Brian Scholer (@briantist)
# 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'''
name: vault_kv1_get
version_added: 2.5.0
author:
- Brian Scholer (@briantist)
short_description: Get a secret from HashiCorp Vault's KV version 1 secret store
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:
- Gets a secret from HashiCorp Vault's KV version 1 secret store.
seealso:
- module: community.hashi_vault.vault_kv1_get
- ref: community.hashi_vault.vault_kv2_get lookup <ansible_collections.community.hashi_vault.vault_kv2_get_lookup>
description: The official documentation for the C(community.hashi_vault.vault_kv2_get) lookup plugin.
- module: community.hashi_vault.vault_kv2_get
- ref: community.hashi_vault Lookup Guide <ansible_collections.community.hashi_vault.docsite.lookup_guide>
description: Guidance on using lookups in C(community.hashi_vault).
- name: KV1 Secrets Engine
description: Documentation for the Vault KV secrets engine, version 1.
link: https://www.vaultproject.io/docs/secrets/kv/kv-v1
extends_documentation_fragment:
- community.hashi_vault.connection
- community.hashi_vault.connection.plugins
- community.hashi_vault.auth
- community.hashi_vault.auth.plugins
- community.hashi_vault.engine_mount
- community.hashi_vault.engine_mount.plugins
options:
_terms:
description:
- Vault KV path(s) to be read.
- These are relative to the I(engine_mount_point), so the mount path should not be included.
type: str
required: True
engine_mount_point:
default: kv
'''
EXAMPLES = r'''
- name: Read a kv1 secret with the default mount point
ansible.builtin.set_fact:
response: "{{ lookup('community.hashi_vault.vault_kv1_get', 'hello', url='https://vault:8201') }}"
# equivalent API path is kv/hello
- name: Display the results
ansible.builtin.debug:
msg:
- "Secret: {{ response.secret }}"
- "Data: {{ response.data }} (same as secret in kv1)"
- "Metadata: {{ response.metadata }} (response info in kv1)"
- "Full response: {{ response.raw }}"
- "Value of key 'password' in the secret: {{ response.secret.password }}"
- name: Read a kv1 secret with a different mount point
ansible.builtin.set_fact:
response: "{{ lookup('community.hashi_vault.vault_kv1_get', 'hello', engine_mount_point='custom/kv1/mount', url='https://vault:8201') }}"
# equivalent API path is custom/kv1/mount/hello
- name: Display the results
ansible.builtin.debug:
msg:
- "Secret: {{ response.secret }}"
- "Data: {{ response.data }} (same as secret in kv1)"
- "Metadata: {{ response.metadata }} (response info in kv1)"
- "Full response: {{ response.raw }}"
- "Value of key 'password' in the secret: {{ response.secret.password }}"
- name: Perform multiple kv1 reads with a single Vault login, showing the secrets
vars:
paths:
- hello
- my-secret/one
- my-secret/two
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_kv1_get', *paths, auth_method='userpass', username=user, password=pwd)['secret'] }}"
- name: Perform multiple kv1 reads with a single Vault login in a loop
vars:
paths:
- hello
- my-secret/one
- my-secret/two
ansible.builtin.debug:
msg: '{{ item }}'
loop: "{{ query('community.hashi_vault.vault_kv1_get', *paths, auth_method='userpass', username=user, password=pwd) }}"
- name: Perform multiple kv1 reads with a single Vault login in a loop (via with_), display values only
vars:
ansible_hashi_vault_auth_method: userpass
ansible_hashi_vault_username: '{{ user }}'
ansible_hashi_vault_password: '{{ pwd }}'
ansible.builtin.debug:
msg: '{{ item.values() | list }}'
with_community.hashi_vault.vault_kv1_get:
- hello
- my-secret/one
- my-secret/two
'''
RETURN = r'''
_raw:
description:
- The result of the read(s) against the given path(s).
type: list
elements: dict
contains:
raw:
description: The raw result of the read against the given path.
returned: success
type: dict
sample:
auth: null
data:
Key1: value1
Key2: value2
lease_duration: 2764800
lease_id: ""
renewable: false
request_id: e99f145f-f02a-7073-1229-e3f191057a70
warnings: null
wrap_info: null
data:
description: The C(data) field of raw result. This can also be accessed via C(raw.data).
returned: success
type: dict
sample:
Key1: value1
Key2: value2
secret:
description: The C(data) field of the raw result. This is identical to C(data) in the return values.
returned: success
type: dict
sample:
Key1: value1
Key2: value2
metadata:
description: This is a synthetic result. It is the same as C(raw) with C(data) removed.
returned: success
type: dict
sample:
auth: null
lease_duration: 2764800
lease_id: ""
renewable: false
request_id: e99f145f-f02a-7073-1229-e3f191057a70
warnings: null
wrap_info: null
'''
from ansible.errors import AnsibleError
from ansible.utils.display import Display
from ansible.module_utils.six import raise_from
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_lookup_base import HashiVaultLookupBase
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
display = Display()
try:
import hvac
except ImportError as imp_exc:
HVAC_IMPORT_ERROR = imp_exc
else:
HVAC_IMPORT_ERROR = None
class LookupModule(HashiVaultLookupBase):
def run(self, terms, variables=None, **kwargs):
if HVAC_IMPORT_ERROR:
raise_from(
AnsibleError("This plugin requires the 'hvac' Python library"),
HVAC_IMPORT_ERROR
)
ret = []
self.set_options(direct=kwargs, var_options=variables)
# TODO: remove process_deprecations() if backported fix is available (see method definition)
self.process_deprecations()
self.connection_options.process_connection_options()
client_args = self.connection_options.get_hvac_connection_options()
client = self.helper.get_vault_client(**client_args)
engine_mount_point = self._options_adapter.get_option('engine_mount_point')
try:
self.authenticator.validate()
self.authenticator.authenticate(client)
except (NotImplementedError, HashiVaultValueError) as e:
raise AnsibleError(e)
for term in terms:
try:
raw = client.secrets.kv.v1.read_secret(path=term, mount_point=engine_mount_point)
except hvac.exceptions.Forbidden as e:
raise_from(AnsibleError("Forbidden: Permission Denied to path ['%s']." % term), e)
except hvac.exceptions.InvalidPath as e:
if 'Invalid path for a versioned K/V secrets engine' in str(e):
msg = "Invalid path for a versioned K/V secrets engine ['%s']. If this is a KV version 2 path, use community.hashi_vault.vault_kv2_get."
else:
msg = "Invalid or missing path ['%s']."
raise_from(AnsibleError(msg % (term,)), e)
metadata = raw.copy()
data = metadata.pop('data')
ret.append(dict(raw=raw, data=data, secret=data, metadata=metadata))
return ret

View File

@@ -0,0 +1,233 @@
# (c) 2022, Brian Scholer (@briantist)
# 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'''
name: vault_kv2_get
version_added: 2.5.0
author:
- Brian Scholer (@briantist)
short_description: Get a secret from HashiCorp Vault's KV version 2 secret store
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:
- Gets a secret from HashiCorp Vault's KV version 2 secret store.
seealso:
- module: community.hashi_vault.vault_kv2_get
- ref: community.hashi_vault.vault_kv1_get lookup <ansible_collections.community.hashi_vault.vault_kv1_get_lookup>
description: The official documentation for the C(community.hashi_vault.vault_kv1_get) lookup plugin.
- module: community.hashi_vault.vault_kv1_get
- ref: community.hashi_vault Lookup Guide <ansible_collections.community.hashi_vault.docsite.lookup_guide>
description: Guidance on using lookups in C(community.hashi_vault).
- name: KV2 Secrets Engine
description: Documentation for the Vault KV secrets engine, version 2.
link: https://www.vaultproject.io/docs/secrets/kv/kv-v2
extends_documentation_fragment:
- community.hashi_vault.connection
- community.hashi_vault.connection.plugins
- community.hashi_vault.auth
- community.hashi_vault.auth.plugins
- community.hashi_vault.engine_mount
- community.hashi_vault.engine_mount.plugins
options:
_terms:
description:
- Vault KV path(s) to be read.
- These are relative to the I(engine_mount_point), so the mount path should not be included.
type: str
required: True
engine_mount_point:
default: secret
version:
description: Specifies the version to return. If not set the latest version is returned.
type: int
'''
EXAMPLES = r'''
- name: Read a kv2 secret with the default mount point
ansible.builtin.set_fact:
response: "{{ lookup('community.hashi_vault.vault_kv2_get', 'hello', url='https://vault:8201') }}"
# equivalent API path in 3.x.x is kv/data/hello
# equivalent API path in 4.0.0+ is secret/data/hello
- name: Display the results
ansible.builtin.debug:
msg:
- "Secret: {{ response.secret }}"
- "Data: {{ response.data }} (contains secret data & metadata in kv2)"
- "Metadata: {{ response.metadata }}"
- "Full response: {{ response.raw }}"
- "Value of key 'password' in the secret: {{ response.secret.password }}"
- name: Read version 5 of a kv2 secret with a different mount point
ansible.builtin.set_fact:
response: "{{ lookup('community.hashi_vault.vault_kv2_get', 'hello', version=5, engine_mount_point='custom/kv2/mount', url='https://vault:8201') }}"
# equivalent API path is custom/kv2/mount/data/hello
- name: Assert that the version returned is as expected
ansible.builtin.assert:
that:
- response.metadata.version == 5
- name: Perform multiple kv2 reads with a single Vault login, showing the secrets
vars:
paths:
- hello
- my-secret/one
- my-secret/two
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_kv2_get', *paths, auth_method='userpass', username=user, password=pwd)['secret'] }}"
- name: Perform multiple kv2 reads with a single Vault login in a loop
vars:
paths:
- hello
- my-secret/one
- my-secret/two
ansible.builtin.debug:
msg: '{{ item }}'
loop: "{{ query('community.hashi_vault.vault_kv2_get', *paths, auth_method='userpass', username=user, password=pwd) }}"
- name: Perform multiple kv2 reads with a single Vault login in a loop (via with_), display values only
vars:
ansible_hashi_vault_auth_method: userpass
ansible_hashi_vault_username: '{{ user }}'
ansible_hashi_vault_password: '{{ pwd }}'
ansible_hashi_vault_engine_mount_point: special/kv2
ansible.builtin.debug:
msg: '{{ item.values() | list }}'
with_community.hashi_vault.vault_kv2_get:
- hello
- my-secret/one
- my-secret/two
'''
RETURN = r'''
_raw:
description:
- The result of the read(s) against the given path(s).
type: list
elements: dict
contains:
raw:
description: The raw result of the read against the given path.
returned: success
type: dict
sample:
auth: null
data:
data:
Key1: value1
Key2: value2
metadata:
created_time: "2022-04-21T15:56:58.8525402Z"
custom_metadata: null
deletion_time: ""
destroyed: false
version: 2
lease_duration: 0
lease_id: ""
renewable: false
request_id: dc829675-9119-e831-ae74-35fc5d33d200
warnings: null
wrap_info: null
data:
description: The C(data) field of raw result. This can also be accessed via C(raw.data).
returned: success
type: dict
sample:
data:
Key1: value1
Key2: value2
metadata:
created_time: "2022-04-21T15:56:58.8525402Z"
custom_metadata: null
deletion_time: ""
destroyed: false
version: 2
secret:
description: The C(data) field within the C(data) field. Equivalent to C(raw.data.data).
returned: success
type: dict
sample:
Key1: value1
Key2: value2
metadata:
description: The C(metadata) field within the C(data) field. Equivalent to C(raw.data.metadata).
returned: success
type: dict
sample:
created_time: "2022-04-21T15:56:58.8525402Z"
custom_metadata: null
deletion_time: ""
destroyed: false
version: 2
'''
from ansible.errors import AnsibleError
from ansible.utils.display import Display
from ansible.module_utils.six import raise_from
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_lookup_base import HashiVaultLookupBase
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
display = Display()
try:
import hvac
except ImportError as imp_exc:
HVAC_IMPORT_ERROR = imp_exc
else:
HVAC_IMPORT_ERROR = None
class LookupModule(HashiVaultLookupBase):
def run(self, terms, variables=None, **kwargs):
if HVAC_IMPORT_ERROR:
raise_from(
AnsibleError("This plugin requires the 'hvac' Python library"),
HVAC_IMPORT_ERROR
)
ret = []
self.set_options(direct=kwargs, var_options=variables)
# TODO: remove process_deprecations() if backported fix is available (see method definition)
self.process_deprecations()
self.connection_options.process_connection_options()
client_args = self.connection_options.get_hvac_connection_options()
client = self.helper.get_vault_client(**client_args)
version = self._options_adapter.get_option_default('version')
engine_mount_point = self._options_adapter.get_option('engine_mount_point')
try:
self.authenticator.validate()
self.authenticator.authenticate(client)
except (NotImplementedError, HashiVaultValueError) as e:
raise AnsibleError(e)
for term in terms:
try:
raw = client.secrets.kv.v2.read_secret_version(path=term, version=version, mount_point=engine_mount_point)
except hvac.exceptions.Forbidden as e:
raise_from(AnsibleError("Forbidden: Permission Denied to path ['%s']." % term), e)
except hvac.exceptions.InvalidPath as e:
raise_from(
AnsibleError("Invalid or missing path ['%s'] with secret version '%s'. Check the path or secret version." % (term, version or 'latest')),
e
)
data = raw['data']
metadata = data['metadata']
secret = data['data']
ret.append(dict(raw=raw, data=data, secret=secret, metadata=metadata))
return ret

View File

@@ -0,0 +1,183 @@
# (c) 2023, Tom Kivlin (@tomkivlin)
# 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 = """
name: vault_list
version_added: 4.1.0
author:
- Tom Kivlin (@tomkivlin)
short_description: Perform a list operation against HashiCorp Vault
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:
- Performs a generic list operation against a given path in HashiCorp Vault.
seealso:
- module: community.hashi_vault.vault_list
extends_documentation_fragment:
- community.hashi_vault.connection
- community.hashi_vault.connection.plugins
- community.hashi_vault.auth
- community.hashi_vault.auth.plugins
options:
_terms:
description: Vault path(s) to be listed.
type: str
required: true
"""
EXAMPLES = """
- name: List all secrets at a path
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_list', 'secret/metadata', url='https://vault:8201') }}"
# For kv2, the path needs to follow the pattern 'mount_point/metadata' or 'mount_point/metadata/path' to list all secrets in that path
- name: List access policies
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_list', 'sys/policies/acl', url='https://vault:8201') }}"
- name: Perform multiple list operations with a single Vault login
vars:
paths:
- secret/metadata
- sys/policies/acl
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_list', *paths, auth_method='userpass', username=user, password=pwd) }}"
- name: Perform multiple list operations with a single Vault login in a loop
vars:
paths:
- secret/metadata
- sys/policies/acl
ansible.builtin.debug:
msg: '{{ item }}'
loop: "{{ query('community.hashi_vault.vault_list', *paths, auth_method='userpass', username=user, password=pwd) }}"
- name: Perform list operations with a single Vault login in a loop (via with_)
vars:
ansible_hashi_vault_auth_method: userpass
ansible_hashi_vault_username: '{{ user }}'
ansible_hashi_vault_password: '{{ pwd }}'
ansible.builtin.debug:
msg: '{{ item }}'
with_community.hashi_vault.vault_list:
- secret/metadata
- sys/policies/acl
- name: Create fact consisting of list of dictionaries each with secret name (e.g. username) and value of a key (e.g. 'password') within that secret
ansible.builtin.set_fact:
credentials: >-
{{
credentials
| default([]) + [
{
'username': item,
'password': lookup('community.hashi_vault.vault_kv2_get', item, engine_mount_point='vpn-users').secret.password
}
]
}}
loop: "{{ query('community.hashi_vault.vault_list', 'vpn-users/metadata')[0].data['keys'] }}"
no_log: true
- ansible.builtin.debug:
msg: "{{ credentials }}"
- name: Create the same as above without looping, and only 2 logins
vars:
secret_names: >-
{{
query('community.hashi_vault.vault_list', 'vpn-users/metadata')
| map(attribute='data')
| map(attribute='keys')
| flatten
}}
secret_values: >-
{{
lookup('community.hashi_vault.vault_kv2_get', *secret_names, engine_mount_point='vpn-users')
| map(attribute='secret')
| map(attribute='password')
| flatten
}}
credentials_dict: "{{ dict(secret_names | zip(secret_values)) }}"
ansible.builtin.set_fact:
credentials_dict: "{{ credentials_dict }}"
credentials_list: "{{ credentials_dict | dict2items(key_name='username', value_name='password') }}"
no_log: true
- ansible.builtin.debug:
msg:
- "Dictionary: {{ credentials_dict }}"
- "List: {{ credentials_list }}"
- name: List all userpass users and output the token policies for each user
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_read', 'auth/userpass/users/' + item).data.token_policies }}"
loop: "{{ query('community.hashi_vault.vault_list', 'auth/userpass/users')[0].data['keys'] }}"
"""
RETURN = """
_raw:
description:
- The raw result of the read against the given path.
type: list
elements: dict
"""
from ansible.errors import AnsibleError
from ansible.utils.display import Display
from ansible.module_utils.six import raise_from
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_lookup_base import HashiVaultLookupBase
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
display = Display()
try:
import hvac
except ImportError as imp_exc:
HVAC_IMPORT_ERROR = imp_exc
else:
HVAC_IMPORT_ERROR = None
class LookupModule(HashiVaultLookupBase):
def run(self, terms, variables=None, **kwargs):
if HVAC_IMPORT_ERROR:
raise_from(
AnsibleError("This plugin requires the 'hvac' Python library"),
HVAC_IMPORT_ERROR
)
ret = []
self.set_options(direct=kwargs, var_options=variables)
# TODO: remove process_deprecations() if backported fix is available (see method definition)
self.process_deprecations()
self.connection_options.process_connection_options()
client_args = self.connection_options.get_hvac_connection_options()
client = self.helper.get_vault_client(**client_args)
try:
self.authenticator.validate()
self.authenticator.authenticate(client)
except (NotImplementedError, HashiVaultValueError) as e:
raise AnsibleError(e)
for term in terms:
try:
data = client.list(term)
except hvac.exceptions.Forbidden:
raise AnsibleError("Forbidden: Permission Denied to path '%s'." % term)
if data is None:
raise AnsibleError("The path '%s' doesn't seem to exist." % term)
ret.append(data)
return ret

View File

@@ -0,0 +1,138 @@
# (c) 2021, Brian Scholer (@briantist)
# 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 = """
name: vault_login
version_added: 2.2.0
author:
- Brian Scholer (@briantist)
short_description: Perform a login operation against HashiCorp Vault
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:
- Performs a login operation against a given path in HashiCorp Vault, returning the login response, including the token.
seealso:
- module: community.hashi_vault.vault_login
- ref: community.hashi_vault.vault_login_token filter <ansible_collections.community.hashi_vault.vault_login_token_filter>
description: The official documentation for the C(community.hashi_vault.vault_login_token) filter plugin.
notes:
- This lookup does not use the term string and will not work correctly in loops. Only a single response will be returned.
- "A login is a write operation (creating a token persisted to storage), so this module always reports C(changed=True),
except when used with C(token) auth, because no new token is created in that case. For the purposes of Ansible playbooks however,
it may be more useful to set C(changed_when=false) if you're doing idempotency checks against the target system."
- The C(none) auth method is not valid for this plugin because there is no response to return.
- "With C(token) auth, no actual login is performed.
Instead, the given token's additional information is returned in a structure that resembles what login responses look like."
- "The C(token) auth method will only return full information if I(token_validate=True).
If the token does not have the C(lookup-self) capability, this will fail. If I(token_validate=False), only the token value itself
will be returned in the structure."
extends_documentation_fragment:
- community.hashi_vault.connection
- community.hashi_vault.connection.plugins
- community.hashi_vault.auth
- community.hashi_vault.auth.plugins
options:
_terms:
description: This is unused and any terms supplied will be ignored.
type: str
required: false
token_validate:
default: true
"""
EXAMPLES = """
- name: Set a fact with a lookup result
set_fact:
login_data: "{{ lookup('community.hashi_vault.vault_login', url='https://vault', auth_method='userpass', username=user, password=pwd) }}"
- name: Retrieve an approle role ID (token via filter)
community.hashi_vault.vault_read:
url: https://vault:8201
auth_method: token
token: '{{ login_data | community.hashi_vault.vault_login_token }}'
path: auth/approle/role/role-name/role-id
register: approle_id
- name: Retrieve an approle role ID (token via direct dict access)
community.hashi_vault.vault_read:
url: https://vault:8201
auth_method: token
token: '{{ login_data.auth.client_token }}'
path: auth/approle/role/role-name/role-id
register: approle_id
"""
RETURN = """
_raw:
description:
- The result of the login with the given auth method.
type: list
elements: dict
contains:
auth:
description: The C(auth) member of the login response.
returned: success
type: dict
contains:
client_token:
description: Contains the token provided by the login operation (or the input token when I(auth_method=token)).
returned: success
type: str
data:
description: The C(data) member of the login response.
returned: success, when available
type: dict
"""
from ansible.errors import AnsibleError
from ansible.utils.display import Display
from ansible.module_utils.six import raise_from
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_lookup_base import HashiVaultLookupBase
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
display = Display()
try:
import hvac
except ImportError as imp_exc:
HVAC_IMPORT_ERROR = imp_exc
else:
HVAC_IMPORT_ERROR = None
class LookupModule(HashiVaultLookupBase):
def run(self, terms, variables=None, **kwargs):
if HVAC_IMPORT_ERROR:
raise_from(
AnsibleError("This plugin requires the 'hvac' Python library"),
HVAC_IMPORT_ERROR
)
self.set_options(direct=kwargs, var_options=variables)
# TODO: remove process_deprecations() if backported fix is available (see method definition)
self.process_deprecations()
if self.get_option('auth_method') == 'none':
raise AnsibleError("The 'none' auth method is not valid for this lookup.")
self.connection_options.process_connection_options()
client_args = self.connection_options.get_hvac_connection_options()
client = self.helper.get_vault_client(**client_args)
if len(terms) != 0:
display.warning("Supplied term strings will be ignored. This lookup does not use term strings.")
try:
self.authenticator.validate()
response = self.authenticator.authenticate(client)
except (NotImplementedError, HashiVaultValueError) as e:
raise AnsibleError(e)
return [response]

View File

@@ -0,0 +1,137 @@
# (c) 2021, Brian Scholer (@briantist)
# 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 = """
name: vault_read
version_added: 1.4.0
author:
- Brian Scholer (@briantist)
short_description: Perform a read operation against HashiCorp Vault
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:
- Performs a generic read operation against a given path in HashiCorp Vault.
seealso:
- module: community.hashi_vault.vault_read
- ref: community.hashi_vault.hashi_vault lookup <ansible_collections.community.hashi_vault.hashi_vault_lookup>
description: The official documentation for the C(community.hashi_vault.hashi_vault) lookup plugin.
extends_documentation_fragment:
- community.hashi_vault.connection
- community.hashi_vault.connection.plugins
- community.hashi_vault.auth
- community.hashi_vault.auth.plugins
options:
_terms:
description: Vault path(s) to be read.
type: str
required: True
"""
EXAMPLES = """
- name: Read a kv2 secret
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_read', 'secret/data/hello', url='https://vault:8201') }}"
- name: Retrieve an approle role ID
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_read', 'auth/approle/role/role-name/role-id', url='https://vault:8201') }}"
- name: Perform multiple reads with a single Vault login
vars:
paths:
- secret/data/hello
- auth/approle/role/role-one/role-id
- auth/approle/role/role-two/role-id
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_read', *paths, auth_method='userpass', username=user, password=pwd) }}"
- name: Perform multiple reads with a single Vault login in a loop
vars:
paths:
- secret/data/hello
- auth/approle/role/role-one/role-id
- auth/approle/role/role-two/role-id
ansible.builtin.debug:
msg: '{{ item }}'
loop: "{{ query('community.hashi_vault.vault_read', *paths, auth_method='userpass', username=user, password=pwd) }}"
- name: Perform multiple reads with a single Vault login in a loop (via with_)
vars:
ansible_hashi_vault_auth_method: userpass
ansible_hashi_vault_username: '{{ user }}'
ansible_hashi_vault_password: '{{ pwd }}'
ansible.builtin.debug:
msg: '{{ item }}'
with_community.hashi_vault.vault_read:
- secret/data/hello
- auth/approle/role/role-one/role-id
- auth/approle/role/role-two/role-id
"""
RETURN = """
_raw:
description:
- The raw result of the read against the given path.
type: list
elements: dict
"""
from ansible.errors import AnsibleError
from ansible.utils.display import Display
from ansible.module_utils.six import raise_from
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_lookup_base import HashiVaultLookupBase
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
display = Display()
try:
import hvac
except ImportError as imp_exc:
HVAC_IMPORT_ERROR = imp_exc
else:
HVAC_IMPORT_ERROR = None
class LookupModule(HashiVaultLookupBase):
def run(self, terms, variables=None, **kwargs):
if HVAC_IMPORT_ERROR:
raise_from(
AnsibleError("This plugin requires the 'hvac' Python library"),
HVAC_IMPORT_ERROR
)
ret = []
self.set_options(direct=kwargs, var_options=variables)
# TODO: remove process_deprecations() if backported fix is available (see method definition)
self.process_deprecations()
self.connection_options.process_connection_options()
client_args = self.connection_options.get_hvac_connection_options()
client = self.helper.get_vault_client(**client_args)
try:
self.authenticator.validate()
self.authenticator.authenticate(client)
except (NotImplementedError, HashiVaultValueError) as e:
raise AnsibleError(e)
for term in terms:
try:
data = client.read(term)
except hvac.exceptions.Forbidden:
raise AnsibleError("Forbidden: Permission Denied to path '%s'." % term)
if data is None:
raise AnsibleError("The path '%s' doesn't seem to exist." % term)
ret.append(data)
return ret

View File

@@ -0,0 +1,195 @@
# (c) 2022, Brian Scholer (@briantist)
# 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 = """
name: vault_token_create
version_added: 2.3.0
author:
- Brian Scholer (@briantist)
short_description: Create a HashiCorp Vault token
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 token in HashiCorp Vault, returning the response, including the token.
seealso:
- module: community.hashi_vault.vault_token_create
- ref: community.hashi_vault.vault_login lookup <ansible_collections.community.hashi_vault.vault_login_lookup>
description: The official documentation for the C(community.hashi_vault.vault_login) lookup plugin.
- module: community.hashi_vault.vault_login
- ref: community.hashi_vault.vault_login_token filter <ansible_collections.community.hashi_vault.vault_login_token_filter>
description: The official documentation for the C(community.hashi_vault.vault_login_token) filter plugin.
notes:
- Token creation is a write operation (creating a token persisted to storage), so this module always reports C(changed=True).
- For the purposes of Ansible playbooks however,
it may be more useful to set I(changed_when=false) if you are doing idempotency checks against the target system.
- In check mode, this module will not create a token, and will instead return a basic structure with an empty token.
However, this may not be useful if the token is required for follow on tasks.
It may be better to use this module with I(check_mode=no) in order to have a valid token that can be used.
extends_documentation_fragment:
- community.hashi_vault.connection
- community.hashi_vault.connection.plugins
- community.hashi_vault.auth
- community.hashi_vault.auth.plugins
- community.hashi_vault.token_create
- community.hashi_vault.wrapping
- community.hashi_vault.wrapping.plugins
options:
_terms:
description: This is unused and any terms supplied will be ignored.
type: str
required: false
"""
EXAMPLES = """
- name: Login via userpass and create a child token
ansible.builtin.set_fact:
token_data: "{{ lookup('community.hashi_vault.vault_token_create', url='https://vault', auth_method='userpass', username=user, password=passwd) }}"
- name: Retrieve an approle role ID using the child token (token via filter)
community.hashi_vault.vault_read:
url: https://vault:8201
auth_method: token
token: '{{ token_data | community.hashi_vault.vault_login_token }}'
path: auth/approle/role/role-name/role-id
register: approle_id
- name: Retrieve an approle role ID (token via direct dict access)
community.hashi_vault.vault_read:
url: https://vault:8201
auth_method: token
token: '{{ token_data.auth.client_token }}'
path: auth/approle/role/role-name/role-id
register: approle_id
# implicitly uses url & token auth with a token from the environment
- name: Create an orphaned token with a short TTL and display the full response
ansible.builtin.debug:
var: lookup('community.hashi_vault.vault_token_create', orphan=True, ttl='60s')
"""
RETURN = """
_raw:
description: The result of the token creation operation.
returned: success
type: dict
sample:
auth:
client_token: s.rlwajI2bblHAWU7uPqZhLru3
data: null
contains:
auth:
description: The C(auth) member of the token response.
returned: success
type: dict
contains:
client_token:
description: Contains the newly created token.
returned: success
type: str
data:
description: The C(data) member of the token response.
returned: success, when available
type: dict
"""
from ansible.errors import AnsibleError
from ansible.utils.display import Display
from ansible.module_utils.six import raise_from
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_lookup_base import HashiVaultLookupBase
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
display = Display()
try:
import hvac
except ImportError as imp_exc:
HVAC_IMPORT_ERROR = imp_exc
else:
HVAC_IMPORT_ERROR = None
class LookupModule(HashiVaultLookupBase):
PASS_THRU_OPTION_NAMES = [
'no_parent',
'no_default_policy',
'policies',
'id',
'role_name',
'meta',
'renewable',
'ttl',
'type',
'explicit_max_ttl',
'display_name',
'num_uses',
'period',
'entity_alias',
'wrap_ttl',
]
ORPHAN_OPTION_TRANSLATION = {
'id': 'token_id',
'role_name': 'role',
'type': 'token_type',
}
def run(self, terms, variables=None, **kwargs):
if HVAC_IMPORT_ERROR:
raise_from(
AnsibleError("This plugin requires the 'hvac' Python library"),
HVAC_IMPORT_ERROR
)
self.set_options(direct=kwargs, var_options=variables)
# TODO: remove process_deprecations() if backported fix is available (see method definition)
self.process_deprecations()
self.connection_options.process_connection_options()
client_args = self.connection_options.get_hvac_connection_options()
client = self.helper.get_vault_client(**client_args)
if len(terms) != 0:
display.warning("Supplied term strings will be ignored. This lookup does not use term strings.")
try:
self.authenticator.validate()
self.authenticator.authenticate(client)
except (NotImplementedError, HashiVaultValueError) as e:
raise AnsibleError(e)
pass_thru_options = self._options_adapter.get_filled_options(*self.PASS_THRU_OPTION_NAMES)
orphan_options = pass_thru_options.copy()
for key in pass_thru_options.keys():
if key in self.ORPHAN_OPTION_TRANSLATION:
orphan_options[self.ORPHAN_OPTION_TRANSLATION[key]] = orphan_options.pop(key)
response = None
if self.get_option('orphan'):
try:
try:
# this method was added in hvac 1.0.0
# See: https://github.com/hvac/hvac/pull/869
response = client.auth.token.create_orphan(**orphan_options)
except AttributeError:
# this method was removed in hvac 1.0.0
# See: https://github.com/hvac/hvac/issues/758
response = client.create_token(orphan=True, **orphan_options)
except Exception as e:
raise AnsibleError(e)
else:
try:
response = client.auth.token.create(**pass_thru_options)
except Exception as e:
raise AnsibleError(e)
return [response]

View File

@@ -0,0 +1,191 @@
# (c) 2022, Brian Scholer (@briantist)
# 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 = """
name: vault_write
version_added: 2.4.0
author:
- Brian Scholer (@briantist)
short_description: Perform a write operation against HashiCorp Vault
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:
- Performs a generic write operation against a given path in HashiCorp Vault, returning any output.
seealso:
- module: community.hashi_vault.vault_write
- ref: community.hashi_vault.vault_read lookup <ansible_collections.community.hashi_vault.vault_read_lookup>
description: The official documentation for the C(community.hashi_vault.vault_read) lookup plugin.
- module: community.hashi_vault.vault_read
- ref: community.hashi_vault Lookup Guide <ansible_collections.community.hashi_vault.docsite.lookup_guide>
description: Guidance on using lookups in C(community.hashi_vault).
notes:
- C(vault_write) is a generic plugin to do operations that do not yet have a dedicated plugin. Where a specific plugin exists, that should be used instead.
- In the vast majority of cases, it will be better to do writes as a task, with the M(community.hashi_vault.vault_write) module.
- The lookup can be used in cases where you need a value directly in templating, but there is risk of executing the write many times unintentionally.
- The lookup is best used for endpoints that directly manipulate the input data and return a value, while not changing state in Vault.
- See the R(Lookup Guide,ansible_collections.community.hashi_vault.docsite.lookup_guide) for more information.
extends_documentation_fragment:
- community.hashi_vault.connection
- community.hashi_vault.connection.plugins
- community.hashi_vault.auth
- community.hashi_vault.auth.plugins
- community.hashi_vault.wrapping
- community.hashi_vault.wrapping.plugins
options:
_terms:
description: Vault path(s) to be written to.
type: str
required: true
data:
description: A dictionary to be serialized to JSON and then sent as the request body.
type: dict
required: false
default: {}
"""
EXAMPLES = """
# These examples show some uses that might work well as a lookup.
# For most uses, the vault_write module should be used.
- name: Retrieve and display random data
vars:
data:
format: hex
num_bytes: 64
ansible.builtin.debug:
msg: "{{ lookup('community.hashi_vault.vault_write', 'sys/tools/random/' ~ num_bytes, data=data) }}"
- name: Hash some data and display the hash
vars:
input: |
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Pellentesque posuere dui a ipsum dapibus, et placerat nibh bibendum.
data:
input: '{{ input | b64encode }}'
hash_algo: sha2-256
ansible.builtin.debug:
msg: "The hash is {{ lookup('community.hashi_vault.vault_write', 'sys/tools/hash/' ~ hash_algo, data=data) }}"
# In this next example, the Ansible controller's token does not have permission to read the secrets we need.
# It does have permission to generate new secret IDs for an approle which has permission to read the secrets,
# however the approle is configured to:
# 1) allow a maximum of 1 use per secret ID
# 2) restrict the IPs allowed to use login using the approle to those of the remote hosts
#
# Normally, the fact that a new secret ID would be generated on every loop iteration would not be desirable,
# but here it's quite convenient.
- name: Retrieve secrets from the remote host with one-time-use approle creds
vars:
role_id: "{{ lookup('community.hashi_vault.vault_read', 'auth/approle/role/role-name/role-id') }}"
secret_id: "{{ lookup('community.hashi_vault.vault_write', 'auth/approle/role/role-name/secret-id') }}"
community.hashi_vault.vault_read:
auth_method: approle
role_id: '{{ role_id }}'
secret_id: '{{ secret_id }}'
path: '{{ item }}'
register: secret_data
loop:
- secret/data/secret1
- secret/data/app/deploy-key
- secret/data/access-codes/self-destruct
# This time we have a secret values on the controller, and we need to run a command the remote host,
# that is expecting to a use single-use token as input, so we need to use wrapping to send the data.
- name: Run a command that needs wrapped secrets
vars:
secrets:
secret1: '{{ my_secret_1 }}'
secret2: '{{ second_secret }}'
wrapped: "{{ lookup('community.hashi_vault.vault_write', 'sys/wrapping/wrap', data=secrets) }}"
ansible.builtin.command: 'vault unwrap {{ wrapped }}'
"""
RETURN = """
_raw:
description: The raw result of the write against the given path.
type: list
elements: dict
"""
from ansible.errors import AnsibleError
from ansible.utils.display import Display
from ansible.module_utils.six import raise_from
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_lookup_base import HashiVaultLookupBase
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultValueError
display = Display()
try:
import hvac
except ImportError as imp_exc:
HVAC_IMPORT_ERROR = imp_exc
else:
HVAC_IMPORT_ERROR = None
class LookupModule(HashiVaultLookupBase):
def run(self, terms, variables=None, **kwargs):
if HVAC_IMPORT_ERROR:
raise_from(
AnsibleError("This plugin requires the 'hvac' Python library"),
HVAC_IMPORT_ERROR
)
ret = []
self.set_options(direct=kwargs, var_options=variables)
# TODO: remove process_deprecations() if backported fix is available (see method definition)
self.process_deprecations()
self.connection_options.process_connection_options()
client_args = self.connection_options.get_hvac_connection_options()
client = self.helper.get_vault_client(**client_args)
data = self._options_adapter.get_option('data')
wrap_ttl = self._options_adapter.get_option_default('wrap_ttl')
try:
self.authenticator.validate()
self.authenticator.authenticate(client)
except (NotImplementedError, HashiVaultValueError) as e:
raise_from(AnsibleError(e), e)
for term in terms:
try:
response = client.write(path=term, wrap_ttl=wrap_ttl, **data)
except hvac.exceptions.Forbidden as e:
raise_from(AnsibleError("Forbidden: Permission Denied to path '%s'." % term), e)
except hvac.exceptions.InvalidPath as e:
raise_from(AnsibleError("The path '%s' doesn't seem to exist." % term), e)
except hvac.exceptions.InternalServerError as e:
raise_from(AnsibleError("Internal Server Error: %s" % str(e)), e)
# https://github.com/hvac/hvac/issues/797
# HVAC returns a raw response object when the body is not JSON.
# That includes 204 responses, which are successful with no body.
# So we will try to detect that and a act accordingly.
# A better way may be to implement our own adapter for this
# collection, but it's a little premature to do that.
if hasattr(response, 'json') and callable(response.json):
if response.status_code == 204:
output = {}
else:
display.warning('Vault returned status code %i and an unparsable body.' % response.status_code)
output = response.content
else:
output = response
ret.append(output)
return ret

View File

@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultAuthMethodBase
class HashiVaultAuthMethodApprole(HashiVaultAuthMethodBase):
'''HashiVault option group class for auth: approle'''
NAME = 'approle'
OPTIONS = ['role_id', 'secret_id', 'mount_point']
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodApprole, self).__init__(option_adapter, warning_callback, deprecate_callback)
def validate(self):
self.validate_by_required_fields('role_id')
def authenticate(self, client, use_token=True):
params = self._options.get_filled_options(*self.OPTIONS)
try:
response = client.auth.approle.login(use_token=use_token, **params)
except (NotImplementedError, AttributeError):
self.warn("HVAC should be updated to version 0.10.6 or higher. Deprecated method 'auth_approle' will be used.")
response = client.auth_approle(use_token=use_token, **params)
return response

View File

@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import (
HashiVaultAuthMethodBase,
HashiVaultValueError,
)
class HashiVaultAuthMethodAwsIam(HashiVaultAuthMethodBase):
'''HashiVault option group class for auth: userpass'''
NAME = 'aws_iam'
OPTIONS = [
'aws_profile',
'aws_access_key',
'aws_secret_key',
'aws_security_token',
'region',
'aws_iam_server_id',
'role_id',
]
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodAwsIam, self).__init__(option_adapter, warning_callback, deprecate_callback)
def validate(self):
params = {
'access_key': self._options.get_option_default('aws_access_key'),
'secret_key': self._options.get_option_default('aws_secret_key'),
}
session_token = self._options.get_option_default('aws_security_token')
if session_token:
params['session_token'] = session_token
mount_point = self._options.get_option_default('mount_point')
if mount_point:
params['mount_point'] = mount_point
role = self._options.get_option_default('role_id')
if role:
params['role'] = role
region = self._options.get_option_default('region')
if region:
params['region'] = region
header_value = self._options.get_option_default('aws_iam_server_id')
if header_value:
params['header_value'] = header_value
if not (params['access_key'] and params['secret_key']):
try:
import boto3
import botocore
except ImportError:
raise HashiVaultValueError("boto3 is required for loading a profile or IAM role credentials.")
profile = self._options.get_option_default('aws_profile')
try:
session_credentials = boto3.session.Session(profile_name=profile).get_credentials()
except botocore.exceptions.ProfileNotFound:
raise HashiVaultValueError("The AWS profile '%s' was not found." % profile)
if not session_credentials:
raise HashiVaultValueError("No AWS credentials supplied or available.")
params['access_key'] = session_credentials.access_key
params['secret_key'] = session_credentials.secret_key
if session_credentials.token:
params['session_token'] = session_credentials.token
self._auth_aws_iam_login_params = params
def authenticate(self, client, use_token=True):
params = self._auth_aws_iam_login_params
try:
response = client.auth.aws.iam_login(use_token=use_token, **params)
except (NotImplementedError, AttributeError):
self.warn("HVAC should be updated to version 0.9.3 or higher. Deprecated method 'auth_aws_iam' will be used.")
client.auth_aws_iam(use_token=use_token, **params)
return response

View File

@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022 Junrui Chen (@jchenship)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import (
HashiVaultAuthMethodBase,
HashiVaultValueError,
)
class HashiVaultAuthMethodAzure(HashiVaultAuthMethodBase):
'''HashiVault auth method for Azure'''
NAME = 'azure'
OPTIONS = [
'role_id',
'jwt',
'mount_point',
'azure_tenant_id',
'azure_client_id',
'azure_client_secret',
'azure_resource',
]
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodAzure, self).__init__(
option_adapter, warning_callback, deprecate_callback
)
def validate(self):
params = {
'role': self._options.get_option_default('role_id'),
'jwt': self._options.get_option_default('jwt'),
}
if not params['role']:
raise HashiVaultValueError(
'role_id is required for azure authentication.'
)
# if mount_point is not provided, it will use the default value defined
# in hvac library (e.g. `azure`)
mount_point = self._options.get_option_default('mount_point')
if mount_point:
params['mount_point'] = mount_point
# if jwt exists, use provided jwt directly, otherwise trying to get jwt
# from azure service principal or managed identity
if not params['jwt']:
azure_tenant_id = self._options.get_option_default('azure_tenant_id')
azure_client_id = self._options.get_option_default('azure_client_id')
azure_client_secret = self._options.get_option_default('azure_client_secret')
# the logic of getting azure scope is from this function
# https://github.com/Azure/azure-cli/blob/azure-cli-2.39.0/src/azure-cli-core/azure/cli/core/auth/util.py#L72
# the reason we expose resource instead of scope is resource is
# more aligned with the vault azure auth config here
# https://www.vaultproject.io/api-docs/auth/azure#resource
azure_resource = self._options.get_option('azure_resource')
azure_scope = azure_resource + "/.default"
try:
import azure.identity
except ImportError:
raise HashiVaultValueError(
"azure-identity is required for getting access token from azure service principal or managed identity."
)
if azure_client_id and azure_client_secret:
# service principal
if not azure_tenant_id:
raise HashiVaultValueError(
'azure_tenant_id is required when using azure service principal.'
)
azure_credentials = azure.identity.ClientSecretCredential(
azure_tenant_id, azure_client_id, azure_client_secret
)
elif azure_client_id:
# user assigned managed identity
azure_credentials = azure.identity.ManagedIdentityCredential(
client_id=azure_client_id
)
else:
# system assigned managed identity
azure_credentials = azure.identity.ManagedIdentityCredential()
params['jwt'] = azure_credentials.get_token(azure_scope).token
self._auth_azure_login_params = params
def authenticate(self, client, use_token=True):
params = self._auth_azure_login_params
response = client.auth.azure.login(use_token=use_token, **params)
return response

View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Devon Mar (@devon-mar)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultAuthMethodBase
class HashiVaultAuthMethodCert(HashiVaultAuthMethodBase):
"""HashiVault option group class for auth: cert"""
NAME = "cert"
OPTIONS = ["cert_auth_public_key", "cert_auth_private_key", "mount_point", "role_id"]
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodCert, self).__init__(option_adapter, warning_callback, deprecate_callback)
def validate(self):
self.validate_by_required_fields("cert_auth_public_key", "cert_auth_private_key")
def authenticate(self, client, use_token=True):
options = self._options.get_filled_options(*self.OPTIONS)
params = {
"cert_pem": options["cert_auth_public_key"],
"key_pem": options["cert_auth_private_key"],
}
if "mount_point" in options:
params["mount_point"] = options["mount_point"]
if "role_id" in options:
params["name"] = options["role_id"]
try:
response = client.auth.cert.login(use_token=use_token, **params)
except NotImplementedError:
raise NotImplementedError("cert authentication requires HVAC version 0.10.12 or higher.")
return response

View File

@@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultAuthMethodBase
class HashiVaultAuthMethodJwt(HashiVaultAuthMethodBase):
'''HashiVault option group class for auth: jwt'''
NAME = 'jwt'
OPTIONS = ['jwt', 'role_id', 'mount_point']
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodJwt, self).__init__(option_adapter, warning_callback, deprecate_callback)
def validate(self):
self.validate_by_required_fields('role_id', 'jwt')
def authenticate(self, client, use_token=True):
params = self._options.get_filled_options(*self.OPTIONS)
params['role'] = params.pop('role_id')
if 'mount_point' in params:
params['path'] = params.pop('mount_point')
try:
response = client.auth.jwt.jwt_login(**params)
except (NotImplementedError, AttributeError):
raise NotImplementedError("JWT authentication requires HVAC version 0.10.5 or higher.")
# must manually set the client token with JWT login
# see https://github.com/hvac/hvac/issues/644
# fixed in https://github.com/hvac/hvac/pull/746
# but we do it manually to maintain compatibilty with older hvac versions.
if use_token:
client.token = response['auth']['client_token']
return response

View File

@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultAuthMethodBase
class HashiVaultAuthMethodLdap(HashiVaultAuthMethodBase):
'''HashiVault option group class for auth: ldap'''
NAME = 'ldap'
OPTIONS = ['username', 'password', 'mount_point']
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodLdap, self).__init__(option_adapter, warning_callback, deprecate_callback)
def validate(self):
self.validate_by_required_fields('username', 'password')
def authenticate(self, client, use_token=True):
params = self._options.get_filled_options(*self.OPTIONS)
try:
response = client.auth.ldap.login(use_token=use_token, **params)
except (NotImplementedError, AttributeError):
self.warn("HVAC should be updated to version 0.7.0 or higher. Deprecated method 'auth_ldap' will be used.")
response = client.auth_ldap(use_token=use_token, **params)
return response

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultAuthMethodBase
class HashiVaultAuthMethodNone(HashiVaultAuthMethodBase):
'''HashiVault option group class for auth: none'''
NAME = 'none'
OPTIONS = []
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodNone, self).__init__(option_adapter, warning_callback, deprecate_callback)
def validate(self):
pass
def authenticate(self, client, use_token=False):
return None

View File

@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import (
HashiVaultAuthMethodBase,
HashiVaultValueError,
)
class HashiVaultAuthMethodToken(HashiVaultAuthMethodBase):
'''HashiVault option group class for auth: userpass'''
NAME = 'token'
OPTIONS = ['token', 'token_path', 'token_file', 'token_validate']
_LATE_BINDING_ENV_VAR_OPTIONS = {
'token': dict(env=['VAULT_TOKEN']),
'token_path': dict(env=['HOME']),
}
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodToken, self).__init__(option_adapter, warning_callback, deprecate_callback)
def _simulate_login_response(self, token, lookup_response=None):
'''returns a similar structure to a login method's return, optionally incorporating a lookup-self response'''
response = {
'auth': {
'client_token': token
}
}
if lookup_response is None:
return response
# first merge in the entire response at the top level
# but, rather than being missing, the auth field is going to be None,
# so we explicitly overwrite that with our original value.
response.update(lookup_response, auth=response['auth'])
# then we'll merge the data field right into the auth field
response['auth'].update(lookup_response['data'])
# and meta->metadata needs a name change
metadata = response['auth'].pop('meta', None)
if metadata:
response['auth']['metadata'] = metadata
return response
def validate(self):
self.process_late_binding_env_vars(self._LATE_BINDING_ENV_VAR_OPTIONS)
if self._options.get_option_default('token') is None and self._options.get_option_default('token_path') is not None:
token_filename = os.path.join(
self._options.get_option('token_path'),
self._options.get_option('token_file')
)
if os.path.exists(token_filename):
if not os.path.isfile(token_filename):
raise HashiVaultValueError("The Vault token file '%s' was found but is not a file." % token_filename)
with open(token_filename) as token_file:
self._options.set_option('token', token_file.read().strip())
if self._options.get_option_default('token') is None:
raise HashiVaultValueError("No Vault Token specified or discovered.")
def authenticate(self, client, use_token=True, lookup_self=False):
token = self._stringify(self._options.get_option('token'))
validate = self._options.get_option_default('token_validate')
response = None
if use_token:
client.token = token
if lookup_self or validate:
from hvac import exceptions
try:
try:
response = client.auth.token.lookup_self()
except (NotImplementedError, AttributeError):
# usually we would warn here, but the v1 method doesn't seem to be deprecated (yet?)
response = client.lookup_token() # when token=None on this method, it calls lookup-self
except (exceptions.Forbidden, exceptions.InvalidPath, exceptions.InvalidRequest):
if validate:
raise HashiVaultValueError("Invalid Vault Token Specified.")
return self._simulate_login_response(token, response)

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultAuthMethodBase
class HashiVaultAuthMethodUserpass(HashiVaultAuthMethodBase):
'''HashiVault option group class for auth: userpass'''
NAME = 'userpass'
OPTIONS = ['username', 'password', 'mount_point']
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodUserpass, self).__init__(option_adapter, warning_callback, deprecate_callback)
def validate(self):
self.validate_by_required_fields('username', 'password')
def authenticate(self, client, use_token=True):
params = self._options.get_filled_options(*self.OPTIONS)
try:
response = client.auth.userpass.login(**params)
except (NotImplementedError, AttributeError):
self.warn("HVAC should be updated to version 0.9.6 or higher. Deprecated method 'auth_userpass' will be used.")
response = client.auth_userpass(**params)
# must manually set the client token with userpass login
# see https://github.com/hvac/hvac/issues/644
# fixed in 0.11.0 (https://github.com/hvac/hvac/pull/733)
# but we keep the old behavior to maintain compatibility with older hvac
if use_token:
client.token = response['auth']['client_token']
return response

View File

@@ -0,0 +1,102 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
# please keep this list in alphabetical order of auth method name
from ansible_collections.community.hashi_vault.plugins.module_utils._auth_method_approle import HashiVaultAuthMethodApprole
from ansible_collections.community.hashi_vault.plugins.module_utils._auth_method_aws_iam import HashiVaultAuthMethodAwsIam
from ansible_collections.community.hashi_vault.plugins.module_utils._auth_method_azure import HashiVaultAuthMethodAzure
from ansible_collections.community.hashi_vault.plugins.module_utils._auth_method_cert import HashiVaultAuthMethodCert
from ansible_collections.community.hashi_vault.plugins.module_utils._auth_method_jwt import HashiVaultAuthMethodJwt
from ansible_collections.community.hashi_vault.plugins.module_utils._auth_method_ldap import HashiVaultAuthMethodLdap
from ansible_collections.community.hashi_vault.plugins.module_utils._auth_method_none import HashiVaultAuthMethodNone
from ansible_collections.community.hashi_vault.plugins.module_utils._auth_method_token import HashiVaultAuthMethodToken
from ansible_collections.community.hashi_vault.plugins.module_utils._auth_method_userpass import HashiVaultAuthMethodUserpass
class HashiVaultAuthenticator():
ARGSPEC = dict(
auth_method=dict(type='str', default='token', choices=[
'token',
'userpass',
'ldap',
'approle',
'aws_iam',
'azure',
'jwt',
'cert',
'none',
]),
mount_point=dict(type='str'),
token=dict(type='str', no_log=True, default=None),
token_path=dict(type='str', default=None, no_log=False),
token_file=dict(type='str', default='.vault-token'),
token_validate=dict(type='bool', default=False),
username=dict(type='str'),
password=dict(type='str', no_log=True),
role_id=dict(type='str'),
secret_id=dict(type='str', no_log=True),
jwt=dict(type='str', no_log=True),
aws_profile=dict(type='str', aliases=['boto_profile']),
aws_access_key=dict(type='str', aliases=['aws_access_key_id'], no_log=False),
aws_secret_key=dict(type='str', aliases=['aws_secret_access_key'], no_log=True),
aws_security_token=dict(type='str', no_log=False),
region=dict(type='str'),
aws_iam_server_id=dict(type='str'),
azure_tenant_id=dict(type='str'),
azure_client_id=dict(type='str'),
azure_client_secret=dict(type='str', no_log=True),
azure_resource=dict(type='str', default='https://management.azure.com/'),
cert_auth_private_key=dict(type='path', no_log=False),
cert_auth_public_key=dict(type='path'),
)
def __init__(self, option_adapter, warning_callback, deprecate_callback):
self._options = option_adapter
self._selector = {
# please keep this list in alphabetical order of auth method name
# so that it's easier to scan and see at a glance that a given auth method is present or absent
'approle': HashiVaultAuthMethodApprole(option_adapter, warning_callback, deprecate_callback),
'aws_iam': HashiVaultAuthMethodAwsIam(option_adapter, warning_callback, deprecate_callback),
'azure': HashiVaultAuthMethodAzure(option_adapter, warning_callback, deprecate_callback),
'cert': HashiVaultAuthMethodCert(option_adapter, warning_callback, deprecate_callback),
'jwt': HashiVaultAuthMethodJwt(option_adapter, warning_callback, deprecate_callback),
'ldap': HashiVaultAuthMethodLdap(option_adapter, warning_callback, deprecate_callback),
'none': HashiVaultAuthMethodNone(option_adapter, warning_callback, deprecate_callback),
'token': HashiVaultAuthMethodToken(option_adapter, warning_callback, deprecate_callback),
'userpass': HashiVaultAuthMethodUserpass(option_adapter, warning_callback, deprecate_callback),
}
self.warn = warning_callback
self.deprecate = deprecate_callback
def _get_method_object(self, method=None):
if method is None:
method = self._options.get_option('auth_method')
try:
o_method = self._selector[method]
except KeyError:
raise NotImplementedError("auth method '%s' is not implemented in HashiVaultAuthenticator" % method)
return o_method
def validate(self, *args, **kwargs):
method = self._get_method_object(kwargs.pop('method', None))
method.validate(*args, **kwargs)
def authenticate(self, *args, **kwargs):
method = self._get_method_object(kwargs.pop('method', None))
return method.authenticate(*args, **kwargs)

View File

@@ -0,0 +1,260 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.common.validation import (
check_type_dict,
check_type_str,
check_type_bool,
check_type_int,
)
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import HashiVaultOptionGroupBase
# we implement retries via the urllib3 Retry class
# https://github.com/ansible-collections/community.hashi_vault/issues/58
HAS_RETRIES = False
try:
from requests import Session
from requests.adapters import HTTPAdapter
try:
# try for a standalone urllib3
import urllib3
HAS_RETRIES = True
except ImportError:
try:
# failing that try for a vendored version within requests
from requests.packages import urllib3
HAS_RETRIES = True
except ImportError:
pass
except ImportError:
pass
class HashiVaultConnectionOptions(HashiVaultOptionGroupBase):
'''HashiVault option group class for connection options'''
OPTIONS = ['url', 'proxies', 'ca_cert', 'validate_certs', 'namespace', 'timeout', 'retries', 'retry_action']
ARGSPEC = dict(
url=dict(type='str', default=None),
proxies=dict(type='raw'),
ca_cert=dict(type='str', aliases=['cacert'], default=None),
validate_certs=dict(type='bool'),
namespace=dict(type='str', default=None),
timeout=dict(type='int'),
retries=dict(type='raw'),
retry_action=dict(type='str', choices=['ignore', 'warn'], default='warn'),
)
_LATE_BINDING_ENV_VAR_OPTIONS = {
'url': dict(env=['VAULT_ADDR'], required=True),
'ca_cert': dict(env=['VAULT_CACERT']),
'namespace': dict(env=['VAULT_NAMESPACE']),
}
_RETRIES_DEFAULT_PARAMS = {
'status_forcelist': [
# https://www.vaultproject.io/api#http-status-codes
# 429 is usually a "too many requests" status, but in Vault it's the default health status response for standby nodes.
412, # Precondition failed. Returned on Enterprise when a request can't be processed yet due to some missing eventually consistent data.
# Should be retried, perhaps with a little backoff.
500, # Internal server error. An internal error has occurred, try again later. If the error persists, report a bug.
502, # A request to Vault required Vault making a request to a third party; the third party responded with an error of some kind.
503, # Vault is down for maintenance or is currently sealed. Try again later.
],
(
# this field name changed in 1.26.0, and in the interest of supporting a wider range of urllib3 versions
# we'll use the new name whenever possible, but fall back seamlessly when needed.
# See also:
# - https://github.com/urllib3/urllib3/issues/2092
# - https://github.com/urllib3/urllib3/blob/main/CHANGES.rst#1260-2020-11-10
"allowed_methods" if HAS_RETRIES and hasattr(urllib3.util.Retry.DEFAULT, "allowed_methods") else "method_whitelist"
): None, # None allows retries on all methods, including those which may not be considered idempotent, like POST
'backoff_factor': 0.3,
}
def __init__(self, option_adapter, retry_callback_generator=None):
super(HashiVaultConnectionOptions, self).__init__(option_adapter)
self._retry_callback_generator = retry_callback_generator
def get_hvac_connection_options(self):
'''returns kwargs to be used for constructing an hvac.Client'''
# validate_certs is only used to optionally change the value of ca_cert
def _filter(k, v):
return v is not None and k != 'validate_certs'
# our transformed ca_cert value will become the verify parameter for the hvac client
hvopts = self._options.get_filtered_options(_filter, *self.OPTIONS)
hvopts['verify'] = hvopts.pop('ca_cert')
retry_action = hvopts.pop('retry_action')
if 'retries' in hvopts:
hvopts['session'] = self._get_custom_requests_session(new_callback=self._retry_callback_generator(retry_action), **hvopts.pop('retries'))
return hvopts
def process_connection_options(self):
'''executes special processing required for certain options'''
self.process_late_binding_env_vars(self._LATE_BINDING_ENV_VAR_OPTIONS)
self._boolean_or_cacert()
self._process_option_proxies()
self._process_option_retries()
def _get_custom_requests_session(self, **retry_kwargs):
'''returns a requests.Session to pass to hvac (or None)'''
if not HAS_RETRIES:
# because hvac requires requests which requires urllib3 it's unlikely we'll ever reach this condition.
raise NotImplementedError("Retries are unavailable. This may indicate very old versions of one or more of the following: hvac, requests, urllib3.")
# This is defined here because Retry may not be defined if its import failed.
# As mentioned above, that's very unlikely, but it'll fail sanity tests nonetheless if defined with other classes.
class CallbackRetry(urllib3.util.Retry):
def __init__(self, *args, **kwargs):
self._newcb = kwargs.pop('new_callback')
super(CallbackRetry, self).__init__(*args, **kwargs)
def new(self, **kwargs):
if self._newcb is not None:
self._newcb(self)
kwargs['new_callback'] = self._newcb
return super(CallbackRetry, self).new(**kwargs)
# We don't want the Retry class raising its own exceptions because that will prevent
# hvac from raising its own on various response codes.
# We set this here, rather than in the defaults, because if the caller sets their own
# dict for retries, we use it directly, but we don't want them to have to remember to always
# set raise_on_status=False themselves to get proper error handling.
# On the off chance someone does set it, we leave it alone, even though it's probably a mistake.
# That will be mentioned in the parameter docs.
if 'raise_on_status' not in retry_kwargs:
retry_kwargs['raise_on_status'] = False
# needs urllib 1.15+ https://github.com/urllib3/urllib3/blob/main/CHANGES.rst#115-2016-04-06
# but we should always have newer ones via requests, via hvac
retry = CallbackRetry(**retry_kwargs)
adapter = HTTPAdapter(max_retries=retry)
sess = Session()
sess.mount("https://", adapter)
sess.mount("http://", adapter)
return sess
def _process_option_retries(self):
'''check if retries option is int or dict and interpret it appropriately'''
# this method focuses on validating the option, and setting a valid Retry object construction dict
# it intentionally does not build the Session object, which will be done elsewhere
retries_opt = self._options.get_option('retries')
if retries_opt is None:
return
# we'll start with a copy of our defaults
retries = self._RETRIES_DEFAULT_PARAMS.copy()
try:
# try int
# on int, retry the specified number of times, and use the defaults for everything else
# on zero, disable retries
retries_int = check_type_int(retries_opt)
if retries_int < 0:
raise ValueError("Number of retries must be >= 0 (got %i)" % retries_int)
elif retries_int == 0:
retries = None
else:
retries['total'] = retries_int
except TypeError:
try:
# try dict
# on dict, use the value directly (will be used as the kwargs to initialize the Retry instance)
retries = check_type_dict(retries_opt)
except TypeError:
raise TypeError("retries option must be interpretable as int or dict. Got: %r" % retries_opt)
self._options.set_option('retries', retries)
def _process_option_proxies(self):
'''check if 'proxies' option is dict or str and set it appropriately'''
proxies_opt = self._options.get_option('proxies')
if proxies_opt is None:
return
try:
# if it can be interpreted as dict
# do it
proxies = check_type_dict(proxies_opt)
except TypeError:
# if it can't be interpreted as dict
proxy = check_type_str(proxies_opt)
# but can be interpreted as str
# use this str as http and https proxy
proxies = {
'http': proxy,
'https': proxy,
}
# record the new/interpreted value for 'proxies' option
self._options.set_option('proxies', proxies)
def _boolean_or_cacert(self):
# This is needed because of this (https://hvac.readthedocs.io/en/stable/source/hvac_v1.html):
#
# # verify (Union[bool,str]) - Either a boolean to indicate whether TLS verification should
# # be performed when sending requests to Vault, or a string pointing at the CA bundle to use for verification.
#
'''return a bool or cacert'''
ca_cert = self._options.get_option('ca_cert')
validate_certs = self._options.get_option('validate_certs')
if validate_certs is None:
# Validate certs option was not explicitly set
# Check if VAULT_SKIP_VERIFY is set
vault_skip_verify = os.environ.get('VAULT_SKIP_VERIFY')
if vault_skip_verify is not None:
# VAULT_SKIP_VERIFY is set
try:
# Check that we have a boolean value
vault_skip_verify = check_type_bool(vault_skip_verify)
except TypeError:
# Not a boolean value fallback to default value (True)
validate_certs = True
else:
# Use the inverse of VAULT_SKIP_VERIFY
validate_certs = not vault_skip_verify
else:
validate_certs = True
if not (validate_certs and ca_cert):
self._options.set_option('ca_cert', validate_certs)
else:
self._options.set_option('ca_cert', to_text(ca_cert, errors='surrogate_or_strict'))

View File

@@ -0,0 +1,302 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
'''Python versions supported: >=3.6'''
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
HAS_HVAC = False
try:
import hvac
HAS_HVAC = True
except ImportError:
HAS_HVAC = False
def _stringify(input):
'''
This method is primarily used to Un-Unsafe values that come from Ansible.
We want to remove the Unsafe context so that libraries don't get confused
by the values.
'''
# Since this is a module_util, and will be used by both plugins and modules,
# we cannot import the AnsibleUnsafe* types, because they are controller-only.
# However, they subclass the native types, so we can check for that.
# bytes is the only consistent type to check against in both py2 and py3
if isinstance(input, bytes):
# seems redundant, but this will give us a regular bytes object even
# when the input is AnsibleUnsafeBytes
return bytes(input)
else:
# instead of checking for py2 vs. py3 to cast to str or unicode,
# let's get the type from the literal.
return type(u'')(input)
class HashiVaultValueError(ValueError):
'''Use in common code to raise an Exception that can be turned into AnsibleError or used to fail_json()'''
class HashiVaultHelper():
STRINGIFY_CANDIDATES = set([
'token', # Token will end up in a header, requests requires headers to be str or bytes,
# and newer versions of requests stopped converting automatically. Because our
# token could have been passed in from a previous lookup call, it could be one
# of the AnsibleUnsafe types instead, causing a failure. Tokens should always
# be strings, so we will convert them.
'namespace', # namespace is also set in a header
])
def __init__(self):
# TODO move hvac checking here?
pass
@staticmethod
def _stringify(input):
return _stringify(input)
def get_vault_client(
self,
hashi_vault_logout_inferred_token=True, hashi_vault_revoke_on_logout=False, hashi_vault_stringify_args=True,
**kwargs
):
'''
creates a Vault client with the given kwargs
:param hashi_vault_logout_inferred_token: if True performs "logout" after creation to remove any token that
the hvac library itself may have read in. Only used if "token" is not included in kwargs.
:type hashi_vault_logout_implied_token: bool
:param hashi_vault_revoke_on_logout: if True revokes any current token on logout. Only used if a logout is performed. Not recommended.
:type hashi_vault_revoke_on_logout: bool
:param hashi_vault_stringify_args: if True converts a specific set of defined kwargs to a string type.
:type hashi_vault_stringify_args: bool
'''
if hashi_vault_stringify_args:
for key in kwargs.keys():
if key in self.STRINGIFY_CANDIDATES:
kwargs[key] = self._stringify(kwargs[key])
client = hvac.Client(**kwargs)
# logout to prevent accidental use of inferred tokens
# https://github.com/ansible-collections/community.hashi_vault/issues/13
if hashi_vault_logout_inferred_token and 'token' not in kwargs:
client.logout(revoke_token=hashi_vault_revoke_on_logout)
return client
class HashiVaultOptionAdapter(object):
'''
The purpose of this class is to provide a standard interface for option getting/setting
within module_utils code, since the processes are so different in plugins and modules.
Attention is paid to ensuring that in plugins we use the methods provided by Config Manager,
but to allow flexibility to create an adapter to work with other sources, hence the design
of defining specific methods exposed, and having them call provided function references.
'''
# More context on the need to call Config Manager methods:
#
# Some issues raised around deprecations in plugins not being processed led to comments
# from core maintainers around the need to use Config Manager and also to ensure any
# option needed is always retrieved using AnsiblePlugin.get_option(). At the time of this
# writing, based on the way Config Manager is implemented, that's not actually necessary,
# and calling AnsiblePlugin.set_options() to initialize them is enough. But that's not
# guaranteed to stay that way, if get_option() is used to "trigger" internal events.
#
# More reading:
# - https://github.com/ansible-collections/community.hashi_vault/issues/35
# - https://github.com/ansible/ansible/issues/73051
# - https://github.com/ansible/ansible/pull/73058
# - https://github.com/ansible/ansible/pull/73239
# - https://github.com/ansible/ansible/pull/73240
@classmethod
def from_dict(cls, dict):
return cls(
getter=dict.__getitem__,
setter=dict.__setitem__,
haver=lambda key: key in dict,
updater=dict.update,
defaultsetter=dict.setdefault,
defaultgetter=dict.get,
)
@classmethod
def from_ansible_plugin(cls, plugin):
return cls(
getter=plugin.get_option,
setter=plugin.set_option,
haver=plugin.has_option if hasattr(plugin, 'has_option') else None,
# AnsiblePlugin.has_option was added in 2.10, see https://github.com/ansible/ansible/pull/61078
)
@classmethod
def from_ansible_module(cls, module):
return cls.from_dict(module.params)
def __init__(
self,
getter, setter,
haver=None, updater=None, getitems=None, getfiltereditems=None, getfilleditems=None, defaultsetter=None, defaultgetter=None):
def _default_default_setter(key, default=None):
try:
value = self.get_option(key)
return value
except KeyError:
self.set_option(key, default)
return default
def _default_updater(**kwargs):
for key, value in kwargs.items():
self.set_option(key, value)
def _default_haver(key):
try:
self.get_option(key)
return True
except KeyError:
return False
def _default_getitems(*args):
return dict((key, self.get_option(key)) for key in args)
def _default_getfiltereditems(filter, *args):
return dict((key, value) for key, value in self.get_options(*args).items() if filter(key, value))
def _default_getfilleditems(*args):
return self.get_filtered_options(lambda k, v: v is not None, *args)
def _default_default_getter(key, default):
try:
return self.get_option(key)
except KeyError:
return default
self._getter = getter
self._setter = setter
self._haver = haver or _default_haver
self._updater = updater or _default_updater
self._getitems = getitems or _default_getitems
self._getfiltereditems = getfiltereditems or _default_getfiltereditems
self._getfilleditems = getfilleditems or _default_getfilleditems
self._defaultsetter = defaultsetter or _default_default_setter
self._defaultgetter = defaultgetter or _default_default_getter
def get_option(self, key):
return self._getter(key)
def get_option_default(self, key, default=None):
return self._defaultgetter(key, default)
def set_option(self, key, value):
return self._setter(key, value)
def set_option_default(self, key, default=None):
return self._defaultsetter(key, default)
def has_option(self, key):
return self._haver(key)
def set_options(self, **kwargs):
return self._updater(**kwargs)
def get_options(self, *args):
return self._getitems(*args)
def get_filtered_options(self, filter, *args):
return self._getfiltereditems(filter, *args)
def get_filled_options(self, *args):
return self._getfilleditems(*args)
class HashiVaultOptionGroupBase:
'''A base class for class option group classes'''
def __init__(self, option_adapter):
self._options = option_adapter
def process_late_binding_env_vars(self, option_vars):
'''looks through a set of options, and if empty/None, looks for a value in specified env vars, or sets an optional default'''
# see https://github.com/ansible-collections/community.hashi_vault/issues/10
#
# Options which seek to use environment vars that are not Ansible-specific
# should load those as values of last resort, so that INI values can override them.
# For default processing, list such options and vars here.
# Alternatively, process them in another appropriate place like an auth method's
# validate_ method.
#
# key = option_name
# value = dict with "env" key which is a list of env vars (in order of those checked first; process stops when value is found),
# and an optional "default" key whose value will be set if none of the env vars are found.
# An optional boolean "required" key can be used to specify that a value is required, so raise if one is not found.
for opt, config in option_vars.items():
for env in config['env']:
# we use has_option + get_option rather than get_option_default
# because we will only override if the option exists and
# is None, not if it's missing. For plugins, that is the usual,
# but for modules, they may have to set the default to None
# in the argspec if it has late binding env vars.
if self._options.has_option(opt) and self._options.get_option(opt) is None:
self._options.set_option(opt, os.environ.get(env))
if 'default' in config and self._options.has_option(opt) and self._options.get_option(opt) is None:
self._options.set_option(opt, config['default'])
if 'required' in config and self._options.get_option_default(opt) is None:
raise HashiVaultValueError("Required option %s was not set." % opt)
class HashiVaultAuthMethodBase(HashiVaultOptionGroupBase):
'''Base class for individual auth method implementations'''
def __init__(self, option_adapter, warning_callback, deprecate_callback):
super(HashiVaultAuthMethodBase, self).__init__(option_adapter)
self._warner = warning_callback
self._deprecator = deprecate_callback
def validate(self):
'''Validates the given auth method as much as possible without calling Vault.'''
raise NotImplementedError('validate must be implemented')
def authenticate(self, client, use_token=True):
'''Authenticates against Vault, returns a token.'''
raise NotImplementedError('authenticate must be implemented')
def validate_by_required_fields(self, *field_names):
missing = [field for field in field_names if self._options.get_option_default(field) is None]
if missing:
raise HashiVaultValueError("Authentication method %s requires options %r to be set, but these are missing: %r" % (self.NAME, field_names, missing))
def warn(self, message):
self._warner(message)
def deprecate(self, message, version=None, date=None, collection_name=None):
self._deprecator(message, version=version, date=date, collection_name=collection_name)
@staticmethod
def _stringify(input):
return _stringify(input)

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import (
HashiVaultHelper,
HashiVaultOptionAdapter,
)
from ansible_collections.community.hashi_vault.plugins.module_utils._connection_options import HashiVaultConnectionOptions
from ansible_collections.community.hashi_vault.plugins.module_utils._authenticator import HashiVaultAuthenticator
class HashiVaultModule(AnsibleModule):
def __init__(self, *args, **kwargs):
if 'hashi_vault_custom_retry_callback' in kwargs:
callback = kwargs.pop('hashi_vault_custom_retry_callback')
else:
callback = self._generate_retry_callback
super(HashiVaultModule, self).__init__(*args, **kwargs)
self.helper = HashiVaultHelper()
self.adapter = HashiVaultOptionAdapter.from_dict(self.params)
self.connection_options = HashiVaultConnectionOptions(option_adapter=self.adapter, retry_callback_generator=callback)
self.authenticator = HashiVaultAuthenticator(option_adapter=self.adapter, warning_callback=self.warn, deprecate_callback=self.deprecate)
@classmethod
def generate_argspec(cls, **kwargs):
spec = HashiVaultConnectionOptions.ARGSPEC.copy()
spec.update(HashiVaultAuthenticator.ARGSPEC.copy())
spec.update(**kwargs)
return spec
def _generate_retry_callback(self, retry_action):
'''returns a Retry callback function for modules'''
def _on_retry(retry_obj):
if retry_obj.total > 0:
if retry_action == 'warn':
self.warn('community.hashi_vault: %i %s remaining.' % (retry_obj.total, 'retry' if retry_obj.total == 1 else 'retries'))
else:
pass
return _on_retry

View File

@@ -0,0 +1,197 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2022, Brian Scholer (@briantist)
# 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_kv1_get
version_added: 2.5.0
author:
- Brian Scholer (@briantist)
short_description: Get a secret from HashiCorp Vault's KV version 1 secret store
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:
- Gets a secret from HashiCorp Vault's KV version 1 secret store.
seealso:
- ref: community.hashi_vault.vault_kv1_get lookup <ansible_collections.community.hashi_vault.vault_kv1_get_lookup>
description: The official documentation for the C(community.hashi_vault.vault_kv1_get) lookup plugin.
- module: community.hashi_vault.vault_kv2_get
- name: KV1 Secrets Engine
description: Documentation for the Vault KV secrets engine, version 1.
link: https://www.vaultproject.io/docs/secrets/kv/kv-v1
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:
engine_mount_point:
default: kv
path:
description:
- Vault KV path to be read.
- This is relative to the I(engine_mount_point), so the mount path should not be included.
type: str
required: True
'''
EXAMPLES = r'''
- name: Read a kv1 secret from Vault via the remote host with userpass auth
community.hashi_vault.vault_kv1_get:
url: https://vault:8201
path: hello
auth_method: userpass
username: user
password: '{{ passwd }}'
register: response
# equivalent API path is kv/hello
- name: Display the results
ansible.builtin.debug:
msg:
- "Secret: {{ response.secret }}"
- "Data: {{ response.data }} (same as secret in kv1)"
- "Metadata: {{ response.metadata }} (response info in kv1)"
- "Full response: {{ response.raw }}"
- "Value of key 'password' in the secret: {{ response.secret.password }}"
- name: Read a secret from kv1 with a different mount via the remote host
community.hashi_vault.vault_kv1_get:
url: https://vault:8201
engine_mount_point: custom/kv1/mount
path: hello
register: response
# equivalent API path is custom/kv1/mount/hello
- name: Display the results
ansible.builtin.debug:
msg:
- "Secret: {{ response.secret }}"
- "Data: {{ response.data }} (same as secret in kv1)"
- "Metadata: {{ response.metadata }} (response info in kv1)"
- "Full response: {{ response.raw }}"
'''
RETURN = r'''
raw:
description: The raw result of the read against the given path.
returned: success
type: dict
sample:
auth: null
data:
Key1: value1
Key2: value2
lease_duration: 2764800
lease_id: ""
renewable: false
request_id: e99f145f-f02a-7073-1229-e3f191057a70
warnings: null
wrap_info: null
data:
description: The C(data) field of raw result. This can also be accessed via C(raw.data).
returned: success
type: dict
sample:
Key1: value1
Key2: value2
secret:
description: The C(data) field of the raw result. This is identical to C(data) in the return values.
returned: success
type: dict
sample:
Key1: value1
Key2: value2
metadata:
description: This is a synthetic result. It is the same as C(raw) with C(data) removed.
returned: success
type: dict
sample:
auth: null
lease_duration: 2764800
lease_id: ""
renewable: false
request_id: e99f145f-f02a-7073-1229-e3f191057a70
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 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
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', default='kv'),
path=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
)
engine_mount_point = module.params.get('engine_mount_point')
path = module.params.get('path')
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.kv.v1.read_secret(path=path, mount_point=engine_mount_point)
except hvac.exceptions.Forbidden as e:
module.fail_json(msg="Forbidden: Permission Denied to path ['%s']." % path, exception=traceback.format_exc())
except hvac.exceptions.InvalidPath as e:
if 'Invalid path for a versioned K/V secrets engine' in to_native(e):
msg = "Invalid path for a versioned K/V secrets engine ['%s']. If this is a KV version 2 path, use community.hashi_vault.vault_kv2_get."
else:
msg = "Invalid or missing path ['%s']."
module.fail_json(msg=msg % (path,), exception=traceback.format_exc())
metadata = raw.copy()
data = metadata.pop('data')
module.exit_json(raw=raw, data=data, secret=data, metadata=metadata)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,179 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2022, Isaac Wagner (@idwagner)
# 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 = '''
module: vault_kv2_delete
version_added: 3.4.0
author:
- Isaac Wagner (@idwagner)
short_description: Delete one or more versions of a secret from HashiCorp Vault's KV version 2 secret store
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:
- Delete one or more versions of a secret from HashiCorp Vault's KV version 2 secret store.
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, the module returns C(changed) status without contacting Vault.
- Consider using M(community.hashi_vault.vault_kv2_get) to verify the existence of the secret first.
seealso:
- module: community.hashi_vault.vault_kv2_get
- name: KV2 Secrets Engine
description: Documentation for the Vault KV secrets engine, version 2.
link: https://www.vaultproject.io/docs/secrets/kv/kv-v2
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:
engine_mount_point:
default: secret
path:
description:
- Vault KV path to be deleted.
- This is relative to the I(engine_mount_point), so the mount path should not be included.
- For kv2, do not include C(/data/) or C(/metadata/).
type: str
required: True
versions:
description:
- One or more versions of the secret to delete.
- When omitted, the latest version of the secret is deleted.
type: list
elements: int
required: False
'''
EXAMPLES = """
- name: Delete the latest version of the secret/mysecret secret.
community.hashi_vault.vault_kv2_delete:
url: https://vault:8201
path: secret/mysecret
auth_method: userpass
username: user
password: '{{ passwd }}'
register: result
- name: Delete versions 1 and 3 of the secret/mysecret secret.
community.hashi_vault.vault_kv2_delete:
url: https://vault:8201
path: secret/mysecret
versions: [1, 3]
auth_method: userpass
username: user
password: '{{ passwd }}'
"""
RETURN = """
data:
description:
- The raw result of the delete against the given path.
- This is usually empty, but may contain warnings or other information.
returned: success
type: dict
"""
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
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', default='secret'),
path=dict(type='str', required=True),
versions=dict(type='list', elements='int', 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
)
engine_mount_point = module.params.get('engine_mount_point')
path = module.params.get('path')
versions = module.params.get('versions')
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:
# Vault has two separate methods, one for delete latest version,
# and delete specific versions.
if module.check_mode:
response = {}
elif not versions:
response = client.secrets.kv.v2.delete_latest_version_of_secret(
path=path, mount_point=engine_mount_point)
else:
response = client.secrets.kv.v2.delete_secret_versions(
path=path, versions=versions, mount_point=engine_mount_point)
except hvac.exceptions.Forbidden as e:
module.fail_json(msg="Forbidden: Permission Denied to path ['%s']." % path, exception=traceback.format_exc())
# https://github.com/hvac/hvac/issues/797
# HVAC returns a raw response object when the body is not JSON.
# That includes 204 responses, which are successful with no body.
# So we will try to detect that and a act accordingly.
# A better way may be to implement our own adapter for this
# collection, but it's a little premature to do that.
if hasattr(response, 'json') and callable(response.json):
if response.status_code == 204:
output = {}
else:
module.warn(
'Vault returned status code %i and an unparsable body.' % response.status_code)
output = response.content
else:
output = response
module.exit_json(changed=True, data=output)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,212 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2022, Brian Scholer (@briantist)
# 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_kv2_get
version_added: 2.5.0
author:
- Brian Scholer (@briantist)
short_description: Get a secret from HashiCorp Vault's KV version 2 secret store
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:
- Gets a secret from HashiCorp Vault's KV version 2 secret store.
seealso:
- ref: community.hashi_vault.vault_kv2_get lookup <ansible_collections.community.hashi_vault.vault_kv2_get_lookup>
description: The official documentation for the C(community.hashi_vault.vault_kv2_get) lookup plugin.
- module: community.hashi_vault.vault_kv1_get
- name: KV2 Secrets Engine
description: Documentation for the Vault KV secrets engine, version 2.
link: https://www.vaultproject.io/docs/secrets/kv/kv-v2
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:
engine_mount_point:
default: secret
path:
description:
- Vault KV path to be read.
- This is relative to the I(engine_mount_point), so the mount path should not be included.
- For kv2, do not include C(/data/) or C(/metadata/).
type: str
required: True
version:
description: Specifies the version to return. If not set the latest version is returned.
type: int
'''
EXAMPLES = r'''
- name: Read the latest version of a kv2 secret from Vault via the remote host with userpass auth
community.hashi_vault.vault_kv2_get:
url: https://vault:8201
path: hello
auth_method: userpass
username: user
password: '{{ passwd }}'
register: response
# equivalent API path is secret/data/hello
- name: Display the results
ansible.builtin.debug:
msg:
- "Secret: {{ response.secret }}"
- "Data: {{ response.data }} (contains secret data & metadata in kv2)"
- "Metadata: {{ response.metadata }}"
- "Full response: {{ response.raw }}"
- "Value of key 'password' in the secret: {{ response.secret.password }}"
- name: Read version 5 of a secret from kv2 with a different mount via the remote host
community.hashi_vault.vault_kv2_get:
url: https://vault:8201
engine_mount_point: custom/kv2/mount
path: hello
version: 5
register: response
# equivalent API path is custom/kv2/mount/data/hello
- name: Assert that the version returned is as expected
ansible.builtin.assert:
that:
- response.metadata.version == 5
'''
RETURN = r'''
raw:
description: The raw result of the read against the given path.
returned: success
type: dict
sample:
auth: null
data:
data:
Key1: value1
Key2: value2
metadata:
created_time: "2022-04-21T15:56:58.8525402Z"
custom_metadata: null
deletion_time: ""
destroyed: false
version: 2
lease_duration: 0
lease_id: ""
renewable: false
request_id: dc829675-9119-e831-ae74-35fc5d33d200
warnings: null
wrap_info: null
data:
description: The C(data) field of raw result. This can also be accessed via C(raw.data).
returned: success
type: dict
sample:
data:
Key1: value1
Key2: value2
metadata:
created_time: "2022-04-21T15:56:58.8525402Z"
custom_metadata: null
deletion_time: ""
destroyed: false
version: 2
secret:
description: The C(data) field within the C(data) field. Equivalent to C(raw.data.data).
returned: success
type: dict
sample:
Key1: value1
Key2: value2
metadata:
description: The C(metadata) field within the C(data) field. Equivalent to C(raw.data.metadata).
returned: success
type: dict
sample:
created_time: "2022-04-21T15:56:58.8525402Z"
custom_metadata: null
deletion_time: ""
destroyed: false
version: 2
'''
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
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', default='secret'),
path=dict(type='str', required=True),
version=dict(type='int'),
)
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
)
engine_mount_point = module.params.get('engine_mount_point')
path = module.params.get('path')
version = module.params.get('version')
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.kv.v2.read_secret_version(path=path, version=version, mount_point=engine_mount_point)
except hvac.exceptions.Forbidden as e:
module.fail_json(msg="Forbidden: Permission Denied to path ['%s']." % path, exception=traceback.format_exc())
except hvac.exceptions.InvalidPath as e:
module.fail_json(
msg="Invalid or missing path ['%s'] with secret version '%s'. Check the path or secret version." % (path, version or 'latest'),
exception=traceback.format_exc()
)
data = raw['data']
metadata = data['metadata']
secret = data['data']
module.exit_json(raw=raw, data=data, secret=secret, metadata=metadata)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,134 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2023, Tom Kivlin (@tomkivlin)
# 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 = """
module: vault_list
version_added: 4.1.0
author:
- Tom Kivlin (@tomkivlin)
short_description: Perform a list operation against HashiCorp Vault
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:
- Performs a generic list operation against a given path in HashiCorp Vault.
seealso:
- ref: community.hashi_vault.vault_list lookup <ansible_collections.community.hashi_vault.vault_list_lookup>
description: The official documentation for the C(community.hashi_vault.vault_list) lookup plugin.
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
options:
path:
description: Vault path to be listed.
type: str
required: true
"""
EXAMPLES = """
- name: List kv2 secrets from Vault via the remote host with userpass auth
community.hashi_vault.vault_list:
url: https://vault:8201
path: secret/metadata
# For kv2, the path needs to follow the pattern 'mount_point/metadata' or 'mount_point/metadata/path' to list all secrets in that path
auth_method: userpass
username: user
password: '{{ passwd }}'
register: secret
- name: Display the secrets found at the path provided above
ansible.builtin.debug:
msg: "{{ secret.data.data['keys'] }}"
# Note that secret.data.data.keys won't work as 'keys' is a built-in method
- name: List access policies from Vault via the remote host
community.hashi_vault.vault_list:
url: https://vault:8201
path: sys/policies/acl
register: policies
- name: Display the policy names
ansible.builtin.debug:
msg: "{{ policies.data.data['keys'] }}"
# Note that secret.data.data.keys won't work as 'keys' is a built-in method
"""
RETURN = """
data:
description: The raw result of the list against the given path.
returned: success
type: dict
"""
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
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(
path=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
)
path = module.params.get('path')
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:
data = client.list(path)
except hvac.exceptions.Forbidden as e:
module.fail_json(msg="Forbidden: Permission Denied to path '%s'." % path, exception=traceback.format_exc())
if data is None:
module.fail_json(msg="The path '%s' doesn't seem to exist." % path)
module.exit_json(data=data)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,177 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2021, Brian Scholer (@briantist)
# 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 = """
module: vault_login
version_added: 2.2.0
author:
- Brian Scholer (@briantist)
short_description: Perform a login operation against HashiCorp Vault
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:
- Performs a login operation against a given path in HashiCorp Vault, returning the login response, including the token.
seealso:
- ref: community.hashi_vault.vault_login lookup <ansible_collections.community.hashi_vault.vault_login_lookup>
description: The official documentation for the C(community.hashi_vault.vault_login) lookup plugin.
- ref: community.hashi_vault.vault_login_token filter <ansible_collections.community.hashi_vault.vault_login_token_filter>
description: The official documentation for the C(community.hashi_vault.vault_login_token) filter plugin.
extends_documentation_fragment:
- community.hashi_vault.attributes
- community.hashi_vault.attributes.action_group
- community.hashi_vault.connection
- community.hashi_vault.auth
notes:
- "A login is a write operation (creating a token persisted to storage), so this module always reports C(changed=True),
except when used with C(token) auth, because no new token is created in that case. For the purposes of Ansible playbooks however,
it may be more useful to set C(changed_when=false) if you're doing idempotency checks against the target system."
- The C(none) auth method is not valid for this module because there is no response to return.
- "With C(token) auth, no actual login is performed.
Instead, the given token's additional information is returned in a structure that resembles what login responses look like."
- "The C(token) auth method will only return full information if I(token_validate=True).
If the token does not have the C(lookup-self) capability, this will fail. If I(token_validate=False), only the token value itself
will be returned in the structure."
attributes:
check_mode:
support: partial
details:
- In check mode, this module will not perform a login, and will instead return a basic structure with an empty token.
However this may not be useful if the token is required for follow on tasks.
- It may be better to use this module with C(check_mode=false) in order to have a valid token that can be used.
options:
token_validate:
default: true
"""
EXAMPLES = """
- name: Login and use the resulting token
community.hashi_vault.vault_login:
url: https://vault:8201
auth_method: userpass
username: user
password: '{{ passwd }}'
register: login_data
- name: Retrieve an approle role ID (token via filter)
community.hashi_vault.vault_read:
url: https://vault:8201
auth_method: token
token: '{{ login_data | community.hashi_vault.vault_login_token }}'
path: auth/approle/role/role-name/role-id
register: approle_id
- name: Retrieve an approle role ID (token via direct dict access)
community.hashi_vault.vault_read:
url: https://vault:8201
auth_method: token
token: '{{ login_data.login.auth.client_token }}'
path: auth/approle/role/role-name/role-id
register: approle_id
"""
RETURN = """
login:
description: The result of the login against the given auth method.
returned: success
type: dict
contains:
auth:
description: The C(auth) member of the login response.
returned: success
type: dict
contains:
client_token:
description: Contains the token provided by the login operation (or the input token when I(auth_method=token)).
returned: success
type: str
data:
description: The C(data) member of the login response.
returned: success, when available
type: dict
"""
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
# we don't actually need to import hvac directly in this module
# because all of the hvac calls happen in module utils, but
# we would like to control the error message here for consistency.
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(
# we override this from the shared argspec in order to turn off no_log
# otherwise we would not be able to return the input token value
token=dict(type='str', no_log=False, default=None),
# we override this from the shared argspec because the default for
# this module should be True, which differs from the rest of the
# collection since 4.0.0.
token_validate=dict(type='bool', default=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
)
# a login is technically a write operation, using storage and resources
changed = True
auth_method = module.params.get('auth_method')
if auth_method == 'none':
module.fail_json(msg="The 'none' auth method is not valid for this module.")
if auth_method == 'token':
# with the token auth method, we don't actually perform a login operation
# nor change the state of Vault; it's read-only (to lookup the token's info)
changed = False
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()
if module.check_mode:
response = {'auth': {'client_token': None}}
else:
response = module.authenticator.authenticate(client)
except (NotImplementedError, HashiVaultValueError) as e:
module.fail_json(msg=to_native(e), exception=traceback.format_exc())
module.exit_json(changed=changed, login=response)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,296 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2022, Florent David (@Ripolin)
# 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 = """
module: vault_pki_generate_certificate
version_added: 2.3.0
author:
- Florent David (@Ripolin)
short_description: Generates a new set of credentials (private key and certificate) using HashiCorp Vault PKI
requirements:
- C(hvac) (L(Python library,https://hvac.readthedocs.io/en/stable/changelog.html#may-25th-2019)) version C(0.9.1) or higher
- For detailed requirements, see R(the collection requirements page,ansible_collections.community.hashi_vault.docsite.user_guide.requirements).
description:
- Generates a new set of credentials (private key and certificate) based on a Vault PKI role.
seealso:
- name: HashiCorp Vault PKI Secrets Engine API
description: API documentation for the HashiCorp Vault PKI secrets engine.
link: https://www.vaultproject.io/api/secret/pki#generate-certificate
- name: HVAC library reference
description: HVAC library reference about the PKI engine.
link: https://hvac.readthedocs.io/en/stable/usage/secrets_engines/pki.html#generate-certificate
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
attributes:
check_mode:
support: partial
details:
- In check mode, this module will not contact Vault and will return an empty C(data) field and C(changed) status.
options:
alt_names:
description:
- Specifies requested Subject Alternative Names.
- These can be host names or email addresses; they will be parsed into their respective fields.
- If any requested names do not match role policy, the entire request will be denied.
type: list
elements: str
default: []
common_name:
description:
- Specifies the requested CN for the certificate.
- If the CN is allowed by role policy, it will be issued.
type: str
required: true
exclude_cn_from_sans:
description:
- If true, the given I(common_name) will not be included in DNS or Email Subject Alternate Names (as appropriate).
- Useful if the CN is not a hostname or email address, but is instead some human-readable identifier.
type: bool
default: False
format:
description:
- Specifies the format for returned data.
- Can be C(pem), C(der), or C(pem_bundle).
- If C(der), the output is base64 encoded.
- >-
If C(pem_bundle), the C(certificate) field will contain the private key and certificate, concatenated. If the issuing CA is not a Vault-derived
self-signed root, this will be included as well.
type: str
choices: [pem, der, pem_bundle]
default: pem
ip_sans:
description:
- Specifies requested IP Subject Alternative Names.
- Only valid if the role allows IP SANs (which is the default).
type: list
elements: str
default: []
role_name:
description:
- Specifies the name of the role to create the certificate against.
type: str
required: true
other_sans:
description:
- Specifies custom OID/UTF8-string SANs.
- These must match values specified on the role in C(allowed_other_sans).
- "The format is the same as OpenSSL: C(<oid>;<type>:<value>) where the only current valid type is C(UTF8)."
type: list
elements: str
default: []
engine_mount_point:
description:
- Specify the mount point used by the PKI engine.
- Defaults to the default used by C(hvac).
private_key_format:
description:
- Specifies the format for marshaling the private key.
- Defaults to C(der) which will return either base64-encoded DER or PEM-encoded DER, depending on the value of I(format).
- The other option is C(pkcs8) which will return the key marshalled as PEM-encoded PKCS8.
type: str
choices: [der, pkcs8]
default: der
ttl:
description:
- Specifies requested Time To Live.
- Cannot be greater than the role's C(max_ttl) value.
- If not provided, the role's C(ttl) value will be used.
- Note that the role values default to system values if not explicitly set.
type: str
uri_sans:
description:
- Specifies the requested URI Subject Alternative Names.
type: list
elements: str
default: []
"""
EXAMPLES = """
- name: Login and use the resulting token
community.hashi_vault.vault_login:
url: https://localhost:8200
auth_method: ldap
username: "john.doe"
password: "{{ user_passwd }}"
register: login_data
- name: Generate a certificate with an existing token
community.hashi_vault.vault_pki_generate_certificate:
role_name: test.example.org
common_name: test.example.org
ttl: 8760h
alt_names:
- test2.example.org
- test3.example.org
url: https://vault:8201
auth_method: token
token: "{{ login_data.login.auth.client_token }}"
register: cert_data
- name: Display generated certificate
debug:
msg: "{{ cert_data.data.data.certificate }}"
"""
RETURN = """
data:
description: Information about newly generated certificate
returned: success
type: complex
contains:
lease_id:
description: Vault lease attached to certificate.
returned: success
type: str
sample: pki/issue/test/7ad6cfa5-f04f-c62a-d477-f33210475d05
renewable:
description: True if certificate is renewable.
returned: success
type: bool
sample: false
lease_duration:
description: Vault lease duration.
returned: success
type: int
sample: 21600
data:
description: Payload
returned: success
type: complex
contains:
certificate:
description: Generated certificate.
returned: success
type: str
sample: "-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----"
issuing_ca:
description: CA certificate.
returned: success
type: str
sample: "-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----"
ca_chain:
description: Linked list of CA certificates.
returned: success
type: list
elements: str
sample: ["-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----"]
private_key:
description: Private key used to generate certificate.
returned: success
type: str
sample: "-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----"
private_key_type:
description: Private key algorithm.
returned: success
type: str
sample: rsa
serial_number:
description: Certificate's serial number.
returned: success
type: str
sample: 39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:58
warning:
description: Warnings returned by Vault during generation.
returned: success
type: str
"""
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
HAS_HVAC = False
try:
import hvac
from hvac.api.secrets_engines.pki import DEFAULT_MOUNT_POINT
except ImportError:
HVAC_IMPORT_ERROR = traceback.format_exc()
HAS_HVAC = False
else:
HVAC_IMPORT_ERROR = None
HAS_HVAC = True
def run_module():
argspec = HashiVaultModule.generate_argspec(
role_name=dict(type='str', required=True),
common_name=dict(type='str', required=True),
alt_names=dict(type='list', elements='str', required=False, default=[]),
ip_sans=dict(type='list', elements='str', required=False, default=[]),
uri_sans=dict(type='list', elements='str', required=False, default=[]),
other_sans=dict(type='list', elements='str', required=False, default=[]),
ttl=dict(type='str', required=False, default=None),
format=dict(type='str', required=False, choices=['pem', 'der', 'pem_bundle'], default='pem'),
private_key_format=dict(type='str', required=False, choices=['der', 'pkcs8'], default='der'),
exclude_cn_from_sans=dict(type='bool', required=False, default=False),
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)
role_name = module.params.get('role_name')
common_name = module.params.get('common_name')
engine_mount_point = module.params.get('engine_mount_point') or DEFAULT_MOUNT_POINT
extra_params = {
'alt_names': ','.join(module.params.get('alt_names')),
'ip_sans': ','.join(module.params.get('ip_sans')),
'uri_sans': ','.join(module.params.get('uri_sans')),
'other_sans': ','.join(module.params.get('other_sans')),
'ttl': module.params.get('ttl'),
'format': module.params.get('format'),
'private_key_format': module.params.get('private_key_format'),
'exclude_cn_from_sans': module.params.get('exclude_cn_from_sans')
}
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:
if module.check_mode:
data = {}
else:
data = client.secrets.pki.generate_certificate(
name=role_name, common_name=common_name,
extra_params=extra_params, mount_point=engine_mount_point
)
except hvac.exceptions.VaultError as e:
module.fail_json(msg=to_native(e), exception=traceback.format_exc())
# generate_certificate is a write operation which always return a new certificate
module.exit_json(changed=True, data=data)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,133 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2021, Brian Scholer (@briantist)
# 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 = """
module: vault_read
version_added: 1.4.0
author:
- Brian Scholer (@briantist)
short_description: Perform a read operation against HashiCorp Vault
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:
- Performs a generic read operation against a given path in HashiCorp Vault.
seealso:
- ref: community.hashi_vault.vault_read lookup <ansible_collections.community.hashi_vault.vault_read_lookup>
description: The official documentation for the C(community.hashi_vault.vault_read) lookup plugin.
- ref: community.hashi_vault.hashi_vault lookup <ansible_collections.community.hashi_vault.hashi_vault_lookup>
description: The official documentation for the C(community.hashi_vault.hashi_vault) lookup plugin.
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
options:
path:
description: Vault path to be read.
type: str
required: True
"""
EXAMPLES = """
- name: Read a kv2 secret from Vault via the remote host with userpass auth
community.hashi_vault.vault_read:
url: https://vault:8201
path: secret/data/hello
auth_method: userpass
username: user
password: '{{ passwd }}'
register: secret
- name: Display the secret data
ansible.builtin.debug:
msg: "{{ secret.data.data.data }}"
- name: Retrieve an approle role ID from Vault via the remote host
community.hashi_vault.vault_read:
url: https://vault:8201
path: auth/approle/role/role-name/role-id
register: approle_id
- name: Display the role ID
ansible.builtin.debug:
msg: "{{ approle_id.data.data.role_id }}"
"""
RETURN = """
data:
description: The raw result of the read against the given path.
returned: success
type: dict
"""
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
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(
path=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
)
path = module.params.get('path')
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:
data = client.read(path)
except hvac.exceptions.Forbidden as e:
module.fail_json(msg="Forbidden: Permission Denied to path '%s'." % path, exception=traceback.format_exc())
if data is None:
module.fail_json(msg="The path '%s' doesn't seem to exist." % path)
module.exit_json(data=data)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,223 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2022, Brian Scholer (@briantist)
# 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 = """
module: vault_token_create
version_added: 2.3.0
author:
- Brian Scholer (@briantist)
short_description: Create a HashiCorp Vault token
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 token in HashiCorp Vault, returning the response, including the token.
seealso:
- ref: community.hashi_vault.vault_token_create lookup <ansible_collections.community.hashi_vault.vault_token_create_lookup>
description: The official documentation for the C(community.hashi_vault.vault_token_create) lookup plugin.
- module: community.hashi_vault.vault_login
- ref: community.hashi_vault.vault_login lookup <ansible_collections.community.hashi_vault.vault_login_lookup>
description: The official documentation for the C(community.hashi_vault.vault_login) lookup plugin.
- ref: community.hashi_vault.vault_login_token filter <ansible_collections.community.hashi_vault.vault_login_token_filter>
description: The official documentation for the C(community.hashi_vault.vault_login_token) filter plugin.
extends_documentation_fragment:
- community.hashi_vault.attributes
- community.hashi_vault.attributes.action_group
- community.hashi_vault.connection
- community.hashi_vault.auth
- community.hashi_vault.token_create
- community.hashi_vault.wrapping
notes:
- Token creation is a write operation (creating a token persisted to storage), so this module always reports C(changed=True).
- For the purposes of Ansible playbooks however,
it may be more useful to set I(changed_when=false) if you are doing idempotency checks against the target system.
attributes:
check_mode:
support: partial
details:
- In check mode, this module will not create a token, and will instead return a basic structure with an empty token.
However, this may not be useful if the token is required for follow on tasks.
- It may be better to use this module with I(check_mode=false) in order to have a valid token that can be used.
options: {}
"""
EXAMPLES = """
- name: Login via userpass and create a child token
community.hashi_vault.vault_token_create:
url: https://vault:8201
auth_method: userpass
username: user
password: '{{ passwd }}'
register: token_data
- name: Retrieve an approle role ID using the child token (token via filter)
community.hashi_vault.vault_read:
url: https://vault:8201
auth_method: token
token: '{{ token_data | community.hashi_vault.vault_login_token }}'
path: auth/approle/role/role-name/role-id
register: approle_id
- name: Retrieve an approle role ID using the child token (token via direct dict access)
community.hashi_vault.vault_read:
url: https://vault:8201
auth_method: token
token: '{{ token_data.login.auth.client_token }}'
path: auth/approle/role/role-name/role-id
register: approle_id
# implicitly uses token auth with a token from the environment
- name: Create an orphaned token with a short TTL
community.hashi_vault.vault_token_create:
url: https://vault:8201
orphan: true
ttl: 60s
register: token_data
- name: Display the full response
ansible.builtin.debug:
var: token_data.login
"""
RETURN = """
login:
description: The result of the token creation operation.
returned: success
type: dict
sample:
auth:
client_token: s.rlwajI2bblHAWU7uPqZhLru3
data: null
contains:
auth:
description: The C(auth) member of the token response.
returned: success
type: dict
contains:
client_token:
description: Contains the newly created token.
returned: success
type: str
data:
description: The C(data) member of the token response.
returned: success, when available
type: dict
"""
import traceback
from ansible.module_utils._text import to_native
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
PASS_THRU_OPTION_NAMES = [
'no_parent',
'no_default_policy',
'policies',
'id',
'role_name',
'meta',
'renewable',
'ttl',
'type',
'explicit_max_ttl',
'display_name',
'num_uses',
'period',
'entity_alias',
'wrap_ttl',
]
ORPHAN_OPTION_TRANSLATION = {
'id': 'token_id',
'role_name': 'role',
'type': 'token_type',
}
def run_module():
argspec = HashiVaultModule.generate_argspec(
orphan=dict(type='bool', default=False),
no_parent=dict(type='bool'),
no_default_policy=dict(type='bool'),
policies=dict(type='list', elements='str'),
id=dict(type='str'),
role_name=dict(type='str'),
meta=dict(type='dict'),
renewable=dict(type='bool'),
ttl=dict(type='str'),
type=dict(type='str', choices=['batch', 'service']),
explicit_max_ttl=dict(type='str'),
display_name=dict(type='str'),
num_uses=dict(type='int'),
period=dict(type='str'),
entity_alias=dict(type='str'),
wrap_ttl=dict(type='str'),
)
module = HashiVaultModule(
argument_spec=argspec,
supports_check_mode=True
)
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())
pass_thru_options = module.adapter.get_filled_options(*PASS_THRU_OPTION_NAMES)
orphan_options = pass_thru_options.copy()
for key in pass_thru_options.keys():
if key in ORPHAN_OPTION_TRANSLATION:
orphan_options[ORPHAN_OPTION_TRANSLATION[key]] = orphan_options.pop(key)
# token creation is a write operation, using storage and resources
changed = True
response = None
if module.check_mode:
module.exit_json(changed=changed, login={'auth': {'client_token': None}})
if module.adapter.get_option('orphan'):
try:
try:
# this method was added in hvac 1.0.0
# See: https://github.com/hvac/hvac/pull/869
response = client.auth.token.create_orphan(**orphan_options)
except AttributeError:
# this method was removed in hvac 1.0.0
# See: https://github.com/hvac/hvac/issues/758
response = client.create_token(orphan=True, **orphan_options)
except Exception as e:
module.fail_json(msg=to_native(e), exception=traceback.format_exc())
else:
try:
response = client.auth.token.create(**pass_thru_options)
except Exception as e:
module.fail_json(msg=to_native(e), exception=traceback.format_exc())
module.exit_json(changed=changed, login=response)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,191 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2022, Brian Scholer (@briantist)
# 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 = """
module: vault_write
version_added: 2.4.0
author:
- Brian Scholer (@briantist)
short_description: Perform a write operation against HashiCorp Vault
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:
- Performs a generic write operation against a given path in HashiCorp Vault, returning any output.
notes:
- C(vault_write) is a generic module to do operations that do not yet have a dedicated module. Where a specific module exists, that should be used instead.
- The I(data) option is not treated as secret and may be logged. Use the C(no_log) keyword if I(data) contains sensitive values.
- 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, an empty response will be returned and the write will not be performed.
seealso:
- ref: community.hashi_vault.vault_write lookup <ansible_collections.community.hashi_vault.vault_write_lookup>
description: The official documentation for the C(community.hashi_vault.vault_write) lookup plugin.
- module: community.hashi_vault.vault_read
- ref: community.hashi_vault.vault_read lookup <ansible_collections.community.hashi_vault.vault_read_lookup>
description: The official documentation for the C(community.hashi_vault.vault_read) lookup plugin.
extends_documentation_fragment:
- community.hashi_vault.attributes
- community.hashi_vault.attributes.action_group
- community.hashi_vault.connection
- community.hashi_vault.auth
- community.hashi_vault.wrapping
options:
path:
description: Vault path to be written to.
type: str
required: True
data:
description: A dictionary to be serialized to JSON and then sent as the request body.
type: dict
required: false
default: {}
"""
EXAMPLES = """
- name: Write a value to the cubbyhole via the remote host with userpass auth
community.hashi_vault.vault_write:
url: https://vault:8201
path: cubbyhole/mysecret
data:
key1: val1
key2: val2
auth_method: userpass
username: user
password: '{{ passwd }}'
register: result
- name: Display the result of the write (this can be empty)
ansible.builtin.debug:
msg: "{{ result.data }}"
- name: Write secret to Vault using key value V2 engine
community.hashi_vault.vault_write:
path: secret/data/mysecret
data:
data:
key1: val1
key2: val2
- name: Retrieve an approle role ID from Vault via the remote host
community.hashi_vault.vault_read:
url: https://vault:8201
path: auth/approle/role/role-name/role-id
register: approle_id
- name: Generate a secret-id for the given approle
community.hashi_vault.vault_write:
url: https://vault:8201
path: auth/approle/role/role-name/secret-id
register: secret_id
- name: Display the role ID and secret ID
ansible.builtin.debug:
msg:
- "role-id: {{ approle_id.data.data.role_id }}"
- "secret-id: {{ secret_id.data.data.secret_id }}"
"""
RETURN = """
data:
description: The raw result of the write against the given path.
returned: success
type: dict
"""
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
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(
path=dict(type='str', required=True),
data=dict(type='dict', required=False, default={}),
wrap_ttl=dict(type='str'),
)
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
)
path = module.params.get('path')
data = module.params.get('data')
wrap_ttl = module.params.get('wrap_ttl')
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:
if module.check_mode:
response = {}
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:
module.fail_json(msg="The path '%s' doesn't seem to exist." % path, exception=traceback.format_exc())
except hvac.exceptions.InternalServerError as e:
module.fail_json(msg="Internal Server Error: %s" % to_native(e), exception=traceback.format_exc())
# https://github.com/hvac/hvac/issues/797
# HVAC returns a raw response object when the body is not JSON.
# That includes 204 responses, which are successful with no body.
# So we will try to detect that and a act accordingly.
# A better way may be to implement our own adapter for this
# collection, but it's a little premature to do that.
if hasattr(response, 'json') and callable(response.json):
if response.status_code == 204:
output = {}
else:
module.warn('Vault returned status code %i and an unparsable body.' % response.status_code)
output = response.content
else:
output = response
module.exit_json(changed=True, data=output)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# 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
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase
from ansible.utils.display import Display
from ansible_collections.community.hashi_vault.plugins.plugin_utils._hashi_vault_plugin import HashiVaultPlugin
display = Display()
class HashiVaultLookupBase(HashiVaultPlugin, LookupBase):
def __init__(self, loader=None, templar=None, **kwargs):
HashiVaultPlugin.__init__(self)
LookupBase.__init__(self, loader=loader, templar=templar, **kwargs)
def parse_kev_term(self, term, plugin_name, first_unqualified=None):
'''parses a term string into a dictionary'''
param_dict = {}
for i, param in enumerate(term.split()):
try:
key, value = param.split('=', 1)
except ValueError:
if i == 0 and first_unqualified is not None:
# allow first item to be specified as value only and assign to assumed option name
key = first_unqualified
value = param
else:
raise AnsibleError("%s lookup plugin needs key=value pairs, but received %s" % (plugin_name, term))
param_dict[key] = value
return param_dict

View File

@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Brian Scholer (@briantist)
# 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
# FOR INTERNAL COLLECTION USE ONLY
# The interfaces in this file are meant for use within the community.hashi_vault collection
# and may not remain stable to outside uses. Changes may be made in ANY release, even a bugfix release.
# See also: https://github.com/ansible/community/issues/539#issuecomment-780839686
# Please open an issue if you have questions about this.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.plugins import AnsiblePlugin
from ansible import constants as C
from ansible.utils.display import Display
from ansible_collections.community.hashi_vault.plugins.module_utils._hashi_vault_common import (
HashiVaultHelper,
HashiVaultOptionAdapter,
)
from ansible_collections.community.hashi_vault.plugins.module_utils._connection_options import HashiVaultConnectionOptions
from ansible_collections.community.hashi_vault.plugins.module_utils._authenticator import HashiVaultAuthenticator
display = Display()
class HashiVaultPlugin(AnsiblePlugin):
def __init__(self):
super(HashiVaultPlugin, self).__init__()
self.helper = HashiVaultHelper()
self._options_adapter = HashiVaultOptionAdapter.from_ansible_plugin(self)
self.connection_options = HashiVaultConnectionOptions(self._options_adapter, self._generate_retry_callback)
self.authenticator = HashiVaultAuthenticator(self._options_adapter, display.warning, display.deprecated)
def _generate_retry_callback(self, retry_action):
'''returns a Retry callback function for plugins'''
def _on_retry(retry_obj):
if retry_obj.total > 0:
if retry_action == 'warn':
display.warning('community.hashi_vault: %i %s remaining.' % (retry_obj.total, 'retry' if retry_obj.total == 1 else 'retries'))
else:
pass
return _on_retry
def process_deprecations(self, collection_name='community.hashi_vault'):
'''processes deprecations related to the collection'''
# TODO: this is a workaround for deprecations not being shown in lookups
# See:
# - https://github.com/ansible/ansible/issues/73051
# - https://github.com/ansible/ansible/pull/73058
# - https://github.com/ansible/ansible/pull/73239
# - https://github.com/ansible/ansible/pull/73240
#
# If a fix is backported to 2.9, this should be removed.
# Otherwise, we'll have to test with fixes that are available and see how we
# can determine whether to execute this conditionally.
# nicked from cli/__init__.py
# with slight customizations to help filter out relevant messages
# (relying on the collection name since it's a valid attrib and we only have 1 plugin at this time)
# warn about deprecated config options
for deprecated in list(C.config.DEPRECATED):
name = deprecated[0]
why = deprecated[1]['why']
if deprecated[1].get('collection_name') != collection_name:
continue
if 'alternatives' in deprecated[1]:
alt = ', use %s instead' % deprecated[1]['alternatives']
else:
alt = ''
ver = deprecated[1].get('version')
date = deprecated[1].get('date')
collection_name = deprecated[1].get('collection_name')
display.deprecated("%s option, %s%s" % (name, why, alt), version=ver, date=date, collection_name=collection_name)
# remove this item from the list so it won't get processed again by something else
C.config.DEPRECATED.remove(deprecated)