예제 #1
0
        /// <inheritdoc/>
        public async Task ValidateSubscription(int subscriptionId)
        {
            try
            {
                string endpointUrl = "subscriptions/validate/" + subscriptionId;

                string certBase64 = await _keyVaultService.GetCertificateAsync(_keyVaultSettings.KeyVaultURI, _keyVaultSettings.PlatformCertSecretId);

                string accessToken = _accessTokenGenerator.GenerateAccessToken(
                    "platform",
                    "events",
                    new X509Certificate2(Convert.FromBase64String(certBase64), (string)null, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable));

                HttpResponseMessage response = await _client.PutAsync(endpointUrl, null, accessToken);

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    _logger.LogError($"// Validate subscription with id {subscriptionId} failed with statuscode {response.StatusCode}");
                    throw new Exception($"// Validate subscription with id {subscriptionId} failed with statuscode {response.StatusCode}");
                }
            }
            catch (Exception e)
            {
                _logger.LogError(e, $"// Validate subscription with id {subscriptionId} failed with errormessage {e.Message}");
                throw e;
            }
        }
        public async Task Submit(HashMode hashMode, string name, string description, string descriptionUrl, IList <string> files, string filter)
        {
            logger.LogInformation("Editing AppInstaller job {0} with {1} files", name, files.Count());

            var cert = await keyVaultService.GetCertificateAsync().ConfigureAwait(false);

            var publisher = cert.SubjectName.Name;

            // We need to open the files, and update the publisher value
            foreach (var file in files)
            {
                XDocument manifest;
                using (var fs = File.OpenRead(file))
                {
                    manifest = XDocument.Load(fs, LoadOptions.PreserveWhitespace);
                    XNamespace ns = "http://schemas.microsoft.com/appx/appinstaller/2017/2";

                    var idElement = manifest.Root?.Element(ns + "MainBundle");
                    idElement?.SetAttributeValue("Publisher", publisher);
                }

                using (var fs = File.Create(file))
                {
                    manifest.Save(fs);
                }
            }
        }
예제 #3
0
        /// <inheritdoc/>
        public async Task SendToPushController(CloudEvent item)
        {
            StringContent httpContent = new StringContent(JsonSerializer.Serialize(item), Encoding.UTF8, "application/json");

            try
            {
                string endpointUrl = "push";

                string certBase64 = await _keyVaultService.GetCertificateAsync(_keyVaultSettings.KeyVaultURI, _keyVaultSettings.PlatformCertSecretId);

                string accessToken = _accessTokenGenerator.GenerateAccessToken(
                    "platform",
                    "events",
                    new X509Certificate2(Convert.FromBase64String(certBase64), (string)null, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable));

                HttpResponseMessage response = await _client.PostAsync(endpointUrl, httpContent, accessToken);

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    _logger.LogError($"// Push event with id {item.Id} failed with statuscode {response.StatusCode}");
                    throw new Exception($"// Push event with id {item.Id} failed with statuscode {response.StatusCode}");
                }
            }
            catch (Exception e)
            {
                _logger.LogError(e, $"// Push event with id {item.Id} failed with errormessage {e.Message}");
                throw e;
            }
        }
예제 #4
0
        async Task SubmitInternal(HashMode hashMode, string name, string description, string descriptionUrl, IList <string> files)
        {
            logger.LogInformation("Signing OpenVsixSignTool job {0} with {1} files", name, files.Count());

            // Dual isn't supported, use sha256
            var alg = hashMode == HashMode.Sha1 ? HashAlgorithmName.SHA1 : HashAlgorithmName.SHA256;

            var config = new RsaSignConfigurationSet
            {
                FileDigestAlgorithm = alg,
                PkcsDigestAlgorithm = alg,
                SigningCertificate  = await keyVaultService.GetCertificateAsync(),
                Rsa = await keyVaultService.ToRSA()
            };

            try
            {
                var tasks = files.Select(file =>
                {
                    telemetryLogger.OnSignFile(file, signToolName);
                    return(Sign(file, config, keyVaultService.CertificateInfo.TimestampUrl, alg));
                });

                await Task.WhenAll(tasks);
            }
            finally
            {
                config.Rsa?.Dispose();
            }
        }
예제 #5
0
    /// <inheritdoc />
    public async Task <string> GetAccessToken()
    {
        await Semaphore.WaitAsync();

        try
        {
            if (_accessToken == null || _cacheTokenUntil < DateTime.UtcNow)
            {
                string certBase64 = await _keyVaultService.GetCertificateAsync(_keyVaultSettings.KeyVaultUri, _keyVaultSettings.PlatformCertSecretId);

                _accessToken = _accessTokenGenerator.GenerateAccessToken(
                    _platformSettings.AccessTokenIssuer,
                    "platform.authorization",
                    new X509Certificate2(Convert.FromBase64String(certBase64), (string)null, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable));

                _cacheTokenUntil = DateTime.UtcNow.AddSeconds(_accessTokenSettings.TokenLifetimeInSeconds - 2); // Add some slack to avoid tokens expiring in transit
            }

            return(_accessToken);
        }
        finally
        {
            Semaphore.Release();
        }
    }
예제 #6
0
        public async Task <string> RunGetFacturaeSignedActivity([ActivityTrigger] string facturae)
        {
            var certificate = await keyvaultService.GetCertificateAsync(configuration["AppSettings:KeyVault:Certificate:Name"]);

            var signedDocument             = new MemoryStream();
            SignatureParameters parameters = new SignatureParameters
            {
                // Política de firma de factura-e 3.1
                SignaturePolicyInfo = new SignaturePolicyInfo
                {
                    PolicyIdentifier = "http://www.facturae.es/politica_de_firma_formato_facturae/politica_de_firma_formato_facturae_v3_1.pdf",
                    PolicyHash       = "Ohixl6upD6av8N7pEvDABhEL6hM="
                },
                SignaturePackaging = SignaturePackaging.ENVELOPED,
                DataFormat         = new DataFormat
                {
                    MimeType = "text/xml"
                },
                SignerRole = new SignerRole()
            };

            parameters.SignerRole.ClaimedRoles.Add("emisor");

            using (parameters.Signer = new Signer(certificate))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(facturae);
                var signed = xadesService.Sign(xmlDocument, parameters);
                signed.Save(signedDocument);
            }

            return(System.Convert.ToBase64String(signedDocument.ToArray()));
        }
예제 #7
0
        public AppxFile Create(string inputFileName)
        {
            if (publisher == null) // don't care about this race
            {
                var cert = keyVaultService.GetCertificateAsync().Result;
                publisher = cert.SubjectName.Name;
            }

            return(new AppxFile(inputFileName, publisher, logger, makeappxPath));
        }
예제 #8
0
        public async Task <AppxFile> Create(string inputFileName, string filter)
        {
            if (publisher == null) // don't care about this race
            {
                var cert = await keyVaultService.GetCertificateAsync();

                publisher = cert.SubjectName.Name;
            }

            return(new AppxFile(inputFileName, publisher, logger, makeappxPath, filter));
        }
예제 #9
0
        void SubmitInternal(HashMode hashMode, string name, string description, string descriptionUrl, IList <string> files)
        {
            logger.LogInformation("Signing SignTool job {0} with {1} files", name, files.Count());

            var certificate = keyVaultService.GetCertificateAsync().Result;

            using var rsa    = keyVaultService.ToRSA().Result;
            using var signer = new AuthenticodeKeyVaultSigner(rsa, certificate, HashAlgorithmName.SHA256, new TimeStampConfiguration(keyVaultService.CertificateInfo.TimestampUrl, HashAlgorithmName.SHA256, TimeStampType.RFC3161));
            // loop through all of the files here, looking for appx/eappx
            // mark each as being signed and strip appx
            Parallel.ForEach(files, (file, state) =>
            {
                telemetryLogger.OnSignFile(file, signToolName);

                if (!Sign(signer, file, description, descriptionUrl))
                {
                    throw new Exception($"Could not append sign {file}");
                }
            });
        }
        void SubmitInternal(HashMode hashMode, string name, string description, string descriptionUrl, IList <string> files, string filter)
        {
            logger.LogInformation("Signing Mage job {0} with {1} files", name, files.Count());

            var args = "-a sha256RSA";

            if (!string.IsNullOrWhiteSpace(name))
            {
                args += $@" -n ""{name}""";
            }

            var certificate  = keyVaultService.GetCertificateAsync().Result;
            var timeStampUrl = keyVaultService.CertificateInfo.TimestampUrl;

            using (var rsaPrivateKey = keyVaultService.ToRSA()
                                       .Result)
            {
                // This outer loop is for a .clickonce file
                Parallel.ForEach(files, options, (file, state) =>
                {
                    // We need to be explicit about the order these files are signed in. The data files must be signed first
                    // Then the .manifest file
                    // Then the nested clickonce/vsto file
                    // finally the top-level clickonce/vsto file

                    using (var zip = new TemporaryZipFile(file, filter, logger))
                    {
                        // Look for the data files first - these are .deploy files
                        // we need to rename them, sign, then restore the name

                        var deployFilesToSign = zip.FilteredFilesInDirectory.Where(f => ".deploy".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase))
                                                .ToList();

                        var contentFiles = new List <string>();
                        foreach (var dfile in deployFilesToSign)
                        {
                            // Rename to file without extension
                            var dest = dfile.Replace(".deploy", "");
                            File.Move(dfile, dest);
                            contentFiles.Add(dest);
                        }

                        var filesToSign = contentFiles.ToList(); // copy it since we may add setup.exe

                        var setupExe = zip.FilteredFilesInDirectory.Where(f => ".exe".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase));
                        filesToSign.AddRange(setupExe);

                        // Safe to call Wait here because we're in a Parallel.ForEach()
                        // sign the inner files
                        signToolAggregate.Value.Submit(hashMode, name, description, descriptionUrl, filesToSign, filter).Wait();

                        // rename the rest of the deploy files since signing the manifest will need them
                        var deployFiles = zip.FilesExceptFiltered.Where(f => ".deploy".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase))
                                          .ToList();

                        foreach (var dfile in deployFiles)
                        {
                            // Rename to file without extension
                            var dest = dfile.Replace(".deploy", "");
                            File.Move(dfile, dest);
                            contentFiles.Add(dest);
                        }

                        // at this point contentFiles has all deploy files renamed

                        // Inner files are now signed
                        // now look for the manifest file and sign that

                        var manifestFile = zip.FilteredFilesInDirectory.Single(f => ".manifest".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase));

                        var fileArgs = $@"-update ""{manifestFile}"" {args}";

                        telemetryLogger.OnSignFile(manifestFile, signToolName);
                        if (!Sign(fileArgs, manifestFile, hashMode, rsaPrivateKey, certificate, timeStampUrl))
                        {
                            throw new Exception($"Could not sign {manifestFile}");
                        }

                        // Read the publisher name from the manifest for use below
                        var manifestDoc  = XDocument.Load(manifestFile);
                        var ns           = manifestDoc.Root.GetDefaultNamespace();
                        var publisherEle = manifestDoc.Root.Element(ns + "publisherIdentity");
                        var pubName      = publisherEle.Attribute("name").Value;

                        var publisherParam = "";

                        var dict = DistinguishedNameParser.Parse(pubName);
                        if (dict.TryGetValue("CN", out var cns))
                        {
                            // get the CN. it may be quoted
                            publisherParam = $@"-pub ""{string.Join("+", cns.Select(s => s.Replace("\"", "")))}"" ";
                        }

                        // Now sign the inner vsto/clickonce file
                        // Order by desending length to put the inner one first
                        var clickOnceFilesToSign = zip.FilteredFilesInDirectory
                                                   .Where(f => ".vsto".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase) ||
                                                          ".application".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase))
                                                   .Select(f => new { file = f, f.Length })
                                                   .OrderByDescending(f => f.Length)
                                                   .Select(f => f.file)
                                                   .ToList();

                        foreach (var f in clickOnceFilesToSign)
                        {
                            fileArgs = $@"-update ""{f}"" {args} -appm ""{manifestFile}"" {publisherParam}";
                            if (!string.IsNullOrWhiteSpace(descriptionUrl))
                            {
                                fileArgs += $@" -SupportURL {descriptionUrl}";
                            }

                            telemetryLogger.OnSignFile(f, signToolName);
                            if (!Sign(fileArgs, f, hashMode, rsaPrivateKey, certificate, timeStampUrl))
                            {
                                throw new Exception($"Could not sign {f}");
                            }
                        }

                        // restore the deploy files
                        foreach (var dfile in contentFiles)
                        {
                            File.Move(dfile, $"{dfile}.deploy");
                        }

                        zip.Save();
                    }
                });
            }
        }