Ejemplo n.º 1
0
        private async Task <byte[]> AcquireCertificateBytesFromOrderAsync(
            IOrderContext order,
            CsrInfo certificateSigningRequest,
            string certificateFriendlyName,
            string certificatePassword,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            _logger.LogInformation("Acquiring certificate through signing request.");

            var privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);

            var certificateChain = await order.Generate(certificateSigningRequest, privateKey);

            var pfxBuilder = certificateChain.ToPfx(privateKey);

            pfxBuilder.FullChain = true;

            var pfxBytes = pfxBuilder.Build(certificateFriendlyName, certificatePassword);

            _logger.LogInformation("Certificate acquired.");

            return(pfxBytes);
        }
Ejemplo n.º 2
0
        public async Task <(X509Certificate2 cert, byte[] rawCert)> AcquireNewCertificateForHosts(
            string hostName,
            CsrInfo certificateSigningRequest,
            string certificateFriendlyName,
            string certificatePassword,
            CancellationToken cancellationToken)
        {
            _logger.LogInformation("Ordering LetsEncrypt certificate for hosts {0}.", new object[] { hostName });
            var order = await _acmeContext.NewOrder(new string[] { hostName });

            await ValidateOrderAsync(order, cancellationToken);

            var certificateBytes = await AcquireCertificateBytesFromOrderAsync(
                order,
                certificateSigningRequest,
                certificateFriendlyName,
                certificatePassword,
                cancellationToken);

            if (certificateBytes == null)
            {
                throw new InvalidOperationException("The certificate from the order was null.");
            }

            var certificate = new X509Certificate2(certificateBytes, certificatePassword);

            return(certificate, certificateBytes);
        }
Ejemplo n.º 3
0
        private async Task <X509Certificate2> CompleteCertificateRequestAsync(IOrderContext order,
                                                                              CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (_client == null)
            {
                throw new InvalidOperationException();
            }

            var commonName = _options.Value.DomainNames[0];

            _logger.LogDebug("Creating cert for {commonName}", commonName);

            var csrInfo = new CsrInfo
            {
                CommonName = commonName,
            };
            var privateKey = KeyFactory.NewKey((Certes.KeyAlgorithm)_options.Value.KeyAlgorithm);
            var acmeCert   = await _client.GetCertificateAsync(csrInfo, privateKey, order);

            _logger.LogAcmeAction("NewCertificate");

            var pfxBuilder = acmeCert.ToPfx(privateKey);
            var pfx        = pfxBuilder.Build("HTTPS Cert - " + _options.Value.DomainNames, string.Empty);

            return(new X509Certificate2(pfx, string.Empty, X509KeyStorageFlags.Exportable));
        }
        public static async Task InitAsync(ILogger logger, CertificateMode certificateMode)
        {
            _logger = logger;

            _logger.LogInformation($"Initializing LetsEncrypt bits");

            //ACCOUNT
            _logger.LogInformation("    Creating or Retrieving account");

            var accountKeyFileName = Constants.AccountKeyFileName;

            if (Settings.UseStaging)
            {
                accountKeyFileName = "staging" + accountKeyFileName;
            }

            IAccountContext account;

            if (await AzureHelper.CheckIfFileExistsBlobStorageAsync(accountKeyFileName))
            {
                _logger.LogInformation("        Retrieving existing account");

                // Load the saved account key
                var pemKey = await AzureHelper.ReadFileFromBlobStorageToStringAsync(accountKeyFileName);

                var accountKey = KeyFactory.FromPem(pemKey);
                _acme   = new AcmeContext(certificateMode == CertificateMode.Production ? WellKnownServers.LetsEncryptV2 : WellKnownServers.LetsEncryptStagingV2, accountKey);
                account = await _acme.Account();
            }
            else
            {
                _logger.LogInformation("        Creating new account");
                _acme   = new AcmeContext(certificateMode == CertificateMode.Production ? WellKnownServers.LetsEncryptV2 : WellKnownServers.LetsEncryptStagingV2);
                account = await _acme.NewAccount(Settings.CertificateOwnerEmail, true);

                // Save the account key for later use
                var pemKey = _acme.AccountKey.ToPem();
                await AzureHelper.SaveFileToBlobStorageAsync(accountKeyFileName, pemKey);
            }

            _logger.LogInformation($"    Account set - { account.Location }");
            _logger.LogInformation(Environment.NewLine);

            _logger.LogInformation("Loading Certificate Info for Issuance");
            _certinfo = await BuildCertificaeInfoAsync();

            _logger.LogInformation("    Certificate Info loaded");
            _logger.LogInformation(Environment.NewLine);
        }
