Skip to content

Commit

Permalink
Update verify command (#1825)
Browse files Browse the repository at this point in the history
* Update verify command

Refactored code, added missing verification steps, added more detailed
printing for verbose and debug mode, cleaned up strings

* zip64 should not be supported
  • Loading branch information
PatoBeltran committed Dec 4, 2017
1 parent 51bf722 commit 74b4f8c
Show file tree
Hide file tree
Showing 46 changed files with 1,275 additions and 1,101 deletions.
26 changes: 22 additions & 4 deletions src/NuGet.Clients/NuGet.CommandLine/Commands/VerifyCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NuGet.Commands;
using static NuGet.Commands.VerifyArgs;

namespace NuGet.CommandLine
{
Expand All @@ -29,6 +27,9 @@ protected VerifyCommand() : base()
[Option(typeof(NuGetCommand), "VerifyCommandSignaturesDescription")]
public bool Signatures { get; set; }

[Option(typeof(NuGetCommand), "VerifyCommandAllDescription")]
public bool All { get; set; }

public override Task ExecuteCommandAsync()
{
var PackagePath = Arguments[0];
Expand All @@ -40,7 +41,7 @@ public override Task ExecuteCommandAsync()

var verifyArgs = new VerifyArgs()
{
Type = Signatures ? VerifyArgs.VerificationType.Signatures : VerifyArgs.VerificationType.Unknown,
Verifications = GetVerificationTypes(),
PackagePath = PackagePath,
CertificateFingerprint = CertificateFingerprint,
Logger = Console
Expand All @@ -67,5 +68,22 @@ public override Task ExecuteCommandAsync()
}
return Task.FromResult(result);
}

private IList<Verification> GetVerificationTypes()
{
if (All)
{
return new[] { Verification.All };
}

var verifications = new List<Verification>();

if (Signatures)
{
verifications.Add(Verification.Signatures);
}

return verifications;
}
}
}
11 changes: 10 additions & 1 deletion src/NuGet.Clients/NuGet.CommandLine/NuGetCommand.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/NuGet.Clients/NuGet.CommandLine/NuGetCommand.resx
Original file line number Diff line number Diff line change
Expand Up @@ -5375,7 +5375,7 @@ nuget verify-Signatures .\*.nupkg</value>
<comment>Please don't localize this string</comment>
</data>
<data name="VerifyCommandSignaturesDescription" xml:space="preserve">
<value>Specifies the type of verification to be done. Currently only -Signatures verification is supported.</value>
<value>Specifies that package signature verification should be performed.</value>
</data>
<data name="SignCommandCertificatePasswordDescription" xml:space="preserve">
<value>Password for the certificate, if needed.
Expand Down Expand Up @@ -5467,4 +5467,7 @@ This option should be used when specifying the certificate via -CertificateSubje
<data name="SignCommandNoTimestamperWarning" xml:space="preserve">
<value>No '-Timestamper' option was provided the signed package will not be timestamped. To learn more about this option, please visit https://docs.nuget.org/docs/reference/command-line-reference</value>
</data>
<data name="VerifyCommandAllDescription" xml:space="preserve">
<value>Specifies that all verifications possible should be performed to the package(s).</value>
</data>
</root>
38 changes: 37 additions & 1 deletion src/NuGet.Core/NuGet.Commands/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion src/NuGet.Core/NuGet.Commands/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -662,10 +662,24 @@ Valid from:</comment>
<value>'{0}' is not a valid package file.</value>
</data>
<data name="VerifyCommand_VerificationTypeNotSupported" xml:space="preserve">
<value>Verification type not supported. Please use only one of the following supported types: -Signatures</value>
<value>Verification type not supported. Please use only one of the following supported types: -All, -Signatures</value>
</data>
<data name="SignCommandOutputPath" xml:space="preserve">
<value>Signed package(s) output path: {0}</value>
<comment>0 - output directory path</comment>
</data>
<data name="VerifyCommand_FinishedWithErrors" xml:space="preserve">
<value>Finished with {0} errors and {1} warnings.</value>
<comment>{0} is the number of errors produced and {1} is the number of warnings.</comment>
</data>
<data name="VerifyCommand_Success" xml:space="preserve">
<value>Successfully verified package(s).</value>
</data>
<data name="VerifyCommand_VerifyingPackage" xml:space="preserve">
<value>Verifying {0}</value>
<comment>{0} should be the package identity of the package to verify</comment>
</data>
<data name="VerifyCommand_Failed" xml:space="preserve">
<value>Could not verify package(s) signature.</value>
</data>
</root>
6 changes: 3 additions & 3 deletions src/NuGet.Core/NuGet.Commands/VerifyCommand/VerifyArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ public class VerifyArgs
/// <summary>
/// Available types of verification.
/// </summary>
public enum VerificationType
public enum Verification
{
Unknown,
All,
Signatures
};

