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

Enable cross-platform package signature verification for restore #3458

Merged
merged 31 commits into from
Jun 20, 2020

Conversation

heng-liu
Copy link
Contributor

Bug

Fixes: NuGet/Home#9004
Regression: No

  • Last working version:
  • How are we preventing it in future:

Fix

Details:
1.Target NuGet.Packaging and projects depend on it to net5.0
2.Enable/implement cross-platform(net5.0 code path) package signing APIs (used in verification tests)
3.Enable/Implement cross-platform(net5.0 code path) package verification APIs.
4.Enable/fix related tests.

Testing/Validation

Tests Added: Yes
Reason for not adding tests:
Validation:

Copy link
Member

@zivkan zivkan left a comment

Choose a reason for hiding this comment

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

There's a breaking API change that concerns me, otherwise it's just little things which could be improved in other PRs.

Comment on lines +19 to +20
<SigningNotSupported Condition=" '$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'netcoreapp2.1' OR '$(TargetFramework)' == 'netstandard2.1' OR '$(TargetFramework)' == 'netcoreapp3.1'">true</SigningNotSupported>
<SigningNotSupported Condition=" '$(SigningNotSupported)' != 'true'">false</SigningNotSupported>
Copy link
Member

Choose a reason for hiding this comment

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

Can be done in another PR, but we should avoid nous with negative names, particularly when they represent a boolean type, as the double negative when the value is false can be confusing.