Ejemplo n.º 5
0
        private async Task <byte[]> AcquireCertificateBytesFromOrderAsync(
            IOrderContext order,
            AcmeOrderOptions orderOptions,
            AcmeAccountOptions accountOptions,
            CertificateOptions certificateOptions)
        {
            _logger.LogInformation("[LetsEncrypt][Certificate] Acquiring certificate through signing request.");

            var privateKey = KeyFactory.NewKey((Certes.KeyAlgorithm)orderOptions.KeyAlgorithm);

            if (orderOptions?.CertificateSigningRequest == null)
            {
                var commonName = accountOptions.Domains[0];
                _logger.LogDebug("Creating cert for {commonName}", commonName);

                var csrInfo = new CsrInfo
                {
                    CommonName = commonName,
                };

                if (orderOptions != null)
                {
                    orderOptions.CertificateSigningRequest = csrInfo;
                }
            }

            var certificateChain = await order.Generate(orderOptions?.CertificateSigningRequest, privateKey);

            var pfxBuilder = certificateChain.ToPfx(privateKey);

            pfxBuilder.FullChain = true;

            var pfxBytes = pfxBuilder.Build(
                $"Let's Encrypt - {accountOptions.Domains[0]} ",
                certificateOptions?.CertificatePassword ?? string.Empty);

            _logger.LogInformation("[LetsEncrypt][Certificate] Certificate acquired.");

            return(pfxBytes);
        }
Ejemplo n.º 6
0
 public async Task <CertificateChain> GetCertificateAsync(CsrInfo csrInfo, IKey privateKey, IOrderContext order)
 {
     _logger.LogAcmeAction("GenerateCertificate", order);
     return(await order.Generate(csrInfo, privateKey));
 }
        public static async void Run([TimerTrigger("0 0 0 1 JAN,APR,JUL,OCT *")] TimerInfo myTimer, ILogger log)
        {
            var domainName         = "cityforcity.com";
            var connString         = Environment.GetEnvironmentVariable("STORAGE_CONN_STRING");
            var shareName          = "nginx-volume";
            var ownerEmail         = Environment.GetEnvironmentVariable("OWNER_EMAIL");
            var wildcardDomainName = $"*.{domainName}";
            var dnsAddr            = $"_acme-challenge";

            AcmeContext acme = new AcmeContext(WellKnownServers.LetsEncryptV2); // change this for production, using staging to not get blocked
            await acme.NewAccount(ownerEmail, true);

            var order = await acme.NewOrder(new [] { wildcardDomainName });

            var orderUri      = order.Location;
            var authorization = await order.Authorization(wildcardDomainName);

            var dnsChallenge = await authorization.Dns();

            var dnsTxt = acme.AccountKey.DnsTxt(dnsChallenge.Token);

            try {
                AzureHelper.AuthenticateAzure();
                var dnsUpdated = AzureHelper.AddTextDnsRecord(domainName, dnsAddr, dnsTxt);
                if (!dnsUpdated)
                {
                    throw new Exception("Failed to update dns record");
                }
                // wait for dns change to propogate
                await Task.Delay(500);

                var validatedChallege = await dnsChallenge.Validate();

                var startedValidation = DateTime.Now;
                while (validatedChallege.Status != Certes.Acme.Resource.ChallengeStatus.Valid)
                {
                    await Task.Delay(500);

                    if (DateTime.Now > startedValidation.AddSeconds(300))
                    {
                        throw new Exception("Failed to validate dns record");
                    }
                    validatedChallege = await dnsChallenge.Resource();
                }
                var dnsRemoved = AzureHelper.RemoveTextDnsRecord(domainName, dnsAddr);
                if (!dnsRemoved)
                {
                    log.LogInformation("Failed to remove DNS record do it manually");
                }

                var privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);
                var certinfo   = new CsrInfo();
                certinfo.CommonName = wildcardDomainName;
                var cert = await order.Generate(certinfo, privateKey);

                var certUpdated = AzureHelper.WriteStringToAzureFileShare(connString, shareName, "fullchain1.pem", cert.ToPem());
                if (!certUpdated)
                {
                    throw new Exception("Failed to update certificate");
                }
                var privKeyUpdated = AzureHelper.WriteStringToAzureFileShare(connString, shareName, "privKey1.pem", privateKey.ToPem());
                if (!privKeyUpdated)
                {
                    throw new Exception("Failed to update private key");
                }
            } catch (Exception _) {
                log.LogError(_.Message);
            }
        }
