diff --git a/plugins/filter/split_pem.py b/plugins/filter/split_pem.py new file mode 100644 index 00000000..a58ce506 --- /dev/null +++ b/plugins/filter/split_pem.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2022, Felix Fontein +# 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: split_pem +short_description: Split PEM file contents into multiple objects +version_added: 2.10.0 +author: + - Felix Fontein (@felixfontein) +description: + - Split PEM file contents into multiple PEM objects. Comments or invalid parts are ignored. +options: + _input: + description: + - The PEM contents to split. + type: string + required: true +''' + +EXAMPLES = ''' +- name: Print all CA certificates + ansible.builtin.debug: + msg: '{{ item }}' + loop: >- + {{ lookup('ansible.builtin.file', '/path/to/ca-bundle.pem') | community.crypto.split_pem }} +''' + +RETURN = ''' +_value: + description: + - A list of PEM file contents. + type: list + elements: string +''' + +from ansible.errors import AnsibleFilterError +from ansible.module_utils.six import string_types +from ansible.module_utils.common.text.converters import to_text + +from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import split_pem_list + + +def split_pem_filter(data): + '''Split PEM file.''' + if not isinstance(data, string_types): + raise AnsibleFilterError('The community.crypto.split_pem input must be a text type, not %s' % type(data)) + + data = to_text(data) + return split_pem_list(data) + + +class FilterModule(object): + '''Ansible jinja2 filters''' + + def filters(self): + return { + 'split_pem': split_pem_filter, + } diff --git a/tests/integration/targets/filter_split_pem/aliases b/tests/integration/targets/filter_split_pem/aliases new file mode 100644 index 00000000..85778914 --- /dev/null +++ b/tests/integration/targets/filter_split_pem/aliases @@ -0,0 +1,6 @@ +# Copyright (c) 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 + +azp/generic/2 +azp/posix/2 diff --git a/tests/integration/targets/filter_split_pem/tasks/main.yml b/tests/integration/targets/filter_split_pem/tasks/main.yml new file mode 100644 index 00000000..0b1dfdf1 --- /dev/null +++ b/tests/integration/targets/filter_split_pem/tasks/main.yml @@ -0,0 +1,64 @@ +--- +# Copyright (c) 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 + +#################################################################### +# WARNING: These are designed specifically for Ansible tests # +# and should not be used as examples of how to write Ansible roles # +#################################################################### + +- name: Run tests that raise no errors + assert: + that: + - >- + '' | community.crypto.split_pem == [] + - >- + (pem_1 + pem_2 + pem_3) | community.crypto.split_pem == [pem_1, pem_2, pem_3] + - >- + (pem_3 + pem_2 + pem_1) | community.crypto.split_pem == [pem_3, pem_2, pem_1] + - >- + (crap_1 + pem_3 + crap_2 + pem_2 + crap_3 + pem_1 + crap_2) | community.crypto.split_pem == [pem_3, pem_2, pem_1] + - >- + (crap_1 + pem_1 + crap_2 + pem_1 + crap_3 + crap_4 + crap_4) | community.crypto.split_pem == [pem_1, pem_1] + vars: + pem_1: | + -----BEGIN CERTIFICATE----- + AAb= + -----END CERTIFICATE----- + pem_2: | + -----BEGIN PRIVATE KEY----- + Foo + Bar + Baz + Bam + -----END PRIVATE KEY----- + pem_3: | + -----BEGIN + foo + -----END + crap_1: | + # Comment + crap_2: | + Random text + In multiple + Lines + crap_3: | + ----BEGIN CERTIFICATE---- + Certificate with too few dashes + ----END CERTIFICATE---- + crap_4: | + -----BEGIN CERTIFICATE----- + AAb= + +- name: Invalid input + debug: + msg: "{{ [] | community.crypto.split_pem }}" + ignore_errors: true + register: output + +- name: Validate error + assert: + that: + - output is failed + - output.msg is search("^The community.crypto.split_pem input must be a text type, not <(?:class|type) 'list'>$")