Node MQTT credentials
Nodes authenticate to EMQX with the same MySQL authenticator as streaming agents. There is no EMQX account API. The Nodes row is the account.
The MQTT username is the node id. The MQTT password is the canonical pairing key: uppercase, with dashes and spaces removed. EMQX compares that password to Nodes.SecretHash (bcrypt).
Authentication
Replace the MySQL authentication query with:
SELECT password_hash FROM ( SELECT SecretHash AS password_hash FROM StreamingAgents WHERE Id = ${username} AND Enabled = 1 UNION ALL SELECT SecretHash AS password_hash FROM Nodes WHERE Id = ${username} AND SecretHash IS NOT NULL) credsLIMIT 1;Authorization
One statement. A streaming agent may publish dataset/{datasetId} and metadata/dataset/{datasetId} when that dataset is linked and allowed to stream. A node may subscribe to dataset/{datasetId} for each streamed dataset whose primary node is this node and that already has a ma-DMP, when Nodes.Id is the MQTT username and SecretHash is set. RelationType and DatasetType are stored as {id}-{name}-{type}.
SELECT 'publish' AS action, 'allow' AS permission, CONCAT('dataset/', sad.DatasetId) AS topicFROM StreamingAgentDatasets AS sadJOIN StreamingAgents AS sa ON sad.StreamingAgentId = sa.IdWHERE sa.Id = ${username} AND sa.Enabled = 1 AND sad.AllowedToStream = 1UNION ALLSELECT 'publish' AS action, 'allow' AS permission, CONCAT('metadata/dataset/', sad.DatasetId) AS topicFROM StreamingAgentDatasets AS sadJOIN StreamingAgents AS sa ON sad.StreamingAgentId = sa.IdWHERE sa.Id = ${username} AND sa.Enabled = 1 AND sad.AllowedToStream = 1UNION ALLSELECT 'subscribe' AS action, 'allow' AS permission, CONCAT('dataset/', dn.DatasetId) AS topicFROM DatasetNodes AS dnJOIN Datasets AS d ON d.Id = dn.DatasetIdJOIN Nodes AS n ON n.Id = dn.NodeIdWHERE n.Id = ${username} AND n.SecretHash IS NOT NULL AND dn.RelationType = '1-Primary-DatasetNodeRelationType' AND d.DatasetType = '2-StreamedDataset-DatasetType' AND EXISTS ( SELECT 1 FROM MaDmps AS m WHERE m.DatasetId = d.Id )Cutover
After every node is using its pairing key, revoke the shared MQTT JWT. Engines no longer send that token. An already-connected session stays up until the engine process exits, so regenerate a pairing key only when someone can paste the new key on that machine.
Restart engines once after replacing the subscribe rule. A session that already subscribed to dataset/+ keeps that wildcard until the engine process reconnects.