/// <summary>
/// Type of verification to be performed.
/// Types of verifications to be performed.
/// </summary>
public VerificationType Type { get; set; }
public IList<Verification> Verifications { get; set; }

/// <summary>
/// Path to the package that has to be signed.
Expand Down
86 changes: 54 additions & 32 deletions src/NuGet.Core/NuGet.Commands/VerifyCommand/VerifyCommandRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using NuGet.Packaging;
using NuGet.Packaging.Signing;
using NuGet.Protocol;
using static NuGet.Commands.VerifyArgs;

namespace NuGet.Commands
{
Expand All @@ -19,64 +20,85 @@ namespace NuGet.Commands
/// </summary>
public class VerifyCommandRunner : IVerifyCommandRunner
{
private const int SuccessCode = 0;
private const int FailureCode = 1;

public async Task<int> ExecuteCommandAsync(VerifyArgs verifyArgs)
{
if (verifyArgs.Type != VerifyArgs.VerificationType.Signatures)
if (verifyArgs.Verifications.Count == 0)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.VerifyCommand_VerificationTypeNotSupported));
verifyArgs.Logger.LogError(string.Format(CultureInfo.CurrentCulture, Strings.VerifyCommand_VerificationTypeNotSupported));
return FailureCode;
}

var packagesToVerify = LocalFolderUtility.ResolvePackageFromPath(verifyArgs.PackagePath);
LocalFolderUtility.EnsurePackageFileExists(verifyArgs.PackagePath, packagesToVerify);

var trustProviders = SignatureVerificationProviderFactory.GetSignatureVerificationProviders();
var verifier = new PackageSignatureVerifier(trustProviders, SignedPackageVerifierSettings.RequireSigned);

var errorCount = 0;

foreach (var package in packagesToVerify)
if (ShouldExecuteVerification(verifyArgs, Verification.Signatures))
{
try
{
errorCount += await VerifyPackageAsync(package, verifyArgs.Logger, verifier);
}
catch (InvalidDataException)
var packagesToVerify = LocalFolderUtility.ResolvePackageFromPath(verifyArgs.PackagePath);
LocalFolderUtility.EnsurePackageFileExists(verifyArgs.PackagePath, packagesToVerify);

var verificationProviders = SignatureVerificationProviderFactory.GetSignatureVerificationProviders();
var verifier = new PackageSignatureVerifier(verificationProviders, SignedPackageVerifierSettings.RequireSigned);


foreach (var package in packagesToVerify)
{
verifyArgs.Logger.LogError(string.Format(CultureInfo.CurrentCulture, Strings.VerifyCommand_PackageIsNotValid, package));
try
{
errorCount += await VerifySignatureForPackageAsync(package, verifyArgs.Logger, verifier);
}
catch (InvalidDataException e)
{
verifyArgs.Logger.LogError(string.Format(CultureInfo.CurrentCulture, Strings.VerifyCommand_PackageIsNotValid, package));
ExceptionUtilities.LogException(e, verifyArgs.Logger);
}
}
}

