private static StepResult InvalidSignatureResult(string description, ErrorAlias errorAlias, MessagingContext context) { Logger.Error(description); context.ErrorResult = new ErrorResult(description, errorAlias); return(StepResult.Failed(context)); }
private async Task <StepResult> DecryptAS4MessageAsync(MessagingContext messagingContext) { try { Logger.Trace("Start decrypting AS4Message ..."); X509Certificate2 decryptionCertificate = GetCertificate(messagingContext); messagingContext.AS4Message.Decrypt(decryptionCertificate); Logger.Info($"{messagingContext.LogTag} AS4Message is decrypted correctly"); JournalLogEntry entry = JournalLogEntry.CreateFrom( messagingContext.AS4Message, $"Decrypted using certificate {decryptionCertificate.FriendlyName}"); return(await StepResult .Success(messagingContext) .WithJournalAsync(entry)); } catch (Exception ex) when(ex is CryptoException || ex is CryptographicException) { Logger.Error(ex); messagingContext.ErrorResult = new ErrorResult( description: "Decryption of message failed", alias: ErrorAlias.FailedDecryption); Logger.Error(messagingContext.ErrorResult.Description); return(StepResult.Failed(messagingContext)); } }
/// <summary> /// Handle the given <paramref name="response" />, but delegate to the next handler if you can't. /// </summary> /// <param name="response"></param> /// <returns></returns> public async Task <StepResult> HandleResponse(IAS4Response response) { if (response.ReceivedAS4Message.IsEmpty) { if (response.StatusCode == HttpStatusCode.Accepted) { response.OriginalRequest.ModifyContext(response.ReceivedAS4Message, MessagingContextMode.Send); return(StepResult.Success(response.OriginalRequest).AndStopExecution()); } Logger.Error($"Response with HTTP status: {response.StatusCode}"); if (Logger.IsErrorEnabled) { using (var r = new StreamReader(response.ReceivedStream.UnderlyingStream)) { string content = await r.ReadToEndAsync(); if (!string.IsNullOrEmpty(content)) { Logger.Error("Response with HTTP content: " + content); } } } response.OriginalRequest.ModifyContext(response.ReceivedStream, MessagingContextMode.Send); return(StepResult.Failed(response.OriginalRequest).AndStopExecution()); } return(await _nextHandler.HandleResponse(response)); }
/// <summary> /// Execute the step for a given <paramref name="messagingContext"/>. /// </summary> /// <param name="messagingContext">Message used during the step execution.</param> /// <returns></returns> public Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { var result = new ErrorResult(description: "error", alias: default(ErrorAlias)); return(Task.FromResult(StepResult.Failed(new HappyContext { ErrorResult = result }))); }
public void IsFalseIfStopExecutionIsCalled() { // Act StepResult actualStepResult = StepResult.Failed(new MessagingContext(AS4Message.Empty, MessagingContextMode.Send)).AndStopExecution(); // Assert Assert.False(actualStepResult.CanProceed); Assert.False(actualStepResult.Succeeded); }
public Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { return(StepResult .Failed(messagingContext) .WithJournalAsync( JournalLogEntry.CreateFrom( messagingContext.AS4Message, "Log entry 3"))); }
/// <summary> /// Send the <see cref="AS4Message" /> /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.ReceivedMessage == null && messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(SendAS4MessageStep)} requires a MessagingContext with a ReceivedStream or an AS4Message to correctly send the message"); } if (messagingContext.ReceivedMessage == null && messagingContext.AS4Message.IsPullRequest == false) { throw new InvalidOperationException( $"{nameof(SendAS4MessageStep)} expects a PullRequest AS4Message when the MessagingContext does not contain a ReceivedStream"); } PushConfiguration pushConfig = GetPushConfiguration(messagingContext.SendingPMode, messagingContext.ReceivingPMode); if (pushConfig?.Protocol?.Url == null) { throw new ConfigurationErrorsException( "Message cannot be send because neither the Sending or Receiving PMode has a Protocol.Url child in a <PushConfiguration/> or <ResponseConfiguration/> element"); } AS4Message as4Message = await DeserializeUnderlyingStreamIfPresentAsync( messagingContext.ReceivedMessage, otherwise : messagingContext.AS4Message); try { string contentType = messagingContext.ReceivedMessage?.ContentType ?? messagingContext.AS4Message.ContentType; HttpWebRequest request = CreateWebRequest(pushConfig, contentType.Replace("charset=\"utf-8\"", "")); await WriteToHttpRequestStreamAsync(request, messagingContext).ConfigureAwait(false); messagingContext.ModifyContext(as4Message); return(await HandleHttpResponseAsync(request, messagingContext).ConfigureAwait(false)); } catch { await UpdateRetryStatusForMessageAsync(messagingContext, SendResult.RetryableFail); return(StepResult.Failed(messagingContext).AndStopExecution()); } }
/// <summary> /// Start updating the Data store /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> /// <exception cref="Exception">A delegate callback throws an exception.</exception> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.ReceivedMessage == null) { throw new InvalidOperationException( $"{nameof(SaveReceivedMessageStep)} requires a ReceivedMessage to store the incoming message into the datastore but no ReceivedMessage is present in the MessagingContext"); } if (messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(SaveReceivedMessageStep)} requires an AS4Message to save but no AS4Message is present in the MessagingContext"); } Logger.Trace($"{messagingContext.LogTag} Store the incoming AS4 Message to the datastore"); MessagingContext resultContext = await InsertReceivedAS4MessageAsync(messagingContext); if (resultContext != null && resultContext.Exception == null) { /* PullRequests will not be notified, so we don't need a referenced Id, * Receipts and Errors will need to have a referenced UserMessage * if we want to know the original Sending PMode required for the notification. */ MessageUnit primaryMessageUnit = resultContext.AS4Message.PrimaryMessageUnit; if ((primaryMessageUnit is Receipt || primaryMessageUnit is Error) && string.IsNullOrWhiteSpace(primaryMessageUnit.RefToMessageId)) { Logger.Warn( $"{messagingContext.LogTag} Received message is a SignalMessage without RefToMessageId. " + "No such SignalMessage are supported so the message cannot be processed any further"); return(StepResult .Success(new MessagingContext(AS4Message.Empty, messagingContext.Mode)) .AndStopExecution()); } Logger.Trace($"{messagingContext.LogTag} The AS4Message is successfully stored into the datastore"); return(StepResult.Success(resultContext)); } Logger.Error($"{messagingContext.LogTag} The AS4Message is not stored correctly into the datastore {resultContext?.Exception}"); return(StepResult.Failed(resultContext)); }
/// <summary> /// It is only executed when the external message (received) is an AS4 UserMessage /// </summary> /// <param name="messagingContext"></param> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(CreateAS4ReceiptStep)} requires an AS4Message to create ebMS Receipts but no AS4Message is present in the MessagingContext"); } bool receiptSigning = messagingContext.ReceivingPMode?.ReplyHandling?.ResponseSigning?.IsEnabled ?? false; bool useNRRFormat = messagingContext.ReceivingPMode?.ReplyHandling?.ReceiptHandling?.UseNRRFormat ?? false; if (!receiptSigning && useNRRFormat) { Logger.Error( "Cannot create Non-Repudiation Receipts that aren\'t signed, please change either the " + $"ReceivingPMode {messagingContext.ReceivingPMode.Id} ReplyHandling.ReceiptHandling.UseNRRFormat or the ReplyHandling.ResponseSigning"); messagingContext.ErrorResult = new ErrorResult( "Cannot create Non-Repudiation Receipts that aren't signed", ErrorAlias.InvalidReceipt); return(StepResult.Failed(messagingContext)); } AS4Message receivedMessage = messagingContext.AS4Message; AS4Message receiptMessage = AS4Message.Empty; receiptMessage.SigningId = receivedMessage.SigningId; foreach (UserMessage userMessage in receivedMessage.UserMessages) { Receipt receipt = CreateReferencedReceipt(userMessage, receivedMessage, messagingContext.ReceivingPMode); receiptMessage.AddMessageUnit(receipt); } if (Logger.IsInfoEnabled && receiptMessage.MessageUnits.Any()) { Logger.Info($"{messagingContext.LogTag} {receiptMessage.MessageUnits.Count()} Receipt message(s) has been created for received AS4 UserMessages"); } messagingContext.ModifyContext(receiptMessage); return(await StepResult.SuccessAsync(messagingContext)); }
/// <summary> /// Decompress any Attachments /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(DecompressAttachmentsStep)} requires a AS4Message but no AS4Message is present in the MessagingContext"); } if (messagingContext.ReceivedMessageMustBeForwarded) { Logger.Debug("No decompression will happen because the incoming AS4Message must be forwarded unchanged"); return(StepResult.Success(messagingContext)); } if (messagingContext.AS4Message.HasAttachments == false) { Logger.Debug("No decompression will happen because the AS4Message hasn't got any attachments to decompress"); return(StepResult.Success(messagingContext)); } if (messagingContext.AS4Message.IsEncrypted) { Logger.Warn("Incoming attachmets are still encrypted will fail to decompress correctly"); } try { messagingContext.AS4Message.DecompressAttachments(); Logger.Info("(Receive) AS4Message is decompressed correctly"); JournalLogEntry entry = JournalLogEntry.CreateFrom( messagingContext.AS4Message, $"Decompressed {messagingContext.AS4Message.Attachments.Count()} with GZip compression"); return(await StepResult .Success(messagingContext) .WithJournalAsync(entry)); } catch (Exception exception) when(exception is ArgumentException || exception is ObjectDisposedException || exception is InvalidDataException) { var description = "Decompression failed due to an exception"; if (messagingContext.AS4Message.IsEncrypted) { Logger.Error( "Decompression failed because the incoming attachments are still encrypted. " + "Make sure that you specify <Decryption/> information in the <Security/> element of the " + "ReceivingPMode so the attachments are first decrypted before decompressed"); description = "Decompression failed because the incoming attachments are still encrypted"; } messagingContext.ErrorResult = new ErrorResult( description, ErrorAlias.DecompressionFailure); return(StepResult.Failed(messagingContext)); } }
/// <summary> /// Start uploading the AS4 Message Payloads /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.DeliverMessage == null) { throw new InvalidOperationException( $"{nameof(UploadAttachmentsStep)} requires a DeliverMessage to upload the attachments from but no DeliverMessage is present in the MessagingContext"); } DeliverMessageEnvelope deliverEnvelope = messagingContext.DeliverMessage; if (!deliverEnvelope.Attachments.Any()) { Logger.Debug("(Deliver) No attachments to upload for DeliverMessage"); return(StepResult.Success(messagingContext)); } if (messagingContext.ReceivingPMode == null) { throw new InvalidOperationException( "Unable to send DeliverMessage: no ReceivingPMode is set"); } if (messagingContext.ReceivingPMode.MessageHandling?.DeliverInformation?.PayloadReferenceMethod == null) { throw new InvalidOperationException( $"Unable to send the DeliverMessage: the ReceivingPMode {messagingContext.ReceivingPMode.Id} " + "does not contain any <PayloadReferenceMethod/> element in the MessageHandling.Deliver element. " + "Please provide a correct <PayloadReferenceMethod/> tag to indicate where the attachments of the DeliverMessage should be sent to."); } if (messagingContext.ReceivingPMode.MessageHandling.DeliverInformation.PayloadReferenceMethod.Type == null) { throw new InvalidOperationException( $"Unable to send the DeliverMessage: the ReceivingPMode {messagingContext.ReceivingPMode.Id} " + "does not contain any <Type/> element in the MessageHandling.Deliver.PayloadReferenceMethod element " + "that indicates which uploading strategy that must be used." + "Default uploading strategies are: 'FILE' and 'HTTP'. See 'Deliver Uploading' for more information"); } IAttachmentUploader uploader = GetAttachmentUploader(messagingContext.ReceivingPMode); var results = new Collection <UploadResult>(); foreach (Attachment att in deliverEnvelope.Attachments) { UploadResult result = await TryUploadAttachmentAsync(att, deliverEnvelope, uploader).ConfigureAwait(false); results.Add(result); } SendResult accResult = results .Select(r => r.Status) .Aggregate(SendResultUtils.Reduce); await UpdateDeliverMessageAccordinglyToUploadResult( messageId : deliverEnvelope.Message.MessageInfo?.MessageId, status : accResult); if (accResult == SendResult.Success) { return(StepResult.Success(messagingContext)); } return(StepResult.Failed(messagingContext)); }
/// <summary> /// Start Decrypting <see cref="AS4Message"/> /// </summary> /// <param name="context"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.AS4Message == null) { throw new InvalidOperationException( $"{nameof(DecryptAS4MessageStep)} requires a AS4Message to decrypt but no AS4Message is present in the MessagingContext"); } if (context.AS4Message.IsSignalMessage) { Logger.Debug("AS4Message is SignalMessage so will skip decryption since AS4.NET Component only supports encryption of payloads"); return(StepResult.Success(context)); } if (context.ReceivingPMode?.Security?.Decryption == null) { Logger.Debug("AS4Message will not be decrypted sicne ReceivingPMode hasn't got a Security.Decryption element"); return(StepResult.Success(context)); } ReceivingProcessingMode receivePMode = context.ReceivingPMode; if (receivePMode.Security.Decryption.Encryption == Limit.Required && !context.AS4Message.IsEncrypted) { Logger.Error( $"AS4Message is not encrypted but ReceivingPMode {receivePMode.Id} requires it. " + $"{Environment.NewLine} Please alter the PMode Decryption.Encryption element to Allowed or Ignored"); context.ErrorResult = new ErrorResult("AS4Message is not encrypted but ReceivingPMode requires it", ErrorAlias.PolicyNonCompliance); return(StepResult.Failed(context)); } if (receivePMode.Security.Decryption.Encryption == Limit.NotAllowed && context.AS4Message.IsEncrypted) { Logger.Error( $"AS4Message is encrypted but ReceivingPMode {receivePMode.Id} doesn't allow it. " + $"{Environment.NewLine} Please alter the PMode Decryption.Encryption element to Required, Allowed or Ignored"); context.ErrorResult = new ErrorResult("AS4Message is encrypted but ReceivingPMode doesn't allow it", ErrorAlias.PolicyNonCompliance); return(StepResult.Failed(context)); } if (!context.AS4Message.IsEncrypted) { Logger.Debug("AS4Message is not encrypted so will skip decryption"); return(StepResult.Success(context)); } if (context.ReceivingPMode?.Security?.Decryption?.Encryption == Limit.Ignored) { Logger.Debug($"Decryption is ignored in ReceivingPMode {receivePMode.Id}, so no decryption will take place"); return(StepResult.Success(context)); } return(await DecryptAS4MessageAsync(context).ConfigureAwait(false)); }
private static StepResult ValidationFailure(MessagingContext context) { Logger.Error($"{context.LogTag} AS4Message is not valid: {context.ErrorResult.Description}"); return(StepResult.Failed(context)); }
private static StepResult FailedStepResult(string description, MessagingContext context) { context.ErrorResult = new ErrorResult(description, ErrorAlias.ProcessingModeMismatch); return(StepResult.Failed(context)); }