-
Notifications
You must be signed in to change notification settings - Fork 689
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
Make verify command consider default nuget.config file and nuget.config option #4396
Make verify command consider default nuget.config file and nuget.config option #4396
Conversation
b73afcc
to
4c17651
Compare
be350d2
to
f555e35
Compare
src/NuGet.Core/NuGet.Commands/VerifyCommand/VerifyCommandRunner.cs
Outdated
Show resolved
Hide resolved
6910e0f
to
896a0a9
Compare
@@ -58,10 +60,16 @@ public async Task<int> ExecuteCommandAsync(VerifyArgs verifyArgs) | |||
_defaultFingerprintAlgorithm)).ToList(); | |||
|
|||
var verifierSettings = SignedPackageVerifierSettings.GetVerifyCommandDefaultPolicy(); | |||
var trustedSignersSection = verifyArgs.Settings.GetSection(TrustedSignersSectionName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not backwards compatible because the obsolete constructor you added will have Settings
as null, and therefore this code will throw a NullReferenceException
.
Perhaps have a re-read of https://github.com/NuGet/NuGet.Client/blob/dev/docs/nuget-sdk.md#types-of-compatibility as a refresher to different types of compatibility.
0d841d7
to
448dbb3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's considered default nuget.config here?
wrt current working directory?
src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/Signing/TrustedSignersCommand.cs
Show resolved
Hide resolved
SettingSection trustedSignersSection = verifyArgs.Settings?.GetSection(TrustedSignersSectionName); | ||
List<TrustedSignerItem> trustedSigners = trustedSignersSection?.Items.Select(c => c as TrustedSignerItem).Where(c => c != null).ToList(); | ||
IEnumerable<KeyValuePair<string, HashAlgorithmName>> allowUntrustedRootList = trustedSigners? | ||
.SelectMany(c => c.Certificates) | ||
.Where(c => c.AllowUntrustedRoot) | ||
.Select(c => new KeyValuePair<string, HashAlgorithmName>(c.Fingerprint, c.HashAlgorithm)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nuget.exe verify command spec
specifies that -ConfigFile option from NuGet.Config file is used for only repository signature verification.
This makes me think that verify
command should not apply all the settings from the NuGet.Config
file while verifying package signature.
I posted this comment in another issue but here are the default settings used by Verify
command. I would check with @dtivel and @heng-liu just to make sure required options are read from the NuGet.Config
file.
Setting | Verify Command default setting |
---|---|
AllowUnsigned | ❌ |
AllowIllegal | ❌ |
AllowUntrusted | ❌ |
AllowIgnoreTimestamp | ❌ |
AllowMultipleTimestamps | ✔️ |
AllowNoTimestamp | ✔️ |
AllowUnknownRevocation | ✔️ |
ReportUnknownRevocation | ✔️ |
VerificationTarget | Targets unknown, Author and Repository signatures |
SignaturePlacement | Primary, Counter signatures |
RepositoryCountersignatureVerificationBehavior | IfExists (Verify a signature if it exists) |
RevocationMode | Online unless "NUGET_CERT_REVOCATION_MODE" environment variable is set |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, let's wait for Damon to clarify for us. Mean time I looked at dotnet nuget verify
spec. It does have --config
file section. Should we implement according to it? Somehow it doesn't say anything about repository signature verification
.
--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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JonDouglas
Hi. I know it happened very long time ago. Could you be able to check if discrepancy between 2 specs? I couldn't see any other spec contributors from spec file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aortiz-msft
Fyi: Should we ignore --configFile
option? How about NuGet.config file current working directory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kartheekp-ms
Could you able to clarify your comment about #10011? I'm bit confused now. Shouldn't #10011 already be closed or at least P3 priority item based on your above comment since nuget.config file is ignored?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes me think that verify command should not apply all the settings from the NuGet.Config file while verifying package signature.
What are the main concerns here? There should be a way to specify what configuration file is applied & if not, defaulting to the user location given it applies to all operations. If in a directory that contains a solution/project, they are overridden by solution level config settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't find anything in nuget verify command spec, but found a wiki (not sure if it's still up to date though): https://github.com/NuGet/Home/wiki/NuGet-Verify-Command#config-file-for-repository-signature-verification, saying that verify command will take the config file option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kartheekp-ms
Could you able to clarify your comment about #10011? I'm bit confused now. Shouldn't #10011 already be closed or at least P3 priority item based on your above comment since nuget.config file is ignored?
My message in that comment is, the behavior of nuget.exe verify and dotnet nuget verify command should match once we add an option to accept config file. The reason is we try to maintain parity between nuget.exe and dotnet commands. I agree with Nikolche's comment (next to mine in the same issue) because the changes would impact both the commands because the code base is shared.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason is we try to maintain parity between nuget.exe and dotnet commands.
I see people in the NuGet team keep saying this, but the dotnet cli intentionally distanced itself from the older msbuild.exe, including changing defaults to make more sense given the decade(s) that passed since msbuild/nuget.exe was first created. Some examples are most commands changing default verbosity from normal to minimal, and changing from Microsoft/cmd.exe style /arg
arguments to GNU style -a
and --arg
style. So, by design, the dotnet CLI is not 100% compatible with the older tools. A third example is that msbuild.exe does not do an implicit NuGet restore (the -restore
argument), whereas the dotnet CLI does.
I agree with reading nuget.config files, and think it's a bug that nuget.exe verify didn't. But I don't like seeing "make dotnet nuget the same as nuget.exe" used as any justification since I think we can improve customer experience with the newer tool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kartheekp-ms, the current version of that spec is misleading. NuGet 4.6.0 delivered author signing, while NuGet 4.7.0 delivered repository signing. I think that the engineer who worked on repository signing updated the verify
spec, which already supported author signatures, with such single-feature focus that the changes read like the command has a behavioral difference between author- and repository-signed packages. A previous version of the spec doesn't have this problem. Based on this information, I don't see any concern around the verify
command applying settings from the NuGet.Config file incorrectly while verifying package signatures. Do you? The verifier settings are not changing with this PR.
@erdembayar, as part of this work can you please update https://github.com/NuGet/Home/wiki/NuGet-Verify-Command/ to not sound like it works only for repository signatures? As an example,
Config file for repository signature verification should be "Config file for signature verification".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks fine to me.
Sounds like @kartheekp-ms has behavior concern.
I'll be happy to take a look again when that's figured out.
SettingSection trustedSignersSection = verifyArgs.Settings?.GetSection(TrustedSignersSectionName); | ||
List<TrustedSignerItem> trustedSigners = trustedSignersSection?.Items.Select(c => c as TrustedSignerItem).Where(c => c != null).ToList(); | ||
IEnumerable<KeyValuePair<string, HashAlgorithmName>> allowUntrustedRootList = trustedSigners? | ||
.SelectMany(c => c.Certificates) | ||
.Where(c => c.AllowUntrustedRoot) | ||
.Select(c => new KeyValuePair<string, HashAlgorithmName>(c.Fingerprint, c.HashAlgorithm)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be using TrustedSignersProvider.GetAllowListEntries(...)
instead, which will do this for you and get the "owners" that you didn't.
Advice: try to find out how existing code does it before implementing something new.
SettingSection trustedSignersSection = verifyArgs.Settings?.GetSection(TrustedSignersSectionName); | ||
List<TrustedSignerItem> trustedSigners = trustedSignersSection?.Items.Select(c => c as TrustedSignerItem).Where(c => c != null).ToList(); | ||
IEnumerable<KeyValuePair<string, HashAlgorithmName>> allowUntrustedRootList = trustedSigners? | ||
.SelectMany(c => c.Certificates) | ||
.Where(c => c.AllowUntrustedRoot) | ||
.Select(c => new KeyValuePair<string, HashAlgorithmName>(c.Fingerprint, c.HashAlgorithm)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kartheekp-ms, the current version of that spec is misleading. NuGet 4.6.0 delivered author signing, while NuGet 4.7.0 delivered repository signing. I think that the engineer who worked on repository signing updated the verify
spec, which already supported author signatures, with such single-feature focus that the changes read like the command has a behavioral difference between author- and repository-signed packages. A previous version of the spec doesn't have this problem. Based on this information, I don't see any concern around the verify
command applying settings from the NuGet.Config file incorrectly while verifying package signatures. Do you? The verifier settings are not changing with this PR.
@erdembayar, as part of this work can you please update https://github.com/NuGet/Home/wiki/NuGet-Verify-Command/ to not sound like it works only for repository signatures? As an example,
Config file for repository signature verification should be "Config file for signature verification".
828a3da
to
8ec6ad7
Compare
dd6b6dd
to
4baba17
Compare
// trustedSigners section >> allowUntrustedRoot set true are considered here. | ||
verificationProviders.Add(new SignatureTrustAndValidityVerificationProvider(trustedSignerAllowUntrustedRootList)); | ||
|
||
// List of values passed through --certificate-fingerprint option are considered here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For verify action repository signing allow list not considered.
NuGet.Client/src/NuGet.Core/NuGet.Packaging/PackageExtractor.cs
Lines 1019 to 1029 in b8fe2a0
if (repositorySignatureInfo != null && repositorySignatureInfo.RepositoryCertificateInfos != null) | |
{ | |
var repositoryAllowList = RepositorySignatureInfoUtility.GetRepositoryAllowList(repositorySignatureInfo.RepositoryCertificateInfos); | |
verificationProviders.Add(new AllowListVerificationProvider( | |
repositoryAllowList, | |
repositorySignatureInfo.AllRepositorySigned, | |
Strings.Error_NoRepoAllowList, | |
Strings.Error_NoMatchingRepositoryCertificate)); | |
} |
We expect |
4baba17
to
1ebb2df
Compare
1ebb2df
to
328ef60
Compare
@@ -50,6 +50,9 @@ public async Task<int> ExecuteCommandAsync(VerifyArgs verifyArgs) | |||
return packages; | |||
}); | |||
|
|||
var clientPolicyContext = ClientPolicyContext.GetClientPolicy(verifyArgs.Settings, verifyArgs.Logger); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use explicit type instead of var
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, addressed.
// nuget.config >> trustedSigners section read | ||
IReadOnlyList<TrustedSignerAllowListEntry> trustedSignerAllowList = TrustedSignersProvider.GetAllowListEntries(verifyArgs.Settings, verifyArgs.Logger); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, I recommended using TrustedSignersProvider.GetAllowListEntries(...)
directly (instead of ClientPolicyContext.GetClientPolicy(...)
). My reasoning was that ClientPolicyContext.GetClientPolicy(...)
already does 2 things:
- Determine the signature validation mode.
- Fetch the allow list using
TrustedSignersProvider.GetAllowListEntries(...)
.
...and that you only need # 2. However, with your latest changes, we're now setting signature validation mode --- which is fine, provided that we have good test coverage.
Make sure you delete this statement and replace trustedSignerAllowList
with clientPolicyContext.AllowList
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed.
test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/VerifyCommandTests.cs
Outdated
Show resolved
Hide resolved
test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/VerifyCommandTests.cs
Outdated
Show resolved
Hide resolved
test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/VerifyCommandTests.cs
Outdated
Show resolved
Hide resolved
new AllowListVerificationProvider( | ||
trustedSignerAllowList, | ||
requireNonEmptyAllowList: clientPolicyContext.Policy == SignatureValidationMode.Require, | ||
emptyListErrorMessage: Strings.Error_NoClientAllowList, | ||
noMatchErrorMessage: Strings.Error_NoMatchingClientCertificate)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 level of indentation is 4 spaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
List<string> configPaths = settings.GetConfigFilePaths().ToList(); | ||
Assert.True(configPaths.Count > 1); | ||
// Assert user default nuget.config is loaded | ||
Assert.True(configPaths.Contains(baseNugetConfigPath)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put that comment in the code.
@@ -191,5 +192,20 @@ public void AddNetStandardFeeds() | |||
|
|||
Save(); | |||
} | |||
|
|||
// Simply add any text as section into nuget.config file, adding large child node into nuget.config via api is tedious. | |||
public static void AddSectionIntoNuGetConfig(string path, string content, string parentNode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a utility method to simplify/deduplicate code is great. Trying to create a general-purpose utility method with only 1 scenario in use is risky.
Should this method guard against adding a section when a like-named section already exists?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your feedback.
I added guard preventing this scenario, please check now. But I didn't add unit test for asserting it, since we don't have specific file for adding test for test utility
itself. Alternatively, I could add one DotnetVerifyTests.cs, but not sure if it's correct thing to do.
test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetVerifyTests.cs
Outdated
Show resolved
Hide resolved
5a7ee62
to
fad5bb9
Compare
37a01aa
to
f5f0313
Compare
@nkolev92 @dtivel |
Sure, but that makes this PR harder to review as we're dealing double the code. |
test/TestUtilities/Test.Utility/SimpleTestSetup/SimpleTestSettingsContext.cs
Outdated
Show resolved
Hide resolved
NuGet.Commands.PackCollectorLogger.PackCollectorLogger(NuGet.Common.ILogger innerLogger, NuGet.ProjectModel.WarningProperties warningProperties, NuGet.Commands.PackCommand.PackageSpecificWarningProperties packageSpecificWarningProperties) -> void | ||
NuGet.Commands.PackCommand.PackageSpecificWarningProperties | ||
NuGet.Commands.PackCommand.PackageSpecificWarningProperties.PackageSpecificWarningProperties() -> void | ||
static NuGet.Commands.PackCommand.PackageSpecificWarningProperties.CreatePackageSpecificWarningProperties(System.Collections.Generic.IDictionary<string, System.Collections.Generic.HashSet<(NuGet.Common.NuGetLogCode, NuGet.Frameworks.NuGetFramework)>> noWarnProperties) -> NuGet.Commands.PackCommand.PackageSpecificWarningProperties |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The public API changes in your latest commit look accidental. Please confirm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is ok, it happened because I resolved merge conflicts by merging to dev branch instead of rebasing the dev branch (with rebase if file has conflict on early commit, then it is very time consuming to resolve in all subsequent commits same), final compare you wouldn't see it.
[InlineData("true", true)] | ||
[InlineData("true", false)] | ||
[InlineData("false", true)] | ||
[InlineData("false", false)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this implementation https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Boolean.cs#L82, I think we can simply call allowUntrustedRoot.ToString()
wherever we need "true/false" as strings without allocation additional strings.
978f91a
to
c26dade
Compare
Bug
Fixes: NuGet/Home#10774
Fixes: NuGet/Home#10011
Regression? Last working version:
Description
Currently both
nuget verify
anddotnet nuget verify
command ignorenuget.config
file content. So, this makestrustedSigners
section, speciallyallowUntrustedRoot
value ignored for verify command for both default nuget.config and passed nuget.config option. Alsodotnet nuget verify
doesn't even has passnuget.config
option yet.This PR add followings:
dotnet nuget verify
command doesn't ignorenuget.config
file, detect broken/missing tags.allowUntrustedRoot
value into account for certificates with untrusted root fromtrustedSigners
section in nuget.config file (It's default nuget.config or passed nuget.config option)nuget.config
option fordotnet nuget verify
Follow up issue: https://github.com/NuGet/docs.microsoft.com-nuget/issues/2632
PR Checklist
PR has a meaningful title
PR has a linked issue.
Described changes
Tests
Documentation