return (errorCount > 0) ? 1 : 0;
return errorCount == 0 ? SuccessCode : FailureCode;
}

private async Task<int> VerifyPackageAsync(string packagePath, ILogger logger, PackageSignatureVerifier verifier)
private async Task<int> VerifySignatureForPackageAsync(string packagePath, ILogger logger, PackageSignatureVerifier verifier)
{
var result = 0;
using (var packageReader = new PackageArchiveReader(packagePath))
{
var verificationResult = await verifier.VerifySignaturesAsync(packageReader, logger, CancellationToken.None);
var verificationResult = await verifier.VerifySignaturesAsync(packageReader, CancellationToken.None);

if (verificationResult.Valid)
{
logger.LogInformation("Successfully verified package integrity and author signature.");
}
else
var packageIdentity = packageReader.GetIdentity();

logger.LogInformation(Environment.NewLine + string.Format(CultureInfo.CurrentCulture,
Strings.VerifyCommand_VerifyingPackage,
packageIdentity.ToString()));
logger.LogInformation($"{packagePath}{Environment.NewLine}");

var logMessages = verificationResult.Results.SelectMany(p => p.Issues).Select(p => p.ToLogMessage()).ToList();
await logger.LogMessagesAsync(logMessages);

if (logMessages.Any(m => m.Level >= LogLevel.Warning))
{
var logMessages = verificationResult.Results.SelectMany(p => p.Issues).Select(p => p.ToLogMessage()).ToList();
await logger.LogMessagesAsync(logMessages);
if (logMessages.Any(m => m.Level >= LogLevel.Warning))
{
var errors = logMessages.Where(m => m.Level == LogLevel.Error).Count();
var warnings = logMessages.Where(m => m.Level == LogLevel.Warning).Count();
var errors = logMessages.Count(m => m.Level == LogLevel.Error);
var warnings = logMessages.Count(m => m.Level == LogLevel.Warning);

logger.LogInformation($"Finished with {errors} errors and {warnings} warnings.");
logger.LogInformation(string.Format(CultureInfo.CurrentCulture, Strings.VerifyCommand_FinishedWithErrors, errors, warnings));
logger.LogError(Environment.NewLine + Strings.VerifyCommand_Failed);

result = errors;
}
result = errors;
}

if (verificationResult.Valid)
{
logger.LogInformation(Environment.NewLine + Strings.VerifyCommand_Success);
}

return result;
}
}

private bool ShouldExecuteVerification(VerifyArgs args, Verification v)
{
return args.Verifications.Any(verification => verification == Verification.All || verification == v);
}
}
}
2 changes: 1 addition & 1 deletion src/NuGet.Core/NuGet.Common/ExceptionUtilities.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
Expand Down
5 changes: 4 additions & 1 deletion src/NuGet.Core/NuGet.Packaging/PackageArchiveReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,10 @@ public override async Task ValidateIntegrityAsync(SignatureManifest signatureMan
{
var hashAlgorithm = signatureManifest.HashAlgorithm.GetHashProvider();
var expectedHash = Convert.FromBase64String(signatureManifest.HashValue);
SignedPackageArchiveUtility.VerifySignedZipIntegrity(reader, hashAlgorithm, expectedHash);
if (!SignedPackageArchiveUtility.VerifySignedZipIntegrity(reader, hashAlgorithm, expectedHash))
{
throw new SignatureException(Strings.SignaturePackageIntegrityFailure, GetIdentity());
}
}
#endif
}
Expand Down
1 change: 0 additions & 1 deletion src/NuGet.Core/NuGet.Packaging/PackageExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,6 @@ public static class PackageExtractor
{
var verifyResult = await packageExtractionContext.SignedPackageVerifier.VerifySignaturesAsync(
signedPackageReader,
packageExtractionContext.Logger,
token);

if (!verifyResult.Valid)
Expand Down
Loading

0 comments on commit 74b4f8c

Please sign in to comment.