Beispiel #1
0
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var(serverUri, key) = await ReadAccountKey(syntax, true, false);

            var orderUri = syntax.GetParameter <Uri>(OrderIdParam, true);
            var domain   = syntax.GetParameter <string>(DomainParam, true);

            var azureCredentials = await ReadAzureCredentials(syntax);

            var resourceGroup = syntax.GetOption <string>(AzureResourceGroupOption, true);
            var appName       = syntax.GetParameter <string>(AppNameParam, true);
            var appSlot       = syntax.GetOption <string>(SlotOption, false);

            var privKey = await syntax.ReadKey(PrivateKeyOption, "CERTES_CERT_KEY", File, environment, true);

            var acme     = ContextFactory.Invoke(serverUri, key);
            var orderCtx = acme.Order(orderUri);

            var order = await orderCtx.Resource();

            if (order.Certificate == null)
            {
                throw new CertesCliException(string.Format(Strings.ErrorOrderIncompleted, orderCtx.Location));
            }

            var cert = await orderCtx.Download();

            var x509Cert   = new X509Certificate2(cert.Certificate.ToDer());
            var thumbprint = x509Cert.Thumbprint;

            using (var client = clientFactory.Invoke(azureCredentials))
            {
                client.SubscriptionId = azureCredentials.DefaultSubscriptionId;

                var certUploaded = await FindCertificate(client, resourceGroup, thumbprint);

                if (certUploaded == null)
                {
                    certUploaded = await UploadCertificate(
                        client, resourceGroup, appName, appSlot, cert.ToPfx(privKey), thumbprint);
                }

                var hostNameBinding = new HostNameBindingInner
                {
                    SslState   = SslState.SniEnabled,
                    Thumbprint = certUploaded.Thumbprint,
                };

                var hostName = string.IsNullOrWhiteSpace(appSlot) ?
                               await client.WebApps.CreateOrUpdateHostNameBindingAsync(
                    resourceGroup, appName, domain, hostNameBinding) :
                               await client.WebApps.CreateOrUpdateHostNameBindingSlotAsync(
                    resourceGroup, appName, domain, hostNameBinding, appSlot);

                return(new
                {
                    data = hostName
                });
            }
        }
Beispiel #2
0
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var(serverUri, key) = await ReadAccountKey(syntax, true, false);

            var orderUri = syntax.GetParameter <Uri>(OrderIdParam, true);
            var domain   = syntax.GetParameter <string>(DomainParam, true);
            var typeStr  = syntax.GetParameter <string>(ChallengeTypeParam, true);

            var type =
                string.Equals(typeStr, "dns", OrdinalIgnoreCase) ? Dns01 :
                string.Equals(typeStr, "http", OrdinalIgnoreCase) ? Http01 :
                throw new ArgumentSyntaxException(string.Format(Strings.ErrorInvalidChallengeType, typeStr));

            logger.Debug("Validating authz on '{0}'.", serverUri);

            var acme     = ContextFactory.Invoke(serverUri, key);
            var orderCtx = acme.Order(orderUri);
            var authzCtx = await orderCtx.Authorization(domain)
                           ?? throw new CertesCliException(string.Format(Strings.ErrorIdentifierNotAvailable, domain));

            var challengeCtx = await authzCtx.Challenge(type)
                               ?? throw new CertesCliException(string.Format(Strings.ErrorChallengeNotAvailable, typeStr));

            logger.Debug("Validating challenge '{0}'.", challengeCtx.Location);
            var challenge = await challengeCtx.Validate();

            return(new
            {
                location = challengeCtx.Location,
                resource = challenge,
            });
        }
Beispiel #3
0
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var keyPath = syntax.GetParameter <string>(PrivateKeyOption, true);
            var pwd     = syntax.GetParameter <string>(PasswordParam, true);

            var(location, cert) = await DownloadCertificate(syntax);

            var pfxName = string.Format(CultureInfo.InvariantCulture, "[certes] {0:yyyyMMddhhmmss}", DateTime.UtcNow);
            var privKey = await syntax.ReadKey(PrivateKeyOption, "CERTES_CERT_KEY", File, environment, true);

            var pfx = cert.ToPfx(privKey).Build(pfxName, pwd);

            var outPath = syntax.GetOption <string>(OutOption);

            if (string.IsNullOrWhiteSpace(outPath))
            {
                return(new
                {
                    location,
                    pfx,
                });
            }
            else
            {
                logger.Debug("Saving certificate to '{0}'.", outPath);
                await File.WriteAllBytes(outPath, pfx);

                return(new
                {
                    location,
                });
            }
        }
