private async Task <int> PerformAzureSignOnVsixAsync(string vsixPath, bool force,
                                                             Uri timestampUri, HashAlgorithmName fileDigestAlgorithm, HashAlgorithmName timestampDigestAlgorithm,
                                                             string azureUri, string azureClientId, string azureClientCertificateName, string azureClientSecret, string azureAccessToken
                                                             )
        {
            using (var package = OpcPackage.Open(vsixPath, OpcPackageFileMode.ReadWrite))
            {
                if (package.GetSignatures().Any() && !force)
                {
                    _signCommandApplication.Out.WriteLine("The VSIX is already signed.");
                    return(EXIT_CODES.FAILED);
                }
                var signBuilder = package.CreateSignatureBuilder();
                signBuilder.EnqueueNamedPreset <VSIXSignatureBuilderPreset>();
                var signingConfiguration = new AzureKeyVaultSignConfigurationSet
                {
                    FileDigestAlgorithm          = fileDigestAlgorithm,
                    PkcsDigestAlgorithm          = fileDigestAlgorithm,
                    AzureClientId                = azureClientId,
                    AzureClientSecret            = azureClientSecret,
                    AzureKeyVaultCertificateName = azureClientCertificateName,
                    AzureKeyVaultUrl             = azureUri,
                    AzureAccessToken             = azureAccessToken
                };

                var signature = await signBuilder.SignAsync(signingConfiguration);

                if (timestampUri != null)
                {
                    var timestampBuilder = signature.CreateTimestampBuilder();
                    var result           = await timestampBuilder.SignAsync(timestampUri, timestampDigestAlgorithm);

                    if (result == TimestampResult.Failed)
                    {
                        return(EXIT_CODES.FAILED);
                    }
                }
                _signCommandApplication.Out.WriteLine("The signing operation is complete.");
                return(EXIT_CODES.SUCCESS);
            }
        }
