/// <inheritdoc cref="IMqttRepositoryGrain" /> /// <summary> /// Proceeds the subscription. /// </summary> /// <param name="context">The context.</param> /// <returns>A value indicating whether the subscription is accepted or not.</returns> /// <seealso cref="IMqttRepositoryGrain" /> public async Task <bool> ProceedSubscription(MqttSubscriptionInterceptorContext context) { try { // Handle subscription in grain var mqttClientGrain = this.GrainFactory.GetGrain <IMqttClientGrain>(context.ClientId); var subscriptionValid = await mqttClientGrain.ProceedSubscription(context); if (!subscriptionValid) { return(false); } // Save subscription to the database var eventLog = new EventLog { EventType = EventType.Subscription, EventDetails = $"New subscription: ClientId = {context.ClientId}, TopicFilter = {context.TopicFilter}." }; this.eventLogQueue.Enqueue(eventLog); return(true); } catch (Exception ex) { this.logger.Error("An error occurred: {@ex}.", ex); return(false); } }
public Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { try { var pythonContext = new PythonDictionary { { "accept_subscription", context.AcceptSubscription }, { "close_connection", context.CloseConnection }, { "client_id", context.ClientId }, { "topic", context.TopicFilter.Topic }, { "qos", (int)context.TopicFilter.QualityOfServiceLevel } }; _pythonScriptHostService.InvokeOptionalFunction("on_intercept_subscription", pythonContext); context.AcceptSubscription = (bool)pythonContext["accept_subscription"]; context.CloseConnection = (bool)pythonContext["close_connection"]; } catch (Exception exception) { _logger.LogError(exception, "Error while intercepting subscription."); } return(Task.CompletedTask); }
private MqttSubscriptionInterceptorContext InterceptSubscribe(TopicFilter topicFilter) { var interceptorContext = new MqttSubscriptionInterceptorContext(_clientId, topicFilter); _options.SubscriptionInterceptor?.Invoke(interceptorContext); return(interceptorContext); }
public async Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { context.AcceptSubscription = false; try { var profile = await profileService.GetProfileWithSubscriptionByUserIdAsync(context.ClientId); if (context.TopicFilter.Topic.StartsWith("$SYS", System.StringComparison.OrdinalIgnoreCase) || context.TopicFilter.Topic.StartsWith("#")) { if (profile.Type == Common.Enums.ProfileType.Agent) { context.AcceptSubscription = true; } } else if (profile.Type == Common.Enums.ProfileType.Agent) { context.AcceptSubscription = true; } else { foreach (var subscription in profile.Subscriptions) { if (MqttTopicFilterComparer.IsMatch(context.TopicFilter.Topic, subscription.Path)) { context.AcceptSubscription = true; } } } } catch (NotFoundException) { } }
/// <summary> /// Logs the message from the MQTT subscription interceptor context. /// </summary> /// <param name="context">The MQTT subscription interceptor context.</param> /// <param name="successful">A <see cref="bool"/> value indicating whether the subscription was successful or not.</param> private static void LogMessage(MqttSubscriptionInterceptorContext context, bool successful) { if (context == null) { return; } Log.Information(successful ? $"New subscription: ClientId = {context.ClientId}, TopicFilter = {context.TopicFilter}" : $"Subscription failed for clientId = {context.ClientId}, TopicFilter = {context.TopicFilter}"); }
public Task InterceptSubscriptionAsync( MqttSubscriptionInterceptorContext context) { if (context == null) { return(Task.CompletedTask); } if (context.TopicFilter.Topic.StartsWith("platooning/broadcast/")) { var tree = context.TopicFilter.Topic.Split('/'); //var plotooningId = context.TopicFilter.Topic.Replace("platooning/broadcast/", ""); var platoon = tree.Length > 2 ? _repo.GetPlatoonById(tree[2]) : null; if (platoon == null) { context.AcceptSubscription = false; context.CloseConnection = true; _logger.LogInformation( $"Reject for not found platoonId on our system | ClientId = {context.ClientId}, TopicFilter = {context.TopicFilter}," + $" AcceptSubscription = {context.AcceptSubscription}, SessionItems = {context.SessionItems}"); } try { if (_repo.GetPlatoon(context.ClientId) == null) { context.AcceptSubscription = false; context.CloseConnection = true; _logger.LogInformation( $"Reject for not found joined ClientId = {context.ClientId}, TopicFilter = {context.TopicFilter}," + $" AcceptSubscription = {context.AcceptSubscription}, SessionItems = {context.SessionItems}"); } } catch (Exception exception) { context.AcceptSubscription = false; context.CloseConnection = true; _repo.AddLogAsync(new Log() { Exception = $"Close connection for subscriptions Exception MqttSubscriptionInterceptorContext = {exception.StackTrace}", CreationDate = DateTime.Now }); _logger.LogError($"Close connection for subscriptions Exception MqttSubscriptionInterceptorContext = {exception.StackTrace}"); } } context.AcceptSubscription = true; _logger.LogInformation( $"New Subcription: ClientId = {context.ClientId}, TopicFilter = {context.TopicFilter}," + $" AcceptSubscription = {context.AcceptSubscription}, SessionItems = {context.SessionItems}"); return(Task.CompletedTask); }
/// <summary> /// Logs the message from the MQTT subscription interceptor context. /// </summary> /// <param name="context">The MQTT subscription interceptor context.</param> /// <param name="successful">A <see cref="bool"/> value indicating whether the subscription was successful or not.</param> private void LogMessage(MqttSubscriptionInterceptorContext context, bool successful) { this.logger.Information( successful ? "New subscription: ClientId = {ClientId}, TopicFilter = {TopicFilter}" : "Subscription failed for clientId = {ClientId}, TopicFilter = {TopicFilter}", context.ClientId, context.TopicFilter); }
public async Task TestValidateSubscription() { // Add users to users dictionary to simulate that the connection was established successfully: var users = new Dictionary <string, User> { { "Test", new User { Id = User1Id, UserName = "******", ValidateClientId = false } } }; // Test user var mqttTopicFilter = new MqttTopicFilter { Topic = "d/e", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce }; var mqttConnectionValidatorContext = new MqttSubscriptionInterceptorContext("Test", mqttTopicFilter, new Dictionary <object, object>()); var blacklist = await this.userRepository.GetBlacklistItemsForUser(User1Id, BlacklistWhitelistType.Subscribe); var whitelist = await this.userRepository.GetWhitelistItemsForUser(User1Id, BlacklistWhitelistType.Subscribe); var result = this.mqttValidator.ValidateSubscription( mqttConnectionValidatorContext, blacklist, whitelist, users["Test"], ClientIdPrefixes); Assert.IsTrue(result); mqttTopicFilter = new MqttTopicFilter { Topic = "e", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce }; mqttConnectionValidatorContext = new MqttSubscriptionInterceptorContext("Test", mqttTopicFilter, new Dictionary <object, object>()); result = this.mqttValidator.ValidateSubscription( mqttConnectionValidatorContext, blacklist, whitelist, users["Test"], ClientIdPrefixes); Assert.IsTrue(result); }
private void LogMessage(MqttSubscriptionInterceptorContext context, bool successful) { if (context == null) { return; } Debug.WriteLine("Udane?:" + successful); Debug.WriteLine(context.ClientId); Debug.WriteLine(context.TopicFilter); notifyObservers("Klient: " + context.ClientId + " rozpoczął nasłuchiwanie tematu: " + context.TopicFilter); }
public Task InterceptSubscriptionAsync( MqttSubscriptionInterceptorContext context) { if (context == null) { return(Task.CompletedTask); } context.AcceptSubscription = true; _logger.LogInformation($"New subscription: ClientId = {context.ClientId}, TopicFilter = {context.TopicFilter}"); return(Task.CompletedTask); }
/// <inheritdoc cref="IMqttClientGrain" /> /// <summary> /// Proceeds the subscription for one client identifier. /// </summary> /// <param name="context">The context.</param> /// <returns>A value indicating whether the subscription is accepted or not.</returns> /// <seealso cref="IMqttClientGrain" /> public async Task <bool> ProceedSubscription(MqttSubscriptionInterceptorContext context) { try { return(await this.mqttValidator.ValidateSubscription(context, this.userRepository, this.users)); } catch (Exception ex) { this.logger.Error("An error occured: {ex}.", ex); return(false); } }
/// <summary> /// Validates the subscription. /// </summary> /// <param name="context">The context.</param> private void ValidateSubscription(MqttSubscriptionInterceptorContext context) { if (this.cancellationToken.IsCancellationRequested) { return; } var repositoryGrain = this.clusterClient.GetGrain <IMqttRepositoryGrain>(0); var subscriptionValid = repositoryGrain.ProceedSubscription(context).Result; context.AcceptSubscription = subscriptionValid; }
public MqttSubscriptionInterceptorContext GetSubscriptionInterceptorValue(MqttSubscriptionInterceptorContext context) { if (context.TopicFilter.Topic.StartsWith("test")) { context.AcceptSubscription = true; } else { context.AcceptSubscription = false; } return(context); }
private void LogMessage(MqttSubscriptionInterceptorContext context, bool successful) { if (context == null) { return; } var message = successful ? $"New subscription: ClientId = {context.ClientId}, TopicFilter = {context.TopicFilter}" : $"Subscription failed for clientId = {context.ClientId}, TopicFilter = {context.TopicFilter}"; _logger.LogInformation(message); }
/// <inheritdoc cref="IMqttClientGrain" /> /// <summary> /// Proceeds the subscription for one client identifier. /// </summary> /// <param name="context">The context.</param> /// <returns>A value indicating whether the subscription is accepted or not.</returns> /// <seealso cref="IMqttClientGrain" /> public Task <bool> ProceedSubscription(MqttSubscriptionInterceptorContext context) { try { var result = this.mqttValidator.ValidateSubscription(context, this.userData.SubscriptionBlacklist, this.userData.SubscriptionWhitelist, this.user, this.userData.ClientIdPrefixes); return(Task.FromResult(result)); } catch (Exception ex) { this.logger.Error("An error occurred: {@ex}.", ex); return(Task.FromResult(false)); } }
/// <summary> /// Validates the MQTT subscriptions. /// </summary> /// <param name="context">The context.</param> public Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { try { context.AcceptSubscription = true; this.LogMessage(context, true); return(Task.CompletedTask); } catch (Exception ex) { this.logger.Error("An error occurred: {Exception}.", ex); return(Task.FromException(ex)); } }
public Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { try { _logger.LogInformation($"Received subscription for topic: {context.TopicFilter} from ClientId: {context.ClientId}"); context.AcceptSubscription = true; } catch (Exception exception) { _logger.LogError(exception, "Error while intercepting subscription."); } return(Task.CompletedTask); }
/// <summary> /// Validates the MQTT subscriptions. /// </summary> /// <param name="context">The context.</param> /// <returns>A <see cref="Task"/> representing any asynchronous operation.</returns> public async Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { try { var repositoryGrain = clusterClient.GetGrain <IMqttRepositoryGrain>(0); var subscriptionValid = await repositoryGrain.ProceedSubscription(context); context.AcceptSubscription = subscriptionValid; } catch (Exception ex) { this.logger.Error("An error occurred: {@ex}.", ex); } }
/// <summary> /// Fired when a client wants to subscribe a topic /// </summary> /// <param name="context">MqttSubscriptionInterceptorContext</param> /// <returns>Task</returns> public Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { // Don't allow subscriptions to other topics than "metrics" or "status" if (!(context.TopicFilter.Topic.StartsWith("metrics") || context.TopicFilter.Topic.StartsWith("status"))) { context.AcceptSubscription = false; Helper.Log(new LogMessage(LogSeverity.Warning, nameof(MqttService), $"Denied subscription by {context.ClientId} with topic {context.TopicFilter.Topic}")); return(Task.CompletedTask); } context.AcceptSubscription = true; Helper.Log(new LogMessage(LogSeverity.Info, nameof(MqttService), $"Accepted subscription by {context.ClientId} with topic {context.TopicFilter.Topic}")); return(Task.CompletedTask); }
public Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { context.AcceptSubscription = true; if (context.ClientId != _theGameServer.Options.ClientId) { context.AcceptSubscription = false; } if (context.TopicFilter.Topic.StartsWith(FedNetConstante.SERVER_TO_CLIENT + FedNetConstante.DEFAULT_TOPIC_SEPARATOR + context.ClientId)) { context.AcceptSubscription = true; } if (context.TopicFilter.Topic.StartsWith(FedNetConstante.SERVER_BROADCAST)) { context.AcceptSubscription = true; } if (!context.AcceptSubscription) /*context.CloseConnection = true;*/ _logSystem {
// Protect several topics from being subscribed from every client. public async void HandleMessage(MqttSubscriptionInterceptorContext context) { Console.WriteLine("Broker: Subscription detected"); if (context.ClientId.EndsWith("_fake")) { return; } Console.WriteLine("Broker: ClientOut subscribing"); while (!clientManagers[context.ClientId].clientOut.IsConnected()) { Thread.Sleep(100); } await clientManagers[context.ClientId].clientOut.SubscribeTo(context.TopicFilter.Topic); Console.WriteLine("Broker: ClientOut subscribed"); }
async Task <MqttSubscriptionInterceptorContext> InterceptSubscribe(MqttTopicFilter topicFilter) { var interceptor = _options.SubscriptionInterceptor; if (interceptor == null) { return(null); } var context = new MqttSubscriptionInterceptorContext { ClientId = _clientSession.ClientId, TopicFilter = topicFilter, SessionItems = _clientSession.Items }; await interceptor.InterceptSubscriptionAsync(context).ConfigureAwait(false); return(context); }
public async Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { object bearer; context.SessionItems.TryGetValue(nameof(bearer), out bearer); if (bearer == null) { context.AcceptSubscription = false; context.CloseConnection = true; return; } var tokenDto = new TokenDto { Bearer = bearer.ToString() }; try { var subscription = await apiService.GetUserSubscriptionsAsync(context.ClientId, tokenDto); foreach (var path in subscription.Path) { if (MqttTopicFilterComparer.IsMatch(context.TopicFilter.Topic, path)) { context.AcceptSubscription = true; return; } } context.AcceptSubscription = false; } catch (UnauthorizedException) { context.AcceptSubscription = false; context.CloseConnection = true; } catch (Exception) { context.AcceptSubscription = false; } }
public async Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { if (context.ClientId == _clientSettings.Id || context.ClientId == _zigbeeSettings.Id) { context.AcceptSubscription = true; } else { var mqttDevice = await _mediator.Send(new GetMqttDeviceByIdQuery() { Id = context.ClientId }); if (!mqttDevice.IsConfirmed) { context.AcceptSubscription = false; } else { context.AcceptSubscription = true; } } }
private void MqttSubscriptionInterceptor(MqttSubscriptionInterceptorContext subscription_context) { Log.Debug(TAG, "MqttSubscriptionInterceptor"); logsDB.AddLogRow(LogStatusesEnum.Info, $"MqttSubscriptionInterceptor - ClientId={subscription_context.ClientId} Topic={subscription_context.TopicFilter.Topic}", TAG); }
/// <inheritdoc cref="IMqttValidator"/> /// <summary> /// Validates the subscription. /// </summary> /// <param name="context">The context.</param> /// <param name="userRepository">The user repository.</param> /// <param name="users">The users.</param> /// <returns>A value indicating whether the subscription is accepted or not.</returns> /// <seealso cref="IMqttValidator"/> public async Task <bool> ValidateSubscription(MqttSubscriptionInterceptorContext context, IUserRepository userRepository, IDictionary <string, User> users) { Logger.Information("Executed ValidateSubscription with parameters: {context}, {users}", context, users); var clientIdPrefix = await GetClientIdPrefix(context.ClientId, userRepository); Logger.Information("Client id prefix is {clientIdPrefix}.", clientIdPrefix); User currentUser; bool userFound; if (string.IsNullOrWhiteSpace(clientIdPrefix)) { userFound = users.TryGetValue(context.ClientId, out var currentUserObject); // ReSharper disable once StyleCop.SA1126 currentUser = currentUserObject; Logger.Information("User was found: {userFound}, Current user was {currentUser} when client id prefix was null.", userFound, currentUser); } else { userFound = users.TryGetValue(clientIdPrefix, out var currentUserObject); // ReSharper disable once StyleCop.SA1126 currentUser = currentUserObject; Logger.Information("User was found: {userFound}, Current user was {currentUser} when client id prefix was not null.", userFound, currentUser); } if (currentUser == null) { Logger.Information("Current user was null."); } if (!userFound || currentUser == null) { return(false); } var topic = context.TopicFilter.Topic; Logger.Information("Topic was {topic}.", topic); // Get blacklist var subscriptionBlacklist = await userRepository.GetBlacklistItemsForUser(currentUser.Id, BlacklistWhitelistType.Subscribe); var blacklist = subscriptionBlacklist?.ToList() ?? new List <BlacklistWhitelist>(); Logger.Information("The blacklist was {blacklist}.", blacklist); // Get whitelist var subscriptionWhitelist = await userRepository.GetWhitelistItemsForUser(currentUser.Id, BlacklistWhitelistType.Subscribe); var whitelist = subscriptionWhitelist?.ToList() ?? new List <BlacklistWhitelist>(); Logger.Information("The whitelist was {whitelist}.", whitelist); // Check matches if (blacklist.Any(b => b.Value == topic)) { Logger.Information("The blacklist matched a topic."); return(false); } if (whitelist.Any(b => b.Value == topic)) { Logger.Information("The whitelist matched a topic."); return(true); } // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator foreach (var forbiddenTopic in blacklist) { var doesTopicMatch = TopicChecker.Regex(forbiddenTopic.Value, topic); if (!doesTopicMatch) { continue; } Logger.Information("The blacklist matched a topic with regex."); return(false); } // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator foreach (var allowedTopic in whitelist) { var doesTopicMatch = TopicChecker.Regex(allowedTopic.Value, topic); if (!doesTopicMatch) { continue; } Logger.Information("The whitelist matched a topic with regex."); return(true); } Logger.Information("We fell through everything else. This should never happen!"); return(false); }
/// <summary> /// Validates the subscription. /// </summary> /// <param name="context">The context.</param> private async void ValidateSubscription(MqttSubscriptionInterceptorContext context) { var clientIdPrefix = await this.GetClientIdPrefix(context.ClientId); User currentUser; bool userFound; if (string.IsNullOrWhiteSpace(clientIdPrefix)) { userFound = context.SessionItems.TryGetValue(context.ClientId, out var currentUserObject); currentUser = currentUserObject as User; } else { userFound = context.SessionItems.TryGetValue(clientIdPrefix, out var currentUserObject); currentUser = currentUserObject as User; } if (!userFound || currentUser == null) { context.AcceptSubscription = false; LogMessage(context, false); return; } var topic = context.TopicFilter.Topic; // Get blacklist var publishBlackList = await this.userRepository.GetBlacklistItemsForUser(currentUser.Id, BlacklistWhitelistType.Subscribe); var blacklist = publishBlackList?.ToList() ?? new List <BlacklistWhitelist>(); // Get whitelist var publishWhitelist = await this.userRepository.GetWhitelistItemsForUser(currentUser.Id, BlacklistWhitelistType.Subscribe); var whitelist = publishWhitelist?.ToList() ?? new List <BlacklistWhitelist>(); // Check matches if (blacklist.Any(b => b.Value == topic)) { context.AcceptSubscription = false; LogMessage(context, false); return; } if (whitelist.Any(b => b.Value == topic)) { context.AcceptSubscription = true; LogMessage(context, true); return; } // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator foreach (var forbiddenTopic in blacklist) { var doesTopicMatch = TopicChecker.Regex(forbiddenTopic.Value, topic); if (!doesTopicMatch) { continue; } context.AcceptSubscription = false; LogMessage(context, false); return; } // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator foreach (var allowedTopic in whitelist) { var doesTopicMatch = TopicChecker.Regex(allowedTopic.Value, topic); if (!doesTopicMatch) { continue; } context.AcceptSubscription = true; LogMessage(context, true); return; } context.AcceptSubscription = false; LogMessage(context, false); }
/// <inheritdoc cref="IMqttValidator"/> /// <summary> /// Validates the subscription. /// </summary> /// <param name="context">The context.</param> /// <param name="blacklist">The blacklist.</param> /// <param name="whitelist">The whitelist.</param> /// <param name="user">The user.</param> /// <param name="clientIdPrefixes">The client identifier prefixes.</param> /// <returns>A value indicating whether the subscription is accepted or not.</returns> /// <seealso cref="IMqttValidator"/> public bool ValidateSubscription( MqttSubscriptionInterceptorContext context, List <BlacklistWhitelist> blacklist, List <BlacklistWhitelist> whitelist, User user, List <string> clientIdPrefixes) { Logger.Debug("Executed ValidateSubscription with parameters: {@context}, {@user}.", context, user); var clientIdPrefix = GetClientIdPrefix(context.ClientId, clientIdPrefixes); Logger.Debug("Client id prefix is {@clientIdPrefix}.", clientIdPrefix); if (user == null) { Logger.Debug("Current user was null."); return(false); } var topic = context.TopicFilter.Topic; Logger.Debug("Topic was {@topic}.", topic); Logger.Debug("The blacklist was {@blacklist}.", blacklist); Logger.Debug("The whitelist was {@whitelist}.", whitelist); // Check matches if (blacklist.Any(b => b.Value == topic)) { Logger.Debug("The blacklist matched a topic."); return(false); } if (whitelist.Any(b => b.Value == topic)) { Logger.Debug("The whitelist matched a topic."); return(true); } // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator foreach (var forbiddenTopic in blacklist) { var doesTopicMatch = TopicChecker.Regex(forbiddenTopic.Value, topic); if (!doesTopicMatch) { continue; } Logger.Debug("The blacklist matched a topic with regex."); return(false); } // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator foreach (var allowedTopic in whitelist) { var doesTopicMatch = TopicChecker.Regex(allowedTopic.Value, topic); if (!doesTopicMatch) { continue; } Logger.Debug("The whitelist matched a topic with regex."); return(true); } Logger.Warning( "We fell through everything else. This should never happen! Context was {@context}.", context); return(false); }
public async Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) { context.AcceptSubscription = true; }
private static void MqttSubscribeHandler(MqttSubscriptionInterceptorContext c) { LogToScreen("MQTT: Client " + c.ClientId + " subscribed to: " + c.TopicFilter.Topic); c.AcceptSubscription = true; }