/// <summary> /// Make sure we have authorization for every host in target /// </summary> /// <param name="target"></param> /// <returns></returns> private static AuthorizationState Authorize(ILifetimeScope renewalScope, Target target) { List <string> identifiers = target.GetHosts(false); List <AuthorizationState> authStatus = new List <AuthorizationState>(); var client = renewalScope.Resolve <LetsEncryptClient>(); foreach (var identifier in identifiers) { var authzState = client.Acme.AuthorizeIdentifier(identifier); if (authzState.Status == _authorizationValid && !_options.Test) { _log.Information("Cached authorization result: {Status}", authzState.Status); authStatus.Add(authzState); } else { using (var identifierScope = AutofacBuilder.Identifier(renewalScope, target, identifier)) { IValidationPluginFactory validationPluginFactory = null; IValidationPlugin validationPlugin = null; try { validationPluginFactory = identifierScope.Resolve <IValidationPluginFactory>(); validationPlugin = identifierScope.Resolve <IValidationPlugin>(); } catch { } if (validationPluginFactory == null || validationPluginFactory is INull || validationPlugin == null) { return(new AuthorizationState { Status = _authorizationInvalid }); } _log.Information("Authorizing {dnsIdentifier} using {challengeType} validation ({name})", identifier, validationPluginFactory.ChallengeType, validationPluginFactory.Name); var challenge = client.Acme.DecodeChallenge(authzState, validationPluginFactory.ChallengeType); validationPlugin.PrepareChallenge(challenge); _log.Debug("Submitting answer"); authzState.Challenges = new AuthorizeChallenge[] { challenge }; client.Acme.SubmitChallengeAnswer(authzState, validationPluginFactory.ChallengeType, true); // have to loop to wait for server to stop being pending. // TODO: put timeout/retry limit in this loop while (authzState.Status == _authorizationPending) { _log.Debug("Refreshing authorization"); Thread.Sleep(4000); // this has to be here to give ACME server a chance to think var newAuthzState = client.Acme.RefreshIdentifierAuthorization(authzState); if (newAuthzState.Status != _authorizationPending) { authzState = newAuthzState; } } if (authzState.Status != _authorizationValid) { _log.Information("Authorization result: {Status}", authzState.Status); } else { _log.Error("Authorization result: {Status}", authzState.Status); } authStatus.Add(authzState); } } } foreach (var authState in authStatus) { if (authState.Status != _authorizationValid) { return(authState); } } return(new AuthorizationState { Status = _authorizationValid }); }
/// <summary> /// Make sure we have authorization for every host in target /// </summary> /// <param name="target"></param> /// <returns></returns> private static AuthorizationState Authorize(ILifetimeScope renewalScope, Target target) { var invalid = new AuthorizationState { Status = _authorizationInvalid }; try { var identifiers = target.GetHosts(false); var authStatus = new List <AuthorizationState>(); var client = renewalScope.Resolve <AcmeClientWrapper>(); foreach (var identifier in identifiers) { _log.Information("Authorize identifier: {identifier}", identifier); var authzState = client.Acme.AuthorizeIdentifier(identifier); if (authzState.Status == _authorizationValid && !_options.Test) { _log.Information("Cached authorization result: {Status}", authzState.Status); authStatus.Add(authzState); } else { using (var identifierScope = AutofacBuilder.Identifier(renewalScope, target, identifier)) { IValidationPluginFactory validationPluginFactory = null; IValidationPlugin validationPlugin = null; try { validationPluginFactory = identifierScope.Resolve <IValidationPluginFactory>(); validationPlugin = identifierScope.Resolve <IValidationPlugin>(); } catch (Exception ex) { _log.Error(ex, "Error resolving validation plugin"); } if (validationPluginFactory == null || validationPluginFactory is INull || validationPlugin == null) { _log.Error("Validation plugin not found or not created."); return(invalid); } if (!authzState.Challenges.Any(c => c.Type == validationPluginFactory.ChallengeType)) { _log.Error("Expected challenge type {type} not available for {identifier}.", validationPluginFactory.ChallengeType, identifier); return(invalid); } _log.Information("Authorizing {dnsIdentifier} using {challengeType} validation ({name})", identifier, validationPluginFactory.ChallengeType, validationPluginFactory.Name); var challenge = client.Acme.DecodeChallenge(authzState, validationPluginFactory.ChallengeType); try { validationPlugin.PrepareChallenge(challenge); } catch (Exception ex) { _log.Error(ex, "Error preparing for challenge answer"); return(invalid); } _log.Debug("Submitting answer"); authzState.Challenges = new AuthorizeChallenge[] { challenge }; client.Acme.SubmitChallengeAnswer(authzState, validationPluginFactory.ChallengeType, true); // have to loop to wait for server to stop being pending. // TODO: put timeout/retry limit in this loop while (authzState.Status == _authorizationPending) { _log.Debug("Refreshing authorization"); Thread.Sleep(4000); // this has to be here to give ACME server a chance to think var newAuthzState = client.Acme.RefreshIdentifierAuthorization(authzState); if (newAuthzState.Status != _authorizationPending) { authzState = newAuthzState; } } if (authzState.Status != _authorizationValid) { _log.Error("Authorization result: {Status}", authzState.Status); } else { _log.Information("Authorization result: {Status}", authzState.Status); } authStatus.Add(authzState); } } } foreach (var authState in authStatus) { if (authState.Status != _authorizationValid) { return(authState); } } return(new AuthorizationState { Status = _authorizationValid }); } catch (Exception ex) { _log.Error("Error authorizing {target}", target); HandleException(ex); return(invalid); } }