Skip to content

Conversation

@t-kranz
Copy link

@t-kranz t-kranz commented Jun 26, 2024

SUMMARY

Fixes # #83394

Took the changes from #75251 (for #50615) - which implement checking for multiple key ids when importing keys with the rpm_key module (see #75251 (comment)):

Make rpm_key module use lists for key ids since a single key file can contain multiple keys.

I also made the fingerprint option accept lists of fingerprints since they correspond with key ids. All fingerprints in a keyfile should be present when the fingerprints option is set for task success.

ISSUE TYPE
  • Bugfix Pull Request

COMPONENT NAME

rpm_key

ADDITIONAL INFORMATION

Fixed the concerns from @sivel regarding # #75251:

Additional Info from #75251

Example:

- name: Add Google GPG keys to system
  rpm_key:
    key: https://dl.google.com/linux/linux_signing_key.pub
    fingerprint:
      # First key in keyfile
      - 4CCA 1EAF 950C EE4A B839 76DC A040 830F 7FAC 5991
      # Second key in keyfile
      - EB4C 1BFD 4F04 2F6D DDCC EC91 7721 F63B D38B 4796

The rpm_key module only checked for the presence of the first key in a file when importing keys from files. This meant that in cases where a single file contained multiple keys it was possible for later keys to not be imported if the first key in a key file was already installed. It could also mean that multiple keys could be installed even when only expecting a single key in a file.

Sofia Nieves and others added 6 commits July 11, 2021 11:04
Google makes a RPM key file containing multiple public keys publicly
avaiable which is great for making sure ansible's rpm_key module can
handle multiple keys being present in a single file.
Multiple keys can be concatenated into a single file however. This aims
to make the module check for multiple key fingerprints beng present in a
single file. This also allows for a list of fingerprints to be passed to
module arguments for verification. If there's any mismatch, then the
module throws an error.
@ansibot ansibot added bug This issue/PR relates to a bug. needs_triage Needs a first human triage before being processed. module This issue/PR relates to a module. needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. labels Jun 26, 2024
@ansibot
Copy link
Contributor

ansibot commented Jun 26, 2024

The test ansible-test sanity --test pep8 [explain] failed with 4 errors:

lib/ansible/modules/rpm_key.py:123:23: E201: whitespace after '['
lib/ansible/modules/rpm_key.py:123:27: E202: whitespace before ']'
lib/ansible/modules/rpm_key.py:242:29: W291: trailing whitespace
lib/ansible/modules/rpm_key.py:247:1: W293: blank line contains whitespace

The test ansible-test sanity --test pylint [explain] failed with 2 errors:

lib/ansible/modules/rpm_key.py:242:28: trailing-whitespace: Trailing whitespace
lib/ansible/modules/rpm_key.py:247:0: trailing-whitespace: Trailing whitespace

click here for bot help

Tobias Kranz added 3 commits June 26, 2024 23:50
…A1 not available'

assemble a key for the test with multiple fingerprints not containing a SHA1 signature
@ansibot ansibot removed the needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. label Jun 26, 2024
@t-kranz
Copy link
Author

t-kranz commented Jun 27, 2024

I would like to remove the RHEL9 SHA1 deprecation from /test/integration/targets/rpm_key/tasks/rpm_key.yaml

To be able to do that i guess a GPG key file would need to be added to https://ci-files.testing.ansible.com/test/integration/targets/

That file needs to contain keys with at least two different fingerprints and those keys have to comply with the SHA-1 deprecation in RHEL 9.

The example ('Google GPG keys') from the original PR will result in

"msg": "warning: Signature not supported. Hash algorithm SHA1 not available.\nerror: /tmp/tmpuc4h77a5: key 2 import failed.\n"

@mattclay mattclay removed the needs_triage Needs a first human triage before being processed. label Jun 27, 2024
@Akasurde Akasurde changed the title Issue83394 rpm key rpm_key: support multiple siging keys Jul 2, 2024
@ansibot ansibot added the stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. label Jul 8, 2024

