public static PackageAnalysisContext Create( ITestOutputHelper output, ManifestMetadata metadata, string[] emptyFiles = null, string signRequest = null) { var disposableDirectory = new DisposableDirectory(); var basePath = disposableDirectory.Path; var nupkgFileName = $"{PackageId}.{metadata.Version}.nupkg"; var nupkgPath = Path.Combine(basePath, nupkgFileName); // set required metadata metadata.Id = metadata.Id ?? "Test"; metadata.Version = metadata.Version ?? new NuGetVersion("1.0.0"); metadata.Authors = metadata.Authors.Any() ? metadata.Authors : new[] { "test" }; metadata.Description = metadata.Description ?? "Description"; // prevent PackageException for packages with no dependencies or content emptyFiles = emptyFiles ?? new[] { "_._" }; var builder = new PackageBuilder(); builder.Populate(metadata); using (var nupkg = File.Create(nupkgPath)) { foreach (var dest in emptyFiles) { var fileName = Path.GetFileName(dest); File.WriteAllText(Path.Combine(basePath, fileName), ""); builder.AddFiles(basePath, fileName, dest); } builder.Save(nupkg); } SignRequestItem packageSignRequest = null; if (signRequest != null) { var reader = new StringReader(signRequest); var signManifest = SignRequestManifestXmlReader.Load(reader, basePath); packageSignRequest = signManifest.First(f => f.Path == nupkgFileName); } var context = new TestPackageAnalysisContext(disposableDirectory) { Logger = new TestLogger(output), PackageFileInfo = new FileInfo(nupkgPath), SignRequest = packageSignRequest, Metadata = builder, }; return(context); }
public IEnumerable <PackageVerifierIssue> Validate(PackageAnalysisContext context) { if (context.SignRequest == null) { context.Logger.Log(LogLevel.Info, "Skipping signing rule request verification for " + context.PackageFileInfo.FullName); yield break; } foreach (var file in context.PackageReader.GetFiles()) { if (!SignRequestItem.IsFileTypeSignable(file)) { continue; } if (!context.SignRequest.Children.Any(f => string.Equals(f.Path, file))) { yield return(PackageIssueFactory.SignRequestMissingPackageFile(context.Metadata.Id, file)); } } }
internal bool Execute(Func <TextWriter> writerFactory) { var signRequestCollection = new SignRequestCollection(); var containers = new Dictionary <string, SignRequestItem>(StringComparer.OrdinalIgnoreCase); var isContainer = new bool[Requests.Length]; for (var i = 0; i < Requests.Length; i++) { var item = Requests[i]; if (bool.TryParse(item.GetMetadata("IsContainer"), out var isc) && isc) { isContainer[i] = true; var itemType = string.IsNullOrEmpty(item.GetMetadata("Type")) ? Path.GetExtension(item.ItemSpec) : item.GetMetadata("Type"); var type = SignRequestItem.GetTypeFromFileExtension(itemType); var normalizedPath = GetRelativePath(BasePath, item.ItemSpec); SignRequestItem container; switch (type) { case SignRequestItemType.Zip: container = SignRequestItem.CreateZip(normalizedPath); break; case SignRequestItemType.Nupkg: container = SignRequestItem.CreateNugetPackage(normalizedPath, item.GetMetadata("Certificate")); break; case SignRequestItemType.Vsix: container = SignRequestItem.CreateVsix(normalizedPath, item.GetMetadata("Certificate")); break; default: Log.LogError( $"Unknown container type for signed file request:'{item.ItemSpec}'. Signing request container must specify the metadata 'Type'."); continue; } containers[item.ItemSpec] = container; if (signRequestCollection.ContainsItemForPath(container.Path)) { Log.LogError( $"Duplicate sign request for {container.ItemType} '{container.Path}'"); continue; } signRequestCollection.Add(container); } } for (var i = 0; i < Requests.Length; i++) { if (isContainer[i]) { continue; } var item = Requests[i]; var normalizedPath = GetRelativePath(BasePath, item.ItemSpec); var containerPath = item.GetMetadata("Container"); if (!string.IsNullOrEmpty(containerPath)) { if (!containers.TryGetValue(containerPath, out var container)) { Log.LogError( $"Signing request item '{item.ItemSpec}' specifies an unknown container '{containerPath}'."); continue; } var itemPath = GetPathWithinContainer(item); if (string.IsNullOrEmpty(itemPath)) { Log.LogError(null, null, null, item.GetMetadata(ProjectFileMetadataName), 0, 0, 0, 0, message: $"Could not identify the path for the signable file {item.ItemSpec}"); continue; } normalizedPath = NormalizePath(itemPath); var file = SignRequestItem.CreateFile(normalizedPath, item.GetMetadata("Certificate"), item.GetMetadata("StrongName")); if (container.ContainsChildPath(file.Path)) { Log.LogError($"Duplicate sign request for file '{file.Path}' inside '{container.Path}'"); continue; } container.AddChild(file); } else { var file = SignRequestItem.CreateFile(normalizedPath, item.GetMetadata("Certificate"), item.GetMetadata("StrongName")); if (signRequestCollection.ContainsItemForPath(file.Path)) { Log.LogError( $"Duplicate sign request for file '{file.Path}'"); continue; } signRequestCollection.Add(file); } } if (Exclusions != null) { foreach (var item in Exclusions) { var normalizedPath = GetRelativePath(BasePath, item.ItemSpec); var containerPath = item.GetMetadata("Container"); if (!string.IsNullOrEmpty(containerPath)) { if (!containers.TryGetValue(containerPath, out var container)) { Log.LogError( $"Exclusion item '{item.ItemSpec}' specifies an unknown container '{containerPath}'."); continue; } var itemPath = GetPathWithinContainer(item); if (string.IsNullOrEmpty(itemPath)) { Log.LogError(null, null, null, item.GetMetadata(ProjectFileMetadataName), 0, 0, 0, 0, message: $"Could not identify the path for signing exclusion {item.ItemSpec}"); continue; } normalizedPath = NormalizePath(itemPath); var file = SignRequestItem.CreateExclusion(normalizedPath); if (container.ContainsChildPath(file.Path)) { // ignore duplicate exclusions continue; } container.AddChild(file); } else { var file = SignRequestItem.CreateExclusion(normalizedPath); if (signRequestCollection.ContainsItemForPath(file.Path)) { // ignore duplicate exclusions continue; } signRequestCollection.Add(file); } } } if (Log.HasLoggedErrors) { return(false); } using (var stream = writerFactory()) using (var writer = new SignRequestManifestXmlWriter(stream)) { writer.Write(signRequestCollection); } Log.LogMessage($"Generated bill of materials in {OutputPath}"); return(!Log.HasLoggedErrors); }