Ejemplo n.º 8
0
        public async Task <ProcessStepResult> PerformCertificateRequestProcess(string primaryDnsIdentifier, string[] alternativeDnsIdentifiers, CertRequestConfig config)
        {
            // create our new certificate
            var orderContext = _currentOrders[config.PrimaryDomain];

            //update order status
            var order = await orderContext.Resource();

            // order.Generate()
            var csrKey = KeyFactory.NewKey(KeyAlgorithm.RS256);
            var csr    = new CsrInfo
            {
                CommonName = config.PrimaryDomain
            };

            //alternative to certes IOrderContextExtension.Finalize
            var builder = new CertificationRequestBuilder(csrKey);

            foreach (var authzCtx in await orderContext.Authorizations())
            {
                var authz = await authzCtx.Resource();

                if (!builder.SubjectAlternativeNames.Contains(authz.Identifier.Value))
                {
                    if (config.PrimaryDomain != $"*.{authz.Identifier.Value}")
                    {
                        //only add domain to SAN if it is not derived from a wildcard domain eg test.com from *.test.com
                        builder.SubjectAlternativeNames.Add(authz.Identifier.Value);
                    }
                }
            }

            // if main request is for a wildcard domain, add that to SAN list
            if (config.PrimaryDomain.StartsWith("*."))
            {
                //add wildcard domain to san
                builder.SubjectAlternativeNames.Add(config.PrimaryDomain);
            }
            builder.AddName("CN", config.PrimaryDomain);

            /* foreach (var f in csr.AllFieldsDictionary)
             * {
             *   builder.AddName(f.Key, f.Value);
             * }*/

            if (string.IsNullOrWhiteSpace(csr.CommonName))
            {
                builder.AddName("CN", builder.SubjectAlternativeNames[0]);
            }

            var certResult = await orderContext.Finalize(builder.Generate());

            var pem = await orderContext.Download();

            var cert = new CertificateInfo(pem, csrKey);

            var certFriendlyName = config.PrimaryDomain + "[Certify]";
            var certFolderPath   = _settingsFolder + "\\assets\\pfx";

            if (!System.IO.Directory.Exists(certFolderPath))
            {
                System.IO.Directory.CreateDirectory(certFolderPath);
            }

            string certFile = Guid.NewGuid().ToString() + ".pfx";
            string pfxPath  = certFolderPath + "\\" + certFile;

            System.IO.File.WriteAllBytes(pfxPath, cert.ToPfx(certFriendlyName, ""));

            return(new ProcessStepResult {
                IsSuccess = true, Result = pfxPath
            });
        }