Project

Profile

Help

Task #5946

Task #5944: [Epic] As a plugin writer, I can use a SigningService to produce ascii-armored signatures

Add sign_file(filename) interface to SigningService model

Added by dkliban@redhat.com 7 months ago. Updated 6 months ago.

Status:
CLOSED - CURRENTRELEASE
Priority:
Normal
Assignee:
Category:
-
Sprint/Milestone:
Start date:
Due date:
% Done:

100%

Estimated time:
Platform Release:
Groomed:
Yes
Sprint Candidate:
Yes
Tags:
Sprint:
Sprint 65

Description

A plugin author should be able to use an instance of a SigningService to produce a signed Artifact from an Artifact.

SigningService needs to provide a method called 'sign_file(filename)'. This method always returns a dictionary where each key is a relative path inside the worker's working directory and the value is the sha256 sum of that file. E.g.:

{
 "repomd.xml.asc": "ce72f1c9f90c6ca85a88352b677ed8cc85d4ba81b4887be39afb01ad9c4fd8f8",
 "repomd.xml.gpg": "e36e08b23107745247855b1a06d6d8ae27883fb56d7d7a282d93393db801cfe0"
}

The following code[0] in pulp_rpm:

with open(repomd_path, "w") as repomd_f:
    repomd_f.write(repomd.xml_dump())

PublishedMetadata.create_from_file(
    relative_path=os.path.join(repodata_path, os.path.basename(repomd_path)),
    publication=publication,
    file=File(open(repomd_path, 'rb'))
)

Would look more like this:

signer = SigningService.objects.get(pk=blah)

with open(repomd_path, "w") as repomd_f:
    repomd_f.write(repomd.xml_dump())

signed_files = signer.sign_file(repomd_path)

for file_path, sha256 in signed_files.items():
    PublishedMetadata.create_from_file(
        relative_path=os.path.join(repodata_path, os.path.basename(file_path)),
        publication=publication,
        file=File(open(file_path, 'rb'))
    )

[0] https://github.com/pulp/pulp_rpm/blob/aecc23c41d384a34e661410ae389d3fa1a3c315b/pulp_rpm/app/tasks/publishing.py#L353-L360

History

#1 Updated by bmbouter 7 months ago

  • Sprint/Milestone set to 3.1.0
  • Sprint Candidate changed from No to Yes

#2 Updated by bmbouter 7 months ago

  • Groomed changed from No to Yes

#3 Updated by rchan 7 months ago

  • Sprint set to Sprint 64

#4 Updated by daviddavis 7 months ago

  • Tracker changed from Issue to Story
  • % Done set to 0

#5 Updated by mihai.ibanescu@gmail.com 7 months ago

There is a reason the interface implemented for metadata signing in pulp2 is modifying the file in place.

Sometimes, the plugin writer may not know what types of signatures (detached or not) are needed.

As an extreme (and maybe hypothetical) example, let's look at a yum repository (repomd, really).

yum expects a clear-text signature. zypper expects a detached signature.

At the time the plugin developer writes the plugin, it may not be aware that the repo may even be used for zypper.

So, the plugin should typically only care that a call to make a signature was made. The instance of the signing service, as implemented by the pulp administrator, will decide whether it's a detached or clear-text signature.

#6 Updated by dkliban@redhat.com 7 months ago

  • Description updated (diff)

#7 Updated by dkliban@redhat.com 7 months ago

  • Subject changed from As a plugin author, I can use a SigningService to create a signed Artifact. to As a plugin author, I can use a SigningService to sign a file

#8 Updated by bmbouter 7 months ago

Question: What are the use cases for detached versus inline signatures?

I'm concerned about the semantic differences when plugin writers expect one type and administrators configuring the signing service could return another. Do we need one, or the other, or both?

Question: Won't the return data returning a public key always return a file ending in .key?

I'm asking because the example shows repomd.xml.gpg which didn't seem like a public key specifically by its file extension.

Question: In the case of detached signatures, we're expecting them to the ASCII armor style right?

Idea

What if we only have the signing service produce ascii armored detached signatures to keep admins from having to configure two types? If we did couldn't we have Pulp's code produce a clearsigned version by combining the detached armored signature to the original signed file and adding the header? Conceptually this made sense to me, and in searching the internet it seems possible https://unix.stackexchange.com/questions/498618/gpg-armor-vs-clearsign/498619#498619

Note this could be a terrible idea.

#9 Updated by dkliban@redhat.com 7 months ago

bmbouter wrote:

Question: What are the use cases for detached versus inline signatures?

I'm concerned about the semantic differences when plugin writers expect one type and administrators configuring the signing service could return another. Do we need one, or the other, or both?

I am really not sure what the use case is for inline signatures. Having looked at debian and rpm repositories, I have identified that in all cases an ascii-armored detached gpg signature is provided.

In yum[0] and zypper[1] repos, the repomd.xml file is accompanied by repomd.xml.asc file that contains an ascii-armored detached gpg signature. The zypper repo also provides a repomd.xml.key file with the public key.

In debian repositories[2], the Releases file is accompanied by Releases.gpg file that contains an ascii-armored detached gpg signature.

