Skip to content

Commit

Permalink
Merge pull request pulp#689 from sdherr/default-signing-service
Browse files Browse the repository at this point in the history
pulp#641: Specify and remember the Signing Services we want to use for each Repo / Release.
  • Loading branch information
hstct authored Jun 5, 2023
2 parents a0816d5 + 60a3abc commit b620904
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGES/641.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Specify and remember the Signing Services we want to use for each Repo / Release.
7 changes: 6 additions & 1 deletion docs/feature_overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,12 @@ The short version:

``/pulp/api/v3/signing-services/``

6. And use it when you Publish content. ``pulp_deb`` will call out to your script to sign the ``Release`` file and publish the signatures as part of the Publish action.
6. And use it when you Publish content. ``pulp_deb`` will call out to your script to sign the ``Release`` file and publish the signatures as part of the Publish action. The three ways you can specify the Signing Service are:

1. If you specify ``signing_service`` when creating the Publication, that service will sign all the Releases in the Publication.
2. You can specify that particular Release in a Repository use particular SigningServices by setting the ``signing_service_release_overrides`` field on the Repository. For example:
``signing_service_release_overrides = {"bionic": "/pulp/api/v3/signing-services/433a1f70-c589-4413-a803-c50b842ea9b5/"}``
3. Finally, if you have set a ``signing_service`` on a Repository then the other Releases in that Repo will use that Service.

.. _verbatim_publishing:

Expand Down
36 changes: 36 additions & 0 deletions pulp_deb/app/migrations/0023_add_default_signing_services.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 3.2.16 on 2022-11-28 16:56

from django.db import migrations, models
import django.db.models.deletion
import django_lifecycle.mixins
import pulpcore.app.models.base


class Migration(migrations.Migration):

dependencies = [
('deb', '0022_alter_aptdistribution_distribution_ptr_and_more'),
]

operations = [
migrations.AddField(
model_name='aptrepository',
name='signing_service',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='deb.aptreleasesigningservice'),
),
migrations.CreateModel(
name='AptRepositoryReleaseServiceOverride',
fields=[
('pulp_id', models.UUIDField(default=pulpcore.app.models.base.pulp_uuid, editable=False, primary_key=True, serialize=False)),
('pulp_created', models.DateTimeField(auto_now_add=True)),
('pulp_last_updated', models.DateTimeField(auto_now=True, null=True)),
('release_distribution', models.TextField()),
('repository', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='signing_service_release_overrides', to='deb.aptrepository')),
('signing_service', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='deb.aptreleasesigningservice')),
],
options={
'unique_together': {('repository', 'release_distribution')},
},
bases=(django_lifecycle.mixins.LifecycleModelMixin, models.Model),
),
]
6 changes: 3 additions & 3 deletions pulp_deb/app/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
Package,
)

from .signing_service import AptReleaseSigningService

from .content.metadata import (
Release,
)
Expand All @@ -24,6 +26,4 @@

from .remote import AptRemote

from .repository import AptRepository

from .signing_service import AptReleaseSigningService
from .repository import AptRepository, AptRepositoryReleaseServiceOverride
38 changes: 36 additions & 2 deletions pulp_deb/app/models/repository.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from pulpcore.plugin.models import Repository

from django.db import models
from pulpcore.plugin.models import BaseModel, Repository
from pulpcore.plugin.repo_version_utils import remove_duplicates, validate_version_paths

from pulp_deb.app.models import (
AptReleaseSigningService,
AptRemote,
GenericContent,
InstallerFileIndex,
Expand Down Expand Up @@ -39,9 +40,27 @@ class AptRepository(Repository):
AptRemote,
]

signing_service = models.ForeignKey(
AptReleaseSigningService, on_delete=models.PROTECT, null=True
)
# Implicit signing_service_release_overrides

class Meta:
default_related_name = "%(app_label)s_%(model_name)s"

def release_signing_service(self, release):
"""
Return the Signing Service specified in the overrides if there is one for this release,
else return self.signing_service.
"""
if isinstance(release, Release):
release = release.distribution
try:
override = self.signing_service_release_overrides.get(release_distribution=release)
return override.signing_service
except AptRepositoryReleaseServiceOverride.DoesNotExist:
return self.signing_service

def initialize_new_version(self, new_version):
"""
Remove old metadata from the repo before performing anything else for the new version. This
Expand Down Expand Up @@ -75,3 +94,18 @@ def finalize_new_version(self, new_version):
if distribution in distributions:
raise DuplicateDistributionException(distribution)
distributions.append(distribution)


class AptRepositoryReleaseServiceOverride(BaseModel):
"""
Override the SigningService that a single Release will use in this AptRepository.
"""

repository = models.ForeignKey(
AptRepository, on_delete=models.CASCADE, related_name="signing_service_release_overrides"
)
signing_service = models.ForeignKey(AptReleaseSigningService, on_delete=models.PROTECT)
release_distribution = models.TextField()

class Meta:
unique_together = (("repository", "release_distribution"),)
96 changes: 94 additions & 2 deletions pulp_deb/app/serializers/repository_serializers.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,118 @@
from gettext import gettext as _
from django.db import transaction
from pulpcore.plugin.models import SigningService
from pulpcore.plugin.serializers import (
RelatedField,
RepositorySerializer,
RepositorySyncURLSerializer,
validate_unknown_fields,
)
from pulpcore.plugin.util import get_url

from pulp_deb.app.models import AptRepository
from pulp_deb.app.models import (
AptRepositoryReleaseServiceOverride,
AptReleaseSigningService,
AptRepository,
)

from jsonschema import Draft7Validator
from rest_framework import serializers
from rest_framework.exceptions import ValidationError as DRFValidationError
from pulp_deb.app.schema import COPY_CONFIG_SCHEMA


class ServiceOverrideField(serializers.DictField):
child = RelatedField(
view_name="signing-services-detail",
queryset=AptReleaseSigningService.objects.all(),
many=False,
required=False,
allow_null=True,
)

def to_representation(self, overrides):
return {
# Cast to parent class so get_url can look up resource url.
x.release_distribution: get_url(SigningService(x.signing_service.pk))
for x in overrides.all()
}


class AptRepositorySerializer(RepositorySerializer):
"""
A Serializer for AptRepository.
"""

signing_service = RelatedField(
help_text="A reference to an associated signing service. Used if "
"AptPublication.signing_service is not set",
view_name="signing-services-detail",
queryset=AptReleaseSigningService.objects.all(),
many=False,
required=False,
allow_null=True,
)
signing_service_release_overrides = ServiceOverrideField(
default=dict,
required=False,
help_text=_(
"A dictionary of Release distributions and the Signing Service URLs they should use."
"Example: "
'{"bionic": "/pulp/api/v3/signing-services/433a1f70-c589-4413-a803-c50b842ea9b5/"}'
),
)

class Meta:
fields = RepositorySerializer.Meta.fields
fields = RepositorySerializer.Meta.fields + (
"signing_service",
"signing_service_release_overrides",
)
model = AptRepository

@transaction.atomic
def create(self, validated_data):
"""Create an AptRepository, special handling for signing_service_release_overrides."""
overrides = validated_data.pop("signing_service_release_overrides", -1)
repo = super().create(validated_data)

try:
self._update_overrides(repo, overrides)
except DRFValidationError as exc:
repo.delete()
raise exc
return repo

def update(self, instance, validated_data):
"""Update an AptRepository, special handling for signing_service_release_overrides."""
overrides = validated_data.pop("signing_service_release_overrides", -1)
with transaction.atomic():
self._update_overrides(instance, overrides)
instance = super().update(instance, validated_data)
return instance

def _update_overrides(self, repo, overrides):
"""Update signing_service_release_overrides."""
if overrides == -1:
# Sentinel value, no updates
return

current = {x.release_distribution: x for x in repo.signing_service_release_overrides.all()}
# Intentionally only updates items the user specified.
for distro, service in overrides.items():
if not service and distro in current: # the user wants to delete this override
current[distro].delete()
elif service:
signing_service = AptReleaseSigningService.objects.get(pk=service)
if distro in current: # update
current[distro] = signing_service
current[distro].save()
else: # create
AptRepositoryReleaseServiceOverride(
repository=repo,
signing_service=signing_service,
release_distribution=distro,
).save()


class AptRepositorySyncURLSerializer(RepositorySyncURLSerializer):
"""
Expand Down
8 changes: 6 additions & 2 deletions pulp_deb/app/tasks/publishing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from pulp_deb.app.models import (
AptPublication,
AptRepository,
Package,
PackageReleaseComponent,
Release,
Expand Down Expand Up @@ -101,7 +102,7 @@ def publish(repository_version_pk, simple=False, structured=False, signing_servi
publication.simple = simple
publication.structured = structured
publication.signing_service = signing_service
repository = repo_version.repository
repository = AptRepository.objects.get(pk=repo_version.repository.pk)

if simple:
codename = "default"
Expand All @@ -126,6 +127,7 @@ def publish(repository_version_pk, simple=False, structured=False, signing_servi
description=repository.description,
label=repository.name,
version=str(repo_version.number),
signing_service=repository.signing_service,
)

for package in Package.objects.filter(
Expand Down Expand Up @@ -191,6 +193,7 @@ def publish(repository_version_pk, simple=False, structured=False, signing_servi
label=repository.name,
version=str(repo_version.number),
suite=release.suite,
signing_service=repository.release_signing_service(release),
)

for prc in PackageReleaseComponent.objects.filter(
Expand Down Expand Up @@ -279,6 +282,7 @@ def __init__(
version,
description=None,
suite=None,
signing_service=None,
):
self.publication = publication
self.distribution = distribution
Expand Down Expand Up @@ -312,7 +316,7 @@ def __init__(

self.architectures = architectures
self.components = {component: _ComponentHelper(self, component) for component in components}
self.signing_service = publication.signing_service
self.signing_service = publication.signing_service or signing_service

def add_metadata(self, metadata):
artifact = metadata._artifacts.get()
Expand Down
Loading

0 comments on commit b620904

Please sign in to comment.