Skip to content

Commit

Permalink
Implement signing on workers
Browse files Browse the repository at this point in the history
  • Loading branch information
pedro-psb committed Mar 14, 2024
1 parent fcd9417 commit 9299ed4
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 76 deletions.
2 changes: 1 addition & 1 deletion pulp_rpm/app/shared_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import tempfile
import typing as t
from hashlib import sha256
from importlib_resources import files
from pathlib import Path

import createrepo_c as cr
from django.conf import settings
from django.utils.dateparse import parse_datetime
from importlib_resources import files
from pulpcore.plugin.exceptions import InvalidSignatureError


Expand Down
2 changes: 1 addition & 1 deletion pulp_rpm/app/tasks/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .publishing import publish # noqa
from .synchronizing import synchronize # noqa
from .uploading import sign_and_create # noqa
from .signing import sign_and_create # noqa
from .copy import copy_content # noqa
from .comps import upload_comps # noqa
44 changes: 44 additions & 0 deletions pulp_rpm/app/tasks/signing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from tempfile import NamedTemporaryFile

from django.core.files import File
from pulpcore.app.apps import get_plugin_config
from pulpcore.plugin.models import Artifact, CreatedResource, MasterModel
from pulpcore.plugin.util import extract_pk, get_url

from pulp_rpm.app.models.content import RpmPackageSigningService


def sign_and_create(app_label, serializer_name, signing_service_pk, *args, **kwargs):
data = kwargs.pop("data", None)
context = kwargs.pop("context", {})
serializer_class = get_plugin_config(app_label).named_serializers[serializer_name]
package_signing_service = RpmPackageSigningService.objects.get(pk=signing_service_pk)

# Get unsigned packaged from Artifact
unsigned_artifact = Artifact.objects.get(pk=extract_pk(data["artifact"]))

with NamedTemporaryFile(mode="wb", dir=".", delete=False) as f:
final_package = File(f)
# Get copy of package
with unsigned_artifact.file.open() as unsigned_package:
final_package.write(unsigned_package.read())
final_package.flush()
# Sign package
package_signing_service.sign(final_package.name)
# Create new artifact from signed package
artifact = Artifact.init_and_validate(final_package.name)
artifact.save()
resource = CreatedResource(content_object=artifact)
resource.save()

# Replace data["artifact"] with signed one
data["artifact"] = get_url(artifact)

# Create Package
serializer = serializer_class(data=data, context=context)
serializer.is_valid(raise_exception=True)
instance = serializer.save()
if isinstance(instance, MasterModel):
instance = instance.cast()
resource = CreatedResource(content_object=instance)
resource.save()
45 changes: 0 additions & 45 deletions pulp_rpm/app/tasks/uploading.py

This file was deleted.

54 changes: 27 additions & 27 deletions pulp_rpm/app/viewsets/package.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from django_filters import CharFilter
from pulpcore.app import tasks as base_tasks
from pulpcore.app.response import OperationPostponedResponse
from pulpcore.plugin.files import PulpTemporaryUploadedFile
from pulpcore.plugin.viewsets import ContentFilter, SingleArtifactContentUploadViewSet
from pulpcore.tasking.tasks import dispatch
from drf_spectacular.utils import extend_schema
from pulpcore.plugin.serializers import AsyncOperationResponseSerializer
from pulpcore.plugin.tasking import dispatch, general_create
from pulpcore.plugin.viewsets import (
ContentFilter,
OperationPostponedResponse,
SingleArtifactContentUploadViewSet,
)

from pulp_rpm.app import tasks as rpm_tasks
from pulp_rpm.app.models import Package
Expand Down Expand Up @@ -68,6 +71,11 @@ class PackageViewSet(SingleArtifactContentUploadViewSet):
"queryset_scoping": {"function": "scope_queryset"},
}

@extend_schema(
description="Trigger an asynchronous task to create content,"
"optionally create new repository version.",
responses={202: AsyncOperationResponseSerializer},
)
def create(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
Expand All @@ -77,33 +85,25 @@ def create(self, request):
"app_label": self.queryset.model._meta.app_label,
"serializer_name": serializer.__class__.__name__,
}
task_exclusive = [
item
for item in (serializer.validated_data.get(key) for key in ("upload", "repository"))
if item
]

# handle signing, if required
sign_package = serializer.validated_data.get("sign_package")
pulp_tmp_file = serializer.validated_data.get("file")
if sign_package is True and pulp_tmp_file:
repo = serializer.validated_data["repository"]

task_fn = rpm_tasks.uploading.sign_and_create
task_args["temporary_file_path"] = pulp_tmp_file.temporary_file_path()
task_args["signing_service_pk"] = repo.package_signing_service.pk
task_exclusive = [
item
for item in (serializer.validated_data.get(key) for key in ("upload", "repository"))
if item
]
task_payload = {
k: v for k, v in request.data.items() if k not in ("file", "sign_package")
}
if sign_package is True:
task_fn = rpm_tasks.signing.sign_and_create
# 'repository' is being popped because the 'validated_data' will create
# an intermediary Artifact to be send to the task. The task will
# create a new signed Artifact, so the intermediate should be orphan-cleaned-up
associated_repo = serializer.validated_data.pop("repository")
task_args["signing_service_pk"] = associated_repo.package_signing_service.pk
else:
task_fn = base_tasks.base.general_create
task_exclusive = [
item
for item in (serializer.validated_data.get(key) for key in ("upload", "repository"))
if item
]
task_payload = self.init_content_data(serializer, request)
task_fn = general_create

task_payload = self.init_content_data(serializer, request)
task = dispatch(
task_fn,
exclusive_resources=task_exclusive,
Expand Down
6 changes: 4 additions & 2 deletions pulp_rpm/tests/functional/api/test_package_signing.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@ def test_sign_package_on_upload(
"sign_package": True,
}
upload_task = rpm_package_api.create(**upload_attrs).task
package_href = monitor_task(upload_task).created_resources[1]
# created_resources: [0] artifact [1] repository_version [2] package
package_href = monitor_task(upload_task).created_resources[2]
package = rpm_package_api.read(package_href)

# Verify stored artifact is properly signed
artifact = pulpcore_bindings.ArtifactsApi.read(package.artifact)
with default_storage.open(artifact.file, "r") as package_file:
with default_storage.open(artifact.file, "rb") as package_file:
package_file.read() # hopefully will trigger download on external storages
assert rpm_tool.verify_signature(package_file.name)

0 comments on commit 9299ed4

Please sign in to comment.