- name: Issue 83493 - Verify key fingerprints. This should fail due to multiple key signatures
rpm_key:
key: /tmp/KEY_83493
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this. You should be able to swap this out for https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/rpm_key/linux_signing_key.pub now and remove the few tasks preceding this one.

@ansibot ansibot added stale_review Updates were made after the last review and the last review is more than 7 days old. and removed stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. labels Jul 12, 2024
@ansibot ansibot added the stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. label Jul 26, 2024
@@ -0,0 +1,7 @@
minor_changes:
- >
rpm_key - Check for multiple signing keys in a single GPG key file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you rephrase this in non-imperative mood? The writing style is inconsistent with the following entry (and likely many other changelog fragments).
This is going to show up in the aggregated change log document on release. That document refers to the changes that have already happened since the previous release, so it's natural to describe things as if they are already merged. Imperative mood is a better fit for Git commit summary lines and TODO entries, but change logs have different style, purpose and audience.

self.rpm = self.module.get_bin_path('rpm', True)
state = module.params['state']
key = module.params['key']
fingerprint = module.params['fingerprint']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is now a list, seeing code iterating over a variable called as a single item reads somewhat counterintuitive.
May I suggest renaming the variable to fingerprints? Even if you keep the public interface with the original name. This will make the code easier to reason about.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even expected_fingerprints?

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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This var should probably be called differently. Currently, set(has_fingerprint) looks as if a boolean is passed to the set() constructor. Perhaps, computed_fingerprint?

if fingerprint:
has_fingerprint = self.getfingerprint(keyfile)
if fingerprint != has_fingerprint:
if set(fingerprint) != set(has_fingerprint):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be something along the lines of

Suggested change
if set(fingerprint) != set(has_fingerprint):
if any(fgrprnt not in computed_fingerprint for fgrprnt in fingerprints):

?

Perhaps, this entire expression could be assigned to a variable, so its intended purpose could be labeled via a variable name?

"""Ensure a keyid doesn't have a leading 0x, has leading or trailing whitespace, and make sure is uppercase"""
ret = keyid.strip().upper()
if ret.startswith('0x'):
if ret.startswith("0x"):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pro tip: mixing formatting changes with functional ones is discouraged because it makes it harder for the reviewers to identify which places in the patch are useful payload. These should always be separated.

return line.split(':')[4]
keyids.append(line.split(':')[4])

if keyids == []:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what people usually expect in Python:

Suggested change
if keyids == []:
if not keyids:

imported_ids.add(keyid)

missing_keys = set(keyids).difference(imported_ids)
return len(missing_keys) == 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be

Suggested change
return len(missing_keys) == 0
return not missing_keys

Comment on lines +254 to +255
missing_keys = set(keyids).difference(imported_ids)
return len(missing_keys) == 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though, I'd probably label the expression with what it intends to compute and return that:

Suggested change
missing_keys = set(keyids).difference(imported_ids)
return len(missing_keys) == 0
some_gpg_keys_missing = bool(set(keyids) - imported_ids)
return some_gpg_keys_missing

(I think that “return whether the length of a set of missing keys is zero” might be more difficult to parse vs. “return whether some GPG keys are missing” — it's low level vs. high level)

- name: Issue 83493 - Verify key fingerprints. This should fail due to multiple key signatures
rpm_key:
key: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/rpm_key/linux_signing_key.pub
fingerprint: 1B09 0CE4 7562 66D7 1203 13F6 3BAC 309A 6EB4 25D5
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I'm wrong, but isn't this a breaking change?

I think the current case is that users would only need to list one of the keys which appears in the import, and this test suggests that all keys would need to be listed for verification. I can imagine scenarios where users upload all their signing keys to a single file and then check for different keys in different modules. This change would break that usage if I have how it currently works right.

@ansibot ansibot added the needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html label Aug 14, 2024
@ansibot ansibot added the stale_pr This PR has not been pushed to for more than one year. label Jul 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug This issue/PR relates to a bug. module This issue/PR relates to a module. needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. stale_pr This PR has not been pushed to for more than one year. stale_review Updates were made after the last review and the last review is more than 7 days old.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants