Package org.openremote.manager.mqtt
Class UserAssetProvisioningMQTTHandler
java.lang.Object
org.openremote.manager.mqtt.MQTTHandler
org.openremote.manager.mqtt.UserAssetProvisioningMQTTHandler
This
MQTTHandler is responsible for provisioning service users and assets and authenticating the client
against the configured ProvisioningConfigs.-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static class -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected AssetStorageServiceprotected ManagerKeycloakIdentityProviderprotected booleanprotected static final Loggerstatic final Stringstatic final Stringprotected final ConcurrentMap<Long, Set<org.apache.activemq.artemis.spi.core.protocol.RemotingConnection>> protected ProvisioningServiceprotected io.micrometer.core.instrument.Timerstatic final Stringstatic final Stringprotected org.openremote.container.timer.TimerServicestatic final StringFields inherited from class org.openremote.manager.mqtt.MQTTHandler
clientEventService, clientSession, executorService, messageBrokerService, mqttBrokerService, producer, TOKEN_MULTI_LEVEL_WILDCARD, TOKEN_SINGLE_LEVEL_WILDCARD -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionbooleancanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Called to authorise a publish ifMQTTHandler.handlesTopic(org.openremote.manager.mqtt.Topic)returned true; should return true if the publish is allowed otherwise return false.booleancanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Called to authorise a subscription ifMQTTHandler.handlesTopic(org.openremote.manager.mqtt.Topic)returned true; should return true if the subscription is allowed otherwise return false.booleancheckCanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Checks that authenticated sessions and topic realm matches the authenticated user and also that topic client ID matches the connection client ID.booleancheckCanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Checks that authenticated session and topic realm matches the authenticated user and also that topic client ID matches the connection client ID.protected voidforceClientDisconnects(long provisioningConfigId) static org.openremote.model.asset.Asset<?> getCreateClientAsset(AssetStorageService assetStorageService, String realm, String uniqueId, org.openremote.model.security.User serviceUser, org.openremote.model.provisioning.ProvisioningConfig<?, ?> provisioningConfig) static org.openremote.model.security.UsergetCreateClientServiceUser(String realm, ManagerKeycloakIdentityProvider identityProvider, String uniqueId, org.openremote.model.provisioning.ProvisioningConfig<?, ?> provisioningConfig) protected Loggerprotected org.openremote.model.provisioning.X509ProvisioningConfiggetMatchingX509ProvisioningConfig(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, X509Certificate clientCertificate) Get the set of topics this handler wants to subscribe to for incoming publish messages; messages that match these topics will be passed toMQTTHandler.onPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.openremote.manager.mqtt.Topic, io.netty.buffer.ByteBuf).protected org.apache.activemq.artemis.core.settings.impl.AddressSettingsgetPublishTopicAddressSettings(org.openremote.model.Container container, String publishTopic) Limit the number of messages allowed in the address queue and fail when over; this will disconnect the client.protected StringgetResponseTopic(Topic topic) booleanhandlesTopic(Topic topic) Checks that topic is valid and has at least 3 tokens (generally first two tokens should be {realm}/{clientId} but it is up to theMQTTHandler.canSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)and/orMQTTHandler.canPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)methods to validate this).voidinit(org.openremote.model.Container container, org.apache.activemq.artemis.core.config.Configuration serverConfiguration) Called when the system starts to allow for initialisation.protected static booleanisProvisioningTopic(Topic topic) protected static booleanisRequestTopic(Topic topic) protected static booleanisResponseTopic(Topic topic) voidonConnectionLost(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Will be called when any client loses connectionvoidonDisconnect(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Will be called when any client disconnectsvoidonPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic, io.netty.buffer.ByteBuf body) Called to handle publish ifMQTTHandler.canPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)returned true.voidonSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) Called to handle subscribe ifMQTTHandler.canSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)returned true.voidonUnsubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) Called to handle unsubscribe ifMQTTHandler.handlesTopic(org.openremote.manager.mqtt.Topic)returned true.protected voidprocessProvisioningRequest(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic, io.netty.buffer.ByteBuf body) protected voidprocessX509ProvisioningMessage(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic, org.openremote.model.provisioning.X509ProvisioningMessage provisioningMessage) voidstart(org.openremote.model.Container container) Called when the system starts to allow for initialisation.booleantopicMatches(Topic topic) Indicates if this handler will handle the specified topic; independent of whether it is a publish or subscribe.Methods inherited from class org.openremote.manager.mqtt.MQTTHandler
addPublishConsumer, addPublishTopicServerConfiguration, getAuthContextFromConnection, getAuthContextFromSecurityContext, getName, getPriority, getSecurityContextFromSubject, getSubjectFromConnection, onConnect, onConnectionAuthenticated, onUserAssetLinksChanged, publishMessage, stop, topicClientID, topicClientIdMatches, topicRealm, topicRealmAllowed, topicTokenCountGreaterThan, topicTokenIndexToString
-
Field Details
-
LOG
-
PROVISIONING_TOKEN
- See Also:
-
REQUEST_TOKEN
- See Also:
-
RESPONSE_TOKEN
- See Also:
-
UNIQUE_ID_PLACEHOLDER
- See Also:
-
PROVISIONING_USER_PREFIX
- See Also:
-
provisioningService
-
timerService
protected org.openremote.container.timer.TimerService timerService -
assetStorageService
-
identityProvider
-
isKeycloak
protected boolean isKeycloak -
provisioningConfigAuthenticatedConnectionMap
protected final ConcurrentMap<Long,Set<org.apache.activemq.artemis.spi.core.protocol.RemotingConnection>> provisioningConfigAuthenticatedConnectionMap -
provisioningTimer
protected io.micrometer.core.instrument.Timer provisioningTimer -
responseSubscribedConnections
-
-
Constructor Details
-
UserAssetProvisioningMQTTHandler
public UserAssetProvisioningMQTTHandler()
-
-
Method Details
-
init
public void init(org.openremote.model.Container container, org.apache.activemq.artemis.core.config.Configuration serverConfiguration) throws Exception Description copied from class:MQTTHandlerCalled when the system starts to allow for initialisation.- Overrides:
initin classMQTTHandler- Throws:
Exception
-
start
Description copied from class:MQTTHandlerCalled when the system starts to allow for initialisation.- Overrides:
startin classMQTTHandler- Throws:
Exception
-
getPublishTopicAddressSettings
protected org.apache.activemq.artemis.core.settings.impl.AddressSettings getPublishTopicAddressSettings(org.openremote.model.Container container, String publishTopic) Limit the number of messages allowed in the address queue and fail when over; this will disconnect the client. Approx 20ms per request with 20s timeout on auto provisioning request = 1000- Overrides:
getPublishTopicAddressSettingsin classMQTTHandler
-
handlesTopic
Description copied from class:MQTTHandlerChecks that topic is valid and has at least 3 tokens (generally first two tokens should be {realm}/{clientId} but it is up to theMQTTHandler.canSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)and/orMQTTHandler.canPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)methods to validate this).- Overrides:
handlesTopicin classMQTTHandler
-
checkCanSubscribe
public boolean checkCanSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Description copied from class:MQTTHandlerChecks that authenticated session and topic realm matches the authenticated user and also that topic client ID matches the connection client ID.- Overrides:
checkCanSubscribein classMQTTHandler
-
checkCanPublish
public boolean checkCanPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Description copied from class:MQTTHandlerChecks that authenticated sessions and topic realm matches the authenticated user and also that topic client ID matches the connection client ID.- Overrides:
checkCanPublishin classMQTTHandler
-
topicMatches
Description copied from class:MQTTHandlerIndicates if this handler will handle the specified topic; independent of whether it is a publish or subscribe. Should generally check the third token onwards unlessMQTTHandler.handlesTopic(org.openremote.manager.mqtt.Topic)has been overridden.- Specified by:
topicMatchesin classMQTTHandler
-
getLogger
- Specified by:
getLoggerin classMQTTHandler
-
canSubscribe
public boolean canSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Description copied from class:MQTTHandlerCalled to authorise a subscription ifMQTTHandler.handlesTopic(org.openremote.manager.mqtt.Topic)returned true; should return true if the subscription is allowed otherwise return false.- Specified by:
canSubscribein classMQTTHandler
-
onSubscribe
public void onSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) Description copied from class:MQTTHandlerCalled to handle subscribe ifMQTTHandler.canSubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)returned true.- Specified by:
onSubscribein classMQTTHandler
-
onUnsubscribe
public void onUnsubscribe(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic) Description copied from class:MQTTHandlerCalled to handle unsubscribe ifMQTTHandler.handlesTopic(org.openremote.manager.mqtt.Topic)returned true.- Specified by:
onUnsubscribein classMQTTHandler
-
getPublishListenerTopics
Description copied from class:MQTTHandlerGet the set of topics this handler wants to subscribe to for incoming publish messages; messages that match these topics will be passed toMQTTHandler.onPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.openremote.manager.mqtt.Topic, io.netty.buffer.ByteBuf).- Specified by:
getPublishListenerTopicsin classMQTTHandler
-
canPublish
public boolean canPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, org.keycloak.KeycloakSecurityContext securityContext, Topic topic) Description copied from class:MQTTHandlerCalled to authorise a publish ifMQTTHandler.handlesTopic(org.openremote.manager.mqtt.Topic)returned true; should return true if the publish is allowed otherwise return false.- Specified by:
canPublishin classMQTTHandler
-
onPublish
public void onPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic, io.netty.buffer.ByteBuf body) Description copied from class:MQTTHandlerCalled to handle publish ifMQTTHandler.canPublish(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection, org.keycloak.KeycloakSecurityContext, org.openremote.manager.mqtt.Topic)returned true.- Specified by:
onPublishin classMQTTHandler
-
onConnectionLost
public void onConnectionLost(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Description copied from class:MQTTHandlerWill be called when any client loses connection- Overrides:
onConnectionLostin classMQTTHandler
-
onDisconnect
public void onDisconnect(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection) Description copied from class:MQTTHandlerWill be called when any client disconnects- Overrides:
onDisconnectin classMQTTHandler
-
processProvisioningRequest
protected void processProvisioningRequest(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic, io.netty.buffer.ByteBuf body) -
isProvisioningTopic
-
isRequestTopic
-
isResponseTopic
-
getResponseTopic
-
processX509ProvisioningMessage
protected void processX509ProvisioningMessage(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, Topic topic, org.openremote.model.provisioning.X509ProvisioningMessage provisioningMessage) -
getMatchingX509ProvisioningConfig
protected org.openremote.model.provisioning.X509ProvisioningConfig getMatchingX509ProvisioningConfig(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection connection, X509Certificate clientCertificate) -
getCreateClientServiceUser
public static org.openremote.model.security.User getCreateClientServiceUser(String realm, ManagerKeycloakIdentityProvider identityProvider, String uniqueId, org.openremote.model.provisioning.ProvisioningConfig<?, ?> provisioningConfig) throws RuntimeException- Throws:
RuntimeException
-
getCreateClientAsset
public static org.openremote.model.asset.Asset<?> getCreateClientAsset(AssetStorageService assetStorageService, String realm, String uniqueId, org.openremote.model.security.User serviceUser, org.openremote.model.provisioning.ProvisioningConfig<?, ?> provisioningConfig) throws RuntimeException- Throws:
RuntimeException
-
forceClientDisconnects
protected void forceClientDisconnects(long provisioningConfigId)
-