Example #2
0
        internal async Task <int> SignAzure(CommandOption azureKeyVaultUrl, CommandOption azureKeyVaultClientId,
                                            CommandOption azureKeyVaultClientSecret, CommandOption azureKeyVaultCertificateName, CommandOption azureKeyVaultAccessToken, CommandOption force,
                                            CommandOption fileDigest, CommandOption timestampUrl, CommandOption timestampAlgorithm, CommandArgument vsixPath)
        {
            if (!azureKeyVaultUrl.HasValue())
            {
                _signCommandApplication.Out.WriteLine("The Azure Key Vault URL must be specified for Azure signing.");
                return(EXIT_CODES.INVALID_OPTIONS);
            }


            // we only need the client id/secret if we don't have an access token
            if (!azureKeyVaultAccessToken.HasValue())
            {
                if (!azureKeyVaultClientId.HasValue())
                {
                    _signCommandApplication.Out.WriteLine("The Azure Key Vault Client ID or Access Token must be specified for Azure signing.");
                    return(EXIT_CODES.INVALID_OPTIONS);
                }

                if (!azureKeyVaultClientSecret.HasValue())
                {
                    _signCommandApplication.Out.WriteLine("The Azure Key Vault Client Secret or Access Token must be specified for Azure signing.");
                    return(EXIT_CODES.INVALID_OPTIONS);
                }
            }

            if (!azureKeyVaultCertificateName.HasValue())
            {
                _signCommandApplication.Out.WriteLine("The Azure Key Vault Client Certificate Name must be specified for Azure signing.");
                return(EXIT_CODES.INVALID_OPTIONS);
            }
            Uri timestampServer = null;

            if (timestampUrl.HasValue())
            {
                if (!Uri.TryCreate(timestampUrl.Value(), UriKind.Absolute, out timestampServer))
                {
                    _signCommandApplication.Out.WriteLine("Specified timestamp URL is invalid.");
                    return(EXIT_CODES.FAILED);
                }
                if (timestampServer.Scheme != Uri.UriSchemeHttp && timestampServer.Scheme != Uri.UriSchemeHttps)
                {
                    _signCommandApplication.Out.WriteLine("Specified timestamp URL is invalid.");
                    return(EXIT_CODES.FAILED);
                }
            }
            var vsixPathValue = vsixPath.Value;

            if (!File.Exists(vsixPathValue))
            {
                _signCommandApplication.Out.WriteLine("Specified file does not exist.");
                return(EXIT_CODES.FAILED);
            }
            HashAlgorithmName fileDigestAlgorithm, timestampDigestAlgorithm;
            var fileDigestResult = AlgorithmFromInput(fileDigest.HasValue() ? fileDigest.Value() : null);

            if (fileDigestResult == null)
            {
                _signCommandApplication.Out.WriteLine("Specified file digest algorithm is not supported.");
                return(EXIT_CODES.INVALID_OPTIONS);
            }
            else
            {
                fileDigestAlgorithm = fileDigestResult.Value;
            }
            var timestampDigestResult = AlgorithmFromInput(timestampAlgorithm.HasValue() ? timestampAlgorithm.Value() : null);

            if (timestampDigestResult == null)
            {
                _signCommandApplication.Out.WriteLine("Specified timestamp digest algorithm is not supported.");
                return(EXIT_CODES.INVALID_OPTIONS);
            }
            else
            {
                timestampDigestAlgorithm = timestampDigestResult.Value;
            }
            var configuration = new AzureKeyVaultSignConfigurationSet
            {
                AzureKeyVaultUrl             = azureKeyVaultUrl.Value(),
                AzureKeyVaultCertificateName = azureKeyVaultCertificateName.Value(),
                AzureClientId     = azureKeyVaultClientId.Value(),
                AzureAccessToken  = azureKeyVaultAccessToken.Value(),
                AzureClientSecret = azureKeyVaultClientSecret.Value(),
            };

            var configurationDiscoverer = new KeyVaultConfigurationDiscoverer();
            var materializedResult      = await configurationDiscoverer.Materialize(configuration);

            AzureKeyVaultMaterializedConfiguration materialized;

            switch (materializedResult)
            {
            case ErrorOr <AzureKeyVaultMaterializedConfiguration> .Ok ok:
                materialized = ok.Value;
                break;

            default:
                _signCommandApplication.Out.WriteLine("Failed to get configuration from Azure Key Vault.");
                return(EXIT_CODES.FAILED);
            }
            var context = new KeyVaultContext(materialized.Client, materialized.KeyId, materialized.PublicCertificate);

            using (var keyVault = new RSAKeyVault(context))
            {
                return(await PerformSignOnVsixAsync(
                           vsixPathValue,
                           force.HasValue(),
                           timestampServer,
                           fileDigestAlgorithm,
                           timestampDigestAlgorithm,
                           materialized.PublicCertificate,
                           keyVault
                           ));
            }
        }
Example #3
0
        public async Task <ErrorOr <AzureKeyVaultMaterializedConfiguration> > Materialize(AzureKeyVaultSignConfigurationSet configuration)
        {
            async Task <string> Authenticate(string authority, string resource, string scope)
            {
                if (!string.IsNullOrWhiteSpace(configuration.AzureAccessToken))
                {
                    return(configuration.AzureAccessToken);
                }

                var context = new AuthenticationContext(authority);
                ClientCredential credential = new ClientCredential(configuration.AzureClientId, configuration.AzureClientSecret);

                try
                {
                    var result = await context.AcquireTokenAsync(resource, credential);

                    return(result.AccessToken);
                }
                catch (AdalServiceException e) when(e.StatusCode >= 400 && e.StatusCode < 500)
                {
                    return(null);
                }
            }

            var vault            = new KeyVaultClient(Authenticate);
            var azureCertificate = await vault.GetCertificateAsync(configuration.AzureKeyVaultUrl, configuration.AzureKeyVaultCertificateName);

            var certificate = new X509Certificate2(azureCertificate.Cer);
            var keyId       = azureCertificate.KeyIdentifier;

            return(new AzureKeyVaultMaterializedConfiguration(vault, certificate, keyId));
        }