Beispiel #4
0
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var(serverUri, key) = await ReadAccountKey(syntax, true, false);

            var orderUri         = syntax.GetParameter <Uri>(OrderIdParam, true);
            var domain           = syntax.GetParameter <string>(DomainParam, true);
            var azureCredentials = await ReadAzureCredentials(syntax);

            var resourceGroup = syntax.GetOption <string>(AzureResourceGroupOption, true);

            var acme     = ContextFactory.Invoke(serverUri, key);
            var orderCtx = acme.Order(orderUri);
            var authzCtx = await orderCtx.Authorization(domain)
                           ?? throw new Exception(string.Format(Strings.ErrorIdentifierNotAvailable, domain));

            var challengeCtx = await authzCtx.Dns()
                               ?? throw new Exception(string.Format(Strings.ErrorChallengeNotAvailable, "dns"));

            var authz = await authzCtx.Resource();

            var dnsValue = acme.AccountKey.DnsTxt(challengeCtx.Token);

            using (var client = clientFactory.Invoke(azureCredentials))
            {
                client.SubscriptionId = azureCredentials.DefaultSubscriptionId;
                var idValue = authz.Identifier.Value;
                var zone    = await FindDnsZone(client, idValue);

                var name = zone.Name.Length == idValue.Length ?
                           "_acme-challenge" :
                           "_acme-challenge." + idValue.Substring(0, idValue.Length - zone.Name.Length - 1);
                logger.Debug("Adding TXT record '{0}' for '{1}' in '{2}' zone.", dnsValue, name, zone.Name);

                var recordSet = await client.RecordSets.CreateOrUpdateAsync(
                    resourceGroup,
                    zone.Name,
                    name,
                    RecordType.TXT,
                    new RecordSetInner(
                        name : name,
                        tTL : 300,
                        txtRecords : new[] { new TxtRecord(new[] { dnsValue }) }));

                return(new
                {
                    data = recordSet
                });
            }
        }
Beispiel #5
0
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var acct = await ReadAccountKey(syntax);

            logger.Debug("Creating new account on '{0}'.", acct.Server);
            var key   = acct.Key ?? KeyFactory.NewKey(KeyAlgorithm.ES256);
            var email = syntax.GetParameter <string>(EmailParam, true);

            var acme    = ContextFactory.Invoke(acct.Server, key);
            var acctCtx = await acme.NewAccount(email, true);

            var outPath = syntax.GetOption <string>(OutOption);

            if (!string.IsNullOrWhiteSpace(outPath))
            {
                logger.Debug("Saving new account key to '{0}'.", outPath);
                var pem = key.ToPem();
                await File.WriteAllText(outPath, pem);
            }
            else
            {
                logger.Debug("Saving new account key to user settings.");
                await UserSettings.SetAccountKey(acct.Server, key);
            }

            return(new
            {
                location = acctCtx.Location,
                resource = await acctCtx.Resource()
            });
        }
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var(serverUri, key) = await ReadAccountKey(syntax, true, false);

            var orderUri          = syntax.GetParameter <Uri>(OrderIdParam, true);
            var distinguishedName = syntax.GetOption <string>(DnOption);
            var outPath           = syntax.GetOption <string>(OutOption);
            var keyAlgorithmStr   = syntax.GetOption <string>(KeyAlgorithmOption);

            var keyAlgorithm =
                keyAlgorithmStr == null ? KeyAlgorithm.ES256 :
                Enum.TryParse <KeyAlgorithm>(keyAlgorithmStr, out var alg) ? alg :
                throw new ArgumentSyntaxException(string.Format(Strings.ErrorInvalidkeyAlgorithm, keyAlgorithmStr));


            var providedKey = await syntax.ReadKey(PrivateKeyOption, "CERTES_CERT_KEY", File, environment);

            var privKey = providedKey ?? KeyFactory.NewKey(keyAlgorithm);

            logger.Debug("Finalizing order from '{0}'.", serverUri);

            var acme     = ContextFactory.Invoke(serverUri, key);
            var orderCtx = acme.Order(orderUri);

            var csr = await orderCtx.CreateCsr(privKey);

            if (!string.IsNullOrWhiteSpace(distinguishedName))
            {
                csr.AddName(distinguishedName);
            }

            var order = await orderCtx.Finalize(csr.Generate());

            // output private key only if it is generated and not being saved
            if (string.IsNullOrWhiteSpace(outPath) && providedKey == null)
            {
                return(new
                {
                    location = orderCtx.Location,
                    privateKey = privKey.ToDer(),
                    resource = order,
                });
            }
            else
            {
                if (providedKey == null)
                {
                    await File.WriteAllText(outPath, privKey.ToPem());
                }

                return(new
                {
                    location = orderCtx.Location,
                    resource = order,
                });
            }
        }