Also comparing against a list of TFMs is hard to read and maintain. We can use a condition something like '$(TargetFrameworkIdentifier)' == '.NETFramework' or ( '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and [MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '5.0') )

Finally, this SigningNotSupported property appears to be used only to change the DefineConstants property below. Just use the condition on DefineConstant's PropertyGroup. We don't need SigningNotSupported.

Copy link
Member

Choose a reason for hiding this comment

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

We should create a follow up to clean it up.

Copy link
Contributor Author

@heng-liu heng-liu Aug 10, 2020

Choose a reason for hiding this comment

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

I tried the following, but the build failed, as TargetFrameworkIdentifier and TargetFrameworkVersion are empty.

<PropertyGroup Condition=" '$(IsDesktop)' == 'true' or ( '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '5.0')) ) ">
<DefineConstants>$(DefineConstants);IS_SIGNING_SUPPORTED</DefineConstants>
</PropertyGroup>

I then tested two projects with TargetFrameworks and TargetFramework, looks like the later one got TargetFrameworkIdentifier and TargetFrameworkVersion correctly, the former one didn't.

{
internal interface IRfc3161TimestampTokenInfo
{
#if IS_SIGNING_SUPPORTED
Copy link
Member

Choose a reason for hiding this comment

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

very minor considering the type is internal, but why not put the #if outside the interface definition, so the interface only exists on TFMs that support signing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Will fix in #3571

Comment on lines +6 to +9
#if IS_SIGNING_SUPPORTED && IS_CORECLR
using System.Net.Http;
using System.Net.Http.Headers;
#endif
Copy link
Member

Choose a reason for hiding this comment

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

The class defined in this function is wrapped in the same #if #endif block. Why are only these using statements excluded when the entire class hidden? Just have a single #if on line 3/4.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Will fix in #3571

<TestProject>true</TestProject>
<Description>Integration tests for NuGet-powered dotnet CLI commands such as pack/restore/list package and dotnet nuget.</Description>
</PropertyGroup>

Copy link
Member

@zivkan zivkan Jun 17, 2020

Choose a reason for hiding this comment

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

nitpick: trailing whitespace goes against coding guideline 23, and our .editorconfig file also instructs compatible editors to remove trailing whitespace, meaning someone is using an editor that does not respect .editorconfig.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Will fix in #3571

<TargetFrameworksLibrary>$(NETFXTargetFramework);$(NetStandardVersion)</TargetFrameworksLibrary>
<TargetFrameworksExe>$(NETFXTargetFramework);$(NETCoreTargetFrameworks)</TargetFrameworksExe>
<TargetFrameworksLibrary Condition=" '$(RequiresSigningXplatAPIs)' != 'true' ">$(NETFXTargetFramework);$(NetStandardVersion)</TargetFrameworksLibrary>
<TargetFrameworksLibrary Condition=" '$(RequiresSigningXplatAPIs)' == 'true' ">$(NETFXTargetFramework);$(NetStandardVersion);netcoreapp5.0</TargetFrameworksLibrary>
Copy link
Member

Choose a reason for hiding this comment

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

I think I've talked to you about when I worked on the dotnet.integration.tests multi-tfm testing: I'm not a fan of defining RequiresSigningXplatAPIs in the project, importing this props file, then using TargetFrameworksLibrary in the csproj's TargetFrameworks element.

In my opnion, either:

  • set properties in the project, import this file, and this file sets the TargetFrameworks

or

  • import this file, which defines a bunch of different properties, and the project file uses the one it likes in its own definition of TargetFrameworks.

I prefer the second option, which is how NuGet.Client worked before the dev-feature-xplatVerification branch, but this current approach where some of the TFM logic is in the project file and other TFM logic is in the common project props file, it makes it harder to understand.

However, it's something we can fix after this branch is merged into dev.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Will fix in #3571

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.

A few nits.

It looks great beyond that.

A product of lots of work over the last year.

Great job @heng-liu , @zkat & @kartheekp-ms.

Some kudos go to @zivkan too I guess.

Comment on lines +19 to +20
<SigningNotSupported Condition=" '$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'netcoreapp2.1' OR '$(TargetFramework)' == 'netstandard2.1' OR '$(TargetFramework)' == 'netcoreapp3.1'">true</SigningNotSupported>
<SigningNotSupported Condition=" '$(SigningNotSupported)' != 'true'">false</SigningNotSupported>
Copy link
Member

Choose a reason for hiding this comment

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

We should create a follow up to clean it up.

@@ -7,7 +11,7 @@
<TargetFrameworks>$(TargetFrameworksLibrary)</TargetFrameworks>
<TargetFramework />
<NoWarn>$(NoWarn);CS1591;CS1574;CS1573;CS1584;CS1658</NoWarn>
<NoWarn Condition="'$(TargetFramework)' == '$(NetStandardVersion)'">$(NoWarn);CS1998</NoWarn>
<NoWarn Condition=" $(TargetFramework.StartsWith('netstandard')) OR $(TargetFramework.StartsWith('netcoreapp')) ">$(NoWarn);CS1998</NoWarn>
Copy link
Member

Choose a reason for hiding this comment

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

Does IsCore not work here?

Copy link
Contributor Author

@heng-liu heng-liu Aug 7, 2020

Choose a reason for hiding this comment

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

IsCore doesn't work.
Properties are evaluated in the order in which they appear in the project file.
The assignment of property IsCore is in common.targets.
And the NuGet.commands.csproj imports the common.targets at the end, that's after the NoWarn.

Copy link
Member

Choose a reason for hiding this comment

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

We can probably move IsCore to common.props...I can look into that clean-up.

namespace NuGet.Packaging.Signing
{
#if IS_SIGNING_SUPPORTED && IS_CORECLR
internal sealed class Rfc3161TimestampTokenInfoNetstandard21Wrapper : IRfc3161TimestampTokenInfo
Copy link
Member

Choose a reason for hiding this comment

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

Do we need this? We are only using net5 aren't we?

Copy link
Member

Choose a reason for hiding this comment

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

Or maybe we do need and should name it so something better :)

Versions change :)
Future Pr would be ok.

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 think the logic of #if IS_SIGNING_SUPPORTED && IS_CORECLR is more clear than #if NET5_0.
We can tell the first one, is related to signing, and when it's the netcore code path.
The second one may be related to signing, or may be related to net5.0 API change unrelated to signing.

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.

I'd wait for @zivkan's sign off before merging (well that and a green build)

@heng-liu
Copy link
Contributor Author

A few nits.

It looks great beyond that.

A product of lots of work over the last year.

Great job @heng-liu , @zkat & @kartheekp-ms.

Some kudos go to @zivkan too I guess.

Yes, @zivkan helps a lot :)
And we also would like to thank for @dtivel
You and @rrelyea also helped a lot when targeting to netstandard2.1 ;)

<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'README.md'))\build\common.test.props" />
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

