Exemple #1
0
        private async Task <CollaborationProtocolProfile> FindProfile(ILogger logger, OutgoingMessage message)
        {
            var profile =
                await CollaborationProtocolRegistry.FindAgreementForCounterpartyAsync(logger, message.ToHerId).ConfigureAwait(false) ??
                await CollaborationProtocolRegistry.FindProtocolForCounterpartyAsync(logger, message.ToHerId).ConfigureAwait(false);

            return(profile);
        }
Exemple #2
0
        /// <summary>
        /// Sends an outgoing message
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="outgoingMessage">Information about the message to send</param>
        /// <param name="queueType">The type of queue that should be used</param>
        /// <param name="replyTo">An optional ReplyTo queue that should be used. Only relevant in synchronous messaging</param>
        /// <param name="correlationId">The correlation id to use when sending the message. Only relevant in synchronous messaging</param>
        /// <returns></returns>
        internal async Task Send(ILogger logger, OutgoingMessage outgoingMessage, QueueType queueType, string replyTo = null, string correlationId = null)
        {
            logger.LogDebug($"Start-ServiceBusCore::Send QueueType: {queueType} replyTo: {replyTo} correlationId: {correlationId}");

            if (outgoingMessage == null)
            {
                throw new ArgumentNullException(nameof(outgoingMessage));
            }
            if (string.IsNullOrEmpty(outgoingMessage.MessageId))
            {
                throw new ArgumentNullException(nameof(outgoingMessage.MessageId));
            }
            if (outgoingMessage.Payload == null)
            {
                throw new ArgumentNullException(nameof(outgoingMessage.Payload));
            }

            var hasAgreement = true;
            // first we try and find an agreement
            var profile = await CollaborationProtocolRegistry.FindAgreementForCounterpartyAsync(logger, outgoingMessage.ToHerId).ConfigureAwait(false);

            if (profile == null)
            {
                hasAgreement = false;                 // if we don't have an agreement, we try to find the specific profile
                profile      = await CollaborationProtocolRegistry.FindProtocolForCounterpartyAsync(logger, outgoingMessage.ToHerId).ConfigureAwait(false);
            }

            logger.LogDebug($"ServiceBusCore::Send - Start retrieving and valiating certificates - correlationId: {correlationId}");
            var signature  = Settings.SigningCertificate.Certificate;
            var encryption = profile.EncryptionCertificate;

            var validator        = Core.DefaultCertificateValidator;
            var encryptionStatus = validator.Validate(encryption, X509KeyUsageFlags.DataEncipherment);
            var signatureStatus  = validator.Validate(signature, X509KeyUsageFlags.NonRepudiation);

            // this is the other parties certificate that may be out of date, not something we can fix
            if (encryptionStatus != CertificateErrors.None)
            {
                if (Core.Settings.IgnoreCertificateErrorOnSend)
                {
                    logger.LogError(EventIds.RemoteCertificate, "Remote encryption certificate is not valid");
                }
                else
                {
                    throw new MessagingException("Remote encryption certificate is not valid")
                          {
                              EventId = EventIds.RemoteCertificate
                          };
                }
            }
            // this is our certificate, something we can fix
            if (signatureStatus != CertificateErrors.None)
            {
                if (Core.Settings.IgnoreCertificateErrorOnSend)
                {
                    logger.LogError(EventIds.LocalCertificate, "Locally installed signing certificate is not valid");
                }
                else
                {
                    throw new MessagingException("Locally installed signing certificate is not valid")
                          {
                              EventId = EventIds.LocalCertificate
                          };
                }
            }
            logger.LogDebug($"ServiceBusCore::Send - End retrieving and valiating certificates - correlationId: {correlationId}");

            logger.LogDebug($"ServiceBusCore::Send - Start encrypting message - correlationId: {correlationId}");
            var protection = Core.DefaultMessageProtection;
            var stream     = protection.Protect(outgoingMessage.Payload, encryption, signature);

            logger.LogDebug($"ServiceBusCore::Send - End encrypting message - correlationId: {correlationId}");

            logger.LogDebug($"ServiceBusCore::Send - Start Create and Initialize message - correlationId: {correlationId}");
            var messagingMessage = FactoryPool.CreateMessage(logger, stream, outgoingMessage);

            if (queueType != QueueType.SynchronousReply)
            {
                messagingMessage.ReplyTo =
                    replyTo ?? await ConstructQueueName(logger, Core.Settings.MyHerId, queueType).ConfigureAwait(false);
            }

            messagingMessage.ContentType = protection.ContentType;
            messagingMessage.MessageId   = outgoingMessage.MessageId;
            // when we are replying to a synchronous message, we need to use the replyto of the original message
            messagingMessage.To =
                (queueType == QueueType.SynchronousReply) ?
                replyTo :
                await ConstructQueueName(logger, outgoingMessage.ToHerId, queueType).ConfigureAwait(false);

            messagingMessage.MessageFunction = outgoingMessage.MessageFunction;
            messagingMessage.CorrelationId   = correlationId ?? outgoingMessage.MessageId;
            messagingMessage.TimeToLive      = (queueType == QueueType.Asynchronous)
                                ? Settings.Asynchronous.TimeToLive
                                : Settings.Synchronous.TimeToLive;
            messagingMessage.ScheduledEnqueueTimeUtc = outgoingMessage.ScheduledSendTimeUtc;
            messagingMessage.FromHerId            = Core.Settings.MyHerId;
            messagingMessage.ToHerId              = outgoingMessage.ToHerId;
            messagingMessage.ApplicationTimestamp = DateTime.Now;

            if (hasAgreement)
            {
                messagingMessage.CpaId = profile.CpaId.ToString("D");
            }
            logger.LogDebug($"ServiceBusCore::Send - End Create and Initialize message - correlationId: {correlationId}");

            await Send(logger, messagingMessage, queueType, outgoingMessage.PersonalId, (LogPayload)?outgoingMessage.Payload : null).ConfigureAwait(false);

            logger.LogDebug($"End-ServiceBusCore::Send QueueType: {queueType} replyTo: {replyTo} correlationId: {correlationId}");
        }
