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); }
private static void Configure(string profile, bool ignoreCertificateErrors, bool noProtection) { // read configuration values var builder = new Microsoft.Extensions.Configuration.ConfigurationBuilder() .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) .AddJsonFile("appsettings.json", false) .AddJsonFile($"{profile}.json", false); var configurationRoot = builder.Build(); // configure logging _loggerFactory = new LoggerFactory(); _loggerFactory.AddConsole(configurationRoot.GetSection("Logging")); _logger = _loggerFactory.CreateLogger("TestClient"); // configure caching var distributedCache = DistributedCacheFactory.Create(); // set up address registry var addressRegistrySettings = new AddressRegistrySettings(); configurationRoot.GetSection("AddressRegistrySettings").Bind(addressRegistrySettings); addressRegistrySettings.WcfConfiguration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); var addressRegistry = new AddressRegistry(addressRegistrySettings, distributedCache); // set up collaboration registry var collaborationProtocolRegistrySettings = new CollaborationProtocolRegistrySettings(); configurationRoot.GetSection("CollaborationProtocolRegistrySettings").Bind(collaborationProtocolRegistrySettings); collaborationProtocolRegistrySettings.WcfConfiguration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); var collaborationProtocolRegistry = new CollaborationProtocolRegistry(collaborationProtocolRegistrySettings, distributedCache, addressRegistry); _clientSettings = new ClientSettings(); configurationRoot.GetSection("ClientSettings").Bind(_clientSettings); // set up messaging var messagingSettings = new MessagingSettings(); configurationRoot.GetSection("MessagingSettings").Bind(messagingSettings); messagingSettings.IgnoreCertificateErrorOnSend = ignoreCertificateErrors; messagingSettings.LogPayload = true; if (noProtection) { _messagingClient = new MessagingClient(messagingSettings, collaborationProtocolRegistry, addressRegistry, null, null, new NoMessageProtection()); } else { _messagingClient = new MessagingClient(messagingSettings, collaborationProtocolRegistry, addressRegistry); } }
private static void Configure(string profile) { // read configuration values var builder = new Microsoft.Extensions.Configuration.ConfigurationBuilder() .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) .AddJsonFile("appsettings.json", false) .AddJsonFile($"{profile}.json", false); var configurationRoot = builder.Build(); // configure logging _loggerFactory = new LoggerFactory(); _loggerFactory.AddConsole(configurationRoot.GetSection("Logging")); _loggerFactory.AddNLog(); LogManager.Configuration = new XmlLoggingConfiguration("nlog.config", true); _logger = _loggerFactory.CreateLogger("TestServer"); // configure caching var distributedCache = DistributedCacheFactory.Create(); // set up address registry var addressRegistrySettings = new AddressRegistrySettings(); configurationRoot.GetSection("AddressRegistrySettings").Bind(addressRegistrySettings); addressRegistrySettings.WcfConfiguration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); var addressRegistry = new AddressRegistry(addressRegistrySettings, distributedCache); // set up collaboration registry var collaborationProtocolRegistrySettings = new CollaborationProtocolRegistrySettings(); configurationRoot.GetSection("CollaborationProtocolRegistrySettings").Bind(collaborationProtocolRegistrySettings); collaborationProtocolRegistrySettings.WcfConfiguration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); var collaborationProtocolRegistry = new CollaborationProtocolRegistry(collaborationProtocolRegistrySettings, distributedCache, addressRegistry); _serverSettings = new ServerSettings(); configurationRoot.GetSection("ServerSettings").Bind(_serverSettings); // set up messaging var messagingSettings = new MessagingSettings(); configurationRoot.GetSection("MessagingSettings").Bind(messagingSettings); messagingSettings.ServiceBus.Synchronous.ReplyQueueMapping.Add(Environment.MachineName, "DUMMY"); // we just need a value, it will never be used messagingSettings.LogPayload = true; _messagingServer = new MessagingServer(messagingSettings, _logger, _loggerFactory, collaborationProtocolRegistry, addressRegistry); _messagingServer.RegisterAsynchronousMessageReceivedStartingCallback((m) => { MappedDiagnosticsLogicalContext.Set("correlationId", m.MessageId); }); _messagingServer.RegisterAsynchronousMessageReceivedCallback((m) => { if (m.Payload.ToString().Contains("ThrowException")) { throw new InvalidOperationException(); } var path = Path.Combine(_serverSettings.DestinationDirectory, "Asynchronous"); if (Directory.Exists(path) == false) { Directory.CreateDirectory(path); } var fileName = Path.Combine(path, m.MessageId + ".xml"); using (var sw = File.CreateText(fileName)) { m.Payload.Save(sw); } }); _messagingServer.RegisterAsynchronousMessageReceivedCompletedCallback((m) => { MappedDiagnosticsLogicalContext.Set("correlationId", m.MessageId); }); _messagingServer.RegisterSynchronousMessageReceivedStartingCallback((m) => { MappedDiagnosticsLogicalContext.Set("correlationId", string.Empty);// reset correlation id }); _messagingServer.RegisterSynchronousMessageReceivedCallback((m) => { var path = Path.Combine(_serverSettings.DestinationDirectory, "Synchronous"); if (Directory.Exists(path) == false) { Directory.CreateDirectory(path); } var fileName = Path.Combine(path, m.MessageId + ".xml"); using (var sw = File.CreateText(fileName)) { m.Payload.Save(sw); } return(new XDocument(new XElement("DummyResponse"))); }); _messagingServer.RegisterSynchronousMessageReceivedCompletedCallback((m) => { MappedDiagnosticsLogicalContext.Set("correlationId", string.Empty); // reset correlation id }); }
/// <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}"); }
/// <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); }