Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/plugin_api/7942.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`SigningService.sign()` and `asign()` now accept an optional `pubkey_fingerprint` to sign with a key other than the one the signing service was created with.
12 changes: 10 additions & 2 deletions pulpcore/app/models/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ def _env_variables(self, env_vars=None):
env.update(env_vars)
return {**os.environ, **env}

def sign(self, filename, env_vars=None):
def sign(self, filename, env_vars=None, pubkey_fingerprint=None):
"""
Signs the file provided via 'filename' by invoking an external script (or executable).

Expand All @@ -825,13 +825,18 @@ def sign(self, filename, env_vars=None):
Args:
filename (str): A relative path to a file which is intended to be signed.
env_vars (dict): dictionary of environment variables
pubkey_fingerprint (str): fingerprint of the key to sign with. Defaults to the
signing service's own key.

Raises:
RuntimeError: If the return code of the script is not equal to 0.

Returns:
A dictionary as validated by the validate() method.
"""
if pubkey_fingerprint:
env_vars = {**(env_vars or {}), "PULP_SIGNING_KEY_FINGERPRINT": pubkey_fingerprint}

completed_process = subprocess.run(
[self.script, filename],
env=self._env_variables(env_vars),
Expand All @@ -849,8 +854,11 @@ def sign(self, filename, env_vars=None):

return return_value

async def asign(self, filename, env_vars=None):
async def asign(self, filename, env_vars=None, pubkey_fingerprint=None):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we make the "default key" fully optional, and make it mandatory in such situations to provide a key? Or perhaps as a "next step".

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I suppose that might be difficult since validate() tests signing, so you need a key for that

"""Async version of sign."""
if pubkey_fingerprint:
env_vars = {**(env_vars or {}), "PULP_SIGNING_KEY_FINGERPRINT": pubkey_fingerprint}

process = await asyncio.create_subprocess_exec(
self.script,
filename,
Expand Down
39 changes: 39 additions & 0 deletions pulpcore/tests/unit/test_signing_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import os

import pytest

from pulpcore.app.models.content import AsciiArmoredDetachedSigningService


@pytest.fixture
def signing_service(tmp_path):
"""A signing service whose script reports the fingerprint and env vars it was invoked with."""
script = tmp_path / "echo_env.sh"
script.write_text(
'#!/bin/sh\nprintf \'{"fingerprint": "%s", "extra": "%s"}\''
' "$PULP_SIGNING_KEY_FINGERPRINT" "$EXTRA"\n'
)
script.chmod(0o755)
return AsciiArmoredDetachedSigningService(
name="echo-env",
public_key="public-key",
pubkey_fingerprint="SERVICE_KEY",
script=str(script),
)


def test_sign_defaults_to_service_key(signing_service):
assert signing_service.sign(os.devnull)["fingerprint"] == "SERVICE_KEY"


def test_sign_override_replaces_key_and_keeps_env_vars(signing_service):
return_value = signing_service.sign(
os.devnull, env_vars={"EXTRA": "kept"}, pubkey_fingerprint="OTHER_KEY"
)
assert return_value == {"fingerprint": "OTHER_KEY", "extra": "kept"}


@pytest.mark.asyncio
async def test_asign_override_replaces_key(signing_service):
return_value = await signing_service.asign(os.devnull, pubkey_fingerprint="OTHER_KEY")
assert return_value["fingerprint"] == "OTHER_KEY"
Loading