public void GivenTwoPartialSigningInfosWithEmptySections()
        {
            SigningInformation actualMerged = pushMetadata.MergeSigningInfo(new List <SigningInformation> {
                PartialSigningInfo3, PartialSigningInfo4
            });

            actualMerged.Should().BeEquivalentTo(MergedPartialMetadataSigningInfos);
        }
Пример #2
0
        /// <summary>
        /// Method that creates a temporary pdf for calating the hash that must be sent to AMA for signing
        /// </summary>
        /// <param name="signingInformation">Information about the signature and its appearance</param>
        /// <returns>Information with the hashes required for signing and completing the retrieved signature injection</returns>
        public HashesForSigning CreateTemporaryPdfForSigning(SigningInformation signingInformation)
        {
            var pdfSigner = new PdfSigner(new PdfReader(signingInformation.PathToPdf),
                                          new FileStream(signingInformation.PathToIntermediaryPdf, FileMode.Create),
                                          new StampingProperties());

            pdfSigner.SetFieldName(_signatureFieldname);


            var appearance = pdfSigner.GetSignatureAppearance();

            appearance.SetPageRect(new Rectangle(10,
                                                 750,
                                                 150,
                                                 50))
            .SetPageNumber(signingInformation.PageNumber)
            .SetLayer2FontSize(6f)
            .SetReason(signingInformation.Reason)
            .SetLocation(signingInformation.Location)
            .SetLayer2Text(BuildVisibleInformation(signingInformation.Reason, signingInformation.Location))
            .SetCertificate(_userCertificateChain[0]);

            if (signingInformation.Logo != null)
            {
                appearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION)
                .SetSignatureGraphic(signingInformation.Logo);
            }


            var crlBytesList = GetCrlByteList();

            var ocspBytesList = GetOcspBytesList();


            var container = new PrefareForAmaSigningContainer(_userCertificateChain, crlBytesList, ocspBytesList);

            pdfSigner.SignExternalContainer(container, EstimateContainerSize(crlBytesList)); // add size for timestamp in signature

            return(new HashesForSigning(container.HashToBeSignedByAma, container.NakedHash));
        }
        public async Task <bool> PushMetadataAsync(CancellationToken cancellationToken)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                Log.LogMessage(MessageImportance.High, "Starting build metadata push to the Build Asset Registry...");

                if (!Directory.Exists(ManifestsPath))
                {
                    Log.LogError($"Required folder '{ManifestsPath}' does not exist.");
                }
                else
                {
                    //get the list of manifests
                    List <Manifest> parsedManifests = GetParsedManifests(ManifestsPath, cancellationToken);

                    if (parsedManifests.Count == 0)
                    {
                        Log.LogError(
                            $"No manifests found matching the search pattern {SearchPattern} in {ManifestsPath}");
                        return(!Log.HasLoggedErrors);
                    }

                    Manifest manifest;
                    //check if the manifest have any duplicate packages and blobs
                    if (parsedManifests.Count > 1)
                    {
                        manifest = MergeManifests(parsedManifests);
                    }
                    else
                    {
                        manifest = parsedManifests[0];
                    }

                    List <SigningInformation> signingInformation = new List <SigningInformation>();
                    foreach (var m in parsedManifests)
                    {
                        if (m.SigningInformation != null)
                        {
                            signingInformation.Add(m.SigningInformation);
                        }
                    }

                    //get packages blobs and signing info
                    (List <PackageArtifactModel> packages,
                     List <BlobArtifactModel> blobs) = GetPackagesAndBlobsInfo(manifest);

                    //create merged buildModel to create the merged manifest
                    BuildModel modelForManifest =
                        CreateMergedManifestBuildModel(packages, blobs, manifest);


                    //add manifest as an asset to the buildModel
                    var mergedManifestAsset = GetManifestAsAsset(blobs, MergedManifestFileName);
                    modelForManifest.Artifacts.Blobs.Add(mergedManifestAsset);

                    SigningInformation finalSigningInfo = MergeSigningInfo(signingInformation);

                    // push the merged manifest, this is required for only publishingVersion 3 and above
                    if (manifest.PublishingVersion >= 3)
                    {
                        PushMergedManifest(modelForManifest, finalSigningInfo);
                    }

                    // populate buildData and assetData using merged manifest data
                    BuildData buildData = GetMaestroBuildDataFromMergedManifest(modelForManifest, manifest, cancellationToken);

                    IMaestroApi client = ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken);

                    var deps = await GetBuildDependenciesAsync(client, cancellationToken);

                    Log.LogMessage(MessageImportance.High, "Calculated Dependencies:");
                    foreach (var dep in deps)
                    {
                        Log.LogMessage(MessageImportance.High, $"    {dep.BuildId}, IsProduct: {dep.IsProduct}");
                    }

                    buildData.Dependencies = deps;
                    LookupForMatchingGitHubRepository(manifest);
                    buildData.GitHubBranch     = GitHubBranch;
                    buildData.GitHubRepository = GitHubRepository;

                    Client.Models.Build recordedBuild = await client.Builds.CreateAsync(buildData, cancellationToken);

                    BuildId = recordedBuild.Id;

                    Log.LogMessage(MessageImportance.High,
                                   $"Metadata has been pushed. Build id in the Build Asset Registry is '{recordedBuild.Id}'");
                    Console.WriteLine($"##vso[build.addbuildtag]BAR ID - {recordedBuild.Id}");

                    // Only 'create' the AzDO (VSO) variables if running in an AzDO build
                    if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("BUILD_BUILDID")))
                    {
                        IEnumerable <DefaultChannel> defaultChannels =
                            await GetBuildDefaultChannelsAsync(client, recordedBuild);

                        HashSet <int> targetChannelIds = new HashSet <int>(defaultChannels.Select(dc => dc.Channel.Id));

                        var defaultChannelsStr = "[" + string.Join("][", targetChannelIds) + "]";
                        Log.LogMessage(MessageImportance.High,
                                       $"Determined build will be added to the following channels: {defaultChannelsStr}");

                        Console.WriteLine($"##vso[task.setvariable variable=BARBuildId]{recordedBuild.Id}");
                        Console.WriteLine($"##vso[task.setvariable variable=DefaultChannels]{defaultChannelsStr}");
                        Console.WriteLine($"##vso[task.setvariable variable=IsStableBuild]{IsStableBuild}");
                    }
                }
            }
            catch (Exception exc)
            {
                Log.LogErrorFromException(exc, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
        public async Task <bool> PushMetadataAsync(CancellationToken cancellationToken)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                Log.LogMessage(MessageImportance.High, "Starting build metadata push to the Build Asset Registry...");

                if (!Directory.Exists(ManifestsPath))
                {
                    Log.LogError($"Required folder '{ManifestsPath}' does not exist.");
                }
                else
                {
                    (List <BuildData> buildsManifestMetadata,
                     List <SigningInformation> signingInformation,
                     ManifestBuildData manifestBuildData) = GetBuildManifestsMetadata(ManifestsPath, cancellationToken);

                    if (buildsManifestMetadata.Count == 0)
                    {
                        Log.LogError($"No build manifests found matching the search pattern {SearchPattern} in {ManifestsPath}");
                        return(!Log.HasLoggedErrors);
                    }

                    BuildData   finalBuild = MergeBuildManifests(buildsManifestMetadata);
                    IMaestroApi client     = ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken);

                    var deps = await GetBuildDependenciesAsync(client, cancellationToken);

                    Log.LogMessage(MessageImportance.High, "Calculated Dependencies:");
                    foreach (var dep in deps)
                    {
                        Log.LogMessage(MessageImportance.High, $"    {dep.BuildId}, IsProduct: {dep.IsProduct}");
                    }
                    finalBuild.Dependencies = deps;

                    // Based on the in-memory merged manifest, create a physical XML file and
                    // upload it to the BlobArtifacts folder only when publishingVersion >= 3
                    if (manifestBuildData.PublishingVersion >= 3)
                    {
                        SigningInformation finalSigningInfo = MergeSigningInfo(signingInformation);

                        // Inject an entry of MergedManifest.xml to the in-memory merged manifest
                        string    location  = null;
                        AssetData assetData = finalBuild.Assets.FirstOrDefault();

                        if (assetData != null)
                        {
                            AssetLocationData assetLocationData = assetData.Locations.FirstOrDefault();

                            if (assetLocationData != null)
                            {
                                location = assetLocationData.Location;
                            }
                        }

                        finalBuild.Assets = finalBuild.Assets.Add(GetManifestAsAsset(finalBuild.Assets, location, MergedManifestFileName));

                        BuildModel modelForManifest = CreateMergedManifestBuildModel(finalBuild.Assets, manifestBuildData);
                        PushMergedManifest(modelForManifest, finalSigningInfo);
                    }

                    Client.Models.Build recordedBuild = await client.Builds.CreateAsync(finalBuild, cancellationToken);

                    BuildId = recordedBuild.Id;

                    Log.LogMessage(MessageImportance.High, $"Metadata has been pushed. Build id in the Build Asset Registry is '{recordedBuild.Id}'");
                    Console.WriteLine($"##vso[build.addbuildtag]BAR ID - {recordedBuild.Id}");

                    // Only 'create' the AzDO (VSO) variables if running in an AzDO build
                    if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("BUILD_BUILDID")))
                    {
                        IEnumerable <DefaultChannel> defaultChannels = await GetBuildDefaultChannelsAsync(client, recordedBuild);

                        HashSet <int> targetChannelIds = new HashSet <int>(defaultChannels.Select(dc => dc.Channel.Id));

                        var defaultChannelsStr = "[" + string.Join("][", targetChannelIds) + "]";
                        Log.LogMessage(MessageImportance.High, $"Determined build will be added to the following channels: { defaultChannelsStr}");

                        Console.WriteLine($"##vso[task.setvariable variable=BARBuildId]{recordedBuild.Id}");
                        Console.WriteLine($"##vso[task.setvariable variable=DefaultChannels]{defaultChannelsStr}");
                        Console.WriteLine($"##vso[task.setvariable variable=IsStableBuild]{IsStableBuild}");
                    }
                }
            }
            catch (Exception exc)
            {
                Log.LogErrorFromException(exc, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
        public static XElement SigningInfoToXml(SigningInformation signingInformation)
        {
            if (signingInformation == null)
            {
                return(null);
            }

            List <XElement> signingMetadata = new List <XElement>();

            foreach (FileExtensionSignInfo fileExtensionSignInfo in signingInformation.FileExtensionSignInfos)
            {
                signingMetadata.Add(new XElement(
                                        nameof(FileExtensionSignInfo),
                                        new XAttribute[]
                {
                    new XAttribute(nameof(fileExtensionSignInfo.Include), fileExtensionSignInfo.Include),
                    new XAttribute(nameof(fileExtensionSignInfo.CertificateName), fileExtensionSignInfo.CertificateName)
                }));
            }

            foreach (FileSignInfo fileSignInfo in signingInformation.FileSignInfos)
            {
                List <XAttribute> xAttributes = new List <XAttribute>()
                {
                    new XAttribute(nameof(fileSignInfo.Include), fileSignInfo.Include),
                    new XAttribute(nameof(fileSignInfo.CertificateName), fileSignInfo.CertificateName)
                };

                if (!string.IsNullOrEmpty(fileSignInfo.PublicKeyToken))
                {
                    xAttributes.Add(new XAttribute(nameof(fileSignInfo.PublicKeyToken), fileSignInfo.PublicKeyToken));
                }
                if (!string.IsNullOrEmpty(fileSignInfo.TargetFramework))
                {
                    xAttributes.Add(new XAttribute(nameof(fileSignInfo.TargetFramework), fileSignInfo.TargetFramework));
                }
                signingMetadata.Add(new XElement(nameof(FileSignInfo), xAttributes.ToArray()));
            }

            foreach (CertificatesSignInfo certificatesSignInfo in signingInformation.CertificatesSignInfo)
            {
                signingMetadata.Add(new XElement(
                                        nameof(CertificatesSignInfo),
                                        new XAttribute[]
                {
                    new XAttribute(nameof(certificatesSignInfo.Include), certificatesSignInfo.Include),
                    new XAttribute(nameof(certificatesSignInfo.DualSigningAllowed), certificatesSignInfo.DualSigningAllowed)
                }));
            }

            foreach (ItemsToSign itemsToSign in signingInformation.ItemsToSign)
            {
                signingMetadata.Add(new XElement(
                                        nameof(ItemsToSign),
                                        new XAttribute[]
                {
                    new XAttribute(nameof(itemsToSign.Include), itemsToSign.Include)
                }));
            }

            foreach (StrongNameSignInfo strongNameSignInfo in signingInformation.StrongNameSignInfos)
            {
                signingMetadata.Add(new XElement(
                                        nameof(StrongNameSignInfo),
                                        new XAttribute[]
                {
                    new XAttribute(nameof(strongNameSignInfo.Include), strongNameSignInfo.Include),
                    new XAttribute(nameof(strongNameSignInfo.PublicKeyToken), strongNameSignInfo.PublicKeyToken),
                    new XAttribute(nameof(strongNameSignInfo.CertificateName), strongNameSignInfo.CertificateName)
                }));
            }
            return(new XElement(nameof(SigningInformation), signingMetadata));
        }
        public void GivenEmptySigningInfoList()
        {
            SigningInformation actualMerged = pushMetadata.MergeSigningInfo(new List <SigningInformation>());

            actualMerged.Should().Be(null);
        }
        public void GivenDuplicateSigningInfo()
        {
            SigningInformation actualMerged = pushMetadata.MergeSigningInfo(ExpectedSigningInfo.Concat(ExpectedSigningInfo).ToList());

            actualMerged.Should().BeEquivalentTo(ExpectedSigningInfo.First());
        }
Пример #8
0
        private SigningInformation GetTestInfo()
        {
            SigningInformation signingInfo = new SigningInformation()
            {
                CertificatesSignInfo = new List <CertificatesSignInfo>()
                {
                    new CertificatesSignInfo()
                    {
                        DualSigningAllowed = true,
                        Include            = Certificate1Name,
                    },
                    new CertificatesSignInfo()
                    {
                        DualSigningAllowed = false,
                        Include            = Certificate2Name,
                    },
                },
                FileExtensionSignInfos = new List <FileExtensionSignInfo>()
                {
                    new FileExtensionSignInfo()
                    {
                        CertificateName = Certificate1Name,
                        Include         = ".dll",
                    },
                    new FileExtensionSignInfo()
                    {
                        CertificateName = Certificate2Name,
                        Include         = ".xbap",
                    }
                },
                FileSignInfos = new List <FileSignInfo>()
                {
                    new FileSignInfo()
                    {
                        CertificateName = Certificate1Name,
                        Include         = "SomeAssembly.dll",
                        PublicKeyToken  = PublicKeyToken1,
                        TargetFramework = TargetFramework1
                    },
                    new FileSignInfo()
                    {
                        CertificateName = Certificate2Name,
                        Include         = "SomeAssembly.dll",
                        PublicKeyToken  = PublicKeyToken1,
                        TargetFramework = TargetFramework2
                    },
                    new FileSignInfo()
                    {
                        CertificateName = Certificate2Name,
                        Include         = "SomeOtherAssembly.dll",
                    },
                },
                ItemsToSign = new List <ItemsToSign>()
                {
                    new ItemsToSign()
                    {
                        Include = "SomeAssembly.dll"
                    },
                    new ItemsToSign()
                    {
                        Include = "SomeOtherAssembly.dll"
                    },
                },
                StrongNameSignInfos = new List <StrongNameSignInfo>()
                {
                    new StrongNameSignInfo()
                    {
                        CertificateName = Certificate1Name,
                        Include         = "StrongName1",
                        PublicKeyToken  = PublicKeyToken1
                    },
                    new StrongNameSignInfo()
                    {
                        CertificateName = Certificate2Name,
                        Include         = "StrongName2",
                        PublicKeyToken  = PublicKeyToken2
                    }
                }
            };

            return(signingInfo);
        }