<PropertyGroup>
<TargetFrameworks>$(TargetFrameworksExe)</TargetFrameworks>
<TargetFrameworks Condition=" '$(IsXPlat)' == 'true' ">$(NETCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition=" '$(IsXPlat)' == 'true' ">$(NETCoreTargetFrameworks)</TargetFrameworks>
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need to test for 2 different frameworks in a project like NuGet.Frameworks.

There is no signing code in here.

Same probably apllies to a bunch of the other projects.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Will fix in #3571

<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'README.md'))\build\common.test.props" />
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

<PropertyGroup>
<TargetFrameworks>$(TargetFrameworksExe)</TargetFrameworks>
<TargetFrameworks Condition=" '$(IsXPlat)' == 'true' ">$(NETCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition=" '$(IsXPlat)' == 'true' ">$(NETCoreTargetFrameworks)</TargetFrameworks>
Copy link
Member

Choose a reason for hiding this comment

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

Likely requiresSigningXplatAPIs is not needed here either.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Will fix in #3571

heng-liu and others added 14 commits June 19, 2020 12:45
Remove 2nd N.B.T.P package (#2984)

remove WorkaroundNetStandard target, change SDK for build from 3.0 preview to 3.1 stable (#3161)

* remove WorkaroundNetStandard target, change SDK for build from 3.0 preview to 3.1 stable version, fix error; change LockSDKVersion default value from empty string to false; apply Linux workaround in my change

Retarget to netcore5.0 (#3162)

* retarget to netcore5.0;  Linux script workaround need to apply for downloading SDK for build

add pkcs and cng packages

Temporary fix on patching SDK, add System.Security.Cryptography.Pkcs.dll and update deps.json, use dll from .nuget/packages

Address PR comments

implement add cert to store on Mac; display openssl version (#3166)

Implement timestamp integrity verification; Implement an equivalent NativeCms; enable signing APIs and tests (#3168)

* implement timestamp integrity verification; implement ManagedCms; enable signing APIs and tests

fix xplat verification branch after rebase (#3191)

Fixes: NuGet/Home#9012

check different cross-platform error messages for self-signed cert test (#3208)

Fixes: NuGet/Home#8933

Xplat Signing/Verification : Fix broken tests for setting privatekey of a X509Certificate2 (#3195)

use workaround to set private key for X509Certificate2 (netcore), change ToRSA to workaround for netcore(especially for non-windows)

enable PathTooLongException test (#3216)

Fixes: NuGet/Home#8920

enable TrustedSignerActionsProvider on netcore, along with tests (#3213)

Fixes: NuGet/Home#8921

Enable SignedPackageIntegrityVerificationTests for netcore5.0 (#3220)

Enable SignedPackageIntegrityVerificationTests for netcore, remove extra preprocessors

Enable timestamp provider test and fix 3 broken tests (#3210)

enable all unit tests; enable 8 more tests; enable timestampProviderTest; fix 3 broken tests in TimestampProviderTests

Fix 4 tests in SignatureTrustAndValidityVerificationProviderTests (#3242)

fix untrusted msg for different platforms

fixed broken tests using utility methods (#3263)

disable outdated tests (#3274)

enable 4 tests on Mac (#3275)

fix 5 broken tests in SignatureTrustAndValidityVerificationProviderTests, add workaround for Linux (#3252)

fix broken test case ExecuteCommandAsync_WithAmbiguousMatch_ThrowsAsync (#3291)
…cate_RaisesErrorsOnceAsync (#3342)

* enable a test, change the comments; extend test limitation on Linux
* fix 2 warnings in CodeAnalysis
* fix string warnings raised by CodeAnalysis
* retarget netcoreapp5.0 (a workaround for net5.0)
* add TFM netcoreapp5.0 to N.B.T.Console and N.P.Core projects
@heng-liu heng-liu force-pushed the dev-feature-xplatVerification branch from 5f89ade to 97f4b70 Compare June 19, 2020 19:46
Copy link
Member

@zivkan zivkan left a comment

Choose a reason for hiding this comment

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

There are several things I would love to have cleaned up, but we can do that after this is merged in dev.

@heng-liu
Copy link
Contributor Author

Thanks.
Yes, there're some comments I haven't addressed. Will do that after this merged in dev.

@aortiz-msft aortiz-msft merged commit 784274c into dev Jun 20, 2020
@aortiz-msft aortiz-msft deleted the dev-feature-xplatVerification branch June 20, 2020 19:23
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.

XPlat Signing: Enable signature verification for restore in dotnet.exe
6 participants