Job & Plugin: MQTT Topic Permissions
Audience: Integrators configuring MQTT topic permissions for job tasks or managed plugins.
This page is a consolidated reference for how the MQTT broker enforces topic permissions for integrator-authored components. For the narrative explanation of how MQTT fits into the broader integration flow, see Step 3 of the Custom Job Integration Guide and Step 2 of the Custom Plugin Integration Guide.
How Enforcement Works
Topic permissions are declared in the component's JSON file and enforced by the broker at runtime. The enforcement model has four stages:
Declaration. A job declares permitted topics in mqttTopics on the job root object. A plugin declares them in metadata.mqttTopics in the plugin JSON.
Connection. When a component connects to the broker, the broker validates the client identity against the launched-process registry and resolves which job or plugin the connection belongs to based on the client ID format.
Enforcement. Every publish and subscribe call is checked against the declared allowed lists for that component. Calls to undeclared topics are denied. The MQTT connection itself is not dropped — only the individual operation fails.
Silent denial. A denied publish or subscribe does not produce a client-visible error in most cases. If operations appear to succeed at the connection level but messages are not arriving, a missing topic declaration is the first thing to check.
Jobs
Topic permissions for job tasks are declared on the job root object — not inside the task definition:
"mqttTopics": {
"allowedPublications": ["KeeperLogger"],
"allowedSubscriptions": []
}allowedPublications
Topics the task may publish to. Must include every topic the binary publishes — KeeperLogger, eventTopic, or any custom topic.
allowedSubscriptions
Topics the task may subscribe to. Empty for most job tasks that only publish logs.
When mqttTopics is present with at least one entry, the agent injects KEEPER_JOB_ID and KEEPER_JOB_NAME as environment variables before starting the task. These are required to form the correct MQTT client ID.
If your task does not use MQTT at all, you may omit mqttTopics entirely. Doing so also means KEEPER_JOB_ID and KEEPER_JOB_NAME are not injected.
Plugins
Topic permissions for managed plugins are declared under metadata in the plugin JSON:
publish
Topics the plugin may publish to.
subscribe
Topics the plugin may subscribe to beyond the primary Subscription.Topic.
The primary Subscription.Topic is a separate field from metadata.mqttTopics.subscribe. Both are subscribed — declare additional topics in metadata.mqttTopics.subscribe alongside the primary subscription, not instead of it.
Side-by-Side Comparison
Jobs (Jobs/*.json)
Plugins (Plugins/*.json)
Declaration location
mqttTopics on the job root
metadata.mqttTopics inside the plugin JSON
Publish field name
allowedPublications
publish
Subscribe field name
allowedSubscriptions
subscribe
Primary subscription
Not applicable
Declared separately as Subscription.Topic
MQTT client ID format
{KEEPER_JOB_ID}_{Token}_{Pid}
{PluginName}_{Pid} or {PluginName}_{UserName}_{Pid}
Environment variables
KEEPER_JOB_ID, KEEPER_JOB_NAME injected when mqttTopics is set
Not injected via environment; plugin reads its own identity from its id
MQTT Client IDs
The broker uses the client ID format to associate a connection with a job or plugin and apply the correct permission set. Using the wrong format causes permission checks to fail even when the topic declarations are correct.
For job tasks:
KEEPER_JOB_IDcomes from the environment variable the agent injectsExecutableTokenis a short, stable name for your binary — no underscores, no path charactersProcessIdis the current OS process ID as a decimal integerThe job
idmust not contain underscores — the broker splits on_to extract the job ID segment
Example: my-scanner_SecretScanner_48292
For managed plugins:
PluginNameshould align with the pluginidDo not use the job triple format for a plugin — the broker applies different permission logic based on client ID format
Wildcards
+
Matches exactly one topic level
Command and response patterns where subtopics vary by type: Commands/+ matches Commands/scan and Commands/reset but not Commands/a/b
#
Matches all levels below a prefix
Broad monitoring or logging patterns — use sparingly and only where required
Prefer explicit topic strings in production. Wildcards are convenient during development but reduce what the broker can enforce. For a bounded command set, list each topic explicitly:
KeeperLogger
KeeperLogger is the well-known topic for structured log delivery. Any job task or plugin that publishes structured log messages must include it in the publish list. The payload must follow the RequestMessage JSON format — see Step 5 in the Custom Job Integration Guide for the complete format and a code example.
Do not publish to product-internal topics (policy, API, and similar) unless your administrator has explicitly extended permissions for your component.
Common Failures
Publish silently fails
Topic not in allowedPublications / publish
Add the topic to the correct declared list
Subscribe silently fails
Topic not in allowedSubscriptions / subscribe
Add the topic to the correct declared list
eventTopic publishes denied
eventTopic string not present in allowedPublications
Add the exact eventTopic string to allowedPublications — the strings must match exactly
Permission check fails despite correct declarations
Wrong client ID format — job triple used for plugin or vice versa
Confirm client ID format matches the component type
MQTT connection refused entirely
Process not in launched-process registry
Ensure binary is started by the agent (job runner or orchestrator), not manually; add retry on startup
Last updated
Was this helpful?

