Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to download/export certificates from Trusted Signing #734

Closed
wants to merge 2 commits into from

Conversation

mjcheetham
Copy link

Add a new option --certificate-export-path to the code trusted-signing command that allows users to export the certificate used to sign from the Trusted Signing service to a file on disk. This is particularly useful for users who need a copy of the latest Trusted Signing certificate to upload to a third-party service such as NuGet.org to allow verification of the signed packages that are published there.

This pull request is organised in two commits that can be reviewed individually and are as follows:

  1. Add (I)Exporter that can export a certificate to a file on disk from a certificate provider.

  2. Add an export certificate option to the code-signing command for Trusted Signing.

Open questions

  • Should we consider adding a --force flag if exporting and overwriting an existing certificate on disk?

  • Should we consider adding a --format flag to allow exporting the certificate in different formats (e.g. PEM, DER, etc)?

  • Does this make sense for other services that provide certificates, or is this only applicable to Trusted Signing?

Alternative implementations

Add new 'export' component that can export a certificate to a file on
disk from a certificate provider.
Add option to export the certificate used to sign code to all `code`
commands, using the Exporter.
@mjcheetham mjcheetham marked this pull request as ready for review June 26, 2024 22:39
@mjcheetham mjcheetham requested a review from a team as a code owner June 26, 2024 22:39
mjcheetham added a commit to git-ecosystem/git-credential-manager that referenced this pull request Jun 27, 2024
)

- Update to the latest version of the GitHub Action (the
`azure/azure-code-signing-action` action has been replaced by the
`azure/trusted-signing-action` one).

- Deploy a forked version of the `Sign.Cli` tool for Trusted Signing,
which includes the ability to export the certificate. The fork can be
found here https://github.com/mjcheetham/sign/tree/export-opt, and the
PR to submit this change upstream here
dotnet/sign#734.

With these changes we are now completely secret/credential free, and
rely on federation only.
@dlemstra
Copy link
Contributor

dlemstra commented Jun 28, 2024

I am not sure if this should be added to this application. In the future nuget.org will probably look at the Subscriber identity validation EKU inside the certificate (NuGet/NuGetGallery#10027).

But I also understand that you need some method to get the certificate from the signed file because it rotates so often. With a NuGet package you could get the certificate by unzipping the file and use openssl to extract it from .signature.p7s. But that is probably not something you would want everybody to do themselves. But I am also not sure that adding an export functionality to this application is the best solution to solve your problem,

I also don't think you can update the certificate through automation on a NuGet account so this still requires some manual work. A user could also use the NuGet package explorer to get the certificate and then upload the package, This is what I am now doing myself. Another option would be something like https://www.nuget.org/packages/Knapcode.CertificateExtractor#readme-body-tab if you want to do this in a pipeline.

p.s. I noticed in your referenced commit that you are still specifying -d and -u but you are no longer required to do that.

p.s. After writing my response I realized that I misunderstood your PR description and I have update this post. Sorry about the confusing earlier messages.

@joelverhagen
Copy link
Member

(btw, I am not a decision maker for Sign CLI, just an interested team member)

I agree with @dlemstra. I feel your pain here. I ran into this problem when using Trusted Signing + Sign CLI + GitHub Actions. The solution I took was writing my own CLI tool which runs after Sign CLI in GitHub Actions and extract the .cer file and includes it in the artifacts. Then I manually upload the .cer file and .nupkg to NuGet.org via the web UI.

Here is a sample:
https://github.com/joelverhagen/PackageLifeCycle/blob/7930b64f7e72518faf6b646187b47b46e2d64d22/.github/workflows/build.yml#L76-L87

This is not ideal but I think this is a point-in-time problem due to NuGet/NuGetGallery#10027.

IMHO interacting with the .cer with Trusted Signing is a bit of a "code smell". It suggests the scenario you're in does NOT support Trusted Signing EKU pinning somewhere and therefore is not resilient to the short-lived .cer files. This is of course the situation with NuGet.org but again I think the fix there is to push the service to support Trusted Signing instead of hacking in support with .cer files.

Unless there is another strong case for .cer retrieval, then I hesitate to make it a part of Sign CLI, which would then need to be supported long after NuGet.org supports proper Trusted Signing pinning based on EKU. I wonder if there is another scenario you have in mind where you really need the .cer?

@mjcheetham
Copy link
Author

This is not ideal but I think this is a point-in-time problem due to NuGet/NuGetGallery#10027.

IMHO interacting with the .cer with Trusted Signing is a bit of a "code smell". It suggests the scenario you're in does NOT support Trusted Signing EKU pinning somewhere and therefore is not resilient to the short-lived .cer files. This is of course the situation with NuGet.org but again I think the fix there is to push the service to support Trusted Signing instead of hacking in support with .cer files.

Unless there is another strong case for .cer retrieval, then I hesitate to make it a part of Sign CLI, which would then need to be supported long after NuGet.org supports proper Trusted Signing pinning based on EKU. I wonder if there is another scenario you have in mind where you really need the .cer?

This is correct, that the .cer file is only needed by me for NuGet.org uploading. I am receiving pressure internally to resolve this issue after we spent time migrating from ESRP to Trusted Signing (and now we are unable to go back because of security implications in authenticating to ESRP, and possible general policy violations).

But I also understand that you need some method to get the certificate from the signed file because it rotates so often. With a NuGet package you could get the certificate by unzipping the file and use openssl to extract it from .signature.p7s.

Right now I am still unable to even upload a signed package using this method; extracting and uploading the .cer file manually, for some reason. I have engaged with the NuGet support email but it's slow progress so far to get an answer to why package verification returns:

The package git-credential-manager 2.5.0 failed validation because of the following reason(s):

  • There was an unknown failure when validating your package.

:(

mjcheetham added a commit to git-ecosystem/git-credential-manager that referenced this pull request Jul 2, 2024
…1647)

Use a 3rd party tool to extract the NuGet signing certificate for upload
rather than relying on an option added to the sign.exe tool in a private
fork. At the same time let's use the `dotnet tool install` command to
acquire the code signing tool, rather than rely on our Azure blob store.

Also let's drop the `-d` and `-u` options from the sign.exe CLI; they
are no longer required
([source](dotnet/sign#734 (comment))).
@dtivel
Copy link
Collaborator

dtivel commented Jul 16, 2024

@mjcheetham, I don't think this functionality belongs in Sign CLI. This feature ask should be on the Trusted Signing team, though I tend to agree with @joelverhagen that interacting with the certificate like this is an indication that something is probably not right with the scenario. The proper solution is for NuGet.org to support Trusted Signing subscriber identities. That would make your sign+publish flow much easier without needing to extract a certificate.

For extracting certificates from a signed NuGet package, there is also https://github.com/NuGet/Entropy/tree/main/ExtractCertificatesFromNuGetPackage. The tool is not officially supported, but it works.

@dtivel dtivel closed this Jul 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants