示例#1
0
        private async Task <AccountDetails> LoadAccount(IJwsTool signer)
        {
            AccountDetails account = null;

            if (File.Exists(AccountPath))
            {
                if (signer != null)
                {
                    _log.Debug("Loading account information from {registrationPath}", AccountPath);
                    account         = JsonConvert.DeserializeObject <AccountDetails>(File.ReadAllText(AccountPath));
                    _client.Account = account;
                    // Maybe we should update the account details
                    // on every start of the program to figure out
                    // if it hasn't been suspended or cancelled?
                    // UpdateAccount();
                }
                else
                {
                    _log.Error("Account found but no valid signer could be loaded");
                }
            }
            else
            {
                var contacts = await GetContacts();

                var(_, filename, content) = await _client.GetTermsOfServiceAsync();

                if (!_arguments.MainArguments.AcceptTos)
                {
                    var tosPath = Path.Combine(_settings.Client.ConfigurationPath, filename);
                    File.WriteAllBytes(tosPath, content);
                    _input.Show($"Terms of service", tosPath);
                    if (await _input.PromptYesNo($"Open in default application?", false))
                    {
                        Process.Start(tosPath);
                    }

                    if (!await _input.PromptYesNo($"Do you agree with the terms?", true))
                    {
                        return(null);
                    }
                }
                account = await _client.CreateAccountAsync(contacts, termsOfServiceAgreed : true);

                _log.Debug("Saving registration");
                var accountKey = new AccountSigner
                {
                    KeyType   = _client.Signer.JwsAlg,
                    KeyExport = _client.Signer.Export(),
                };
                AccountSigner = accountKey;
                File.WriteAllText(AccountPath, JsonConvert.SerializeObject(account));
            }
            return(account);
        }
示例#2
0
        private async Task <AccountDetails> LoadAccount(IJwsTool signer)
        {
            AccountDetails account = null;

            if (File.Exists(AccountPath))
            {
                if (signer != null)
                {
                    _log.Debug("Loading account information from {registrationPath}", AccountPath);
                    account = JsonConvert.DeserializeObject <AccountDetails>(File.ReadAllText(AccountPath));
                }
                else
                {
                    _log.Error("Account found but no valid Signer could be loaded");
                }
            }
            else
            {
                var contacts = GetContacts();
                var(contentType, filename, content) = await _client.GetTermsOfServiceAsync();

                if (!_optionsService.MainArguments.AcceptTos)
                {
                    var tosPath = Path.Combine(_settings.ConfigPath, filename);
                    File.WriteAllBytes(tosPath, content);
                    _input.Show($"Terms of service", tosPath);
                    if (_input.PromptYesNo($"Open in default application?"))
                    {
                        Process.Start(tosPath);
                    }
                    if (!_input.PromptYesNo($"Do you agree with the terms?"))
                    {
                        return(null);
                    }
                }
                account = await _client.CreateAccountAsync(contacts, termsOfServiceAgreed : true);

                _log.Debug("Saving registration");
                var accountKey = new AccountSigner
                {
                    KeyType   = _client.Signer.JwsAlg,
                    KeyExport = _client.Signer.Export(),
                };
                AccountSigner = accountKey;
                File.WriteAllText(AccountPath, JsonConvert.SerializeObject(account));
            }
            return(account);
        }
示例#3
0
        private async Task <AccountDetails?> LoadAccount(AcmeProtocolClient client, IJwsTool?signer)
        {
            AccountDetails?account = null;

            if (File.Exists(AccountPath))
            {
                if (signer != null)
                {
                    _log.Debug("Loading account information from {registrationPath}", AccountPath);
                    account        = JsonConvert.DeserializeObject <AccountDetails>(File.ReadAllText(AccountPath));
                    client.Account = account;
                    // Maybe we should update the account details
                    // on every start of the program to figure out
                    // if it hasn't been suspended or cancelled?
                    // UpdateAccount();
                }
                else
                {
                    _log.Error("Account found but no valid signer could be loaded");
                }
            }
            else
            {
                var contacts = await GetContacts();

                var(_, filename, content) = await client.GetTermsOfServiceAsync();

                if (!string.IsNullOrEmpty(filename))
                {
                    if (!await AcceptTos(filename, content))
                    {
                        return(null);
                    }
                }
                account = await client.CreateAccountAsync(contacts, termsOfServiceAgreed : true);

                _log.Debug("Saving registration");
                var accountKey = new AccountSigner
                {
                    KeyType   = client.Signer.JwsAlg,
                    KeyExport = client.Signer.Export(),
                };
                AccountSigner = accountKey;
                File.WriteAllText(AccountPath, JsonConvert.SerializeObject(account));
            }
            return(account);
        }
