/// <summary> /// Make sure we have authorization for every host in target /// </summary> /// <param name="target"></param> /// <returns></returns> private async Task AnswerChallenge(ValidationContext validationContext) { if (validationContext.Challenge == null) { throw new InvalidOperationException("No challenge found"); } try { _log.Debug("[{identifier}] Submitting challenge answer", validationContext.Label); var client = validationContext.Scope.Resolve <AcmeClient>(); var updatedChallenge = await client.AnswerChallenge(validationContext.Challenge); validationContext.Challenge = updatedChallenge; if (updatedChallenge.Status != AcmeClient.ChallengeValid) { _log.Error("[{identifier}] Authorization result: {Status}", validationContext.Label, updatedChallenge.Status); if (updatedChallenge.Error != null) { _log.Error("[{identifier}] {Error}", validationContext.Label, updatedChallenge.Error.ToString()); } validationContext.AddErrorMessage("Validation failed", validationContext.Success != true); return; } else { validationContext.Success = true; _log.Information("[{identifier}] Authorization result: {Status}", validationContext.Label, updatedChallenge.Status); return; } } catch (Exception ex) { _log.Error("[{identifier}] Error submitting challenge answer", validationContext.Label); var message = _exceptionHandler.HandleException(ex); validationContext.AddErrorMessage(message, validationContext.Success != true); } }
/// <summary> /// Make sure we have authorization for every host in target /// </summary> /// <param name="target"></param> /// <returns></returns> private async Task PrepareChallengeAnswer(ValidationContext context, RunLevel runLevel) { if (context.ValidationPlugin == null) { throw new InvalidOperationException("No validation plugin configured"); } var client = context.Scope.Resolve <AcmeClient>(); try { if (context.Authorization.Status == AcmeClient.AuthorizationValid) { context.Success = true; _log.Information("[{identifier}] Cached authorization result: {Status}", context.Label, context.Authorization.Status); if (!runLevel.HasFlag(RunLevel.Test) && !runLevel.HasFlag(RunLevel.IgnoreCache)) { return; } _log.Information("[{identifier}] Handling challenge anyway because --test and/or --force is active", context.Label); } _log.Information("[{identifier}] Authorizing...", context.Label); _log.Verbose("[{identifier}] Initial authorization status: {status}", context.Label, context.Authorization.Status); _log.Verbose("[{identifier}] Challenge types available: {challenges}", context.Label, context.Authorization.Challenges.Select(x => x.Type ?? "[Unknown]")); var challenge = context.Authorization.Challenges.FirstOrDefault(c => string.Equals(c.Type, context.ChallengeType, StringComparison.InvariantCultureIgnoreCase)); if (challenge == null) { if (context.Success == true) { var usedType = context.Authorization.Challenges. Where(x => x.Status == AcmeClient.ChallengeValid). FirstOrDefault(); _log.Warning("[{identifier}] Expected challenge type {type} not available, already validated using {valided}.", context.Label, context.ChallengeType, usedType?.Type ?? "[unknown]"); return; } else { _log.Error("[{identifier}] Expected challenge type {type} not available.", context.Label, context.ChallengeType); context.AddErrorMessage("Expected challenge type not available", context.Success == false); return; } } else { _log.Verbose("[{identifier}] Initial challenge status: {status}", context.Label, challenge.Status); if (challenge.Status == AcmeClient.ChallengeValid) { // We actually should not get here because if one of the // challenges is valid, the authorization itself should also // be valid. if (!runLevel.HasFlag(RunLevel.Test) && !runLevel.HasFlag(RunLevel.IgnoreCache)) { _log.Information("[{identifier}] Cached challenge result: {Status}", context.Label, context.Authorization.Status); return; } } } _log.Information("[{identifier}] Authorizing using {challengeType} validation ({name})", context.Label, context.ChallengeType, context.PluginName); try { // Now that we're going to call into PrepareChallenge, we will assume // responsibility to also call CleanUp later, which is signalled by // the Challenge propery being not null context.ChallengeDetails = await client.DecodeChallengeValidation(context.Authorization, challenge); context.Challenge = challenge; await context.ValidationPlugin.PrepareChallenge(context); } catch (Exception ex) { _log.Error(ex, "[{identifier}] Error preparing for challenge answer", context.Label); context.AddErrorMessage("Error preparing for challenge answer", context.Success == false); return; } } catch (Exception ex) { _log.Error("[{identifier}] Error preparing challenge answer", context.Label); var message = _exceptionHandler.HandleException(ex); context.AddErrorMessage(message, context.Success == false); } }