Beispiel #7
0
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var(serverUri, key) = await ReadAccountKey(syntax, true, false);

            var orderUri = syntax.GetParameter <Uri>(OrderIdParam, true);
            var domain   = syntax.GetParameter <string>(DomainParam, true);
            var typeStr  = syntax.GetParameter <string>(ChallengeTypeParam, true);

            var type =
                string.Equals(typeStr, "dns", OrdinalIgnoreCase) ? Dns01 :
                string.Equals(typeStr, "http", OrdinalIgnoreCase) ? Http01 :
                throw new ArgumentSyntaxException(string.Format(Strings.ErrorInvalidChallengeType, typeStr));

            logger.Debug("Loading authz from '{0}'.", serverUri);

            var acme     = ContextFactory.Invoke(serverUri, key);
            var orderCtx = acme.Order(orderUri);
            var authzCtx = await orderCtx.Authorization(domain)
                           ?? throw new CertesCliException(string.Format(Strings.ErrorIdentifierNotAvailable, domain));

            var challengeCtx = await authzCtx.Challenge(type)
                               ?? throw new CertesCliException(string.Format(Strings.ErrorChallengeNotAvailable, typeStr));

            var challenge = await challengeCtx.Resource();

            if (string.Equals(type, Dns01, OrdinalIgnoreCase))
            {
                return(new
                {
                    location = challengeCtx.Location,
                    dnsTxt = key.DnsTxt(challenge.Token),
                    resource = challenge,
                });
            }

            return(new
            {
                location = challengeCtx.Location,
                challengeFile = $".well-known/acme-challenge/{challenge.Token}",
                challengeTxt = $"{challenge.Token}.{key.Thumbprint()}",
                resource = challenge,
                keyAuthz = challengeCtx.KeyAuthz
            });
        }
Beispiel #8
0
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var(serverUri, key) = await ReadAccountKey(syntax, true, false);

            var orderUri = syntax.GetParameter <Uri>(OrderIdParam, true);

            logger.Debug("Loading order from '{0}'.", serverUri);

            var acme     = ContextFactory.Invoke(serverUri, key);
            var orderCtx = acme.Order(orderUri);

            return(new
            {
                location = orderCtx.Location,
                resource = await orderCtx.Resource()
            });
        }
Beispiel #9
0
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var(serverUri, key) = await ReadAccountKey(syntax, true, true);

            var email = syntax.GetParameter <string>(EmailParam, true);

            logger.Debug("Updating account on '{0}'.", serverUri);

            var acme    = ContextFactory.Invoke(serverUri, key);
            var acctCtx = await acme.Account();

            var acct = await acctCtx.Update(new[] { $"mailto://{email}" }, true);

            return(new
            {
                location = acctCtx.Location,
                resource = acct,
            });
        }
Beispiel #10
0
        protected async Task <(Uri Location, CertificateChain Cert)> DownloadCertificate(ArgumentSyntax syntax)
        {
            var(serverUri, key) = await ReadAccountKey(syntax, true, true);

            var orderUri = syntax.GetParameter <Uri>(OrderIdParam, true);

            logger.Debug("Downloading certificate from '{0}'.", serverUri);

            var acme     = ContextFactory.Invoke(serverUri, key);
            var orderCtx = acme.Order(orderUri);
            var order    = await orderCtx.Resource();

            if (order.Status != OrderStatus.Valid)
            {
                throw new CertesCliException(
                          string.Format(Strings.ErrorExportInvalidOrder, order.Status));
            }

            return(order.Certificate, await orderCtx.Download());
        }
Beispiel #11
0
        public async Task <object> Execute(ArgumentSyntax syntax)
        {
            var(serverUri, _) = await ReadAccountKey(syntax, false);

            var keyPath = syntax.GetParameter <string>(KeyParam, true);
            var pem     = await File.ReadAllText(keyPath);

            var key = KeyFactory.FromPem(pem);

            logger.Debug("Setting account for '{0}'.", serverUri);

            var acme    = ContextFactory.Invoke(serverUri, key);
            var acctCtx = await acme.Account();

            await UserSettings.SetAccountKey(serverUri, key);

            return(new
            {
                location = acctCtx.Location,
                resource = await acctCtx.Resource()
            });
        }