示例#4
0
        /// <summary>
        /// Setup a new ACME account
        /// </summary>
        /// <param name="client"></param>
        /// <returns></returns>
        private async Task SetupAccount(AcmeProtocolClient client)
        {
            // Accept the terms of service, if defined by the server
            try
            {
                var(_, filename, content) = await client.GetTermsOfServiceAsync();

                _log.Verbose("Terms of service downloaded");
                if (!string.IsNullOrEmpty(filename))
                {
                    if (!await AcceptTos(filename, content))
                    {
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Error getting terms of service");
            }

            var contacts = default(string[]);

            var eabKid      = _accountArguments.EabKeyIdentifier;
            var eabKey      = _accountArguments.EabKey;
            var eabAlg      = _accountArguments.EabAlgorithm ?? "HS256";
            var eabFlow     = client.Directory?.Meta?.ExternalAccountRequired == "true";
            var zeroSslFlow = _settings.BaseUri.Host.Contains("zerossl.com");

            // Warn about unneeded EAB
            if (!eabFlow && !string.IsNullOrWhiteSpace(eabKid))
            {
                eabFlow = true;
                _input.CreateSpace();
                _input.Show(null, "You have provided an external account binding key, even though " +
                            "the server does not indicate that this is required. We will attempt to register " +
                            "using this key anyway.");
            }

            if (zeroSslFlow)
            {
                async Task emailRegistration()
                {
                    var registration = await GetContacts(allowMultiple : false, prefix : "");

                    var eab = await _zeroSsl.Register(registration.FirstOrDefault() ?? "");

                    if (eab != null)
                    {
                        eabKid = eab.Kid;
                        eabKey = eab.Hmac;
                    }
                    else
                    {
                        _log.Error("Unable to retrieve EAB credentials using the provided email address");
                    }
                }

                async Task apiKeyRegistration()
                {
                    var accessKey = await _input.ReadPassword("API access key");

                    var eab = await _zeroSsl.Obtain(accessKey ?? "");

                    if (eab != null)
                    {
                        eabKid = eab.Kid;
                        eabKey = eab.Hmac;
                    }
                    else
                    {
                        _log.Error("Unable to retrieve EAB credentials using the provided API access key");
                    }
                }

                if (!string.IsNullOrWhiteSpace(_accountArguments.EmailAddress))
                {
                    await emailRegistration();
                }
                else
                {
                    var instruction = "ZeroSsl can be used either by setting up a new " +
                                      "account using your email address or by connecting it to your existing " +
                                      "account using the API access key or pre-generated EAB credentials, which can " +
                                      "be obtained from the Developer section of the dashboard.";
                    _input.CreateSpace();
                    _input.Show(null, instruction);
                    var chosen = await _input.ChooseFromMenu(
                        "How would you like to create the account?",
                        new List <Choice <Func <Task> > >()
                    {
                        Choice.Create(apiKeyRegistration, "API access key"),
                        Choice.Create(emailRegistration, "Email address"),
                        Choice.Create <Func <Task> >(() => Task.CompletedTask, "Input EAB credentials directly")
                    });

                    await chosen.Invoke();
                }
            }

            if (eabFlow)
            {
                if (string.IsNullOrWhiteSpace(eabKid))
                {
                    var instruction = "This ACME endpoint requires an external account. " +
                                      "You will need to provide a key identifier and a key to proceed. " +
                                      "Please refer to the providers instructions on how to obtain these.";
                    _input.CreateSpace();
                    _input.Show(null, instruction);
                    eabKid = await _input.RequestString("Key identifier");
                }
                if (string.IsNullOrWhiteSpace(eabKey))
                {
                    eabKey = await _input.ReadPassword("Key (base64url encoded)");
                }
                contacts = await GetContacts(runLevel : RunLevel.Unattended);
            }
            else
            {
                contacts = await GetContacts();
            }

            var signer = _accountManager.DefaultSigner();

            try
            {
                await CreateAccount(client, signer, contacts, eabAlg, eabKid, eabKey);
            }
            catch (AcmeProtocolException apex)
            {
                // Some non-ACME compliant server may not support ES256 or other
                // algorithms, so attempt fallback to RS256
                if (apex.ProblemType == acme.ProblemType.BadSignatureAlgorithm &&
                    signer.KeyType != "RS256")
                {
                    signer = _accountManager.NewSigner("RS256");
                    await CreateAccount(client, signer, contacts, eabAlg, eabKid, eabKey);
                }
                else
                {
                    throw;
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Error creating account");
                throw;
            }
        }
示例#5
0
        private async Task <AccountDetails?> LoadAccount(AcmeProtocolClient client, IJwsTool?signer)
        {
            _log.Verbose("Loading ACME account");
            AccountDetails?account = null;

            if (File.Exists(AccountPath))
            {
                if (signer != null)
                {
                    _log.Debug("Loading account information from {registrationPath}", AccountPath);
                    account        = JsonConvert.DeserializeObject <AccountDetails>(File.ReadAllText(AccountPath));
                    client.Account = account;
                    // Maybe we should update the account details
                    // on every start of the program to figure out
                    // if it hasn't been suspended or cancelled?
                    // UpdateAccount();
                }
                else
                {
                    _log.Error("Account found but no valid signer could be loaded");
                }
            }
            else
            {
                _log.Verbose("No account found at {path}, creating new one", AccountPath);
                try
                {
                    var(_, filename, content) = await client.GetTermsOfServiceAsync();

                    _log.Verbose("Terms of service downloaded");
                    if (!string.IsNullOrEmpty(filename))
                    {
                        if (!await AcceptTos(filename, content))
                        {
                            return(null);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error getting terms of service");
                }
                var contacts        = default(string[]);
                var externalAccount = default(ExternalAccountBinding);

                var kid     = _accountArguments.EabKeyIdentifier;
                var key     = _accountArguments.EabKey;
                var alg     = _accountArguments.EabAlgorithm ?? "HS256";
                var eabFlow = client.Directory?.Meta?.ExternalAccountRequired == "true";
                if (eabFlow)
                {
                    _input.CreateSpace();
                    _input.Show(null, "This ACME endpoint requires an external account. You will " +
                                "need to provide a key identifier and a key to proceed. Please refer to the " +
                                "providers instructions on how to obtain these.");
                }
                else if (!string.IsNullOrWhiteSpace(kid))
                {
                    eabFlow = true;
                    _input.CreateSpace();
                    _input.Show(null, "You have provided external account binding key, but the server" +
                                "claims that is not required. We will attempt to register using this key anyway.");
                }
                if (eabFlow)
                {
                    if (string.IsNullOrWhiteSpace(kid))
                    {
                        kid = await _input.RequestString("Key identifier");
                    }
                    if (string.IsNullOrWhiteSpace(key))
                    {
                        key = await _input.ReadPassword("Key (base64url encoded)");
                    }
                    externalAccount = new ExternalAccountBinding(
                        alg,
                        JsonConvert.SerializeObject(client.Signer.ExportJwk(), Formatting.None),
                        kid,
                        key ?? "",
                        client.Directory?.NewAccount ?? "");
                }
                else
                {
                    contacts = await GetContacts();
                }

                try
                {
                    account = await client.CreateAccountAsync(
                        contacts,
                        termsOfServiceAgreed : true,
                        externalAccountBinding : externalAccount?.Payload() ?? null);
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error creating account");
                }

                if (account != null)
                {
                    try
                    {
                        _log.Debug("Saving account");
                        var accountKey = new AccountSigner
                        {
                            KeyType   = client.Signer.JwsAlg,
                            KeyExport = client.Signer.Export(),
                        };
                        AccountSigner = accountKey;
                        await File.WriteAllTextAsync(AccountPath, JsonConvert.SerializeObject(account));
                    }
                    catch (Exception ex)
                    {
                        _log.Error(ex, "Error saving account");
                        account = null;
                    }
                }
            }
            return(account);
        }
示例#6
0
        protected async Task DoTheWorkAsync(object state)
        {
            _logger.LogInformation("** DOING WORKING *****************************************");
            _logger.LogInformation($"DNS Names:  {string.Join(",", _options.DnsNames)}");

            if (_state.Certificate != null)
            {
                var now = DateTime.Now;
                if (_state.Certificate.NotBefore > now && _state.Certificate.NotAfter < now)
                {
                    _logger.LogInformation("Existing certificate is Good!");
                    return;
                }
                {
                    _logger.LogWarning("Existing Certificate is Expired!");
                }
            }
            else
            {
                _logger.LogWarning("Missing Certificate");
            }

            var acmeUrl = new Uri(_options.CaUrl);

            using (var acme = new AcmeProtocolClient(acmeUrl))
            {
                _state.ServiceDirectory = await acme.GetDirectoryAsync();

                Save(_state.ServiceDirectoryFile, _state.ServiceDirectory);
                acme.Directory = _state.ServiceDirectory;

                Save(_state.TermsOfServiceFile,
                     await acme.GetTermsOfServiceAsync());

                await acme.GetNonceAsync();

                if (!await ResolveAccount(acme))
                {
                    return;
                }

                if (!await ResolveOrder(acme))
                {
                    return;
                }

                if (!await ResolveChallenges(acme))
                {
                    return;
                }

                if (!await ResolveAuthorizations(acme))
                {
                    return;
                }

                if (!await ResolveCertificate(acme))
                {
                    return;
                }
            }
        }
示例#7
0
        private async Task <AccountDetails?> LoadAccount(AcmeProtocolClient client, IJwsTool?signer)
        {
            _log.Verbose("Loading ACME account");
            AccountDetails?account = null;

            if (File.Exists(AccountPath))
            {
                if (signer != null)
                {
                    _log.Debug("Loading account information from {registrationPath}", AccountPath);
                    account        = JsonConvert.DeserializeObject <AccountDetails>(File.ReadAllText(AccountPath));
                    client.Account = account;
                    // Maybe we should update the account details
                    // on every start of the program to figure out
                    // if it hasn't been suspended or cancelled?
                    // UpdateAccount();
                }
                else
                {
                    _log.Error("Account found but no valid signer could be loaded");
                }
            }
            else
            {
                _log.Verbose("No account found at {path}, creating new one", AccountPath);
                try
                {
                    var(_, filename, content) = await client.GetTermsOfServiceAsync();

                    _log.Verbose("Terms of service downloaded");
                    if (!string.IsNullOrEmpty(filename))
                    {
                        if (!await AcceptTos(filename, content))
                        {
                            return(null);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error getting terms of service");
                }
                var contacts        = default(string[]);
                var externalAccount = default(ExternalAccountBinding);

                var kid         = _accountArguments.EabKeyIdentifier;
                var key         = _accountArguments.EabKey;
                var alg         = _accountArguments.EabAlgorithm ?? "HS256";
                var eabFlow     = client.Directory?.Meta?.ExternalAccountRequired == "true";
                var zeroSslFlow = _settings.BaseUri.Host.Contains("zerossl.com");

                // Warn about unneeded EAB
                if (!eabFlow && !string.IsNullOrWhiteSpace(kid))
                {
                    eabFlow = true;
                    _input.CreateSpace();
                    _input.Show(null, "You have provided an external account binding key, even though " +
                                "the server does not indicate that this is required. We will attempt to register " +
                                "using this key anyway.");
                }

                if (zeroSslFlow)
                {
                    async Task emailRegistration()
                    {
                        var registration = await GetContacts(allowMultiple : false, prefix : "");

                        var eab = await _zeroSsl.Register(registration.FirstOrDefault() ?? "");

                        if (eab != null)
                        {
                            kid = eab.Kid;
                            key = eab.Hmac;
                        }
                        else
                        {
                            _log.Error("Unable to retrieve EAB credentials using the provided email address");
                        }
                    }

                    async Task apiKeyRegistration()
                    {
                        var accessKey = await _input.ReadPassword("API access key");

                        var eab = await _zeroSsl.Obtain(accessKey ?? "");

                        if (eab != null)
                        {
                            kid = eab.Kid;
                            key = eab.Hmac;
                        }
                        else
                        {
                            _log.Error("Unable to retrieve EAB credentials using the provided API access key");
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(_accountArguments.EmailAddress))
                    {
                        await emailRegistration();
                    }
                    else
                    {
                        var instruction = "ZeroSsl can be used either by setting up a new " +
                                          "account using your email address or by connecting it to your existing " +
                                          "account using the API access key or pre-generated EAB credentials, which can " +
                                          "be obtained from the Developer section of the dashboard.";
                        _input.CreateSpace();
                        _input.Show(null, instruction);
                        var chosen = await _input.ChooseFromMenu(
                            "How would you like to create the account?",
                            new List <Choice <Func <Task> > >()
                        {
                            Choice.Create((Func <Task>)apiKeyRegistration, "API access key"),
                            Choice.Create((Func <Task>)emailRegistration, "Email address"),
                            Choice.Create <Func <Task> >(() => Task.CompletedTask, "Input EAB credentials directly")
                        });

                        await chosen.Invoke();
                    }
                }

                if (eabFlow)
                {
                    if (string.IsNullOrWhiteSpace(kid))
                    {
                        var instruction = "This ACME endpoint requires an external account. " +
                                          "You will need to provide a key identifier and a key to proceed. " +
                                          "Please refer to the providers instructions on how to obtain these.";
                        _input.CreateSpace();
                        _input.Show(null, instruction);
                        kid = await _input.RequestString("Key identifier");
                    }
                    if (string.IsNullOrWhiteSpace(key))
                    {
                        key = await _input.ReadPassword("Key (base64url encoded)");
                    }
                    externalAccount = new ExternalAccountBinding(
                        alg,
                        JsonConvert.SerializeObject(
                            client.Signer.ExportJwk(),
                            Formatting.None),
                        kid,
                        key ?? "",
                        client.Directory?.NewAccount ?? "");
                }
                else
                {
                    contacts = await GetContacts();
                }

                try
                {
                    account = await client.CreateAccountAsync(
                        contacts,
                        termsOfServiceAgreed : true,
                        externalAccountBinding : externalAccount?.Payload() ?? null);
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error creating account");
                }

                if (account != null)
                {
                    try
                    {
                        _log.Debug("Saving account");
                        var accountKey = new AccountSigner
                        {
                            KeyType   = client.Signer.JwsAlg,
                            KeyExport = client.Signer.Export(),
                        };
                        AccountSigner = accountKey;
                        await File.WriteAllTextAsync(AccountPath, JsonConvert.SerializeObject(account));
                    }
                    catch (Exception ex)
                    {
                        _log.Error(ex, "Error saving account");
                        account = null;
                    }
                }
            }
            return(account);
        }
示例#8
0
        protected async Task DoTheWorkAsync(object state)
        {
            var cts = new CancellationTokenSource();

            cts.CancelAfter(15000);
            try
            {
                var suggestion = await _registryClient.Registry.SuggestAsync(_gameConfiguration.PublicURL, cts.Token);

                if (suggestion != "localhost")
                {
                    _options.DnsNames = new[] { suggestion }
                }
                ;
                else
                {
                    if (!WarnedLocalMode)
                    {
                        _logger.LogWarning("registry reports we are not accessible on http TCP/80 on our public IP. If you're in development mode, this is fine.");
                    }

                    WarnedLocalMode = true;
                    return;
                }
            }
            catch (Exception e)
            {
                _logger.LogError("** failed to get suggestion from registry: " + e);
            }

            if (_options.DnsNames == null)
            {
                return;
            }

            _logger.LogInformation("** Checking LetsEncrypt status *****************************************");
            _logger.LogInformation($"DNS Names:  {string.Join(",", _options.DnsNames)}");

            if (_state.Certificate != null)
            {
                var now = DateTime.Now;
                if (_state.Certificate.NotAfter > now)
                {
                    _logger.LogInformation("Existing certificate is Good!");
                    return;
                }
                else
                {
                    _logger.LogWarning($"Existing Certificate is Expired! {_state.Certificate.NotAfter} > {now}");
                }
            }
            else
            {
                _logger.LogWarning("Missing Certificate");
            }

            try
            {
                Directory.Delete(_state.RootDir, true);
            }
            catch (Exception) { }
            Reinitialize();


            try
            {
                var acmeUrl = new Uri(_options.CaUrl);
                using (var acme = new AcmeProtocolClient(acmeUrl))
                {
                    _state.ServiceDirectory = await acme.GetDirectoryAsync();

                    Save(_state.ServiceDirectoryFile, _state.ServiceDirectory);
                    acme.Directory = _state.ServiceDirectory;

                    Save(_state.TermsOfServiceFile,
                         await acme.GetTermsOfServiceAsync());

                    await acme.GetNonceAsync();

                    if (!await ResolveAccount(acme))
                    {
                        return;
                    }

                    if (!await ResolveOrder(acme))
                    {
                        return;
                    }

                    if (!await ResolveChallenges(acme))
                    {
                        return;
                    }

                    if (!await ResolveAuthorizations(acme))
                    {
                        return;
                    }

                    if (!await ResolveCertificate(acme))
                    {
                        return;
                    }
                }
            }
            catch (Exception e)
            {
                _logger.LogWarning($"Exception while getting SSL Certificate: {e}");
            }
        }