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": []
}
Field
Purpose

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:

Field
Purpose

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_ID comes from the environment variable the agent injects

  • ExecutableToken is a short, stable name for your binary — no underscores, no path characters

  • ProcessId is the current OS process ID as a decimal integer

  • The job id must not contain underscores — the broker splits on _ to extract the job ID segment

Example: my-scanner_SecretScanner_48292

For managed plugins:

  • PluginName should align with the plugin id

  • Do not use the job triple format for a plugin — the broker applies different permission logic based on client ID format

Wildcards

Pattern
Scope
When to Use

+

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 5arrow-up-right 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

Symptom
Cause
Fix

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?