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

initial draft of dotnet nuget trusted-signers commands spec #10628

Merged
merged 9 commits into from
Mar 15, 2021

Conversation

zkat
Copy link
Contributor

@zkat zkat commented Mar 5, 2021

This spec is for #8053

(note: I'm not going to be around until next Tuesday, so feel free to treat this as a first draft and make your own modifications if we need to land this asap.)

We'll also want Kathleen to take a look at this, but I don't remember her GH handle :(

Copy link
Member

@nkolev92 nkolev92 left a comment

Choose a reason for hiding this comment

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

This all seems pretty reasonable to me :)

I'm not the expert in the feature area, so I am curious what the SMEs & .NET CLI folks think here.

proposed/2021/DotnetNugetTrustedSigners.md Outdated Show resolved Hide resolved
proposed/2021/DotnetNugetTrustedSigners.md Outdated Show resolved Hide resolved
proposed/2021/DotnetNugetTrustedSigners.md Outdated Show resolved Hide resolved
proposed/2021/DotnetNugetTrustedSigners.md Outdated Show resolved Hide resolved
proposed/2021/DotnetNugetTrustedSigners.md Outdated Show resolved Hide resolved
Copy link
Contributor

@erdembayar erdembayar left a comment

Choose a reason for hiding this comment

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

@zkat @heng-liu

1 question

proposed/2021/DotnetNugetTrustedSigners.md Outdated Show resolved Hide resolved

USAGE:
dotnet nuget trusted-signers trust-package [OPTIONS] <name> <package>...

Copy link
Contributor

Choose a reason for hiding this comment

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

Currently dotnet nuget verify allows to pass more than 1 path even though nuget verify doesn't, how about here do we have same gesture behavior allow pass more than 1 paths or serviceindexes, fingerprints?
dotnet nuget verify C:\Users\xxxx\source\repos\SigningDemo\TestSigned\TestSigned.1.0.0.nupkg C:\Users\xxxx\source\repos\SigningDemo\TestSigned\*.nupkg -v d

Copy link
Contributor

@heng-liu heng-liu Mar 8, 2021

Choose a reason for hiding this comment

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

That's a very good question.
My understanding is, the reason why we change the dotnet verify command to support multiple paths, is as following:
NuGet.exe only runs Windows(except on Mono) but dotnet.exe will run cross-platform
When executing the command in powershell, the xx*.nupkg will be passed as one argument to nuget.exe,
but when executing the command in bash, the globbing will expand the xx/*.nupkg into multiple paths before passing to dotnet.exe command. So if the dotnet.exe only accept one path, it will only get the first path but ignore the rest paths, and make it inconsistent with what we have on NuGet.exe.

In one word, we change dotnet.exe to accept multiple paths because it makes dotnet acts more like NuGet.exe.

Previously when we only have NuGet.exe, we use ";" to separate elements in one option, if we have multiple serviceindexes, fingerprints.
When we have dotnet.exe later, the ";" indicates the command terminates in bash.
I agree we need to think it over and have more discussion if we want to change the separator. If we're going to deprecate NuGet.exe, we may have less impact on customers.
FYI @JonDouglas

Copy link
Contributor

@loic-sharma loic-sharma Mar 9, 2021

Choose a reason for hiding this comment

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

Is globbing files a scenario customers need when updating their trusted signers? Do you have an example when this would be useful?

The reason I ask is because this scenario scares me a little bit. Ideally customers should thoroughly review each and every author/source they choose to trust.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the good question.
Just checked the code.
In NuGet.exe command, the package path could be wildcard, so there might be multiple paths after parsing.
But there is a checking on "Name" to reject any existing "Name" at https://github.com/NuGet/NuGet.Client/blob/ac97d923e633f4ee65eec5ec690c4d99d7a922f3/src/NuGet.Core/NuGet.Commands/TrustedSignersCommand/TrustedSignerActionsProvider.cs#L243
So when there are multiple packages, the first one will be added successfully, but the reset will fail for A trusted signer 'Test' already exists.
Apparently this is a bug. We should make the two consistent.
That is, do not accept multiple paths, or, accept multiple 'Name'.
Raised issue at #10647

proposed/2021/DotnetNugetTrustedSigners.md Outdated Show resolved Hide resolved
Comment on lines 71 to 74
#### `dotnet nuget trusted-signers sync`

```
Requests the latest list of certificates used in a currently trusted repository to update the the existing certificate list in the trusted signer.
Copy link
Member

Choose a reason for hiding this comment

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

This only updates the trusted source, not trusted author, right? Maybe trusted-source is better than trusted-signers, if it doen't also sync to the latest author certificates.

Copy link
Contributor

Choose a reason for hiding this comment

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

According to the code, yes you're right, it just sync certificate of repository signature.
I think trusted-signers means both author signers and repository signers.
An example is: we add certificate of repository signature by running trusted-signers add command.
So the question is, it good enough to only call it out explicitly in the document, that author certs will not be synced?

#### `dotnet nuget trusted-signers remove`

```
Removes any trusted signers that match the given name.
Copy link
Member

Choose a reason for hiding this comment

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

Is it confusing that when adding a trusted signer you need to specify either source or package, but when you remove you don't specify which 'type'?

Copy link
Contributor

@heng-liu heng-liu Mar 8, 2021

Choose a reason for hiding this comment

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

According to the code , there is a checking on duplicate names in trusted-signers section of config file when adding, to guarantee that there is no duplicate name, among all trusted-signers (both author and repository signers). So it might be good to just specifying the name, without 'type'.

Choose a reason for hiding this comment

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

I actually think this is nice. When you add a signer from a package you are not adding the package, but using it to find the certificate. When you remove the package, it does not matter where you got it.

Not symmetric, but in this case the action is not symmetric

proposed/2021/DotnetNugetTrustedSigners.md Outdated Show resolved Hide resolved
Comment on lines 169 to 170
The exception here is the `add` command, which has been split into the various
`trust-*` commands that otherwise have the same behaviors.
Copy link
Member

Choose a reason for hiding this comment

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

Why's that? In another comment I mentioned there are already multiple dotnet add <noun> and dotnet nuget add <noun>. Therefore, this spec is not following the convention of other commands in the dotnet cli

Copy link
Contributor

@heng-liu heng-liu Mar 8, 2021

Choose a reason for hiding this comment

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

What I remembered from last discussion is that dotnet want to change (they do not want to keep the same with dotnet add source any more). But I'm not 100% sure if that is the final decision.
Perhaps we can discuss with them when reviewing this document.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

3. myUntrustedAuthorSignature [author]
Certificate fingerprint(s):
[U] SHA256 - 518F9CF082C0872025EFB2587B6A6AB198208F63EA58DD54D2B9FF6735CA4434
```
Copy link
Contributor

Choose a reason for hiding this comment

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

The dotnet list package describes the markers like [U] at the bottom of the command output. For example (LINK):

Project 'SentimentAnalysis' has the following package references
   ...
   > Microsoft.NETCore.App   (A)   [2.1.0, )   2.1.0

(A) : Auto-referenced package.

Personally I find that describing the markers at the bottom of the command output grabs my attention more than the end of the command's help description. What do you think of adding the markers at the bottom of the output too?

Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like if we use markers to describe the output, then we haven't done a good enough job explaining the output in the first place. I especially think describing allowUntrustedRoot is going to be difficult to explain in a single line at the bottom of the command.

Copy link
Contributor

@loic-sharma loic-sharma Mar 11, 2021

Choose a reason for hiding this comment

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

I suggest we either:

  1. Remove the [U] marker altogether, or...
  2. Replace the marker with some text next to the SHA-256 fingerprint, or...
  3. Define the [U] marker somewhere in this output. For the single line explanation, I suggest: [U]: NuGet will not reject the certificate if it chains to an untrusted root.. We can skip definition if no certs allow an untrusted root.

I'd vote for option 2 or 3 personally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm impartial. tbh just tell me which one y'all like best and I'll do that :)


OPTIONS:
--allow-untrusted-root Specifies if the certificate for the trusted signer should be allowed to chain to an untrusted root.
--owners Semi-colon separated list of trusted owners to further restrict the trust of a repository. Only valid when using the --repository option.
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like this command doesn't have a --repository option. Consider:

Suggested change
--owners Semi-colon separated list of trusted owners to further restrict the trust of a repository. Only valid when using the --repository option.
--owners Semi-colon separated list of trusted owners to further restrict the trust of a repository.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oops, copy-paste fail. Thanks!

```
Adds a trusted signer based on a given source.

If only `<name>` is provided, and it's an existing configured source, this command will add a trusted signer with the same name as that source to the trusted list.
Copy link
Contributor

@loic-sharma loic-sharma Mar 9, 2021

Choose a reason for hiding this comment

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

What do you think of this phrasing?

Suggested change
If only `<name>` is provided, and it's an existing configured source, this command will add a trusted signer with the same name as that source to the trusted list.
If only `<name>` is provided without `<source-url>`, the package source from your NuGet configuration files with the same name will be added to the trusted list.

This sentence is really hard! Maybe pull in a copywriter 😅

--configfile The NuGet configuration file. If specified, only the settings from this file will be used. If not specified, the hierarchy of configuration files from the current directory will be used.
```

#### `dotnet nuget trusted-signers trust-source`
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's say I've already trusted 15 package owners for my mid-sized project. But now I want to add one more package that is owned by someone I did not previously trust. What would be my flow to append one more trusted owner? Do I need to provide all 16 package owners to the trust-source command? What would my flow be if I have a large project with many more owners?

The reason I ask is that I recently tried to set up trusted signers for the NuGetGallery codebase. This proved to be difficult using nuget.exe, so I resorted to manually editing the nuget.config file instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

One idea may be to add a trust-owner command that appends one or more owners to a trusted repository. See @zivkan comment here: https://github.com/NuGet/Home/pull/10628/files/5263069456da2276d0f3143fd5bf616e933b7809#r589669891

Copy link
Contributor

Choose a reason for hiding this comment

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

I have a similar question about a missing function in NuGet.exe:
After repo certificate rotation, we need to change the trustedSigners section to have two certs :

<trustedSigners>
  <repository name="nuget.org" serviceIndex="https://api.nuget.org/v3/index.json">
    <certificate fingerprint="0E5F38F57DC1BCC806D8494F4F90FBCEDD988B46760709CBEEC6F4219AA6157D" hashAlgorithm="SHA256" allowUntrustedRoot="false" />
    <certificate fingerprint="5A2901D6ADA3D18260B9C6DFE2133C95D74B9EEF6AE0E5DC334C8454D1477DF4" hashAlgorithm="SHA256" allowUntrustedRoot="false" />
  </repository>
</trustedSigners>

But seems there is no command could do that. We have to edit config file manually.
Since we don't have that for NuGet.exe either, perhaps we can address that afterwards.

@loic-sharma
Copy link
Contributor

loic-sharma commented Mar 9, 2021

We'll also want Kathleen to take a look at this, but I don't remember her GH handle :(

I believe her handle is @KathleenDollard :)

#### `> dotnet nuget trust list`

```
Lists all the trusted signers in the configuration. This option will include all the certificates (with fingerprint and fingerprint algorithm) each signer has. If a certificate has a preceding [U], it means that certificate entry has allowUntrustedRoot set as true.
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think of this?

Suggested change
Lists all the trusted signers in the configuration. This option will include all the certificates (with fingerprint and fingerprint algorithm) each signer has. If a certificate has a preceding [U], it means that certificate entry has allowUntrustedRoot set as true.
Lists all the trusted signers in the configuration. This option will include all the certificates (with fingerprint and fingerprint algorithm) each signer has. If a certificate has a preceding [U], NuGet will not reject the certificate if it chains to an untrusted root.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure. I think it's good to make it clear that the [U] corresponds to an actual option in the config file, you know? What do you think, @heng-liu ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm... IMHO ideally no one ever uses allowUntrustedRoot. If so, maybe we shouldn't bring up such an advanced topic in the command description? It is difficult to balance between useful information and verbosity. What do you think of only explaning [U] in command output if the user has allowUntrustedRoot enabled somewhere as per #10628 (comment)? If so, we can detail both the allowUntrustedRoot config plus give a quick human description of what that entails.

Choose a reason for hiding this comment

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

Just pointing out... you can use links to docs on more advanced topics. We anticipate doing this when we clean up all the CLI help near the end of .NET 6 or start of 7.

Co-authored-by: Loïc Sharma <737941+loic-sharma@users.noreply.github.com>
Copy link

@KathleenDollard KathleenDollard left a comment

Choose a reason for hiding this comment

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

I think we landed in a good place. My comments are tweaks.

#### `> dotnet nuget trust`

```
Manage the trusted signers. By default, NuGet accepts all authors and repositories. You can restrict this to just authors or repositories you trust using this command.

Choose a reason for hiding this comment

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

Does that mean if you trust any that makes all others untrusted? If so, I think this could say it more directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's exactly what this does. I'll try a different wording.

#### `> dotnet nuget trust list`

```
Lists all the trusted signers in the configuration. This option will include all the certificates (with fingerprint and fingerprint algorithm) each signer has. If a certificate has a preceding [U], it means that certificate entry has allowUntrustedRoot set as true.

Choose a reason for hiding this comment

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

Just pointing out... you can use links to docs on more advanced topics. We anticipate doing this when we clean up all the CLI help near the end of .NET 6 or start of 7.

#### `> dotnet nuget trust sync`

```
Requests the latest list of certificates used in a currently trusted repository to update the the existing certificate list in the trusted signer.

Choose a reason for hiding this comment

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

As someone not familiar with this space, I found it difficult to understand this sentence. Is the most important part first? If not try that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have a generalized concern that this feature is very complex and hard to explain in general, and I'm having trouble figuring out how to write these docs in a way that creates clarity. :(

```
Requests the latest list of certificates used in a currently trusted repository to update the the existing certificate list in the trusted signer.

Note: This gesture will delete the current list of certificates and replace them with an up-to-date list from the repository.

Choose a reason for hiding this comment

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

Oh, wait. If this is what it does, why not just use this note as the description?

#### `> dotnet nuget trust author`

```
Adds a trusted signer with the given name to the config, based on the author signature(s) of one or more packages. If <name> already exists in the configuration, the signature(s) will be appended.

Choose a reason for hiding this comment

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

For all of these, what does "to the config" add for a normal use reading this. Suggest dropping it in all these commands.

proposed/2021/DotnetNugetTrustedSigners.md Outdated Show resolved Hide resolved
```
Adds a trusted signer with the given name to the config, based on a certificate fingerprint.

Note: If a trusted signer with the given name already exists, the certificate item will be added to that signer. Otherwise a trusted author will be created with a certificate item from given certificate information.

Choose a reason for hiding this comment

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

As someone unfamiliar with this space, I do not know what name means. Is it part of the certificate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The name in all of these refers to the identifier the trusted signer is saved under. The name of the entity itself, if you will. It's an arbitrary name that we use to key off of.

USAGE:
dotnet nuget trust author [OPTIONS] <name> <package>...

EXAMPLE:

Choose a reason for hiding this comment

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

I do not see this example adding much.

Copy link
Contributor

@loic-sharma loic-sharma Mar 11, 2021

Choose a reason for hiding this comment

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

To me <name> and <package> are vague terms. From this command alone, it's unclear how <name> will be used. Also, it's also unclear that <package> should be a path to a .nupkg file. The example does help clarify some of these questions.

Is it possible to add descriptions for the command arguments? Maybe that'd be better than an example.

proposed/2021/DotnetNugetTrustedSigners.md Show resolved Hide resolved
counterparts, and most of their implementations should be reusable (removing
`#if IS_DESKTOP` as needed, from the various TrustedSigners classes).

The exception here is the `add` command, which has been split into separate

Choose a reason for hiding this comment

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

? there is no longer an add command. Appears a couple of times in this section.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is referring to the nuget trusted-signers add command, which is what has been split up.

@zkat zkat requested a review from loic-sharma March 12, 2021 00:48
Copy link
Contributor

@JonDouglas JonDouglas left a comment

Choose a reason for hiding this comment

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

I'm a big fan of the current rework. I think it meets all my concerns & really helps simplify this confusing area. Well done!

@JonDouglas
Copy link
Contributor

JonDouglas commented Mar 12, 2021

I did read through this blog last night & there were some UX items potentially to cover: https://haacked.com/archive/2019/04/03/nuget-package-signing/

  1. When trusting a package author, we need a .nupkg. Can we additionally provide a UX to download the package for the user by specifying a package name / version as an alternative to supplying the package?

One work around is using an API which is a bit hidden to users: i.e. https://api.nuget.org/v3-flatcontainer/newtonsoft.json/12.0.1/newtonsoft.json.12.0.1.nupkg (We should do that for people if we can)

i.e. dotnet nuget trust author Contoso Contoso.Library

  1. Additionally as a future thought, we have no way to just trust a package author through this method. We still are trusting a package in some fashion. Is there a way we can grab details from the package author to then trust the author? In other words, to say we trust "jdouglas" & any package they upload would be "trusted".

i.e. dotnet nuget trust author jdouglas

@zkat zkat merged commit 7f7361a into dev Mar 15, 2021
@zkat zkat deleted the dev-zkat-dotnet-trusted-signers branch March 15, 2021 16:48
@erdembayar
Copy link
Contributor

@zkat
I can run below command nuget trusted-signers Add -Name Nuget -config ..\nuget.config and it works.
But how does it work for dotnet nuget?

@erdembayar
Copy link
Contributor

erdembayar commented Mar 17, 2021

@zkat
Also you can write example full line of code for each of cases?
dotnet nuget trust repository
dotnet nuget trust certificate
dotnet nuget trust author
dotnet nuget trust source

@zkat
Copy link
Contributor Author

zkat commented Mar 17, 2021

@erdembayar The equivalent of nuget trusted-signers Add -Name NuGet -config ..\nuget.config is dotnet nuget trust source NuGet --configfile ..\nuget.config

@zkat
Copy link
Contributor Author

zkat commented Mar 17, 2021

as far as examples go: I got some feedback during code review that unless the example was fairly intricate, it added no value having such a section, so I removed them. Is there a different way I can help clear things up?

@erdembayar
Copy link
Contributor

as far as examples go: I got some feedback during code review that unless the example was fairly intricate, it added no value having such a section, so I removed them. Is there a different way I can help clear things up?

Currently on there is only 1 example: dotnet nuget trust author Contoso ./contoso.library.nupkg
I'm new to package signing, I still have doubt if I'm reading spec correctly, please verify and correct if following trusted-signers commands are valid so we can have them as unit tests in our implementation.

dotnet nuget trust repository NugetOrg ./newtonsoft.json.13.0.1-beta1.nupkg
dotnet nuget trust certificate MyCompanyCert  CE40881FF5F0AD3E58965DA20A9F571EF1651A56933748E1BF1C99E537C4E039 --algorithm SHA256
dotnet nuget trust source NuGetTestTrust https://apidev.nugettest.org/v3-index/index.json --allow-untrusted-root true --owners "NugetTestOrg;MSTestOrg;TrustedTesOwners" 
dotnet nuget trust sync NugetOrg
dotnet nuget trust remove NugetOrg
dotnet nuget trust list -v:d

@zkat
Copy link
Contributor Author

zkat commented Mar 17, 2021

Some corrections below:

--allow-untrusted-root does not take an argument. It's a flag:

dotnet nuget trust source NuGetTestTrust https://apidev.nugettest.org/v3-index/index.json --allow-untrusted-root --owners "NugetTestOrg;MSTestOrg;TrustedTesOwners"

Don't separate the verbosity with a :. Just put a space:

dotnet nuget trust list -v d

The others look fine to me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants