diff options
author | Kellin <kellin@retromud.org> | 2024-08-12 16:13:39 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-12 16:13:39 +0200 |
commit | 0d6b0341030f33c3003103a9547f16aa0fe28524 (patch) | |
tree | d50a11106196c77ec0e30c9d3dba3781259da4bd /lib | |
parent | fix: `COLOR_INCLUDED` to colorize `included` output (#83711) (diff) | |
download | ansible-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.py | 40 |
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, |