/// <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 async Task <Challenge> Authorize( ILifetimeScope execute, RunLevel runLevel, ValidationPluginOptions options, TargetPart targetPart, Authorization authorization) { var invalid = new Challenge { Status = AcmeClient.AuthorizationInvalid }; var valid = new Challenge { Status = AcmeClient.AuthorizationValid }; var client = execute.Resolve <AcmeClient>(); var identifier = authorization.Identifier.Value; try { _log.Information("Authorize identifier: {identifier}", identifier); if (authorization.Status == AcmeClient.AuthorizationValid && !runLevel.HasFlag(RunLevel.Test) && !runLevel.HasFlag(RunLevel.IgnoreCache)) { _log.Information("Cached authorization result: {Status}", authorization.Status); return(valid); } else { using var validation = _scopeBuilder.Validation(execute, options, targetPart, identifier); IValidationPlugin validationPlugin = null; try { validationPlugin = validation.Resolve <IValidationPlugin>(); } catch (Exception ex) { _log.Error(ex, "Error resolving validation plugin"); } if (validationPlugin == null) { _log.Error("Validation plugin not found or not created."); return(invalid); } if (validationPlugin.Disabled) { _log.Error("Validation plugin is not available to the current user, try running as administrator."); return(invalid); } var challenge = authorization.Challenges.FirstOrDefault(c => c.Type == options.ChallengeType); if (challenge == null) { _log.Error("Expected challenge type {type} not available for {identifier}.", options.ChallengeType, authorization.Identifier.Value); return(invalid); } if (challenge.Status == AcmeClient.AuthorizationValid && !runLevel.HasFlag(RunLevel.Test) && !runLevel.HasFlag(RunLevel.IgnoreCache)) { _log.Information("{dnsIdentifier} already validated by {challengeType} validation ({name})", authorization.Identifier.Value, options.ChallengeType, options.Name); return(valid); } _log.Information("Authorizing {dnsIdentifier} using {challengeType} validation ({name})", identifier, options.ChallengeType, options.Name); try { var details = client.DecodeChallengeValidation(authorization, challenge); await validationPlugin.PrepareChallenge(details); } catch (Exception ex) { _log.Error(ex, "Error preparing for challenge answer"); return(invalid); } _log.Debug("Submitting challenge answer"); challenge = await client.AnswerChallenge(challenge); if (challenge.Status != AcmeClient.AuthorizationValid) { if (challenge.Error != null) { _log.Error(challenge.Error.ToString()); } _log.Error("Authorization result: {Status}", challenge.Status); return(invalid); } else { _log.Information("Authorization result: {Status}", challenge.Status); return(valid); } } } catch (Exception ex) { _log.Error("Error authorizing {renewal}", targetPart); _exceptionHandler.HandleException(ex); return(invalid); } }
/// <summary> /// Make sure we have authorization for every host in target /// </summary> /// <param name="target"></param> /// <returns></returns> private Challenge Authorize(ILifetimeScope execute, RunLevel runLevel, OrderDetails order, ValidationPluginOptions options, TargetPart targetPart, Authorization authorization) { var invalid = new Challenge { Status = _authorizationInvalid }; var valid = new Challenge { Status = _authorizationValid }; var client = execute.Resolve <AcmeClient>(); var identifier = authorization.Identifier.Value; try { _log.Information("Authorize identifier: {identifier}", identifier); if (authorization.Status == _authorizationValid && !runLevel.HasFlag(RunLevel.Test)) { _log.Information("Cached authorization result: {Status}", authorization.Status); return(valid); } else { using (var validation = _scopeBuilder.Validation(execute, options, targetPart, identifier)) { IValidationPlugin validationPlugin = null; try { validationPlugin = validation.Resolve <IValidationPlugin>(); } catch (Exception ex) { _log.Error(ex, "Error resolving validation plugin"); } if (validationPlugin == null) { _log.Error("Validation plugin not found or not created."); return(invalid); } var challenge = authorization.Challenges.FirstOrDefault(c => c.Type == options.ChallengeType); if (challenge == null) { _log.Error("Expected challenge type {type} not available for {identifier}.", options.ChallengeType, authorization.Identifier.Value); return(invalid); } if (challenge.Status == _authorizationValid && !runLevel.HasFlag(RunLevel.Test)) { _log.Information("{dnsIdentifier} already validated by {challengeType} validation ({name})", authorization.Identifier.Value, options.ChallengeType, options.Name); return(valid); } _log.Information("Authorizing {dnsIdentifier} using {challengeType} validation ({name})", identifier, options.ChallengeType, options.Name); try { var details = client.DecodeChallengeValidation(authorization, challenge); validationPlugin.PrepareChallenge(details); } catch (Exception ex) { _log.Error(ex, "Error preparing for challenge answer"); return(invalid); } _log.Debug("Submitting challenge answer"); challenge = client.AnswerChallenge(challenge); // Have to loop to wait for server to stop being pending var tries = 0; var maxTries = 4; while (challenge.Status == _authorizationPending) { _log.Debug("Refreshing authorization"); Thread.Sleep(2000); // this has to be here to give ACME server a chance to think challenge = client.GetChallengeDetails(challenge.Url); tries += 1; if (tries > maxTries) { _log.Error("Authorization timed out"); return(invalid); } } if (challenge.Status != _authorizationValid) { _log.Error("Authorization result: {Status}", challenge.Status); return(invalid); } else { _log.Information("Authorization result: {Status}", challenge.Status); return(valid); } } } } catch (Exception ex) { _log.Error("Error authorizing {renewal}", targetPart); HandleException(ex); return(invalid); } }
/// <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); } }