Exemple #3
0
        /// <summary>
        /// Sends an outgoing message
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="outgoingMessage">Information about the message to send</param>
        /// <param name="queueType">The type of queue that should be used</param>
        /// <param name="replyTo">An optional ReplyTo queue that should be used. Only relevant in synchronous messaging</param>
        /// <param name="correlationId">The correlation id to use when sending the message. Only relevant in synchronous messaging</param>
        /// <returns></returns>
        internal async Task Send(ILogger logger, OutgoingMessage outgoingMessage, QueueType queueType, string replyTo = null, string correlationId = null)
        {
            if (outgoingMessage == null)
            {
                throw new ArgumentNullException(nameof(outgoingMessage));
            }
            if (string.IsNullOrEmpty(outgoingMessage.MessageId))
            {
                throw new ArgumentNullException(nameof(outgoingMessage.MessageId));
            }
            if (outgoingMessage.Payload == null)
            {
                throw new ArgumentNullException(nameof(outgoingMessage.Payload));
            }

            logger.LogStartSend(queueType, outgoingMessage.MessageFunction, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId, outgoingMessage.PersonalId, outgoingMessage.Payload);

            var hasAgreement = true;
            // first we try and find an agreement
            var profile = await CollaborationProtocolRegistry.FindAgreementForCounterpartyAsync(logger, outgoingMessage.ToHerId).ConfigureAwait(false);

            if (profile == null)
            {
                hasAgreement = false; // if we don't have an agreement, we try to find the specific profile
                profile      = await CollaborationProtocolRegistry.FindProtocolForCounterpartyAsync(logger, outgoingMessage.ToHerId).ConfigureAwait(false);
            }

            var contentType = Core.MessageProtection.ContentType;

            if (contentType.Equals(ContentType.SignedAndEnveloped, StringComparison.OrdinalIgnoreCase))
            {
                var validator = Core.CertificateValidator;
                // Validate external part's encryption certificate
                logger.LogBeforeValidatingCertificate(outgoingMessage.MessageFunction, profile.EncryptionCertificate.Thumbprint, profile.EncryptionCertificate.Subject, "DataEncipherment", outgoingMessage.ToHerId, outgoingMessage.MessageId);
                var encryptionStatus = validator == null
                    ? CertificateErrors.None
                    : validator.Validate(profile.EncryptionCertificate, X509KeyUsageFlags.DataEncipherment);
                logger.LogAfterValidatingCertificate(outgoingMessage.MessageFunction, profile.EncryptionCertificate.Thumbprint, profile.EncryptionCertificate.Subject, "DataEncipherment", outgoingMessage.ToHerId, outgoingMessage.MessageId);

                logger.LogBeforeValidatingCertificate(outgoingMessage.MessageFunction, Core.MessageProtection.SigningCertificate.Thumbprint, Core.MessageProtection.SigningCertificate.Subject, "NonRepudiation", Core.Settings.MyHerId, outgoingMessage.MessageId);
                // Validate "our" own signature certificate
                var signatureStatus = validator == null
                    ? CertificateErrors.None
                    : validator.Validate(Core.MessageProtection.SigningCertificate, X509KeyUsageFlags.NonRepudiation);
                logger.LogAfterValidatingCertificate(outgoingMessage.MessageFunction, Core.MessageProtection.SigningCertificate.Thumbprint, Core.MessageProtection.SigningCertificate.Subject, "NonRepudiation", Core.Settings.MyHerId, outgoingMessage.MessageId);

                // this is the other parties certificate that may be out of date, not something we can fix
                if (encryptionStatus != CertificateErrors.None)
                {
                    if (Core.Settings.IgnoreCertificateErrorOnSend)
                    {
                        logger.LogError(EventIds.RemoteCertificate, $"Remote encryption certificate {profile.EncryptionCertificate?.SerialNumber} for {outgoingMessage.ToHerId.ToString()} is not valid");
                    }
                    else
                    {
                        throw new MessagingException($"Remote encryption certificate {profile.EncryptionCertificate?.SerialNumber} for {outgoingMessage.ToHerId.ToString()} is not valid")
                              {
                                  EventId = EventIds.RemoteCertificate
                              };
                    }
                }
                // this is our certificate, something we can fix
                if (signatureStatus != CertificateErrors.None)
                {
                    if (Core.Settings.IgnoreCertificateErrorOnSend)
                    {
                        logger.LogError(EventIds.LocalCertificate, $"Locally installed signing certificate {Core.MessageProtection.SigningCertificate?.SerialNumber} is not valid.\nSerial Number: {Core.MessageProtection.SigningCertificate?.SerialNumber}\nThumbprint: {Core.MessageProtection.SigningCertificate?.Thumbprint}");
                    }
                    else
                    {
                        throw new MessagingException($"Locally installed signing certificate {Core.MessageProtection.SigningCertificate?.SerialNumber} is not valid.\nSerial Number: {Core.MessageProtection.SigningCertificate?.SerialNumber}\nThumbprint: {Core.MessageProtection.SigningCertificate?.Thumbprint}")
                              {
                                  EventId = EventIds.LocalCertificate
                              };
                    }
                }
            }
            logger.LogBeforeEncryptingPayload(outgoingMessage.MessageFunction, profile.EncryptionCertificate.Thumbprint, profile.EncryptionCertificate.Subject, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId);
            // Encrypt the payload
            var stream = Core.MessageProtection.Protect(outgoingMessage.Payload?.ToStream(), profile.EncryptionCertificate);

            logger.LogAfterEncryptingPayload(outgoingMessage.MessageFunction, profile.EncryptionCertificate.Thumbprint, profile.EncryptionCertificate.Subject, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId);

            logger.LogBeforeFactoryPoolCreateMessage(outgoingMessage.MessageFunction, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId);
            // Create an empty message
            var messagingMessage = FactoryPool.CreateMessage(logger, stream, outgoingMessage);

            logger.LogAfterFactoryPoolCreateMessage(outgoingMessage.MessageFunction, Core.Settings.MyHerId, outgoingMessage.ToHerId, outgoingMessage.MessageId);

            if (queueType != QueueType.SynchronousReply)
            {
                messagingMessage.ReplyTo =
                    replyTo ?? await ConstructQueueName(logger, Core.Settings.MyHerId, queueType).ConfigureAwait(false);
            }
            messagingMessage.ContentType = Core.MessageProtection.ContentType;
            messagingMessage.MessageId   = outgoingMessage.MessageId;
            // when we are replying to a synchronous message, we need to use the replyto of the original message
            messagingMessage.To =
                (queueType == QueueType.SynchronousReply) ?
                replyTo :
                await ConstructQueueName(logger, outgoingMessage.ToHerId, queueType).ConfigureAwait(false);

            messagingMessage.MessageFunction = outgoingMessage.MessageFunction;
            messagingMessage.CorrelationId   = correlationId ?? outgoingMessage.MessageId;
            messagingMessage.TimeToLive      = (queueType == QueueType.Asynchronous)
                ? Settings.Asynchronous.TimeToLive
                : Settings.Synchronous.TimeToLive;
            messagingMessage.ScheduledEnqueueTimeUtc = outgoingMessage.ScheduledSendTimeUtc;
            messagingMessage.FromHerId            = Core.Settings.MyHerId;
            messagingMessage.ToHerId              = outgoingMessage.ToHerId;
            messagingMessage.ApplicationTimestamp = DateTime.Now;

            if (hasAgreement)
            {
                messagingMessage.CpaId = profile.CpaId.ToString("D");
            }
            await Send(logger, messagingMessage, queueType, outgoingMessage.PersonalId, (LogPayload)?outgoingMessage.Payload : null).ConfigureAwait(false);

            logger.LogEndSend(queueType, messagingMessage.MessageFunction, messagingMessage.FromHerId, messagingMessage.ToHerId, messagingMessage.MessageId, outgoingMessage.PersonalId);
        }