public async Task <string> GetPackageHashAsync( PackageSource source, PackageIdentity package, string hashAlgorithmId, CancellationToken token) { if (source.Type != PackageSourceType.PackagesContainer) { throw new NotSupportedException($"Only the package source type {PackageSourceType.PackagesContainer} is supported."); } var id = package.Id.ToLowerInvariant(); var version = package.Version.ToNormalizedString().ToLowerInvariant(); var packageUri = new Uri($"{source.Url.TrimEnd('/')}/{id}.{version}.nupkg"); using (var packageStream = await _packageDownloader.DownloadAsync(packageUri, token)) { return(CryptographyService.GenerateHash(packageStream, hashAlgorithmId)); } }
private async Task <bool> TryIndexFromSourceAsync(string id, NuGetVersion version) { var idString = id.ToLowerInvariant(); var versionString = version.ToNormalizedString().ToLowerInvariant(); _logger.LogInformation( "Attempting to index package {Id} {Version} from upstream source...", idString, versionString); try { // See https://github.com/NuGet/NuGet.Client/blob/4eed67e7e159796ae486d2cca406b283e23b6ac8/src/NuGet.Core/NuGet.Protocol/Resources/DownloadResourceV3.cs#L82 var packageUri = new Uri(_packageBaseAddress, $"{idString}/{versionString}/{idString}.{versionString}.nupkg"); // TODO: DownloadAsync throws when the package doesn't exist. This could be cleaner. using (var stream = await _downloader.DownloadAsync(packageUri, CancellationToken.None)) { _logger.LogInformation( "Downloaded package {Id} {Version}, indexing...", idString, versionString); var indexingResult = await _indexer.IndexAsync(stream); switch (indexingResult) { case IndexingResult.InvalidPackage: _logger.LogWarning( "Could not index {Id} {Version} as it is an invalid package", idString, versionString); return(false); case IndexingResult.Success: case IndexingResult.PackageAlreadyExists: _logger.LogInformation( "Successfully indexed {Id} {Version}", idString, versionString); return(true); default: _logger.LogError( "Unknown indexing result for {Id} {Version}: {IndexingResult}", idString, versionString, indexingResult); throw new InvalidOperationException($"Unknown indexing result: {indexingResult}"); } } } catch (Exception e) { _logger.LogError(e, "Failed to index package {Id} {Version}", idString, versionString); return(false); } }
public async Task <Stream> DownloadPackageFileToDiskAsync(Package package) { var packageUri = await GetPackageReadUriAsync(package); return(await _packageDownloader.DownloadAsync(packageUri, CancellationToken.None)); }
private async Task <bool> HandleAsync(SignatureValidationMessage message, CancellationToken cancellationToken) { using (_logger.BeginScope("Handling signature validation message for package {PackageId} {PackageVersion}, validation {ValidationId}", message.PackageId, message.PackageVersion, message.ValidationId)) { // Find the signature validation entity that matches this message. var validation = await _validatorStateService.GetStatusAsync(message.ValidationId); // A signature validation should be queued with ValidatorState == Incomplete. if (validation == null) { _logger.LogInformation( "Could not find validation entity, requeueing (package: {PackageId} {PackageVersion}, validationId: {ValidationId})", message.PackageId, message.PackageVersion, message.ValidationId); // Message may be retried. return(false); } else if (validation.State == ValidationStatus.NotStarted) { _logger.LogWarning( "Unexpected signature verification status '{ValidatorState}' when 'Incomplete' was expected, requeueing (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})", validation.State, message.PackageId, message.PackageVersion, message.ValidationId); // Message may be retried. return(false); } else if (validation.State != ValidationStatus.Incomplete) { _logger.LogWarning( "Terminal signature verification status '{ValidatorState}' when 'Incomplete' was expected, dropping message (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})", validation.State, message.PackageId, message.PackageVersion, message.ValidationId); // Consume the message. return(true); } // Validate package using (var packageStream = await _packageDownloader.DownloadAsync(message.NupkgUri, cancellationToken)) { var result = await _signatureValidator.ValidateAsync( validation.PackageKey, packageStream, message, cancellationToken); validation.State = result.State; // Save any issues if the resulting state is terminal. if (validation.State == ValidationStatus.Failed || validation.State == ValidationStatus.Succeeded) { validation.ValidatorIssues = validation.ValidatorIssues ?? new List <ValidatorIssue>(); foreach (var issue in result.Issues) { validation.ValidatorIssues.Add(new ValidatorIssue { IssueCode = issue.IssueCode, Data = issue.Serialize(), }); } } // Save the .nupkg URL if the resulting state is successful. if (validation.State == ValidationStatus.Succeeded && result.NupkgUri != null) { validation.NupkgUrl = result.NupkgUri.AbsoluteUri; } } // The signature validator should do all of the work to bring this validation to its completion. if (validation.State != ValidationStatus.Succeeded && validation.State != ValidationStatus.Failed) { _logger.LogError("The signature validator should have set the status 'Succeeded' or 'Failed', not " + "'{ValidatorState}' (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})", validation.State, message.PackageId, message.PackageVersion, message.ValidationId); return(false); } // Save the resulting validation status. return(await SaveStatusAsync(validation, message)); } }