Question: Won't the return data returning a public key always return a file ending in .key?

I'm asking because the example shows repomd.xml.gpg which didn't seem like a public key specifically by its file extension.

The .gpg was a bad example there. Only the plugin writer knows what the files should be named. The sign_file() interface should have a stronger return type that explicitly states what the file represents.

Question: In the case of detached signatures, we're expecting them to the ASCII armor style right?

Yes for sure.

Idea

What if we only have the signing service produce ascii armored detached signatures to keep admins from having to configure two types? If we did couldn't we have Pulp's code produce a clearsigned version by combining the detached armored signature to the original signed file and adding the header? Conceptually this made sense to me, and in searching the internet it seems possible https://unix.stackexchange.com/questions/498618/gpg-armor-vs-clearsign/498619#498619

Note this could be a terrible idea.

I like this idea. The signing service script would always keep the original file untouched. It would always produce 2 new files: an ascii-armored detached gpg signature and a public key that can be used to verify it. The SigningService.sign_file() interface would always return a dictionary with 3 keys: file, signature, key. The values would be file names in the working directory. The plugin writer would then have to decide what to name these files for their publication.

We could later add a keyword argument called 'inline' and default it to False. When that is set to True, the signing service would attach the signature to the file and return the same dictionary. Except in this case the original file is modified.

[0] http://mirror.linux.duke.edu/pub/centos/8/BaseOS/x86_64/os/repodata/
[1] http://download.opensuse.org/distribution/leap/15.0/repo/oss/repodata/
[2] http://mirror.isoc.org.il/pub/debian/dists/bullseye/

#10 Updated by dkliban@redhat.com 7 months ago

  • Tracker changed from Story to Task
  • Subject changed from As a plugin author, I can use a SigningService to sign a file to Add sign_file(filename) interface to SigningService model
  • Parent task set to #5944

#11 Updated by lmjachky 7 months ago

  • Status changed from NEW to ASSIGNED
  • Assignee set to lmjachky

#12 Updated by mihai.ibanescu@gmail.com 7 months ago

I would try to not make any assumptions about the types of files returned by the signing server, if I can help it.

It's not like pulp users can create instances of a signing service remotely. They need to be set up by a pulp admin, who should be comfortable reading documentation coming from the plugin developer on what the expected output of the signing process should be for that particular plugin, and wrap it in a script of sorts.

Even the assumption that the original file is not to be modified is a stretch. What if some plugin does indeed clear-sign the metadata?

"640kB should be enough for anybody."

I would like to understand more about the drawbacks of the design dkliban proposed in the description. It seems simple enough, extensible, doesn't bake in any assumptions, and the admin configuring the signing service should understand the requirements of the repository type easily enough.

If anything, and I think that's important, I'd add an extensible interface (maybe with environment variables) to specify an optional GPG key fingerprint that pulp_core would know how to extract from the repository metadata, if the repository admin chose to supply one, and maybe the repository name itself. The signing service may use those as it sees fit.

I am sorry I can't seem to distance myself from the current implementation in pulp2 since that's roughly what it does and I find it simple enough, yet extensible.

#13 Updated by dkliban@redhat.com 7 months ago

Since all the use cases so far use an ascii-armored detached gpg signature, it seems better to focus on signing services that produce that. If we discover that some plugin needs to to utilize a different type of signing service, let's make SigningService a typed resource at that time.

#14 Updated by mihai.ibanescu@gmail.com 7 months ago

If a code change is required to enable other types of signatures / artifact changes, then I doubt it will ever happen.

It feels like a small change to the spec that will buy extensibility in the future.

I'd like for this proposal to address additional information being made available to the signing service. I hinted to it above.

If anything, and I think that's important, I'd add an extensible interface (maybe with environment variables) to specify an optional GPG key fingerprint that pulp_core would know how to extract from the repository metadata, if the repository admin chose to supply one, and maybe the repository name itself. The signing service may use those as it sees fit.

#15 Updated by dkliban@redhat.com 7 months ago

Allowing the signing service script to have more information about what is being signed would allow a single service to handle multiple keys and repositories. We should add this feature. I will open a new issue where we can decide what all we should make available to the signing service script.

Yes, we will need to write additional code to enable additional types of signing. However, the strong typing will make life easier for the user. I can imagine an RPM repository needing two completely different types of signing services: ascii-armored detached signer for the metadata and an RPM signer for individual packages. The user would be better served being able to explicitly select a service that is used to sign the packages vs the service that is used to sign metadata. These services may share some underlying infrastructure, but they perform two completely different things.

#16 Updated by bmbouter 7 months ago

  • Sprint/Milestone deleted (3.1.0)

#17 Updated by rchan 7 months ago

  • Sprint changed from Sprint 64 to Sprint 65

#18 Updated by Anonymous 6 months ago

  • Status changed from ASSIGNED to MODIFIED
  • % Done changed from 0 to 100

#19 Updated by bmbouter 6 months ago

  • Sprint/Milestone set to 3.1.0

#20 Updated by bmbouter 6 months ago

  • Status changed from MODIFIED to CLOSED - CURRENTRELEASE

Please register to edit this issue

Also available in: Atom PDF