Adding in Ansible (still a WIP).

This commit is contained in:
2025-01-16 16:12:35 -05:00
parent 91af95090e
commit a28e806b8d
4271 changed files with 606629 additions and 0 deletions
@@ -0,0 +1,44 @@
# Sample ansible-test configuration file for collections.
# Support for this feature was first added in ansible-core 2.12.
# Use of this file is optional.
# If used, this file must be placed in "tests/config.yml" relative to the base of the collection.
# see also:
# - https://github.com/ansible-collections/overview/issues/45#issuecomment-827853900
# - https://github.com/ansible/ansible/blob/devel/test/lib/ansible_test/config/config.yml
modules:
# Configuration for modules/module_utils.
# These settings do not apply to other content in the collection.
python_requires: '>=3.6'
# Python versions supported by modules/module_utils.
# This setting is required.
#
# Possible values:
#
# - 'default' - All Python versions supported by Ansible.
# This is the default value if no configuration is provided.
# - 'controller' - All Python versions supported by the Ansible controller.
# This indicates the modules/module_utils can only run on the controller.
# Intended for use only with modules/module_utils that depend on ansible-connection, which only runs on the controller.
# Unit tests for modules/module_utils will be permitted to import any Ansible code, instead of only module_utils.
# - SpecifierSet - A PEP 440 specifier set indicating the supported Python versions.
# This is only needed when modules/module_utils do not support all Python versions supported by Ansible.
# It is not necessary to exclude versions which Ansible does not support, as this will be done automatically.
#
# What does this affect?
#
# - Unit tests will be skipped on any unsupported Python version.
# - Sanity tests that are Python version specific will be skipped on any unsupported Python version that is not supported by the controller.
#
# Sanity tests that are Python version specific will always be executed for Python versions supported by the controller, regardless of this setting.
# Reasons for this restriction include, but are not limited to:
#
# - AnsiballZ must be able to AST parse modules/module_utils on the controller, even though they may execute on a managed node.
# - ansible-doc must be able to AST parse modules/module_utils on the controller to display documentation.
# - ansible-test must be able to AST parse modules/module_utils to perform static analysis on them.
# - ansible-test must be able to execute portions of modules/module_utils to validate their argument specs.
#
# These settings only apply to modules/module_utils.
# It is not possible to declare supported Python versions for controller-only code.
# All Python versions supported by the controller must be supported by controller-only code.
@@ -0,0 +1,10 @@
# .ansible-lint file for integration tests
---
skip_list:
- unnamed-task
- truthy
- var-naming
- meta-no-info
- ignore-errors
- risky-file-permissions
- command-instead-of-shell
@@ -0,0 +1,64 @@
coverage >= 4.2, < 5.0.0, != 4.3.2 ; python_version <= '3.7' # features in 4.2+ required, avoid known bug in 4.3.2 on python 2.6, coverage 5.0+ incompatible
coverage >= 4.5.4, < 5.0.0 ; python_version > '3.7' # coverage had a bug in < 4.5.4 that would cause unit tests to hang in Python 3.8, coverage 5.0+ incompatible
cryptography < 2.2 ; python_version < '2.7' # cryptography 2.2 drops support for python 2.6
deepdiff < 4.0.0 ; python_version < '3' # deepdiff 4.0.0 and later require python 3
jinja2 < 2.11 ; python_version < '2.7' # jinja2 2.11 and later require python 2.7 or later
urllib3 < 1.24 ; python_version < '2.7' # urllib3 1.24 and later require python 2.7 or later
pywinrm >= 0.3.0 # message encryption support
sphinx < 1.6 ; python_version < '2.7' # sphinx 1.6 and later require python 2.7 or later
sphinx < 1.8 ; python_version >= '2.7' # sphinx 1.8 and later are currently incompatible with rstcheck 3.3
pygments >= 2.4.0 # Pygments 2.4.0 includes bugfixes for YAML and YAML+Jinja lexers
wheel < 0.30.0 ; python_version < '2.7' # wheel 0.30.0 and later require python 2.7 or later
yamllint != 1.8.0, < 1.14.0 ; python_version < '2.7' # yamllint 1.8.0 and 1.14.0+ require python 2.7+
pycrypto >= 2.6 # Need features found in 2.6 and greater
ncclient >= 0.5.2 # Need features added in 0.5.2 and greater
idna < 2.6, >= 2.5 # linode requires idna < 2.9, >= 2.5, requests requires idna < 2.6, but cryptography will cause the latest version to be installed instead
paramiko < 2.4.0 ; python_version < '2.7' # paramiko 2.4.0 drops support for python 2.6
pytest < 3.3.0 ; python_version < '2.7' # pytest 3.3.0 drops support for python 2.6
pytest < 5.0.0 ; python_version == '2.7' # pytest 5.0.0 and later will no longer support python 2.7
pytest-forked < 1.0.2 ; python_version < '2.7' # pytest-forked 1.0.2 and later require python 2.7 or later
pytest-forked >= 1.0.2 ; python_version >= '2.7' # pytest-forked before 1.0.2 does not work with pytest 4.2.0+ (which requires python 2.7+)
ntlm-auth >= 1.3.0 # message encryption support using cryptography
requests < 2.20.0 ; python_version < '2.7' # requests 2.20.0 drops support for python 2.6
requests-ntlm >= 1.1.0 # message encryption support
requests-credssp >= 0.1.0 # message encryption support
voluptuous >= 0.11.0 # Schema recursion via Self
openshift >= 0.6.2, < 0.9.0 # merge_type support
virtualenv < 16.0.0 ; python_version < '2.7' # virtualenv 16.0.0 and later require python 2.7 or later
pathspec < 0.6.0 ; python_version < '2.7' # pathspec 0.6.0 and later require python 2.7 or later
pyopenssl < 18.0.0 ; python_version < '2.7' # pyOpenSSL 18.0.0 and later require python 2.7 or later
pyfmg == 0.6.1 # newer versions do not pass current unit tests
pyyaml < 5.1 ; python_version < '2.7' # pyyaml 5.1 and later require python 2.7 or later
pycparser < 2.19 ; python_version < '2.7' # pycparser 2.19 and later require python 2.7 or later
mock >= 2.0.0 # needed for features backported from Python 3.6 unittest.mock (assert_called, assert_called_once...)
pytest-mock >= 1.4.0 # needed for mock_use_standalone_module pytest option
xmltodict < 0.12.0 ; python_version < '2.7' # xmltodict 0.12.0 and later require python 2.7 or later
lxml < 4.3.0 ; python_version < '2.7' # lxml 4.3.0 and later require python 2.7 or later
pyvmomi < 6.0.0 ; python_version < '2.7' # pyvmomi 6.0.0 and later require python 2.7 or later
pyone == 1.1.9 # newer versions do not pass current integration tests
boto3 < 1.11 ; python_version < '2.7' # boto3 1.11 drops Python 2.6 support
botocore >= 1.10.0, < 1.14 ; python_version < '2.7' # adds support for the following AWS services: secretsmanager, fms, and acm-pca; botocore 1.14 drops Python 2.6 support
botocore >= 1.10.0 ; python_version >= '2.7' # adds support for the following AWS services: secretsmanager, fms, and acm-pca
setuptools < 45 ; python_version <= '2.7' # setuptools 45 and later require python 3.5 or later
cffi >= 1.14.2, != 1.14.3 # Yanked version which older versions of pip will still install:
# freeze pylint and its requirements for consistent test results
astroid == 2.2.5
isort == 4.3.15
lazy-object-proxy == 1.3.1
mccabe == 0.6.1
pylint == 2.3.1
typed-ast == 1.4.0 # 1.4.0 is required to compile on Python 3.8
wrapt == 1.11.1
# hvac
hvac >= 1.2.1 ; python_version >= '3.6'
# urllib3
# these should be satisfied naturally by the requests versions required by hvac anyway
urllib3 >= 1.15 ; python_version >= '3.6' # we need raise_on_status for retry support to raise the correct exceptions https://github.com/urllib3/urllib3/blob/main/CHANGES.rst#115-2016-04-06
# requests
# https://github.com/psf/requests/pull/6356
requests >= 2.29 ; python_version >= '3.7'
requests < 2.28 ; python_version < '3.7'
@@ -0,0 +1,6 @@
# this is the ansible.cfg file used for integration tests
[hashi_vault_collection]
# if any connections are taking longer than this to complete there's probably something really wrong
# with the integration tests, so it'd be better to fail faster than the 30s default
timeout = 5
@@ -0,0 +1,16 @@
# Running integration tests requires you set up an integration_config.yml that
# tells the tests where to find Vault and other dependencies.
# See the contributor guide at:
# https://docs.ansible.com/ansible/devel/collections/community/hashi_vault/docsite/contributor_guide.html#integration-tests
---
# this is just a small sample of what the file looks like,
# this file is not valid on its own. See the guide for details.
vault_version: latest
vault_dev_root_token_id: 47542cbc-6bf8-4fba-8eda-02e0a0d29a0a
vault_proxy_server: 'http://127.0.0.1:8001'
vault_test_server_http: http://localhost:8200
vault_test_server_https: https://localhost:8300
@@ -0,0 +1,4 @@
hvac
urllib3
azure-identity
psycopg[binary,pool]
@@ -0,0 +1,2 @@
vault/auth/approle
context/target
@@ -0,0 +1,14 @@
---
ansible_hashi_vault_url: '{{ vault_test_server_http }}'
ansible_hashi_vault_auth_method: approle
auth_paths:
- approle
- approle-alt
secret_id_role: req-secret-id-role
no_secret_id_role: no-secret-id-role
vault_approle_canary:
path: cubbyhole/configure_approle
value: complete # value does not matter
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,38 @@
- name: "Setup block"
vars:
is_default_path: "{{ this_path == default_path }}"
block:
- name: 'Enable the approle auth method'
vault_ci_enable_auth:
method_type: approle
path: '{{ omit if is_default_path else this_path }}'
config:
default_lease_ttl: 60m
- name: 'Create an approle policy'
vault_ci_policy_put:
name: approle-policy
policy: |
path "auth/{{ this_path }}/login" {
capabilities = [ "create", "read" ]
}
- name: 'Create a named role (secret ID required)'
vault_ci_write:
path: 'auth/{{ this_path }}/role/{{ secret_id_role }}'
data:
# in docs, this is token_policies (changed in Vault 1.2)
# use 'policies' to support older versions
policies: "{{ 'test-policy' if is_default_path else 'alt-policy' }},approle-policy"
secret_id_ttl: 60m
- name: 'Create a named role (without secret id)'
vault_ci_write:
path: 'auth/{{ this_path }}/role/{{ no_secret_id_role }}'
data:
# in docs, this is token_policies (changed in Vault 1.2)
# use 'policies' to support older versions
policies: "{{ 'test-policy' if is_default_path else 'alt-policy' }},approle-policy"
secret_id_ttl: 60m
bind_secret_id: false
secret_id_bound_cidrs: '0.0.0.0/0'
@@ -0,0 +1,55 @@
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
kwargs_mount: "{{ {} if is_default_path else {'mount_point': this_path} }}"
kwargs_secret_id: {}
kwargs: "{{ kwargs_common | combine(kwargs_mount) | combine(kwargs_secret_id) }}"
block:
- name: 'Fetch the RoleID of the AppRole'
vault_ci_read:
path: 'auth/{{ this_path }}/role/{{ approle_name }}/role-id'
register: role_id_cmd
- name: Set common args
set_fact:
kwargs_common:
role_id: '{{ role_id_cmd.result.data.role_id }}'
- name: 'Get a SecretID issued against the AppRole'
when: use_secret_id | bool
vault_ci_write:
path: 'auth/{{ this_path }}/role/{{ approle_name }}/secret-id'
data: {}
register: secret_id_cmd
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
vars:
kwargs_secret_id: |
{% if use_secret_id | bool %}
{{ {'secret_id': secret_id_cmd.result.data.secret_id} }}
{% else %}
{{ {} }}
{% endif %}
set_fact:
response: "{{ lookup('vault_test_auth', **kwargs) }}"
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('test-policy' in response.login.auth.policies) | bool == is_default_path
- ('test-policy' not in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when erroneous credentials are used and secret ID is required
set_fact:
response: "{{ lookup('vault_test_auth', secret_id='fake', want_exception=true, **kwargs) }}"
- assert:
fail_msg: "An invalid secret ID somehow did not cause a failure."
that:
- (response is failed) == use_secret_id
- not use_secret_id or response.msg is search('(?i)invalid (?:role or )?secret id')
@@ -0,0 +1,49 @@
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
module_defaults:
vault_test_auth:
url: '{{ ansible_hashi_vault_url }}'
auth_method: '{{ ansible_hashi_vault_auth_method }}'
mount_point: '{{ omit if is_default_path else this_path }}'
role_id: '{{ role_id_cmd.result.data.role_id | default(omit) }}'
block:
- name: 'Fetch the RoleID of the AppRole'
vault_ci_read:
path: 'auth/{{ this_path }}/role/{{ approle_name }}/role-id'
register: role_id_cmd
- name: 'Get a SecretID issued against the AppRole'
when: use_secret_id | bool
vault_ci_write:
path: 'auth/{{ this_path }}/role/{{ approle_name }}/secret-id'
data: {}
register: secret_id_cmd
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
register: response
vault_test_auth:
secret_id: "{{ secret_id_cmd.result.data.secret_id if (use_secret_id | bool) else omit }}"
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('test-policy' in response.login.auth.policies) | bool == is_default_path
- ('test-policy' not in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when erroneous credentials are used and secret ID is required
register: response
vault_test_auth:
secret_id: fake
want_exception: true
- assert:
fail_msg: "An invalid secret ID somehow did not cause a failure."
that:
- (response.inner is failed) == use_secret_id
- not use_secret_id or response.msg is search('(?i)invalid (?:role or )?secret id')
@@ -0,0 +1,52 @@
---
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- name: Persist defaults
set_fact:
'{{ item.key }}': "{{ lookup('vars', item.key) }}"
loop: "{{ lookup('file', role_path ~ '/defaults/main.yml') | from_yaml | dict2items }}"
loop_control:
label: '{{ item.key }}'
- name: Configuration tasks
module_defaults:
vault_ci_enable_auth: '{{ vault_plugins_module_defaults_common }}'
vault_ci_policy_put: '{{ vault_plugins_module_defaults_common }}'
vault_ci_write: '{{ vault_plugins_module_defaults_common }}'
vault_ci_read: '{{ vault_plugins_module_defaults_common }}'
block:
- name: Canary for approle auth
vault_ci_read:
path: '{{ vault_approle_canary.path }}'
register: canary
- name: Configure approle
when: canary.result is none
loop: '{{ auth_paths }}'
include_tasks:
file: approle_setup.yml
apply:
vars:
default_path: '{{ ansible_hashi_vault_auth_method }}'
this_path: '{{ item }}'
- name: Write Canary
when: canary.result is none
vault_ci_write:
path: '{{ vault_approle_canary.path }}'
data:
value: '{{ vault_approle_canary.value }}'
- name: Run approle tests
loop: '{{ auth_paths | product([secret_id_role, no_secret_id_role]) | product(["target", "controller"]) | list }}'
include_tasks:
file: approle_test_{{ item[1] }}.yml
apply:
vars:
default_path: '{{ ansible_hashi_vault_auth_method }}'
this_path: '{{ item[0][0] }}'
approle_name: '{{ item[0][1] }}'
use_secret_id: '{{ item[0][1] == secret_id_role }}'
module_defaults:
assert:
quiet: true
@@ -0,0 +1,2 @@
vault/auth/aws_iam
context/target
@@ -0,0 +1,10 @@
---
ansible_hashi_vault_url: '{{ vault_mmock_server_http }}'
ansible_hashi_vault_auth_method: aws_iam
auth_paths:
- aws
- aws-alt
aws_access_key: abc
aws_secret_key: xyz
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,33 @@
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
kwargs_mount: "{{ {} if is_default_path else {'mount_point': this_path} }}"
kwargs_common:
aws_access_key: '{{ aws_access_key }}'
aws_secret_key: '{{ aws_secret_key }}'
kwargs: "{{ kwargs_common | combine(kwargs_mount) }}"
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
set_fact:
response: "{{ lookup('vault_test_auth', role_id='not-important', **kwargs) }}"
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('aws-sample-policy' in response.login.auth.policies) | bool == is_default_path
- ('aws-sample-policy' not in response.login.auth.policies) | bool != is_default_path
- ('aws-alt-sample-policy' in response.login.auth.policies) | bool != is_default_path
- ('aws-alt-sample-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when something goes wrong (simulated)
set_fact:
response: "{{ lookup('vault_test_auth', role_id='fail-me-role', want_exception=true, **kwargs) }}"
- assert:
fail_msg: "An invalid request somehow did not cause a failure."
that:
- response is failed
- response.msg is search('<Error>')
@@ -0,0 +1,38 @@
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
module_defaults:
vault_test_auth:
url: '{{ ansible_hashi_vault_url }}'
auth_method: '{{ ansible_hashi_vault_auth_method }}'
mount_point: '{{ omit if is_default_path else this_path }}'
aws_access_key: '{{ aws_access_key }}'
aws_secret_key: '{{ aws_secret_key }}'
role_id: not-important
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
register: response
vault_test_auth:
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('aws-sample-policy' in response.login.auth.policies) | bool == is_default_path
- ('aws-sample-policy' not in response.login.auth.policies) | bool != is_default_path
- ('aws-alt-sample-policy' in response.login.auth.policies) | bool != is_default_path
- ('aws-alt-sample-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when something goes wrong (simulated)
register: response
vault_test_auth:
role_id: fail-me-role
want_exception: true
- assert:
fail_msg: "An invalid request somehow did not cause a failure."
that:
- response.inner is failed
- response.msg is search('<Error>')
@@ -0,0 +1,23 @@
---
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- name: Persist defaults
set_fact:
'{{ item.key }}': "{{ lookup('vars', item.key) }}"
loop: "{{ lookup('file', role_path ~ '/defaults/main.yml') | from_yaml | dict2items }}"
loop_control:
label: '{{ item.key }}'
# there's no setup for this auth method because its API is mocked
- name: Run aws_iam tests
loop: '{{ auth_paths | product(["target", "controller"]) | list }}'
include_tasks:
file: aws_iam_test_{{ item[1] }}.yml
apply:
vars:
default_path: aws
this_path: '{{ item[0] }}'
module_defaults:
assert:
quiet: true
@@ -0,0 +1,2 @@
vault/auth/azure
context/target
@@ -0,0 +1,10 @@
# Copyright (c) 2022 Junrui Chen (@jchenship)
# 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
---
ansible_hashi_vault_url: '{{ vault_mmock_server_http }}'
ansible_hashi_vault_auth_method: azure
auth_paths:
- azure
- azure-alt
@@ -0,0 +1,7 @@
# Copyright (c) 2022 Junrui Chen (@jchenship)
# 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
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,48 @@
# Copyright (c) 2022 Junrui Chen (@jchenship)
# 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
---
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
kwargs_mount: "{{ {} if is_default_path else {'mount_point': this_path} }}"
kwargs_common:
jwt: azure-jwt
kwargs: "{{ kwargs_common | combine(kwargs_mount) }}"
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
set_fact:
response: "{{ lookup('vault_test_auth', role_id='not-important', **kwargs) }}"
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('azure-sample-policy' in response.login.auth.policies) | bool == is_default_path
- ('azure-sample-policy' not in response.login.auth.policies) | bool != is_default_path
- ('azure-alt-sample-policy' in response.login.auth.policies) | bool != is_default_path
- ('azure-alt-sample-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when something goes wrong (simulated)
set_fact:
response: "{{ lookup('vault_test_auth', role_id='fail-me-role', want_exception=true, **kwargs) }}"
- assert:
fail_msg: "An invalid request somehow did not cause a failure."
that:
- response is failed
- response.msg is search('expected audience .+ got .+')
- name: Failure expected when role_id is not given
set_fact:
response: "{{ lookup('vault_test_auth', want_exception=true, **kwargs) }}"
- assert:
fail_msg: |
Missing role_id did not cause an expected failure.
{{ response }}
that:
- response is failed
- response.msg is search('^role_id is required for azure authentication\.$')
@@ -0,0 +1,54 @@
# Copyright (c) 2022 Junrui Chen (@jchenship)
# 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
---
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
module_defaults:
vault_test_auth:
url: '{{ ansible_hashi_vault_url }}'
auth_method: '{{ ansible_hashi_vault_auth_method }}'
mount_point: '{{ omit if is_default_path else this_path }}'
jwt: azure-jwt
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
register: response
vault_test_auth:
role_id: not-important
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('azure-sample-policy' in response.login.auth.policies) | bool == is_default_path
- ('azure-sample-policy' not in response.login.auth.policies) | bool != is_default_path
- ('azure-alt-sample-policy' in response.login.auth.policies) | bool != is_default_path
- ('azure-alt-sample-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when something goes wrong (simulated)
register: response
vault_test_auth:
role_id: fail-me-role
want_exception: true
- assert:
fail_msg: "An invalid request somehow did not cause a failure."
that:
- response.inner is failed
- response.msg is search('expected audience .+ got .+')
- name: Failure expected when role_id is not given
register: response
vault_test_auth:
want_exception: true
- assert:
fail_msg: |
Missing role_id did not cause an expected failure.
{{ response }}
that:
- response.inner is failed
- response.msg is search('^role_id is required for azure authentication\.$')
@@ -0,0 +1,26 @@
# Copyright (c) 2022 Junrui Chen (@jchenship)
# 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
---
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- name: Persist defaults
set_fact:
'{{ item.key }}': "{{ lookup('vars', item.key) }}"
loop: "{{ lookup('file', role_path ~ '/defaults/main.yml') | from_yaml | dict2items }}"
loop_control:
label: '{{ item.key }}'
# there's no setup for this auth method because its API is mocked
- name: Run azure tests
loop: '{{ auth_paths | product(["target", "controller"]) | list }}'
include_tasks:
file: azure_test_{{ item[1] }}.yml
apply:
vars:
default_path: azure
this_path: '{{ item[0] }}'
module_defaults:
assert:
quiet: true
@@ -0,0 +1,2 @@
vault/auth/cert
context/target
@@ -0,0 +1,19 @@
---
vault_run_https_tests: True
ansible_hashi_vault_url: '{{ vault_test_server_http }}'
ansible_hashi_vault_auth_method: cert
auth_paths:
- cert
- cert-alt
vault_cert_canary:
path: cubbyhole/configure_cert
value: complete # value does not matter
auth_cert_cn: vault-test
auth_cert_cert: "{{ role_path }}/files/auth_cert.crt"
auth_cert_key: "{{ role_path }}/files/auth_cert.key"
invalid_auth_cert_cert: "{{ role_path }}/files/auth_cert_invalid.crt"
invalid_auth_cert_key: "{{ role_path }}/files/auth_cert_invalid.key"
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDIjCCAgqgAwIBAgIUcyvqaCXttUgXhdmM8QJgCmaqsK4wDQYJKoZIhvcNAQEL
BQAwFTETMBEGA1UEAwwKdmF1bHQtdGVzdDAgFw0yMTEwMTkwNjAyMzFaGA8yMTIx
MDkyNTA2MDIzMVowFTETMBEGA1UEAwwKdmF1bHQtdGVzdDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAMnAUmlSnZk3RBSs7iW5TPXAkUgdYhOlJKT4xRE1
Ta3rZo1NaPas6rh0fl4lkNHB/OvzaVhNjgptkTXarccMOMhGiQUxhQEfKW+KzqIy
qsXXk68aj/xIgVWu1/IoVUYx89LUHE2Xdd5aO95w1a6goox96spVZp7UaWSb8/V9
SGUexgAJMDGrGTPGbXD2pSsBfDWg5ysxiptZmUfeMWtZ/1OJJ9eFuHjW+tDCuOHe
HcekiKwM90CjvqeEhGdgEtLGVDkT4ud2u7YKeZXxIe5UTML20paCzd12v/LOIlM2
ZEqhySVrBvl+Wzv5BLmffW62UPWXlRDZa9FaCAWG/94F/CMCAwEAAaNoMGYwHQYD
VR0OBBYEFGZFLq7ROcjYDf3n2A+KSe73zFOuMB8GA1UdIwQYMBaAFGZFLq7ROcjY
Df3n2A+KSe73zFOuMA8GA1UdEwEB/wQFMAMBAf8wEwYDVR0lBAwwCgYIKwYBBQUH
AwIwDQYJKoZIhvcNAQELBQADggEBAIe65BTFlTOFtUkxV1Zf3eOE6Lq6HZqzvNmK
1sCDdT1kL080P5Y6pcIeG99+mikN8b9Csh9CB/AqB5WjAF3Hfdg2EHd4d6gwjUwB
t5+hw83FQvckxEQ80ZVn2C83aZ9xIOgLqB2QnWJKGWp47816+/IqNo07NWvttLgM
L5e2cX6Ass1nT4Bjh8P4NQgg2lMDCzwwAZBR5D0mCSO8MbO1Ud8KRfaSIUczemlJ
PFNl3r3hI6efKCVfsbVcbnopuvPgcW4BH1KXZOLEnZm1lUdKCAYjA5g1rCGhKSTC
p/d72HTzqSHlgyEish7ueEeY0Z1sMDWvUZLu46GCGOf5pozxoQo=
-----END CERTIFICATE-----
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDJwFJpUp2ZN0QU
rO4luUz1wJFIHWITpSSk+MURNU2t62aNTWj2rOq4dH5eJZDRwfzr82lYTY4KbZE1
2q3HDDjIRokFMYUBHylvis6iMqrF15OvGo/8SIFVrtfyKFVGMfPS1BxNl3XeWjve
cNWuoKKMferKVWae1Glkm/P1fUhlHsYACTAxqxkzxm1w9qUrAXw1oOcrMYqbWZlH
3jFrWf9TiSfXhbh41vrQwrjh3h3HpIisDPdAo76nhIRnYBLSxlQ5E+Lndru2CnmV
8SHuVEzC9tKWgs3ddr/yziJTNmRKocklawb5fls7+QS5n31utlD1l5UQ2WvRWggF
hv/eBfwjAgMBAAECggEAXhehF9fdAokg6legld1vBCp0V2LEzA64IWyYVCc8/EEO
ShZxPqJ0seQ6z2PLv9guQkj6t6Er/rcNA0XiyDNuBBHJc6+drWFALPJa3pCszqp1
CTRlNK8ICtMJibm/04YWhhxAuvtJkJMa2upa7h+iz80mBImB28+K+840ICj265lz
lua32UCMXw0lDPUm8Ud9lVYKy1tTy9IMOxnwsplXFxtARlxoyn0/f4e1v+4MT1zQ
gm3EXkr7xNK8gEnYB87RZBphpS1QPah3ZQZc81imgeZLEW+bxSKHlTp6qk9OMZYa
VfMNM5WeDEZw7aWaOSrWn2Vc2K2eCZpbV99FAMzDYQKBgQDlMWD9yoCYh46x1C5N
A4DCMkpcoPxQkFSWevUnLVxlvMybKleUrL9EUzJ58Ps2d2Yn5KfS8xjxwrBEF7DW
ReMtEmUhx3PeF3GdIUnsE6ePUgVysbtXHjPcj8LiRXsOrDIQ6g55qNrVczngGqmV
e8UP6fx15QbnTho00aU17K+J0wKBgQDhWUU/7gjtk1Z+3Qeyu5Rm65RirVWJ2lM/
NluLX132uL831+X9v22r8o1P40cXJJ05baX2VCoR88Z6oVxD5g4eOS+scwwTSmIK
3n07awPDffw/Em3I3zhUN26ExM5Ed3IOngf5WLBw2r3gavGV2FDc/RDn28GTgM8I
Bo54MB+CcQKBgQCSuRjRgCjw/J8SIrZ9YQe1yoImaHz+ildMemyk5vomu0X085db
u3c6o1RGEkqQJMHGOjBh8HSAmNVE0jHICreTbBpIFKqNfE6ke+IZ+r8jFiwcr8Ex
1Uj4IyRsvHQ6AWyPvXcE1V86lGhxmkAETVbriCyxwKu5uhs2wxtTuTDrNwKBgCmt
khI92ybdfjzecmMLMGpMndgWSODDIWxqiEnhrIZKKwuQAbiJpCYOKTaiSW6tVere
Lbi+Xj2NwaLCn0brkKbkWr3hVVVoB3QNLEpGA58veOzNYsKpDkj9K5Kgt6mQEedE
MSNb1N46hq2v+diF9oa4w1yul0HJrADG/aia9ejxAoGAU3yES6OdE5QHyuiLHKfy
x5OOcQkTItk9IhxboSjYVB5GsBuKR+RloRZXmR9HhnzAjvbe0FVqGjdr5nHfICdE
8KsYpVf2c6x9NNbHSzqBARRg7x+H+uhfymgXfI4R3eL945ukFMC+qOU57kPvwriF
OvQYefm/1PN7vuLKsZ7g7iQ=
-----END PRIVATE KEY-----
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDDTCCAfWgAwIBAgIUWprzykl5M9p8NmcaS8v7mTQqCZEwDQYJKoZIhvcNAQEL
BQAwFTETMBEGA1UEAwwKdmF1bHQtdGVzdDAgFw0yMTEwMTkwMjE1MThaGA8yMTIx
MDkyNTAyMTUxOFowFTETMBEGA1UEAwwKdmF1bHQtdGVzdDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAM6Aha5bUcWwuikIFZUAccJXYAC5oczybwN6VDHD
dDugikic/AT1AkaRYAhJiLWAD0XeOHghf1eCpeC+ZYcbZssXr7NZ/fUmR28ni1Nt
QRTcZ0bEBBYaEjEoNHenwAOsuBhJuawvfNI+Jns6ejoLIC3nUgQabWp4gPbfrC5y
WWrPRzXZEMp9hFppxHRIHzW3yqxlOXO2hUC5UtVElYkh0ojBSCVXe8iFfWTBnZrc
uTIm85y1x+k1kD7oyWxTZiPaUtTd9UM6pG1iYq5Tfbzx7rx5ntiTMwSZL4Y3lUWv
kQ7WCXPV7L0p7NpRyIQQH6McBZiuatv8kEGRKqDtNhF5kDECAwEAAaNTMFEwHQYD
VR0OBBYEFL04vjdsoUCPoZ64btbGam88REPQMB8GA1UdIwQYMBaAFL04vjdsoUCP
oZ64btbGam88REPQMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
AMaL/01nXbYzlzy6Vrn6R6wcHAsrSWC1syvQTaJzHQFmp3bxs7XUu3ZQdRbppxCK
INDXtrzupxpsBV2qSdwrPsn79umkSb51NFtHz7cMcmK18cuayviPpEPNN3IZuznU
3MFNd+sKoxX2udp12tGwjkerRrgPcG44aWch18QQ7H/jPld51uaujRs6fsA4lUNF
E2uPdiUNridbnxIw7bUgz9Vcq5d+XzHFvaF5QGp/mqmY6tsp/rMJCOME/dpBh27/
Y/xh1qG92gSeT57IPNvd7M/yvKmcG2lRVv2rwm1oruYYaaHgqrai90sFDN+ttfVT
hqcx3qhE67dlFGLN03ico/8=
-----END CERTIFICATE-----
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDOgIWuW1HFsLop
CBWVAHHCV2AAuaHM8m8DelQxw3Q7oIpInPwE9QJGkWAISYi1gA9F3jh4IX9XgqXg
vmWHG2bLF6+zWf31JkdvJ4tTbUEU3GdGxAQWGhIxKDR3p8ADrLgYSbmsL3zSPiZ7
Ono6CyAt51IEGm1qeID236wucllqz0c12RDKfYRaacR0SB81t8qsZTlztoVAuVLV
RJWJIdKIwUglV3vIhX1kwZ2a3LkyJvOctcfpNZA+6MlsU2Yj2lLU3fVDOqRtYmKu
U3288e68eZ7YkzMEmS+GN5VFr5EO1glz1ey9KezaUciEEB+jHAWYrmrb/JBBkSqg
7TYReZAxAgMBAAECggEAFAfJb8kx3GAxHovHNCXP4w8Ao/FdrXiSph62jgEshCAl
abe4hm6RovC1BPjFBv39/UP57EUrifyFRJCTXpCc3vRUOaxwAtiMs059qED/wBtE
9UtMLiynORdyR20BJhoZ3VlBZl9Q1z/qEafxdTHhFDLM9NLvbBV2RPwbQoIbBE4c
LDz02ISvvX/2TQvCzXV723XhAWPAmXDfK0sxONJ2adlp5LdNOBmwbGzHIymTVFFR
yJh9fk67hSi6KBbvVw+AuTXhaZ48hBTfD7aG2PF0knZRug4qlL840u4h+YD/PRb4
FBs26XTzgX/fi4tTfR+fr43tbl/61JVOhV6PgmZqAQKBgQDxnP+aEQ6Lw4FuPFbf
ahwi/kJsng8GR7PfTLE9oOeCErmL2h8BdLqwoFNbUocrxzc7AnYQ2qLi6C+ord2j
huKcqvC4uV9EcBtm5PzszpsmvcYPdlMoJ2uUlpf4gNMw4QAQsdVkBl4dS1RmqfOF
nlB1Qr2fI13KxcTBLnIyF78eEQKBgQDazE9fY3mC859Vkuk90C/1cebb2D3JQ5+p
uyQOFzIrj4dIY9FtleuPG8T6pMRG0+VJdY0m2y25yWddrkR987d9HKdC6+O+7z9d
3K9Cdwudl+UgJDKRAjwpASSW8cN/tRinKqdLMaB7LG6zqjw2c6fPrJQDUpkqYQNW
Nf2oe3uwIQKBgGGUKpaqdNl1Z/yBWgR48kwfq+v6Gc9LfhWc/6gIJ/ecYFtfCE6q
OgvDdGbZecXwexnV8KD16/sAEt9o+K5md3cWgonYM+WL8UUpDg0FlBudYTQ1cXgy
E3y7JT0zqhd/h2s2pxvyhmgGWFvuH2/DdHMnNTXkLqkKHmB2xZ/9fy5BAoGAA4uo
BZ2xDGQyQsq8qNnEzS9pVEquxaIo5jE4JlpN39LVmGC1thbl2E3U5VLiM1ufrY8Q
GH8YwJf46tW2GmxmnspmE3mLGT77QeQfmu4e7BDYD6tGfn8QxoFUPHXyexFOMvdH
+rn1JcnUiWjKzP8WyxC63UrrXHpx+WWqlJ5bpMECgYEAjWUgQyAzep38gVSdwtIc
mrxOVUXHNPgts4DjIcu5Rbxy6E4CQ4jBiBdxNnVNEYgkyNPfKqjOtb4dEOEwO+XC
vz1ZCozUms0ALjbba6/zIHiowBOo8ORIngK4+zMx3fx+2wSfkeZ2kKOTFflvNOBk
QItFtv0Xwa/UhMWmnJ5uAW8=
-----END PRIVATE KEY-----
@@ -0,0 +1,5 @@
---
dependencies:
- setup_vault_test_plugins
- setup_cert_content
- setup_vault_configure
@@ -0,0 +1,31 @@
---
- name: "Setup block"
vars:
is_default_path: "{{ this_path == default_path }}"
block:
- name: "Enable the cert auth method"
vault_ci_enable_auth:
method_type: '{{ ansible_hashi_vault_auth_method }}'
path: "{{ omit if is_default_path else this_path }}"
config:
default_lease_ttl: 60m
- name: Create a cert policy
vault_ci_policy_put:
name: cert-policy
policy: |
path "auth/{{ this_path }}/login" {
capabilities = [ "create", "read" ]
}
- name: "Create a named role"
vault_ci_write:
path: "auth/{{ this_path }}/certs/vault_test"
data:
certificate: "{{ _auth_cert }}"
allowed_common_names: "{{ auth_cert_cn }}"
# in docs, this is token_policies (changed in Vault 1.2)
# use 'policies' to support older versions
policies: "{{ 'test-policy' if is_default_path else 'alt-policy' }},cert-policy"
vars:
_auth_cert: '{{ lookup("file", auth_cert_cert) }}'
@@ -0,0 +1,43 @@
---
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
kwargs_common:
ca_cert: "{{ vault_cert_file }}"
kwargs_mount: "{{ {} if is_default_path else {'mount_point': this_path} }}"
kwargs_cert:
cert_auth_public_key: "{{ auth_cert_cert }}"
cert_auth_private_key: "{{ auth_cert_key }}"
kwargs: "{{ kwargs_common | combine(kwargs_mount) | combine(kwargs_cert) }}"
block:
- name: Set the HTTPS connection address
set_fact:
ansible_hashi_vault_addr: "{{ vault_test_server_https }}"
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
set_fact:
response: "{{ lookup('vault_test_auth', **kwargs) }}"
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('test-policy' in response.login.auth.policies) | bool == is_default_path
- ('test-policy' not in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when erroneous credentials are used
vars:
kwargs_cert:
cert_auth_public_key: "{{ invalid_auth_cert_cert }}"
cert_auth_private_key: "{{ invalid_auth_cert_key }}"
set_fact:
response: "{{ lookup('vault_test_auth', want_exception=true, **kwargs) }}"
- assert:
fail_msg: "An invalid cert somehow did not cause a failure."
that:
- response is failed
- response.msg is search('invalid certificate or no client certificate supplied')
@@ -0,0 +1,40 @@
---
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
module_defaults:
vault_test_auth:
url: "{{ vault_test_server_https }}"
ca_cert: "{{ vault_cert_file }}"
auth_method: "{{ ansible_hashi_vault_auth_method }}"
mount_point: "{{ omit if is_default_path else this_path }}"
cert_auth_public_key: "{{ auth_cert_cert }}"
cert_auth_private_key: "{{ auth_cert_key }}"
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
vault_test_auth:
register: response
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('test-policy' in response.login.auth.policies) | bool == is_default_path
- ('test-policy' not in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when erroneous credentials are used
vault_test_auth:
cert_auth_public_key: "{{ invalid_auth_cert_cert }}"
cert_auth_private_key: "{{ invalid_auth_cert_key }}"
want_exception: true
register: response
- assert:
fail_msg: "An invalid cert somehow did not cause a failure."
that:
- response.inner is failed
- response.msg is search('invalid certificate or no client certificate supplied')
@@ -0,0 +1,57 @@
---
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- name: Persist defaults
set_fact:
'{{ item.key }}': "{{ lookup('vars', item.key) }}"
loop: "{{ lookup('file', role_path ~ '/defaults/main.yml') | from_yaml | dict2items }}"
loop_control:
label: '{{ item.key }}'
- name: Configuration tasks
module_defaults:
vault_ci_enable_auth: '{{ vault_plugins_module_defaults_common }}'
vault_ci_write: '{{ vault_plugins_module_defaults_common }}'
vault_ci_read: '{{ vault_plugins_module_defaults_common }}'
vault_ci_policy_put: '{{ vault_plugins_module_defaults_common }}'
block:
- name: Canary for cert auth
vault_ci_read:
path: '{{ vault_cert_canary.path }}'
register: canary
- name: Configure cert
when: canary.result is none
loop: '{{ auth_paths }}'
include_tasks:
file: cert_setup.yml
apply:
vars:
default_path: '{{ ansible_hashi_vault_auth_method }}'
this_path: '{{ item }}'
- name: Write Canary
when: canary.result is none
vault_ci_write:
path: '{{ vault_cert_canary.path }}'
data:
value: '{{ vault_cert_canary.value }}'
- name: Run cert tests (controller)
loop: '{{ auth_paths }}'
include_tasks:
file: cert_test_controller.yml
apply: &test_apply
vars:
default_path: '{{ ansible_hashi_vault_auth_method }}'
this_path: '{{ item }}'
module_defaults:
assert:
quiet: true
- name: Run cert tests (target)
loop: '{{ auth_paths }}'
include_tasks:
file: cert_test_target.yml
apply: *test_apply
@@ -0,0 +1,2 @@
vault/auth/jwt
context/target
@@ -0,0 +1,11 @@
---
ansible_hashi_vault_url: '{{ vault_test_server_http }}'
ansible_hashi_vault_auth_method: jwt
auth_paths:
- jwt
- jwt-alt
vault_jwt_canary:
path: cubbyhole/configure_jwt
value: complete # value does not matter
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWw
kWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mr
m/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEi
NQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV
3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2
QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQABAoIBACiARq2wkltjtcjs
kFvZ7w1JAORHbEufEO1Eu27zOIlqbgyAcAl7q+/1bip4Z/x1IVES84/yTaM8p0go
amMhvgry/mS8vNi1BN2SAZEnb/7xSxbflb70bX9RHLJqKnp5GZe2jexw+wyXlwaM
+bclUCrh9e1ltH7IvUrRrQnFJfh+is1fRon9Co9Li0GwoN0x0byrrngU8Ak3Y6D9
D8GjQA4Elm94ST3izJv8iCOLSDBmzsPsXfcCUZfmTfZ5DbUDMbMxRnSo3nQeoKGC
0Lj9FkWcfmLcpGlSXTO+Ww1L7EGq+PT3NtRae1FZPwjddQ1/4V905kyQFLamAA5Y
lSpE2wkCgYEAy1OPLQcZt4NQnQzPz2SBJqQN2P5u3vXl+zNVKP8w4eBv0vWuJJF+
hkGNnSxXQrTkvDOIUddSKOzHHgSg4nY6K02ecyT0PPm/UZvtRpWrnBjcEVtHEJNp
bU9pLD5iZ0J9sbzPU/LxPmuAP2Bs8JmTn6aFRspFrP7W0s1Nmk2jsm0CgYEAyH0X
+jpoqxj4efZfkUrg5GbSEhf+dZglf0tTOA5bVg8IYwtmNk/pniLG/zI7c+GlTc9B
BwfMr59EzBq/eFMI7+LgXaVUsM/sS4Ry+yeK6SJx/otIMWtDfqxsLD8CPMCRvecC
2Pip4uSgrl0MOebl9XKp57GoaUWRWRHqwV4Y6h8CgYAZhI4mh4qZtnhKjY4TKDjx
QYufXSdLAi9v3FxmvchDwOgn4L+PRVdMwDNms2bsL0m5uPn104EzM6w1vzz1zwKz
5pTpPI0OjgWN13Tq8+PKvm/4Ga2MjgOgPWQkslulO/oMcXbPwWC3hcRdr9tcQtn9
Imf9n2spL/6EDFId+Hp/7QKBgAqlWdiXsWckdE1Fn91/NGHsc8syKvjjk1onDcw0
NvVi5vcba9oGdElJX3e9mxqUKMrw7msJJv1MX8LWyMQC5L6YNYHDfbPF1q5L4i8j
8mRex97UVokJQRRA452V2vCO6S5ETgpnad36de3MUxHgCOX3qL382Qx9/THVmbma
3YfRAoGAUxL/Eu5yvMK8SAt/dJK6FedngcM3JEFNplmtLYVLWhkIlNRGDwkg3I5K
y18Ae9n7dHVueyslrb6weq7dTkYDi3iOYRW8HRkIQh06wEdbxt0shTzAJvvCQfrB
jg/3747WSsf/zBTcHihTRBdAv6OmdhV4/dD5YBfLAkLrd+mX7iE=
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv
vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc
aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy
tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0
e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb
V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9
MwIDAQAB
-----END PUBLIC KEY-----
@@ -0,0 +1 @@
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0Iiwic3ViIjoiaGFzaGlfdmF1bHRAdGVzdC5hbnNpYmxlLmNvbSIsIm5iZiI6MTYwNDgzNTEwMCwiZXhwIjozMjQ5OTA1MTM1OX0.NEWQR_Eicw8Fa9gU9HPY2M9Rp1czNTUKrICwKe7l1edaZNtgxhMGdyqnBsPrHL_dw1ZIwdvwVAioi8bEyIDEWICls0lzHwM169rrea3WEFrB5CP17A6DkvYL0cnOnGutbwUrXInPCRUfvRogIKEI-w8X-ris9LX2FBPKhXX1K3U0D8uYi5_9t8YWywTe0NkYvY-nTzMugK1MXMoBJ3fCksweJiDp6BOo3v9OU03MLgwgri2UdsqVb7WSk4XvWG-lmbiiSAWVf9BI3mecVDUHpYxbEqjv1HDG_wdX8zy1ZlAFbjp3kIpMlDVK1Q5nu_VPDzQrEvPdTnOzU36LE4UF-w
@@ -0,0 +1 @@
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIxMjM0IiwidXNlcl9jbGFpbSI6InVzZXJfY2xhaW0iLCJuYmYiOjE2MDQ4MzUxMDAsImV4cCI6MzI0OTkwNTEzNTl9.etc2WSH7kR3fHFlVt4wlBYFKNn7Z4DQcRVXUK4gGF-Q
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,32 @@
- name: "Setup block"
vars:
is_default_path: "{{ this_path == default_path }}"
block:
- name: 'Enable the JWT auth method'
vault_ci_enable_auth:
method_type: jwt
path: '{{ omit if is_default_path else this_path }}'
config:
default_lease_ttl: 60m
- name: 'Configure the JWT auth method'
vars:
jwt_public_key: '{{ lookup("file", "jwt_public.pem") }}'
vault_ci_write:
path: 'auth/{{ this_path }}/config'
data:
# in docs, this is token_policies (changed in Vault 1.2)
# use 'policies' to support older versions
policies: "{{ 'test-policy' if is_default_path else 'alt-policy' }},approle-policy"
jwt_validation_pubkeys: '{{ jwt_public_key }}'
- name: 'Create a named role'
vault_ci_write:
path: 'auth/{{ this_path }}/role/test-role'
data:
# in docs, this is token_policies (changed in Vault 1.2)
# use 'policies' to support older versions
policies: "{{ 'test-policy' if is_default_path else 'alt-policy' }},approle-policy"
role_type: jwt
user_claim: sub
bound_audiences: test
@@ -0,0 +1,39 @@
- name: "Test block"
vars:
jwt: '{{ lookup("file", "token.jwt") }}'
jwt_invalid: '{{ lookup("file", "token_invalid.jwt") }}'
is_default_path: "{{ this_path == default_path }}"
kwargs_common:
role_id: test-role
kwargs_mount: "{{ {} if is_default_path else {'mount_point': this_path} }}"
kwargs_jwt:
jwt: '{{ jwt }}'
kwargs: "{{ kwargs_common | combine(kwargs_mount) | combine(kwargs_jwt) }}"
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
set_fact:
response: "{{ lookup('vault_test_auth', **kwargs) }}"
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('test-policy' in response.login.auth.policies) | bool == is_default_path
- ('test-policy' not in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when erroneous credentials are used
vars:
kwargs_jwt:
jwt: '{{ jwt_invalid }}'
set_fact:
response: "{{ lookup('vault_test_auth', want_exception=true, **kwargs) }}"
- assert:
fail_msg: "An invalid JWT somehow did not cause a failure."
that:
- response is failed
- response.msg is search('no known key successfully validated the token signature')
@@ -0,0 +1,39 @@
- name: "Test block"
vars:
jwt: '{{ lookup("file", "token.jwt") }}'
jwt_invalid: '{{ lookup("file", "token_invalid.jwt") }}'
is_default_path: "{{ this_path == default_path }}"
module_defaults:
vault_test_auth:
url: '{{ ansible_hashi_vault_url }}'
auth_method: '{{ ansible_hashi_vault_auth_method }}'
role_id: test-role
mount_point: '{{ omit if is_default_path else this_path }}'
jwt: '{{ jwt }}'
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
register: response
vault_test_auth:
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('test-policy' in response.login.auth.policies) | bool == is_default_path
- ('test-policy' not in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when erroneous credentials are used
register: response
vault_test_auth:
jwt: '{{ jwt_invalid }}'
want_exception: true
- assert:
fail_msg: "An invalid JWT somehow did not cause a failure."
that:
- response.inner is failed
- response.msg is search('no known key successfully validated the token signature')
@@ -0,0 +1,56 @@
---
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- name: Persist defaults
set_fact:
'{{ item.key }}': "{{ lookup('vars', item.key) }}"
loop: "{{ lookup('file', role_path ~ '/defaults/main.yml') | from_yaml | dict2items }}"
loop_control:
label: '{{ item.key }}'
- name: Configuration tasks
module_defaults:
vault_ci_enable_auth: '{{ vault_plugins_module_defaults_common }}'
vault_ci_write: '{{ vault_plugins_module_defaults_common }}'
vault_ci_read: '{{ vault_plugins_module_defaults_common }}'
block:
- name: Canary for JWT auth
vault_ci_read:
path: '{{ vault_jwt_canary.path }}'
register: canary
- name: Configure JWT
when: canary.result is none
loop: '{{ auth_paths }}'
include_tasks:
file: jwt_setup.yml
apply:
vars:
default_path: '{{ ansible_hashi_vault_auth_method }}'
this_path: '{{ item }}'
- name: Write Canary
when: canary.result is none
vault_ci_write:
path: '{{ vault_jwt_canary.path }}'
data:
value: '{{ vault_jwt_canary.value }}'
- name: Run JWT tests (controller)
loop: '{{ auth_paths }}'
include_tasks:
file: jwt_test_controller.yml
apply: &test_apply
vars:
default_path: '{{ ansible_hashi_vault_auth_method }}'
this_path: '{{ item }}'
module_defaults:
assert:
quiet: true
- name: Run JWT tests (target)
loop: '{{ auth_paths }}'
include_tasks:
file: jwt_test_target.yml
apply: *test_apply
@@ -0,0 +1,2 @@
vault/auth/ldap
context/target
@@ -0,0 +1,10 @@
---
ansible_hashi_vault_url: '{{ vault_mmock_server_http }}'
ansible_hashi_vault_auth_method: ldap
auth_paths:
- ldap
- ldap-alt
ldap_username: ldapuser
ldap_password: ldappass
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,32 @@
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
kwargs_mount: "{{ {} if is_default_path else {'mount_point': this_path} }}"
kwargs_common:
password: '{{ ldap_password }}'
kwargs: "{{ kwargs_common | combine(kwargs_mount) }}"
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
set_fact:
response: "{{ lookup('vault_test_auth', username=ldap_username, **kwargs) }}"
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('ldap-sample-policy' in response.login.auth.policies) | bool == is_default_path
- ('ldap-sample-policy' not in response.login.auth.policies) | bool != is_default_path
- ('ldap-alt-sample-policy' in response.login.auth.policies) | bool != is_default_path
- ('ldap-alt-sample-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when something goes wrong (simulated)
set_fact:
response: "{{ lookup('vault_test_auth', username='fail-me-username', want_exception=true, **kwargs) }}"
- assert:
fail_msg: "An invalid request somehow did not cause a failure."
that:
- response is failed
- "response.msg is search('ldap operation failed: failed to bind as user')"
@@ -0,0 +1,37 @@
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
module_defaults:
vault_test_auth:
url: '{{ ansible_hashi_vault_url }}'
auth_method: '{{ ansible_hashi_vault_auth_method }}'
mount_point: '{{ omit if is_default_path else this_path }}'
username: '{{ ldap_username }}'
password: '{{ ldap_password }}'
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
register: response
vault_test_auth:
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('ldap-sample-policy' in response.login.auth.policies) | bool == is_default_path
- ('ldap-sample-policy' not in response.login.auth.policies) | bool != is_default_path
- ('ldap-alt-sample-policy' in response.login.auth.policies) | bool != is_default_path
- ('ldap-alt-sample-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when something goes wrong (simulated)
register: response
vault_test_auth:
username: fail-me-username
want_exception: true
- assert:
fail_msg: "An invalid request somehow did not cause a failure."
that:
- response.inner is failed
- "response.msg is search('ldap operation failed: failed to bind as user')"
@@ -0,0 +1,23 @@
---
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- name: Persist defaults
set_fact:
'{{ item.key }}': "{{ lookup('vars', item.key) }}"
loop: "{{ lookup('file', role_path ~ '/defaults/main.yml') | from_yaml | dict2items }}"
loop_control:
label: '{{ item.key }}'
# there's no setup for this auth method because its API is mocked
- name: Run ldap tests
loop: '{{ auth_paths | product(["target", "controller"]) | list }}'
include_tasks:
file: ldap_test_{{ item[1] }}.yml
apply:
vars:
default_path: ldap
this_path: '{{ item[0] }}'
module_defaults:
assert:
quiet: true
@@ -0,0 +1,2 @@
vault/auth/none
context/target
@@ -0,0 +1,3 @@
---
ansible_hashi_vault_url: '{{ vault_test_server_http }}'
ansible_hashi_vault_auth_method: none
@@ -0,0 +1,3 @@
---
dependencies:
- setup_vault_test_plugins
@@ -0,0 +1,19 @@
---
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- name: Persist defaults
set_fact:
'{{ item.key }}': "{{ lookup('vars', item.key) }}"
loop: "{{ lookup('file', role_path ~ '/defaults/main.yml') | from_yaml | dict2items }}"
loop_control:
label: '{{ item.key }}'
# TODO: consider setting up a Vault agent in CI to provide a better test of the none method
- name: "Perform a login with 'none' auth type"
set_fact:
status: "{{ lookup('vault_test_auth') }}"
- name: "Assert no login information is returned"
assert:
that:
- status.login == None
@@ -0,0 +1,3 @@
---
- import_tasks: target.yml
- import_tasks: controller.yml
@@ -0,0 +1,12 @@
---
# TODO: consider setting up a Vault agent in CI to provide a better test of the none method
- name: "Perform a login with 'none' auth type"
register: status
vault_test_auth:
url: '{{ ansible_hashi_vault_url }}'
auth_method: '{{ ansible_hashi_vault_auth_method }}'
- name: "Assert no login information is returned"
assert:
that:
- status.login == None
@@ -0,0 +1,2 @@
vault/auth/token
context/target
@@ -0,0 +1,3 @@
---
ansible_hashi_vault_url: '{{ vault_test_server_http }}'
ansible_hashi_vault_auth_method: token
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,34 @@
---
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- name: Persist defaults
set_fact:
'{{ item.key }}': "{{ lookup('vars', item.key) }}"
loop: "{{ lookup('file', role_path ~ '/defaults/main.yml') | from_yaml | dict2items }}"
loop_control:
label: '{{ item.key }}'
- name: Configuration tasks
module_defaults:
vault_ci_token_create: '{{ vault_plugins_module_defaults_common }}'
block:
- name: 'Create a test non-root token'
vault_ci_token_create:
policies: test-policy
register: user_token_cmd
- name: 'Create a test non-root token with no default policy'
vault_ci_token_create:
policies: test-policy
no_default_policy: true
register: user_token_no_default_policy_cmd
- import_tasks: token_test_target.yml
module_defaults:
assert:
quiet: true
- import_tasks: token_test_controller.yml
module_defaults:
assert:
quiet: true
@@ -0,0 +1,89 @@
- name: Test token with no default policy (missing lookup-self)
vars:
user_token: '{{ user_token_no_default_policy_cmd.result.auth.client_token }}'
secret: "{{ vault_kv2_api_path ~ '/secret1' }}"
expected_secret_value: foo1
# ansible_hashi_vault_auth_method: token
block:
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- set_fact:
ansible_hashi_vault_token: '{{ user_token }}'
- name: Authenticate with a 'no default policy' token (failure expected)
vars:
ansible_hashi_vault_token_validate: true
set_fact:
response: "{{ lookup('vault_test_auth', want_exception=true) }}"
- assert:
that:
- response is failed
- response.msg is search('Invalid Vault Token')
- name: Authenticate with 'no default policy' token - with no validation
set_fact:
response: "{{ lookup('vault_test_auth') }}"
- assert:
that: response.login.auth.client_token == user_token
# if we could lookup-self, we'd be able to inspect the policies on this token,
# but since we can't, let's use the token to retrieve a secret we expect it to have access to.
# TODO: consider that we can use the root token we have access to in CI to lookup this token.
- name: Check that the token is usable
delegate_to: localhost
vault_ci_read:
url: '{{ ansible_hashi_vault_url }}'
token: '{{ response.login.auth.client_token }}'
path: '{{ secret }}'
register: secret_data
- assert:
that: secret_data.result.data.data.value == expected_secret_value
- name: Authenticate with an invalid token - with no validation
set_fact:
response: "{{ lookup('vault_test_auth', token='fake', token_validate=false) }}"
- assert:
that: response.login.auth.client_token == 'fake'
- name: Try to use the invalid token
delegate_to: localhost
vault_ci_read:
url: '{{ ansible_hashi_vault_url }}'
token: '{{ response.login.auth.client_token }}'
path: '{{ secret }}'
register: secret_data
ignore_errors: true
- assert:
that:
- secret_data is failed
- secret_data.msg is search('permission denied')
- name: Normal token tests
vars:
user_token: '{{ user_token_cmd.result.auth.client_token }}'
expected_policy: test-policy
ansible_hashi_vault_token_validate: true
block:
- name: Authenticate with a token (with validation)
set_fact:
response: "{{ lookup('vault_test_auth', token=user_token) }}"
- assert:
that:
- response.login.auth.client_token == user_token
- expected_policy in response.login.data.policies
- expected_policy in response.login.auth.policies
- name: Authenticate with an invalid token (wuth validation)
set_fact:
response: "{{ lookup('vault_test_auth', token='fake', want_exception=true) }}"
- assert:
that:
- response is failed
- response.msg is search('Invalid Vault Token')
@@ -0,0 +1,94 @@
- name: Test token with no default policy (missing lookup-self)
vars:
user_token: '{{ user_token_no_default_policy_cmd.result.auth.client_token }}'
secret: "{{ vault_kv2_api_path ~ '/secret1' }}"
expected_secret_value: foo1
module_defaults:
vault_test_auth:
url: '{{ ansible_hashi_vault_url }}'
token: '{{ user_token }}'
block:
- name: Authenticate with a 'no default policy' token (failure expected)
register: response
vault_test_auth:
token_validate: true
want_exception: true
- assert:
that:
- response.inner is failed
- response.msg is search('Invalid Vault Token')
- name: Authenticate with 'no default policy' token - with no validation
register: response
vault_test_auth:
- assert:
that: response.login.auth.client_token == user_token
# if we could lookup-self, we'd be able to inspect the policies on this token,
# but since we can't, let's use the token to retrieve a secret we expect it to have access to.
# TODO: consider that we can use the root token we have access to in CI to lookup this token.
- name: Check that the token is usable
vault_ci_read:
url: '{{ ansible_hashi_vault_url }}'
token: '{{ response.login.auth.client_token }}'
path: '{{ secret }}'
register: secret_data
- assert:
that: secret_data.result.data.data.value == expected_secret_value
- name: Authenticate with an invalid token - with no validation
register: response
vault_test_auth:
token: fake
token_validate: false
- assert:
that: response.login.auth.client_token == 'fake'
- name: Try to use the invalid token
vault_ci_read:
url: '{{ ansible_hashi_vault_url }}'
token: '{{ response.login.auth.client_token }}'
path: '{{ secret }}'
register: secret_data
ignore_errors: true
- assert:
that:
- secret_data is failed
- secret_data.msg is search('permission denied')
- name: Normal token tests
vars:
user_token: '{{ user_token_cmd.result.auth.client_token }}'
expected_policy: test-policy
module_defaults:
vault_test_auth:
url: '{{ ansible_hashi_vault_url }}'
block:
- name: Authenticate with a token (with validation)
register: response
vault_test_auth:
token: '{{ user_token }}'
token_validate: true
- assert:
that:
- response.login.auth.client_token == user_token
- expected_policy in response.login.data.policies
- expected_policy in response.login.auth.policies
- name: Authenticate with an invalid token (with validation)
register: response
vault_test_auth:
token: fake
token_validate: true
want_exception: true
- assert:
that:
- response.inner is failed
- response.msg is search('Invalid Vault Token')
@@ -0,0 +1,2 @@
vault/auth/userpass
context/target
@@ -0,0 +1,14 @@
---
ansible_hashi_vault_url: '{{ vault_test_server_http }}'
ansible_hashi_vault_auth_method: userpass
auth_paths:
- userpass
- userpass-alt
userpass_username: testuser
userpass_password: testpass
vault_userpass_canary:
path: cubbyhole/configure_userpass
value: complete # value does not matter
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,50 @@
---
# task vars are not templated when used as vars, so we'll need to set_fact this evaluate the template
# see: https://github.com/ansible/ansible/issues/73268
- name: Persist defaults
set_fact:
'{{ item.key }}': "{{ lookup('vars', item.key) }}"
loop: "{{ lookup('file', role_path ~ '/defaults/main.yml') | from_yaml | dict2items }}"
loop_control:
label: '{{ item.key }}'
- name: Configuration tasks
module_defaults:
vault_ci_enable_auth: '{{ vault_plugins_module_defaults_common }}'
vault_ci_policy_put: '{{ vault_plugins_module_defaults_common }}'
vault_ci_write: '{{ vault_plugins_module_defaults_common }}'
vault_ci_read: '{{ vault_plugins_module_defaults_common }}'
block:
- name: Canary for userpass auth
vault_ci_read:
path: '{{ vault_userpass_canary.path }}'
register: canary
- name: Configure userpass
when: canary.result is none
loop: '{{ auth_paths }}'
include_tasks:
file: userpass_setup.yml
apply:
vars:
default_path: '{{ ansible_hashi_vault_auth_method }}'
this_path: '{{ item }}'
- name: Write Canary
when: canary.result is none
vault_ci_write:
path: '{{ vault_userpass_canary.path }}'
data:
value: '{{ vault_userpass_canary.value }}'
- name: Run userpass tests
loop: '{{ auth_paths | product(["target", "controller"]) | list }}'
include_tasks:
file: userpass_test_{{ item[1] }}.yml
apply:
vars:
default_path: '{{ ansible_hashi_vault_auth_method }}'
this_path: '{{ item[0] }}'
module_defaults:
assert:
quiet: true
@@ -0,0 +1,27 @@
- name: "Setup block"
vars:
is_default_path: "{{ this_path == default_path }}"
block:
- name: 'Enable the userpass auth method'
vault_ci_enable_auth:
method_type: userpass
path: '{{ omit if is_default_path else this_path }}'
config:
default_lease_ttl: 60m
- name: 'Create a userpass policy'
vault_ci_policy_put:
name: userpass-policy
policy: |
path "auth/{{ this_path }}/login" {
capabilities = [ "create", "read" ]
}
- name: 'Create a named role'
vault_ci_write:
path: 'auth/{{ this_path }}/users/{{ userpass_username }}'
data:
# in docs, this is token_policies (changed in Vault 1.2)
# use 'policies' to support older versions
policies: "{{ 'test-policy' if is_default_path else 'alt-policy' }},userpass-policy"
password: '{{ userpass_password }}'
@@ -0,0 +1,32 @@
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
kwargs_mount: "{{ {} if is_default_path else {'mount_point': this_path} }}"
kwargs_common:
username: '{{ userpass_username }}'
kwargs: "{{ kwargs_common | combine(kwargs_mount) }}"
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
set_fact:
response: "{{ lookup('vault_test_auth', password=userpass_password, **kwargs) }}"
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('test-policy' in response.login.auth.policies) | bool == is_default_path
- ('test-policy' not in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when erroneous credentials are used
set_fact:
response: "{{ lookup('vault_test_auth', password='fake', want_exception=true, **kwargs) }}"
- assert:
fail_msg: "An invalid password somehow did not cause a failure."
that:
- response is failed
- response.msg is search('invalid username or password')
@@ -0,0 +1,37 @@
- name: "Test block"
vars:
is_default_path: "{{ this_path == default_path }}"
module_defaults:
vault_test_auth:
url: '{{ ansible_hashi_vault_url }}'
auth_method: '{{ ansible_hashi_vault_auth_method }}'
mount_point: '{{ omit if is_default_path else this_path }}'
username: '{{ userpass_username }}'
password: '{{ userpass_password }}'
block:
# the purpose of this test is to catch when the plugin accepts mount_point but does not pass it into hvac
# we set the policy of the default mount to deny access to this secret and so we expect failure when the mount
# is default, and success when the mount is alternate
- name: Check auth mount differing result
register: response
vault_test_auth:
- assert:
fail_msg: "A token from mount path '{{ this_path }}' had the wrong policy: {{ response.login.auth.policies }}"
that:
- ('test-policy' in response.login.auth.policies) | bool == is_default_path
- ('test-policy' not in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' in response.login.auth.policies) | bool != is_default_path
- ('alt-policy' not in response.login.auth.policies) | bool == is_default_path
- name: Failure expected when erroneous credentials are used
register: response
vault_test_auth:
password: fake
want_exception: true
- assert:
fail_msg: "An invalid password somehow did not cause a failure."
that:
- response.inner is failed
- response.msg is search('invalid username or password')
@@ -0,0 +1,3 @@
---
# when False the tests requiring a valid SSL connection to Vault will be skipped
vault_run_https_tests: True
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_cert_content
@@ -0,0 +1,97 @@
---
- name: Connection Tests
module_defaults:
assert:
quiet: true
vars:
# we don't set kwargs: {} here because of https://github.com/ansible/ansible/issues/75286
test_cmd: &test
set_fact:
result: "{{ lookup('vault_test_connection', '', **kwargs) }}"
assert_cmd: &assert
assert:
that: result.status.initialized
block:
- name: HTTP connection
vars:
kwargs: {}
block:
- name: Set the HTTP connection address
set_fact:
ansible_hashi_vault_url: '{{ vault_test_server_http }}'
- name: test HTTP
<<: *test
- <<: *assert
- name: test HTTP with proxy
<<: *test
vars:
kwargs:
url: '{{ vault_proxy_alt_vault_http | default(vault_test_server_http) }}'
proxies: '{{ vault_proxy_server }}'
- <<: *assert
- name: test HTTP with wrong proxy
<<: *test
vars:
vault_test_connection_want_exception: true
ansible_hashi_vault_proxies: http://127.0.0.1:4567
ansible_hashi_vault_retries: 2
- assert:
that:
- result is failed
- result.msg is search('(?:Cannot|Unable to) connect to proxy')
- result.retries == 2
- name: HTTPS connection
when: vault_run_https_tests | bool
vars:
kwargs: &kwargs
ca_cert: '{{ vault_cert_file }}'
block:
- name: Set the HTTPS connection address
set_fact:
ansible_hashi_vault_addr: '{{ vault_test_server_https }}'
- name: test HTTPS with no cert validation
<<: *test
vars:
ansible_hashi_vault_validate_certs: false
- <<: *assert
- name: test HTTPS with cert validation
<<: *test
vars:
vault_test_connection_want_args: true
vault_test_connection_want_exception: true
- <<: *assert
- name: test HTTPS with proxy & cert validation
<<: *test
vars:
kwargs:
<<: *kwargs
url: '{{ vault_proxy_alt_vault_https | default(vault_test_server_http) }}'
proxies: '{{ vault_proxy_server }}'
- <<: *assert
- name: test HTTPS with wrong proxy & cert validation
<<: *test
vars:
vault_test_connection_want_exception: true
ansible_hashi_vault_validate_certs: true
ansible_hashi_vault_proxies: http://127.0.0.1:4567
ansible_hashi_vault_retries: 2
- assert:
that:
- result is failed
- result.msg is search('(?:Cannot|Unable to) connect to proxy')
- result.retries == 2
@@ -0,0 +1,3 @@
---
- include_tasks: controller.yml
- include_tasks: target.yml
@@ -0,0 +1,84 @@
---
- name: Connection Tests
module_defaults:
assert:
quiet: true
vars:
assert_cmd: &assert
assert:
that: result.status.initialized
block:
- name: HTTP connection
module_defaults:
vault_test_connection:
url: '{{ vault_test_server_http }}'
block:
- name: test HTTP
register: result
vault_test_connection:
- <<: *assert
- name: test HTTP with proxy
register: result
vault_test_connection:
url: '{{ vault_proxy_alt_vault_http | default(vault_test_server_http) }}'
proxies: '{{ vault_proxy_server }}'
- <<: *assert
- name: test HTTP with wrong proxy
register: result
vault_test_connection:
want_exception: true
proxies: http://127.0.0.1:4567
retries: 2
- assert:
that:
- result.inner is failed
- result.msg is search('(?:Cannot|Unable to) connect to proxy')
- result.retries == 2
- name: HTTPS connection
when: vault_run_https_tests | bool
module_defaults:
vault_test_connection:
url: '{{ vault_test_server_https }}'
ca_cert: '{{ vault_cert_file }}'
block:
- name: test HTTPS with no cert validation
register: result
vault_test_connection:
validate_certs: false
- <<: *assert
- name: test HTTPS with cert validation
register: result
vault_test_connection:
want_args: true
- <<: *assert
- name: test HTTPS with proxy & cert validation
register: result
vault_test_connection:
url: '{{ vault_proxy_alt_vault_https | default(vault_test_server_http) }}'
proxies: '{{ vault_proxy_server }}'
- <<: *assert
- name: test HTTPS with wrong proxy & cert validation
register: result
vault_test_connection:
want_exception: true
validate_certs: true
proxies: http://127.0.0.1:4567
retries: 2
- assert:
that:
- result.inner is failed
- result.msg is search('(?:Cannot|Unable to) connect to proxy')
- result.retries == 2
@@ -0,0 +1,17 @@
---
- vars:
token: token_value
login_result:
auth:
client_token: '{{ token }}'
module_login_result:
login: '{{ login_result }}'
alternate_field_result:
alt: '{{ login_result }}'
block:
- assert:
that:
- login_result | community.hashi_vault.vault_login_token == token
- login_result | community.hashi_vault.vault_login_token(optional_field='missing') == token
- module_login_result | community.hashi_vault.vault_login_token == token
- alternate_field_result | community.hashi_vault.vault_login_token(optional_field='alt') == token
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,9 @@
---
- name: Configuration tasks
module_defaults:
vault_ci_token_create: '{{ vault_plugins_module_defaults_common }}'
block:
- name: 'Create a test non-root token'
vault_ci_token_create:
policies: test-policy
register: user_token_cmd
@@ -0,0 +1,111 @@
---
- name: Var block
vars:
ansible_hashi_vault_token_validate: true
user_token: '{{ user_token_cmd.result.auth.client_token }}'
kwargs:
url: '{{ vault_test_server_http }}'
auth_method: token
token: '{{ user_token }}'
block:
- name: 'Check kv2 secret raw return value'
vars:
kv2_secret2_as_raw: "{{ lookup('community.hashi_vault.hashi_vault', vault_kv2_api_path ~ '/secret2 ', return_format='raw', **kwargs) }}"
assert:
that:
- "'data' in kv2_secret2_as_raw"
- "'data' in kv2_secret2_as_raw['data']"
- "'metadata' in kv2_secret2_as_raw['data']"
fail_msg: 'Raw return did not contain expected fields.'
- name: "Check multiple secrets as dict (default)"
vars:
kv2_secrets_as_dict: "{{ lookup('community.hashi_vault.hashi_vault', vault_kv2_multi_api_path ~ '/secrets ', **kwargs) }}"
assert:
that:
- kv2_secrets_as_dict | type_debug == 'dict'
- kv2_secrets_as_dict['value' ~ item] == ('foo' ~ item)
fail_msg: 'Return value was not dict or items do not match.'
loop: [1, 2, 3]
- name: "Check multiple secrets as dict (explicit)"
vars:
kv2_secrets_as_dict: "{{ lookup('community.hashi_vault.hashi_vault', vault_kv2_multi_api_path ~ '/secrets ', return_format='dict', **kwargs) }}"
assert:
that:
- kv2_secrets_as_dict | type_debug == 'dict'
- kv2_secrets_as_dict['value' ~ item] == ('foo' ~ item)
fail_msg: 'Return value was not dict or items do not match.'
loop: [1, 2, 3]
- name: "Check multiple secrets as values"
vars:
kv2_secrets_as_values: "{{ query('community.hashi_vault.hashi_vault', vault_kv2_multi_api_path ~ '/secrets ', return_format='values', **kwargs) }}"
assert:
that:
- kv2_secrets_as_values | type_debug == 'list'
- ('foo' ~ item) in kv2_secrets_as_values
fail_msg: 'Return value was not list or items do not match.'
loop: [1, 2, 3]
### failure tests
- name: 'Failure expected when erroneous credentials are used'
vars:
secret_wrong_cred: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=' ~ vault_kv2_api_path ~ '/secret2 token=wrong_token', **kwargs) }}"
debug:
msg: 'Failure is expected ({{ secret_wrong_cred }})'
register: test_wrong_cred
ignore_errors: true
- assert:
that:
- test_wrong_cred is failed
- test_wrong_cred.msg is search('Invalid Vault Token')
fail_msg: "Expected failure but got success or wrong failure message."
- name: 'Failure expected when unauthorized secret is read'
vars:
secret_unauthorized: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=' ~ vault_kv2_api_path ~ '/secret3', **kwargs) }}"
debug:
msg: 'Failure is expected ({{ secret_unauthorized }})'
register: test_unauthorized
ignore_errors: true
- assert:
that:
- test_unauthorized is failed
- test_unauthorized.msg is search('Permission Denied')
fail_msg: "Expected failure but got success or wrong failure message."
- name: 'Failure expected when inexistent secret is read'
vars:
secret_inexistent: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=' ~ vault_kv2_api_path ~ '/non_existent_secret', **kwargs) }}"
debug:
msg: 'Failure is expected ({{ secret_inexistent }})'
register: test_inexistent
ignore_errors: true
- assert:
that:
- test_inexistent is failed
- test_inexistent.msg is search("doesn't seem to exist")
fail_msg: "Expected failure but got success or wrong failure message."
- name: Failure expected when duplicate terms are used in the term string
vars:
duplicate_terms: >-
{{
lookup('community.hashi_vault.hashi_vault',
vault_kv2_api_path ~ '/secrets secret=' ~ vault_kv2_api_path ~ '/secret2',
**kwargs)
}}
ansible.builtin.debug:
msg: 'Failure is expected ({{ duplicate_terms }})'
register: test_duplicate
ignore_errors: true
- assert:
that:
- test_duplicate is failed
- test_duplicate.msg is search("Duplicate key 'secret' in the term string")
@@ -0,0 +1,8 @@
---
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- import_tasks: lookup_setup.yml
- import_tasks: lookup_test.yml
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,9 @@
---
- name: Configuration tasks
module_defaults:
vault_ci_token_create: '{{ vault_plugins_module_defaults_common }}'
block:
- name: Create a test non-root token
vault_ci_token_create:
policies: test-policy
register: user_token_cmd
@@ -0,0 +1,102 @@
---
- name: assert defaults
vars:
settings: null
module_defaults:
assert:
quiet: true
fail_msg: 'settings: {{ settings }}'
block:
- name: Call with no options
vars:
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings') }}"
assert:
that:
- settings | type_debug == 'dict'
- settings | length == 1
- "'timeout' in settings"
- settings.timeout == 5
# ^ needs to match settings in tests/integration/integration.cfg
- name: Call a non-default plugin (fqcn)
vars:
ansible_hashi_vault_engine_mount_point: canary
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', plugin='community.hashi_vault.vault_kv2_get') }}"
assert:
that:
- settings | type_debug == 'dict'
- "'engine_mount_point' in settings"
- settings.engine_mount_point == 'canary'
- name: Call a non-default plugin (short)
vars:
ansible_hashi_vault_engine_mount_point: canary
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', plugin='vault_kv2_get') }}"
assert:
that:
- settings | type_debug == 'dict'
- "'engine_mount_point' in settings"
- settings.engine_mount_point == 'canary'
- name: Include default
vars:
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', include_default=True) }}"
assert:
that:
- settings | type_debug == 'dict'
- "'auth_method' in settings"
- settings.auth_method == 'token'
- name: Include private & none & default
vars:
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', include_default=True, include_private=True, include_none=True) }}"
assert:
that:
- settings | type_debug == 'dict'
- "'_terms' in settings"
- settings._terms == None
- settings | dict2items | selectattr('value', 'none') | list | length > 1
- name: Filters
vars:
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', '*', '!r*', 'retr[yi]*', '!*s', include_default=True, include_none=True) }}"
assert:
that:
- settings | type_debug == 'dict'
- "'retry_action' in settings"
- "'retries' not in settings"
- settings.retry_action == 'warn'
- settings | dict2items | selectattr('key', 'search', '^r.*') | list | length == 1
- settings | length > 1
- name: No such plugin
register: err
set_fact:
settings: "{{ lookup('community.hashi_vault.vault_ansible_settings', plugin='not.real.plugin') }}"
ignore_errors: true
- assert:
that:
- err is failed
- >
"'not.real.plugin' plugin not found" in err.msg
- name: Set templated variables for testing
set_fact:
ansible_hashi_vault_url: '{{ vault_test_server_http }}'
ansible_hashi_vault_token: '{{ user_token_cmd.result.auth.client_token }}'
- name: Perform a login without config (failure expected)
register: err
community.hashi_vault.vault_login:
url: http://nothing
failed_when: err is not failed or 'No Vault Token specified or discovered' not in err.msg
- name: Set defaults
vars:
ansible_hashi_vault_auth_method: token
module_defaults:
community.hashi_vault.vault_login: "{{ lookup('community.hashi_vault.vault_ansible_settings') }}"
block:
- name: Perform a login with defaulted config
community.hashi_vault.vault_login:
@@ -0,0 +1,3 @@
---
- import_tasks: lookup_vault_ansible_settings_configure.yml
- import_tasks: lookup_vault_ansible_settings_test.yml
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,9 @@
---
- name: Configuration tasks
module_defaults:
vault_ci_token_create: '{{ vault_plugins_module_defaults_common }}'
block:
- name: 'Create a test non-root token'
vault_ci_token_create:
policies: [test-policy, invalid-kv2]
register: user_token_cmd
@@ -0,0 +1,151 @@
---
- name: Var block
vars:
ansible_hashi_vault_token_validate: true
user_token: '{{ user_token_cmd.result.auth.client_token }}'
kwargs:
url: '{{ vault_test_server_http }}'
auth_method: token
token: '{{ user_token }}'
engine_mount_point: '{{ vault_kv1_mount_point }}'
block:
- name: Check kv1 secret read
vars:
kv1_secret2: "{{ lookup('community.hashi_vault.vault_kv1_get', vault_kv1_path ~ '/secret2', **kwargs) }}"
assert:
that:
- "'raw' in kv1_secret2"
- "'data' in kv1_secret2"
- "'metadata' in kv1_secret2"
- "'secret' in kv1_secret2"
- "'data' in kv1_secret2['raw']"
- kv1_secret2['data'] == kv1_secret2['raw']['data']
- kv1_secret2['secret'] == kv1_secret2['data']
- kv1_secret2['metadata'] | combine({'data':kv1_secret2['data']}) == kv1_secret2['raw']
fail_msg: 'Return value did not contain expected fields.'
- name: Check multiple path read as array
vars:
paths:
- '{{ vault_kv1_path }}/secret2'
- '{{ vault_kv1_path }}/secret1'
kv1_secrets: "{{ lookup('community.hashi_vault.vault_kv1_get', *paths, **kwargs) }}"
assert:
that:
- kv1_secrets | type_debug == 'list'
- item | type_debug == 'dict'
- "'raw' in item"
- "'data' in item"
- "'metadata' in item"
- "'secret' in item"
- "'data' in item['raw']"
- item['data'] == item['raw']['data']
- item['secret'] == item['data']
- item['metadata'] | combine({'data':item['data']}) == item['raw']
fail_msg: 'Return value was not correct type or items do not match.'
loop: '{{ kv1_secrets }}'
### failure tests
- name: Test defualt path value
vars:
default_path_access: "{{ lookup('community.hashi_vault.vault_kv1_get', vault_kv1_path ~ '/secret2', url=kwargs.url, token=kwargs.token) }}"
debug:
msg: 'Failure is expected ({{ default_path_access }})'
register: default_path
ignore_errors: true
- assert:
that:
- default_path is failed
- default_path.msg is search('Permission Denied to path')
- name: Failure expected when erroneous credentials are used
vars:
secret_wrong_cred: "{{ lookup('community.hashi_vault.vault_kv1_get', vault_kv1_path ~ '/secret2', token='wrong_token', url=kwargs.url) }}"
debug:
msg: 'Failure is expected ({{ secret_wrong_cred }})'
register: test_wrong_cred
ignore_errors: true
- assert:
that:
- test_wrong_cred is failed
- test_wrong_cred.msg is search('Invalid Vault Token')
fail_msg: "Expected failure but got success or wrong failure message."
- name: Failure expected when unauthorized secret is read
vars:
secret_unauthorized: "{{ lookup('community.hashi_vault.vault_kv1_get', vault_kv1_path ~ '/secret3', **kwargs) }}"
debug:
msg: 'Failure is expected ({{ secret_unauthorized }})'
register: test_unauthorized
ignore_errors: true
- assert:
that:
- test_unauthorized is failed
- test_unauthorized.msg is search('Permission Denied')
fail_msg: "Expected failure but got success or wrong failure message."
- name: Failure expected when inexistent secret is read
vars:
secret_inexistent: "{{ lookup('community.hashi_vault.vault_kv1_get', vault_kv1_path ~ '/non_existent_secret', **kwargs) }}"
debug:
msg: 'Failure is expected ({{ secret_inexistent }})'
register: test_inexistent
ignore_errors: true
- assert:
that:
- test_inexistent is failed
- test_inexistent.msg is search("missing path")
fail_msg: "Expected failure but got success or wrong failure message."
- name: Specific failure message expected when trying to read kv2
vars:
kv2_read: >-
{{
lookup(
'community.hashi_vault.vault_kv1_get',
vault_kv2_path ~ '/secret2',
engine_mount_point=vault_kv2_mount_point,
url=kwargs.url, token=kwargs.token
)
}}
debug:
msg: 'Failure is expected ({{ kv2_read }})'
register: test_kv_mismatch
ignore_errors: true
- assert:
that:
- test_kv_mismatch is failed
- test_kv_mismatch.msg is search('If this is a KV version 2 path, use community.hashi_vault.vault_kv2_get')
# do this last so our set_fact doesn't affect any other tests
- name: Set the vars that will configure the lookup settings we can't set via with_
set_fact:
ansible_hashi_vault_url: '{{ kwargs.url }}'
ansible_hashi_vault_token: '{{ kwargs.token }}'
ansible_hashi_vault_auth_method: '{{ kwargs.auth_method }}'
ansible_hashi_vault_engine_mount_point: '{{ kwargs.engine_mount_point }}'
- name: Check multiple path read via with_
assert:
that:
- item | type_debug == 'dict'
- "'raw' in item"
- "'data' in item"
- "'metadata' in item"
- "'secret' in item"
- "'data' in item['raw']"
- item['data'] == item['raw']['data']
- item['secret'] == item['data']
- item['metadata'] | combine({'data':item['data']}) == item['raw']
fail_msg: 'Return value was not correct type or items do not match.'
with_community.hashi_vault.vault_kv1_get:
- '{{ vault_kv1_path }}/secret2'
- '{{ vault_kv1_path }}/secret1'
@@ -0,0 +1,3 @@
---
- import_tasks: lookup_vault_kv1_get_setup.yml
- import_tasks: lookup_vault_kv1_get_test.yml
@@ -0,0 +1,4 @@
---
dependencies:
- setup_vault_test_plugins
- setup_vault_configure
@@ -0,0 +1,9 @@
---
- name: Configuration tasks
module_defaults:
vault_ci_token_create: '{{ vault_plugins_module_defaults_common }}'
block:
- name: 'Create a test non-root token'
vault_ci_token_create:
policies: [test-policy]
register: user_token_cmd
@@ -0,0 +1,177 @@
---
- name: Var block
vars:
ansible_hashi_vault_token_validate: true
user_token: '{{ user_token_cmd.result.auth.client_token }}'
kwargs:
url: '{{ vault_test_server_http }}'
auth_method: token
token: '{{ user_token }}'
engine_mount_point: '{{ vault_kv2_mount_point }}'
block:
- name: Check kv2 secret read
vars:
kv2_result: "{{ lookup('community.hashi_vault.vault_kv2_get', vault_kv2_path ~ '/secret2', **kwargs) }}"
assert:
that: &assert_basics
- "'raw' in kv2_result"
- "'data' in kv2_result"
- "'metadata' in kv2_result"
- "'secret' in kv2_result"
- "'data' in kv2_result['raw']"
- kv2_result['data'] == kv2_result['raw']['data']
- kv2_result['secret'] == kv2_result['data']['data']
- kv2_result['metadata'] == kv2_result['data']['metadata']
fail_msg: 'Return value did not contain expected fields.'
- name: Check kv2 versioned (latest)
set_fact:
kv2_result: "{{ lookup('community.hashi_vault.vault_kv2_get', vault_kv2_versioned_path ~ '/twover', **kwargs) }}"
- assert:
that: *assert_basics
- name: Check version-specific expected values (latest)
vars: &expected_ver2
expected:
version: 2
a: two
v: 2
assert:
that: &assert_expected
- kv2_result.metadata.version == expected.version
- kv2_result.secret.a == expected.a
- kv2_result.secret.v == expected.v
- name: Check kv2 versioned (2)
set_fact:
kv2_result: "{{ lookup('community.hashi_vault.vault_kv2_get', vault_kv2_versioned_path ~ '/twover', version=2, **kwargs) }}"
- assert:
that: *assert_basics
- name: Check version-specific expected values (2)
vars: *expected_ver2
assert:
that: *assert_expected
- name: Check kv2 versioned (1)
set_fact:
kv2_result: "{{ lookup('community.hashi_vault.vault_kv2_get', vault_kv2_versioned_path ~ '/twover', version=1, **kwargs) }}"
- assert:
that: *assert_basics
- name: Check version-specific expected values (1)
vars:
expected:
version: 1
a: one
v: 1
assert:
that: *assert_expected
- name: Check multiple path read as array
vars:
paths:
- '{{ vault_kv2_path }}/secret2'
- '{{ vault_kv2_path }}/secret1'
kv2_secrets: "{{ lookup('community.hashi_vault.vault_kv2_get', *paths, **kwargs) }}"
assert:
that:
- kv2_secrets | type_debug == 'list'
- item | type_debug == 'dict'
- "'raw' in item"
- "'data' in item"
- "'metadata' in item"
- "'secret' in item"
- "'data' in item['raw']"
- item['data'] == item['raw']['data']
- item['secret'] == item['data']['data']
- item['metadata'] == item['data']['metadata']
fail_msg: 'Return value was not correct type or items do not match.'
loop: '{{ kv2_secrets }}'
### failure tests
- name: Test defualt path value
vars:
default_path_access: "{{ lookup('community.hashi_vault.vault_kv2_get', vault_kv2_path ~ '/secret2', url=kwargs.url, token=kwargs.token) }}"
debug:
msg: 'Failure is expected ({{ default_path_access }})'
register: default_path
ignore_errors: true
- assert:
that:
- default_path is failed
- default_path.msg is search('Permission Denied to path')
- name: Failure expected when erroneous credentials are used
vars:
secret_wrong_cred: "{{ lookup('community.hashi_vault.vault_kv2_get', vault_kv2_path ~ '/secret2', token='wrong_token', url=kwargs.url) }}"
debug:
msg: 'Failure is expected ({{ secret_wrong_cred }})'
register: test_wrong_cred
ignore_errors: true
- assert:
that:
- test_wrong_cred is failed
- test_wrong_cred.msg is search('Invalid Vault Token')
fail_msg: "Expected failure but got success or wrong failure message."
- name: Failure expected when unauthorized secret is read
vars:
secret_unauthorized: "{{ lookup('community.hashi_vault.vault_kv2_get', vault_kv2_path ~ '/secret3', **kwargs) }}"
debug:
msg: 'Failure is expected ({{ secret_unauthorized }})'
register: test_unauthorized
ignore_errors: true
- assert:
that:
- test_unauthorized is failed
- test_unauthorized.msg is search('Permission Denied')
fail_msg: "Expected failure but got success or wrong failure message."
- name: Failure expected when inexistent secret is read
vars:
secret_inexistent: "{{ lookup('community.hashi_vault.vault_kv2_get', vault_kv2_path ~ '/non_existent_secret', **kwargs) }}"
debug:
msg: 'Failure is expected ({{ secret_inexistent }})'
register: test_inexistent
ignore_errors: true
- assert:
that:
- test_inexistent is failed
- test_inexistent.msg is search("missing path")
fail_msg: "Expected failure but got success or wrong failure message."
# do this last so our set_fact doesn't affect any other tests
- name: Set the vars that will configure the lookup settings we can't set via with_
set_fact:
ansible_hashi_vault_url: '{{ kwargs.url }}'
ansible_hashi_vault_token: '{{ kwargs.token }}'
ansible_hashi_vault_auth_method: '{{ kwargs.auth_method }}'
ansible_hashi_vault_engine_mount_point: '{{ kwargs.engine_mount_point }}'
- name: Check multiple path read via with_
assert:
that:
- item | type_debug == 'dict'
- "'raw' in item"
- "'data' in item"
- "'metadata' in item"
- "'secret' in item"
- "'data' in item['raw']"
- item['data'] == item['raw']['data']
- item['secret'] == item['data']['data']
- item['metadata'] == item['data']['metadata']
fail_msg: 'Return value was not correct type or items do not match.'
with_community.hashi_vault.vault_kv2_get:
- '{{ vault_kv2_path }}/secret2'
- '{{ vault_kv2_path }}/secret1'
@@ -0,0 +1,3 @@
---
- import_tasks: lookup_vault_kv2_get_setup.yml
- import_tasks: lookup_vault_kv2_get_test.yml

Some files were not shown because too many files have changed in this diff Show More