summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKellin <kellin@retromud.org>2024-08-12 16:13:39 +0200
committerGitHub <noreply@github.com>2024-08-12 16:13:39 +0200
commit0d6b0341030f33c3003103a9547f16aa0fe28524 (patch)
treed50a11106196c77ec0e30c9d3dba3781259da4bd /lib
parentfix: `COLOR_INCLUDED` to colorize `included` output (#83711) (diff)
downloadansible-0d6b0341030f33c3003103a9547f16aa0fe28524.tar.xz
ansible-0d6b0341030f33c3003103a9547f16aa0fe28524.zip
Enable validation of subkeys in rpm key module (#83716)
* Enable validation of subkeys in rpm key module A gpg subkey may change while the primary key remains the same. Due to this behavior, there are situations where validation of the primary gpg key fingerprint is not sufficient because the desired target is actually the gpg subkey. This change allows the user to validate against either the fingerprint of the primary gpg key or its subkey. Signed-off-by: Kellin <kellin@retromud.org> * Improve tests, add multi-fingerprint - Improve tests to cover all cases - add multi fingerprint validation Signed-off-by: Kellin <kellin@retromud.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/ansible/modules/rpm_key.py40
1 files changed, 30 insertions, 10 deletions
diff --git a/lib/ansible/modules/rpm_key.py b/lib/ansible/modules/rpm_key.py
index d8f7f7e03b..3c7904df88 100644
--- a/lib/ansible/modules/rpm_key.py
+++ b/lib/ansible/modules/rpm_key.py
@@ -40,7 +40,8 @@ options:
description:
- The long-form fingerprint of the key being imported.
- This will be used to verify the specified key.
- type: str
+ type: list
+ elements: str
version_added: 2.9
extends_documentation_fragment:
- action_common_attributes
@@ -73,6 +74,13 @@ EXAMPLES = '''
ansible.builtin.rpm_key:
key: /path/to/RPM-GPG-KEY.dag.txt
fingerprint: EBC6 E12C 62B1 C734 026B 2122 A20E 5214 6B8D 79E6
+
+- name: Verify the key, using multiple fingerprints, before import
+ ansible.builtin.rpm_key:
+ key: /path/to/RPM-GPG-KEY.dag.txt
+ fingerprint:
+ - EBC6 E12C 62B1 C734 026B 2122 A20E 5214 6B8D 79E6
+ - 19B7 913E 6284 8E3F 4D78 D6B4 ECD9 1AB2 2EB6 8D86
'''
RETURN = r'''#'''
@@ -105,8 +113,12 @@ class RpmKey(object):
state = module.params['state']
key = module.params['key']
fingerprint = module.params['fingerprint']
+ fingerprints = set()
+
if fingerprint:
- fingerprint = fingerprint.replace(' ', '').upper()
+ if not isinstance(fingerprint, list):
+ fingerprint = [fingerprint]
+ fingerprints = set(f.replace(' ', '').upper() for f in fingerprint)
self.gpg = self.module.get_bin_path('gpg')
if not self.gpg:
@@ -131,11 +143,12 @@ class RpmKey(object):
else:
if not keyfile:
self.module.fail_json(msg="When importing a key, a valid file must be given")
- if fingerprint:
- has_fingerprint = self.getfingerprint(keyfile)
- if fingerprint != has_fingerprint:
+ if fingerprints:
+ keyfile_fingerprints = self.getfingerprints(keyfile)
+ if not fingerprints.issubset(keyfile_fingerprints):
self.module.fail_json(
- msg="The specified fingerprint, '%s', does not match the key fingerprint '%s'" % (fingerprint, has_fingerprint)
+ msg=("The specified fingerprint, '%s', "
+ "does not match any key fingerprints in '%s'") % (fingerprints, keyfile_fingerprints)
)
self.import_key(keyfile)
if should_cleanup_keyfile:
@@ -183,11 +196,15 @@ class RpmKey(object):
self.module.fail_json(msg="Unexpected gpg output")
- def getfingerprint(self, keyfile):
+ def getfingerprints(self, keyfile):
stdout, stderr = self.execute_command([
self.gpg, '--no-tty', '--batch', '--with-colons',
- '--fixed-list-mode', '--with-fingerprint', keyfile
+ '--fixed-list-mode', '--import', '--import-options', 'show-only',
+ '--dry-run', keyfile
])
+
+ fingerprints = set()
+
for line in stdout.splitlines():
line = line.strip()
if line.startswith('fpr:'):
@@ -199,7 +216,10 @@ class RpmKey(object):
#
# "fpr :: Fingerprint (fingerprint is in field 10)"
#
- return line.split(':')[9]
+ fingerprints.add(line.split(':')[9])
+
+ if fingerprints:
+ return fingerprints
self.module.fail_json(msg="Unexpected gpg output")
@@ -239,7 +259,7 @@ def main():
argument_spec=dict(
state=dict(type='str', default='present', choices=['absent', 'present']),
key=dict(type='str', required=True, no_log=False),
- fingerprint=dict(type='str'),
+ fingerprint=dict(type='list', elements='str'),
validate_certs=dict(type='bool', default=True),
),
supports_check_mode=True,