public PendingAuthorization BeginRegistrationAndValidation(CertRequestConfig requestConfig, string identifierAlias, string challengeType = ACMESharpCompat.ACMESharpUtils.CHALLENGE_TYPE_HTTP, string domain = null) { //if no alternative domain specified, use the primary domains as the subject if (domain == null) { domain = requestConfig.PrimaryDomain; } // if (GetIdentifier(identifierAlias) == null) //if an identifier exists for the same dns in vault, remove it to avoid confusion this.DeleteIdentifierByDNS(domain); // ACME service requires international domain names in ascii mode, register the new // identifier with Lets Encrypt var authState = ACMESharpUtils.NewIdentifier(identifierAlias, idnMapping.GetAscii(domain)); var identifier = this.GetIdentifier(identifierAlias, reloadVaultConfig: true); //FIXME: when validating subsequent SAN names in parallel request mode, the identifier is null? if (identifier != null && identifier.Authorization != null && identifier.Authorization.IsPending()) { ACMESharpUtils.CompleteChallenge(identifier.Alias, challengeType, Handler: "manual", Regenerate: true, Repeat: true); //get challenge info ReloadVaultConfig(); identifier = GetIdentifier(identifierAlias); try { //identifier challenge specification is now ready for use to prepare and answer for LetsEncrypt to check var challengeInfo = identifier.Challenges.FirstOrDefault(c => c.Value.Type == challengeType).Value; return(new PendingAuthorization() { Challenge = GetAuthorizeChallengeItemFromAuthChallenge(challengeInfo), Identifier = GetDomainIdentifierItemFromIdentifierInfo(identifier), TempFilePath = "", ExtensionlessConfigCheckedOK = false, LogItems = this.GetActionLogSummary() }); } catch (Exception exp) { LogAction("GetIdentifier", exp.ToString()); //identifier challenge could not be requested this time (FIXME: did we discard it when reloading vault?) return(null); } } else { //identifier is null or already valid (previously authorized) return(new PendingAuthorization() { Challenge = null, Identifier = GetDomainIdentifierItemFromIdentifierInfo(identifier), TempFilePath = "", ExtensionlessConfigCheckedOK = false, LogItems = this.GetActionLogSummary() }); } }
public PendingAuthorization BeginRegistrationAndValidation(CertRequestConfig requestConfig, string identifierAlias, string challengeType = "http-01", string domain = null) { //if no alternative domain specified, use the primary domains as the subject if (domain == null) { domain = requestConfig.PrimaryDomain; } // if (GetIdentifier(identifierAlias) == null) //if an identifier exists for the same dns in vault, remove it to avoid confusion this.DeleteIdentifierByDNS(domain); // ACME service requires international domain names in ascii mode, regiser the new identifier with Lets Encrypt var authState = ACMESharpUtils.NewIdentifier(identifierAlias, idnMapping.GetAscii(domain)); var identifier = this.GetIdentifier(identifierAlias, reloadVaultConfig: true); //FIXME: when validating subsequent SAN names in parallel request mode, the identifier is null? if (identifier != null && identifier.Authorization != null && identifier.Authorization.IsPending()) { ACMESharpUtils.CompleteChallenge(identifier.Alias, challengeType, Handler: "manual", Regenerate: true, Repeat: true); //get challenge info ReloadVaultConfig(); identifier = GetIdentifier(identifierAlias); var challengeInfo = identifier.Challenges.FirstOrDefault(c => c.Value.Type == challengeType).Value; //identifier challenege specification is now ready for use to prepare and answer for LetsEncrypt to check return(new PendingAuthorization() { Challenge = challengeInfo, Identifier = identifier, TempFilePath = "", ExtensionlessConfigCheckedOK = false }); } else { //identifier is null or already valid (previously authorized) return(new PendingAuthorization() { Challenge = null, Identifier = identifier, TempFilePath = "", ExtensionlessConfigCheckedOK = false }); } }
static void Main(string[] args) { Trace.EnableConsole(); Trace.EnableFile(); if (!CheckParmeter()) { return; } Trace.Info("check config ok!~"); InitializeVault(); Trace.Info("init vault ok!~"); try { ACMESharpUtils.NewRegistration("", new string[] { "mailto:" + Config.Mail }, true); } catch (Exception ex) { Trace.Error("registration error", ex); return; } Trace.Info("registration ok!~"); try { ACMESharpUtils.NewIdentifier("dns1", Config.Domain); } catch (Exception ex) { Trace.Error("newidentityfier error", ex); return; } Trace.Info("newidentityfier ok!~"); try { AuthorizationState state = ACMESharpUtils.CompleteChallenge("dns1", "http-01", "manual"); if (!CreateChallengeFile(state)) { Trace.Error("create challenge file erro"); return; } } catch (Exception ex) { Trace.Error("complete challenge error", ex); return; } Trace.Info("challege ok"); try { ACMESharpUtils.SubmitChallenge("dns1", "http-01"); } catch (Exception ex) { Trace.Error("submit challenge error", ex); return; } Trace.Info("submit challage ok!~"); Trace.Info("wait LE identifier"); DateTime startT = DateTime.Now; bool result = false; while ((DateTime.Now - startT).TotalSeconds < 300) { AuthorizationState state = null; try { state = ACMESharpUtils.UpdateIdentifier("dns1", "http-01"); } catch (Exception ex) { Trace.Error("update identifier error"); return; } if (state == null) { Trace.Error("update identifier state is null"); return; } var subResultState = state.Challenges.First <ACMESharp.AuthorizeChallenge>(item => item.Type == "http-01"); if (subResultState == null) { SaveState(state); Trace.Error("state is null"); return; } if (subResultState.Status.Equals("valid", StringComparison.CurrentCultureIgnoreCase)) { result = true; break; } else if (subResultState.Status.Equals("invalid", StringComparison.CurrentCultureIgnoreCase)) { SaveState(state); Trace.Error("state is invalid"); return; } else { Trace.Info(DateTime.Now.ToString("HH:mm:ss") + ",status is:" + subResultState.Status); } System.Threading.Thread.Sleep(5000); } if (!result) { Trace.Error("update identifer timeout"); return; } Trace.Info("update identifier ok!~"); try { ACMESharpUtils.NewCertificate("cert1", "dns1", null); } catch (Exception ex) { Trace.Error("new certificate erro", ex); return; } Trace.Info("new certificate is ok!~"); try { ACMESharpUtils.SubmitCertificate("cert1"); } catch (Exception ex) { Trace.Error("submit certificateerro", ex); return; } Trace.Info("submit certificate is ok!~"); try { CertificateInfo info = ACMESharpUtils.UpdateCertificate("cert1"); } catch (Exception ex) { Trace.Error("update certificate erro", ex); return; } Trace.Info("update certificate is ok!~"); if (!GenericCertificate()) { return; } Trace.Info("success!~"); if (Environment.UserInteractive) { Trace.Info("Enter press any key exit!~"); Console.ReadKey(); } }
public PendingAuthorization BeginRegistrationAndValidation(CertRequestConfig requestConfig, string identifierAlias, string challengeType = ACMESharpCompat.ACMESharpUtils.CHALLENGE_TYPE_HTTP, string domain = null) { //if no alternative domain specified, use the primary domains as the subject if (domain == null) { domain = requestConfig.PrimaryDomain; } // if (GetIdentifier(identifierAlias) == null) //if an identifier exists for the same dns in vault, remove it to avoid confusion this.DeleteIdentifierByDNS(domain); // ACME service requires international domain names in ascii mode, create new identifier // in vault try { var authState = ACMESharpUtils.NewIdentifier(identifierAlias, idnMapping.GetAscii(domain)); } catch (ACMESharp.AcmeClient.AcmeWebException exp) { //if we don't know the problem details, report the whole exception if (exp.Response?.ProblemDetail == null) { throw exp; } // failed to register the domain identifier with LE (invalid, rate limit or CAA fail?) LogAction("NewIdentifier [" + domain + "]", exp.Response.ProblemDetail.OrignalContent); return(new PendingAuthorization { AuthorizationError = $"{exp.Response.ProblemDetail.Detail} : {exp.Response.ProblemDetail.Type}" }); } catch (Exception exp) { // failed to register the domain identifier with LE (rate limit or CAA fail?) LogAction("NewIdentifier [" + domain + "]", exp.ToString()); return(new PendingAuthorization { AuthorizationError = exp.ToString() }); } Thread.Sleep(200); var identifier = this.GetIdentifier(identifierAlias, reloadVaultConfig: true); //FIXME: when validating subsequent SAN names in parallel request mode, the identifier is null? if (identifier != null && identifier.Authorization != null && identifier.Authorization.IsPending()) { var authState = ACMESharpUtils.CompleteChallenge(identifier.Alias, challengeType, Handler: "manual", Regenerate: true, Repeat: true); LogAction("CompleteChallenge", authState.Status); //get challenge info for this identifier identifier = GetIdentifier(identifierAlias, reloadVaultConfig: true); try { //identifier challenge specification is now ready for use to prepare and answer for LetsEncrypt to check var challenges = new List <AuthorizationChallengeItem>(); foreach (var c in identifier.Challenges) { if (c.Value.Type == SupportedChallengeTypes.CHALLENGE_TYPE_HTTP) { var httpChallenge = (ACMESharp.ACME.HttpChallenge)c.Value.Challenge; challenges.Add(new AuthorizationChallengeItem { ChallengeType = SupportedChallengeTypes.CHALLENGE_TYPE_HTTP, ChallengeData = c.Value, ResourcePath = httpChallenge.FilePath, ResourceUri = httpChallenge.FileUrl, Key = c.Value.Token, Value = httpChallenge.FileContent }); } if (c.Value.Type == SupportedChallengeTypes.CHALLENGE_TYPE_SNI) { var tlsSniChallenge = (ACMESharp.ACME.TlsSniChallenge)c.Value.Challenge; var tlsSniAnswer = (ACMESharp.ACME.TlsSniChallengeAnswer)tlsSniChallenge.Answer; challenges.Add(new AuthorizationChallengeItem { ChallengeType = SupportedChallengeTypes.CHALLENGE_TYPE_SNI, ChallengeData = tlsSniChallenge, Key = tlsSniChallenge.Token, Value = tlsSniAnswer.KeyAuthorization, HashIterationCount = tlsSniChallenge.IterationCount }); } //TODO: dns if (c.Value.Type == SupportedChallengeTypes.CHALLENGE_TYPE_DNS) { var dnsChallenge = (ACMESharp.ACME.DnsChallenge)c.Value.Challenge; challenges.Add(new AuthorizationChallengeItem { ChallengeType = SupportedChallengeTypes.CHALLENGE_TYPE_DNS, ChallengeData = dnsChallenge, Key = dnsChallenge.RecordName, Value = dnsChallenge.RecordValue }); } } return(new PendingAuthorization() { Challenges = challenges, Identifier = GetDomainIdentifierItemFromIdentifierInfo(identifier) }); } catch (Exception exp) { //identifier challenge could not be requested this time LogAction("GetIdentifier", exp.ToString()); return(null); } } else { //identifier is null or already valid (previously authorized) return(new PendingAuthorization() { Challenges = null, Identifier = GetDomainIdentifierItemFromIdentifierInfo(identifier), LogItems = this.GetActionLogSummary() }); } }