Add gpg_fingerprint lookup and filter (#639)
* Add gpg_fingerprint lookup. * Work around problems on some CI targets. * Use get_bin_path to find the gpg executable. Document that we need it. * Improve and test error handling. * Refactor (potentially) common code to module_utils and plugin_utils. This will be useful to create a filter version of this, and further lookups, filters, and modules. * Do not create a keyring when there isn't one. * Fixups. * Fix description. * More fixes for lookup. * Also add a gpg_fingerprint filter. * Improve formulation. Co-authored-by: Sandra McCann <samccann@redhat.com> --------- Co-authored-by: Sandra McCann <samccann@redhat.com>pull/643/head
parent
5e630ffe78
commit
ba456c5eaf
|
@ -0,0 +1,68 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2023, Felix Fontein <felix@fontein.de>
|
||||||
|
# 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: gpg_fingerprint
|
||||||
|
short_description: Retrieve a GPG fingerprint from a GPG public or private key
|
||||||
|
author: Felix Fontein (@felixfontein)
|
||||||
|
version_added: 2.15.0
|
||||||
|
description:
|
||||||
|
- "Takes the content of a private or public GPG key as input and returns its fingerprint."
|
||||||
|
options:
|
||||||
|
_input:
|
||||||
|
description:
|
||||||
|
- The content of a GPG public or private key.
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
requirements:
|
||||||
|
- GnuPG (C(gpg) executable)
|
||||||
|
seealso:
|
||||||
|
- plugin: community.crypto.gpg_fingerprint
|
||||||
|
plugin_type: lookup
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXAMPLES = """
|
||||||
|
- name: Show fingerprint of GPG public key
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ lookup('file', '/path/to/public_key.gpg') | community.crypto.gpg_fingerprint }}"
|
||||||
|
"""
|
||||||
|
|
||||||
|
RETURN = """
|
||||||
|
_value:
|
||||||
|
description:
|
||||||
|
- The fingerprint of the provided public or private GPG key.
|
||||||
|
type: string
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||||
|
from ansible.module_utils.six import string_types
|
||||||
|
|
||||||
|
from ansible_collections.community.crypto.plugins.module_utils.gnupg.cli import GPGError, get_fingerprint_from_bytes
|
||||||
|
from ansible_collections.community.crypto.plugins.plugin_utils.gnupg import PluginGPGRunner
|
||||||
|
|
||||||
|
|
||||||
|
def gpg_fingerprint(input):
|
||||||
|
if not isinstance(input, string_types):
|
||||||
|
raise AnsibleFilterError(
|
||||||
|
'The input for the community.crypto.gpg_fingerprint filter must be a string; got {type} instead'.format(type=type(input))
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
gpg = PluginGPGRunner()
|
||||||
|
return get_fingerprint_from_bytes(gpg, to_bytes(input))
|
||||||
|
except GPGError as exc:
|
||||||
|
raise AnsibleFilterError(to_native(exc))
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModule(object):
|
||||||
|
'''Ansible jinja2 filters'''
|
||||||
|
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
'gpg_fingerprint': gpg_fingerprint,
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2023, Felix Fontein <felix@fontein.de>
|
||||||
|
# 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: gpg_fingerprint
|
||||||
|
short_description: Retrieve a GPG fingerprint from a GPG public or private key file
|
||||||
|
author: Felix Fontein (@felixfontein)
|
||||||
|
version_added: 2.15.0
|
||||||
|
description:
|
||||||
|
- "Takes a list of filenames pointing to GPG public or private key files. Returns the fingerprints for each of these keys."
|
||||||
|
options:
|
||||||
|
_terms:
|
||||||
|
description:
|
||||||
|
- A path to a GPG public or private key.
|
||||||
|
type: list
|
||||||
|
elements: path
|
||||||
|
required: true
|
||||||
|
requirements:
|
||||||
|
- GnuPG (C(gpg) executable)
|
||||||
|
seealso:
|
||||||
|
- plugin: community.crypto.gpg_fingerprint
|
||||||
|
plugin_type: filter
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXAMPLES = """
|
||||||
|
- name: Show fingerprint of GPG public key
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ lookup('community.crypto.gpg_fingerprint', '/path/to/public_key.gpg') }}"
|
||||||
|
"""
|
||||||
|
|
||||||
|
RETURN = """
|
||||||
|
_value:
|
||||||
|
description:
|
||||||
|
- The fingerprints of the provided public or private GPG keys.
|
||||||
|
- The list has one entry for every path provided.
|
||||||
|
type: list
|
||||||
|
elements: string
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ansible.plugins.lookup import LookupBase
|
||||||
|
from ansible.errors import AnsibleLookupError
|
||||||
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
||||||
|
from ansible_collections.community.crypto.plugins.module_utils.gnupg.cli import GPGError, get_fingerprint_from_file
|
||||||
|
from ansible_collections.community.crypto.plugins.plugin_utils.gnupg import PluginGPGRunner
|
||||||
|
|
||||||
|
|
||||||
|
class LookupModule(LookupBase):
|
||||||
|
def run(self, terms, variables=None, **kwargs):
|
||||||
|
self.set_options(direct=kwargs)
|
||||||
|
|
||||||
|
try:
|
||||||
|
gpg = PluginGPGRunner(cwd=self._loader.get_basedir())
|
||||||
|
result = []
|
||||||
|
for path in terms:
|
||||||
|
result.append(get_fingerprint_from_file(gpg, path))
|
||||||
|
return result
|
||||||
|
except GPGError as exc:
|
||||||
|
raise AnsibleLookupError(to_native(exc))
|
|
@ -0,0 +1,64 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2023, Felix Fontein <felix@fontein.de>
|
||||||
|
# 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
|
||||||
|
|
||||||
|
import abc
|
||||||
|
import os
|
||||||
|
|
||||||
|
from ansible.module_utils import six
|
||||||
|
|
||||||
|
|
||||||
|
class GPGError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class GPGRunner(object):
|
||||||
|
@abc.abstractmethod
|
||||||
|
def run_command(self, command, check_rc=True, data=None):
|
||||||
|
"""
|
||||||
|
Run ``[gpg] + command`` and return ``(rc, stdout, stderr)``.
|
||||||
|
|
||||||
|
If ``data`` is not ``None``, it will be provided as stdin.
|
||||||
|
The code assumes it is a bytes string.
|
||||||
|
|
||||||
|
Returned stdout and stderr are native Python strings.
|
||||||
|
Pass ``check_rc=False`` to allow return codes != 0.
|
||||||
|
|
||||||
|
Raises a ``GPGError`` in case of errors.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_fingerprint_from_stdout(stdout):
|
||||||
|
lines = stdout.splitlines(False)
|
||||||
|
for line in lines:
|
||||||
|
if line.startswith('fpr:'):
|
||||||
|
parts = line.split(':')
|
||||||
|
if len(parts) <= 9 or not parts[9]:
|
||||||
|
raise GPGError('Result line "{line}" does not have fingerprint as 10th component'.format(line=line))
|
||||||
|
return parts[9]
|
||||||
|
raise GPGError('Cannot extract fingerprint from stdout "{stdout}"'.format(stdout=stdout))
|
||||||
|
|
||||||
|
|
||||||
|
def get_fingerprint_from_file(gpg_runner, path):
|
||||||
|
if not os.path.exists(path):
|
||||||
|
raise GPGError('{path} does not exist'.format(path=path))
|
||||||
|
stdout = gpg_runner.run_command(
|
||||||
|
['--no-keyring', '--with-colons', '--import-options', 'show-only', '--import', path],
|
||||||
|
check_rc=True,
|
||||||
|
)[1]
|
||||||
|
return get_fingerprint_from_stdout(stdout)
|
||||||
|
|
||||||
|
|
||||||
|
def get_fingerprint_from_bytes(gpg_runner, content):
|
||||||
|
stdout = gpg_runner.run_command(
|
||||||
|
['--no-keyring', '--with-colons', '--import-options', 'show-only', '--import', '/dev/stdin'],
|
||||||
|
data=content,
|
||||||
|
check_rc=True,
|
||||||
|
)[1]
|
||||||
|
return get_fingerprint_from_stdout(stdout)
|
|
@ -0,0 +1,51 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2023, Felix Fontein <felix@fontein.de>
|
||||||
|
# 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 subprocess import Popen, PIPE
|
||||||
|
|
||||||
|
from ansible.module_utils.common.process import get_bin_path
|
||||||
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
||||||
|
from ansible_collections.community.crypto.plugins.module_utils.gnupg.cli import GPGError, GPGRunner
|
||||||
|
|
||||||
|
|
||||||
|
class PluginGPGRunner(GPGRunner):
|
||||||
|
def __init__(self, executable=None, cwd=None):
|
||||||
|
if executable is None:
|
||||||
|
try:
|
||||||
|
executable = get_bin_path('gpg')
|
||||||
|
except ValueError as e:
|
||||||
|
raise GPGError('Cannot find the `gpg` executable on the controller')
|
||||||
|
self.executable = executable
|
||||||
|
self.cwd = cwd
|
||||||
|
|
||||||
|
def run_command(self, command, check_rc=True, data=None):
|
||||||
|
"""
|
||||||
|
Run ``[gpg] + command`` and return ``(rc, stdout, stderr)``.
|
||||||
|
|
||||||
|
If ``data`` is not ``None``, it will be provided as stdin.
|
||||||
|
The code assumes it is a bytes string.
|
||||||
|
|
||||||
|
Returned stdout and stderr are native Python strings.
|
||||||
|
Pass ``check_rc=False`` to allow return codes != 0.
|
||||||
|
|
||||||
|
Raises a ``GPGError`` in case of errors.
|
||||||
|
"""
|
||||||
|
command = [self.executable] + command
|
||||||
|
p = Popen(command, shell=False, cwd=self.cwd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
||||||
|
stdout, stderr = p.communicate(input=data)
|
||||||
|
stdout = to_native(stdout, errors='surrogate_or_replace')
|
||||||
|
stderr = to_native(stderr, errors='surrogate_or_replace')
|
||||||
|
if check_rc and p.returncode != 0:
|
||||||
|
raise GPGError('Running {cmd} yielded return code {rc} with stdout: "{stdout}" and stderr: "{stderr}")'.format(
|
||||||
|
cmd=' '.join(command),
|
||||||
|
rc=p.returncode,
|
||||||
|
stdout=to_native(stdout, errors='surrogate_or_replace'),
|
||||||
|
stderr=to_native(stderr, errors='surrogate_or_replace'),
|
||||||
|
))
|
||||||
|
return p.returncode, stdout, stderr
|
|
@ -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/posix/2
|
||||||
|
destructive
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- prepare_jinja2_compat
|
||||||
|
- setup_remote_tmp_dir
|
||||||
|
- setup_gnupg
|
|
@ -0,0 +1,80 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
- name: Run tests if GPG is available
|
||||||
|
when: has_gnupg
|
||||||
|
block:
|
||||||
|
- name: Create GPG key
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: gpg --homedir "{{ remote_tmp_dir }}" --batch --generate-key
|
||||||
|
stdin: |
|
||||||
|
%echo Generating a basic OpenPGP key
|
||||||
|
%no-ask-passphrase
|
||||||
|
%no-protection
|
||||||
|
Key-Type: RSA
|
||||||
|
Key-Length: 4096
|
||||||
|
Name-Real: Foo Bar
|
||||||
|
Name-Email: foo@bar.com
|
||||||
|
Expire-Date: 0
|
||||||
|
%commit
|
||||||
|
%echo done
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Extract fingerprint
|
||||||
|
ansible.builtin.shell: gpg --homedir "{{ remote_tmp_dir }}" --with-colons --fingerprint foo@bar.com | grep '^fpr:'
|
||||||
|
register: fingerprints
|
||||||
|
|
||||||
|
- name: Show fingerprints
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ fingerprints.stdout_lines | map('split', ':') | list }}"
|
||||||
|
|
||||||
|
- name: Export public key
|
||||||
|
ansible.builtin.command: gpg --homedir "{{ remote_tmp_dir }}" --export --armor foo@bar.com
|
||||||
|
register: public_key
|
||||||
|
|
||||||
|
- name: Export private key
|
||||||
|
ansible.builtin.command: gpg --homedir "{{ remote_tmp_dir }}" --export-secret-key --armor foo@bar.com
|
||||||
|
register: private_key
|
||||||
|
|
||||||
|
- name: Gather fingerprints
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
public_key_fingerprint: "{{ public_key.stdout | community.crypto.gpg_fingerprint }}"
|
||||||
|
private_key_fingerprint: "{{ private_key.stdout | community.crypto.gpg_fingerprint }}"
|
||||||
|
|
||||||
|
- name: Check whether fingerprints match
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- public_key_fingerprint == (fingerprints.stdout_lines[0] | split(':'))[9]
|
||||||
|
- private_key_fingerprint == (fingerprints.stdout_lines[0] | split(':'))[9]
|
||||||
|
|
||||||
|
- name: Error scenario - wrong input type
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
failing_result: "{{ 42 | community.crypto.gpg_fingerprint }}"
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Check result
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
- >-
|
||||||
|
'The input for the community.crypto.gpg_fingerprint filter must be a string; got ' in result.msg
|
||||||
|
- >-
|
||||||
|
'int' in result.msg
|
||||||
|
|
||||||
|
- name: Error scenario - garbage input
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
failing_result: "{{ 'garbage' | community.crypto.gpg_fingerprint }}"
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Check result
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
- >-
|
||||||
|
'Running ' in result.msg
|
||||||
|
- >-
|
||||||
|
('/gpg --no-keyring --with-colons --import-options show-only --import /dev/stdin yielded return code ') in result.msg
|
|
@ -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/posix/2
|
||||||
|
destructive
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- prepare_jinja2_compat
|
||||||
|
- setup_remote_tmp_dir
|
||||||
|
- setup_gnupg
|
|
@ -0,0 +1,93 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
- name: Run tests if GPG is available
|
||||||
|
when: has_gnupg
|
||||||
|
block:
|
||||||
|
- name: Create GPG key
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: gpg --homedir "{{ remote_tmp_dir }}" --batch --generate-key
|
||||||
|
stdin: |
|
||||||
|
%echo Generating a basic OpenPGP key
|
||||||
|
%no-ask-passphrase
|
||||||
|
%no-protection
|
||||||
|
Key-Type: RSA
|
||||||
|
Key-Length: 4096
|
||||||
|
Name-Real: Foo Bar
|
||||||
|
Name-Email: foo@bar.com
|
||||||
|
Expire-Date: 0
|
||||||
|
%commit
|
||||||
|
%echo done
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Extract fingerprint
|
||||||
|
ansible.builtin.shell: gpg --homedir "{{ remote_tmp_dir }}" --with-colons --fingerprint foo@bar.com | grep '^fpr:'
|
||||||
|
register: fingerprints
|
||||||
|
|
||||||
|
- name: Show fingerprints
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ fingerprints.stdout_lines | map('split', ':') | list }}"
|
||||||
|
|
||||||
|
- name: Export public key
|
||||||
|
ansible.builtin.command: gpg --homedir "{{ remote_tmp_dir }}" --export --armor foo@bar.com
|
||||||
|
register: public_key
|
||||||
|
|
||||||
|
- name: Export private key
|
||||||
|
ansible.builtin.command: gpg --homedir "{{ remote_tmp_dir }}" --export-secret-key --armor foo@bar.com
|
||||||
|
register: private_key
|
||||||
|
|
||||||
|
- name: Write public key to disk
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "{{ remote_tmp_dir }}/public-key"
|
||||||
|
content: "{{ public_key.stdout }}"
|
||||||
|
|
||||||
|
- name: Write private key to disk
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "{{ remote_tmp_dir }}/private-key"
|
||||||
|
content: "{{ private_key.stdout }}"
|
||||||
|
|
||||||
|
- name: Gather fingerprints
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
public_key_fingerprint: "{{ lookup('community.crypto.gpg_fingerprint', remote_tmp_dir ~ '/public-key') }}"
|
||||||
|
private_key_fingerprint: "{{ lookup('community.crypto.gpg_fingerprint', remote_tmp_dir ~ '/private-key') }}"
|
||||||
|
|
||||||
|
- name: Check whether fingerprints match
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- public_key_fingerprint == (fingerprints.stdout_lines[0] | split(':'))[9]
|
||||||
|
- private_key_fingerprint == (fingerprints.stdout_lines[0] | split(':'))[9]
|
||||||
|
|
||||||
|
- name: Error scenario - file does not exist
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
failing_result: "{{ lookup('community.crypto.gpg_fingerprint', remote_tmp_dir ~ '/does-not-exist') }}"
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Check result
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
- >-
|
||||||
|
(remote_tmp_dir ~ '/does-not-exist does not exist') in result.msg
|
||||||
|
|
||||||
|
- name: Write garbage to disk
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "{{ remote_tmp_dir }}/garbage"
|
||||||
|
content: gargabe
|
||||||
|
|
||||||
|
- name: Error scenario - file contains garbage
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
failing_result: "{{ lookup('community.crypto.gpg_fingerprint', remote_tmp_dir ~ '/garbage') }}"
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Check result
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
- >-
|
||||||
|
'Running ' in result.msg
|
||||||
|
- >-
|
||||||
|
('/gpg --no-keyring --with-colons --import-options show-only --import ' ~ remote_tmp_dir ~ '/garbage yielded return code ') in result.msg
|
|
@ -0,0 +1,20 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
|
# Added in ansible-core 2.11
|
||||||
|
def compatibility_split_filter(text, by_what):
|
||||||
|
return text.split(by_what)
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModule:
|
||||||
|
''' Jinja2 compat filters '''
|
||||||
|
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
'split': compatibility_split_filter,
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- setup_pkg_mgr
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
- name: Print distribution specific data
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: |
|
||||||
|
Distribution: {{ ansible_facts.distribution }}
|
||||||
|
Distribution version: {{ ansible_facts.distribution_version }}
|
||||||
|
Distribution major version: {{ ansible_facts.distribution_major_version }}
|
||||||
|
OS family: {{ ansible_facts.os_family }}
|
||||||
|
|
||||||
|
- name: Include distribution specific variables
|
||||||
|
ansible.builtin.include_vars: '{{ lookup("ansible.builtin.first_found", params) }}'
|
||||||
|
vars:
|
||||||
|
params:
|
||||||
|
files:
|
||||||
|
- '{{ ansible_facts.distribution }}-{{ ansible_facts.distribution_version }}.yml'
|
||||||
|
- '{{ ansible_facts.distribution }}-{{ ansible_facts.distribution_major_version }}.yml'
|
||||||
|
- '{{ ansible_facts.distribution }}.yml'
|
||||||
|
- '{{ ansible_facts.os_family }}.yml'
|
||||||
|
- default.yml
|
||||||
|
paths:
|
||||||
|
- '{{ role_path }}/vars'
|
||||||
|
|
||||||
|
- name: Install GnuPG
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: '{{ gnupg_package_name }}'
|
||||||
|
when: has_gnupg
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Alpine 3.12 should have GnuPG, but for some reason installing it fails...
|
||||||
|
has_gnupg: "{{ ansible_facts.distribution_version is version('3.13', '>=') }}"
|
||||||
|
gnupg_package_name: gpg
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
has_gnupg: false
|
||||||
|
# The GnuPG version included with CentOS 6 is too old, it doesn't understand --generate-key
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# TODO Homebrew currently isn't happy when running as root, so assume we don't have GnuPG
|
||||||
|
has_gnupg: false
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
has_gnupg: true
|
||||||
|
gnupg_package_name: gnupg2
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
has_gnupg: true
|
||||||
|
gnupg_package_name: gnupg
|
|
@ -1,4 +1,5 @@
|
||||||
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
|
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
|
||||||
|
plugins/lookup/gpg_fingerprint.py validate-modules:invalid-documentation
|
||||||
plugins/modules/openssl_csr_info.py validate-modules:invalid-documentation
|
plugins/modules/openssl_csr_info.py validate-modules:invalid-documentation
|
||||||
plugins/modules/openssl_privatekey_info.py validate-modules:invalid-documentation
|
plugins/modules/openssl_privatekey_info.py validate-modules:invalid-documentation
|
||||||
plugins/modules/openssl_publickey_info.py validate-modules:invalid-documentation
|
plugins/modules/openssl_publickey_info.py validate-modules:invalid-documentation
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
|
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
|
||||||
|
plugins/lookup/gpg_fingerprint.py validate-modules:invalid-documentation
|
||||||
plugins/modules/openssl_csr_info.py validate-modules:invalid-documentation
|
plugins/modules/openssl_csr_info.py validate-modules:invalid-documentation
|
||||||
plugins/modules/openssl_privatekey_info.py validate-modules:invalid-documentation
|
plugins/modules/openssl_privatekey_info.py validate-modules:invalid-documentation
|
||||||
plugins/modules/openssl_publickey_info.py validate-modules:invalid-documentation
|
plugins/modules/openssl_publickey_info.py validate-modules:invalid-documentation
|
||||||
|
|
Loading…
Reference in New Issue