diff options
3 files changed, 96 insertions, 11 deletions
diff --git a/changelogs/fragments/83716-enable-subkey-fingerprint-validation-in-rpm-key-module.yml b/changelogs/fragments/83716-enable-subkey-fingerprint-validation-in-rpm-key-module.yml new file mode 100644 index 0000000000..70306ff57f --- /dev/null +++ b/changelogs/fragments/83716-enable-subkey-fingerprint-validation-in-rpm-key-module.yml @@ -0,0 +1,4 @@ +--- +minor_changes: + - rpm_key - allow validation of gpg key with a subkey fingerprint + - rpm_key - enable gpg validation that requires presence of multiple fingerprints 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, diff --git a/test/integration/targets/rpm_key/tasks/rpm_key.yaml b/test/integration/targets/rpm_key/tasks/rpm_key.yaml index fb0139b3ae..77cdd586d4 100644 --- a/test/integration/targets/rpm_key/tasks/rpm_key.yaml +++ b/test/integration/targets/rpm_key/tasks/rpm_key.yaml @@ -161,7 +161,7 @@ that: - result is success - result is not changed - - "'does not match the key fingerprint' in result.msg" + - "'does not match any key fingerprints' in result.msg" - name: Issue 20325 - Verify fingerprint of key, valid fingerprint rpm_key: @@ -187,6 +187,67 @@ - result is success - result is not changed +# Reset to test subkey validation +- name: remove all keys from key ring + shell: "rpm -q gpg-pubkey | xargs rpm -e" + +- name: Verify fingerprint of subkey, valid fingerprint + rpm_key: + key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag + fingerprint: 19B7 913E 6284 8E3F 4D78 D6B4 ECD9 1AB2 2EB6 8D86 + register: result + +- name: Assert Verify fingerprint of key, valid fingerprint + assert: + that: + - result is success + - result is changed + +- name: Verify fingerprint of subkey, valid fingerprint - Idempotent check + rpm_key: + key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag + fingerprint: 19B7 913E 6284 8E3F 4D78 D6B4 ECD9 1AB2 2EB6 8D86 + register: result + +- name: Assert Verify fingerprint of subkey, valid fingerprint - Idempotent check + assert: + that: + - result is success + - result is not changed + +# Reset to test multi-key validation +- name: remove all keys from key ring + shell: "rpm -q gpg-pubkey | xargs rpm -e" + +- name: Verify fingerprint of primary and subkey, valid fingerprint + rpm_key: + key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag + fingerprint: + - 19B7 913E 6284 8E3F 4D78 D6B4 ECD9 1AB2 2EB6 8D86 + - EBC6 E12C 62B1 C734 026B 2122 A20E 5214 6B8D 79E6 + register: result + +- name: Assert Verify fingerprint of primary and subkey, valid fingerprint + assert: + that: + - result is success + - result is changed + +- name: Verify fingerprint of primary and subkey, valid fingerprint - Idempotent check + rpm_key: + key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag + fingerprint: + - 19B7 913E 6284 8E3F 4D78 D6B4 ECD9 1AB2 2EB6 8D86 + - EBC6 E12C 62B1 C734 026B 2122 A20E 5214 6B8D 79E6 + register: result + +- name: Assert Verify fingerprint of primary and subkey, valid fingerprint - Idempotent check + assert: + that: + - result is success + - result is not changed + + # # Cleanup # |