The azure-native:iotoperations:BrokerAuthorization resource, part of the Pulumi Azure Native provider, defines authorization policies for an IoT Operations MQTT broker: which clients can connect, which topics they can access, and which state store keys they can read or write. This guide focuses on three capabilities: client identification via IDs, usernames, and attributes; MQTT operation permissions (Connect, Publish, Subscribe); and state store access control.
Authorization resources belong to a broker within an IoT Operations instance, both of which must exist. They also reference an Azure Arc CustomLocation for edge deployment. The examples are intentionally small. Combine them with your own broker configuration and client authentication setup.
Allow clients to connect and subscribe to topics
Most broker deployments start by defining which clients can connect and which topics they can subscribe to.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const brokerAuthorization = new azure_native.iotoperations.BrokerAuthorization("brokerAuthorization", {
authorizationName: "resource-name123",
brokerName: "resource-name123",
extendedLocation: {
name: "qmbrfwcpwwhggszhrdjv",
type: azure_native.iotoperations.ExtendedLocationType.CustomLocation,
},
instanceName: "resource-name123",
properties: {
authorizationPolicies: {
cache: azure_native.iotoperations.OperationalMode.Enabled,
rules: [{
brokerResources: [
{
method: azure_native.iotoperations.BrokerResourceDefinitionMethods.Connect,
},
{
method: azure_native.iotoperations.BrokerResourceDefinitionMethods.Subscribe,
topics: [
"topic",
"topic/with/wildcard/#",
],
},
],
principals: {
attributes: [{
floor: "floor1",
site: "site1",
}],
clientIds: ["my-client-id"],
},
stateStoreResources: [{
keyType: azure_native.iotoperations.StateStoreResourceKeyTypes.Pattern,
keys: ["*"],
method: azure_native.iotoperations.StateStoreResourceDefinitionMethods.ReadWrite,
}],
}],
},
},
resourceGroupName: "rgiotoperations",
});
import pulumi
import pulumi_azure_native as azure_native
broker_authorization = azure_native.iotoperations.BrokerAuthorization("brokerAuthorization",
authorization_name="resource-name123",
broker_name="resource-name123",
extended_location={
"name": "qmbrfwcpwwhggszhrdjv",
"type": azure_native.iotoperations.ExtendedLocationType.CUSTOM_LOCATION,
},
instance_name="resource-name123",
properties={
"authorization_policies": {
"cache": azure_native.iotoperations.OperationalMode.ENABLED,
"rules": [{
"broker_resources": [
{
"method": azure_native.iotoperations.BrokerResourceDefinitionMethods.CONNECT,
},
{
"method": azure_native.iotoperations.BrokerResourceDefinitionMethods.SUBSCRIBE,
"topics": [
"topic",
"topic/with/wildcard/#",
],
},
],
"principals": {
"attributes": [{
"floor": "floor1",
"site": "site1",
}],
"client_ids": ["my-client-id"],
},
"state_store_resources": [{
"key_type": azure_native.iotoperations.StateStoreResourceKeyTypes.PATTERN,
"keys": ["*"],
"method": azure_native.iotoperations.StateStoreResourceDefinitionMethods.READ_WRITE,
}],
}],
},
},
resource_group_name="rgiotoperations")
package main
import (
iotoperations "github.com/pulumi/pulumi-azure-native-sdk/iotoperations/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := iotoperations.NewBrokerAuthorization(ctx, "brokerAuthorization", &iotoperations.BrokerAuthorizationArgs{
AuthorizationName: pulumi.String("resource-name123"),
BrokerName: pulumi.String("resource-name123"),
ExtendedLocation: &iotoperations.ExtendedLocationArgs{
Name: pulumi.String("qmbrfwcpwwhggszhrdjv"),
Type: pulumi.String(iotoperations.ExtendedLocationTypeCustomLocation),
},
InstanceName: pulumi.String("resource-name123"),
Properties: &iotoperations.BrokerAuthorizationPropertiesArgs{
AuthorizationPolicies: &iotoperations.AuthorizationConfigArgs{
Cache: pulumi.String(iotoperations.OperationalModeEnabled),
Rules: iotoperations.AuthorizationRuleArray{
&iotoperations.AuthorizationRuleArgs{
BrokerResources: iotoperations.BrokerResourceRuleArray{
&iotoperations.BrokerResourceRuleArgs{
Method: pulumi.String(iotoperations.BrokerResourceDefinitionMethodsConnect),
},
&iotoperations.BrokerResourceRuleArgs{
Method: pulumi.String(iotoperations.BrokerResourceDefinitionMethodsSubscribe),
Topics: pulumi.StringArray{
pulumi.String("topic"),
pulumi.String("topic/with/wildcard/#"),
},
},
},
Principals: &iotoperations.PrincipalDefinitionArgs{
Attributes: pulumi.StringMapArray{
pulumi.StringMap{
"floor": pulumi.String("floor1"),
"site": pulumi.String("site1"),
},
},
ClientIds: pulumi.StringArray{
pulumi.String("my-client-id"),
},
},
StateStoreResources: iotoperations.StateStoreResourceRuleArray{
&iotoperations.StateStoreResourceRuleArgs{
KeyType: pulumi.String(iotoperations.StateStoreResourceKeyTypesPattern),
Keys: pulumi.StringArray{
pulumi.String("*"),
},
Method: pulumi.String(iotoperations.StateStoreResourceDefinitionMethodsReadWrite),
},
},
},
},
},
},
ResourceGroupName: pulumi.String("rgiotoperations"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var brokerAuthorization = new AzureNative.IoTOperations.BrokerAuthorization("brokerAuthorization", new()
{
AuthorizationName = "resource-name123",
BrokerName = "resource-name123",
ExtendedLocation = new AzureNative.IoTOperations.Inputs.ExtendedLocationArgs
{
Name = "qmbrfwcpwwhggszhrdjv",
Type = AzureNative.IoTOperations.ExtendedLocationType.CustomLocation,
},
InstanceName = "resource-name123",
Properties = new AzureNative.IoTOperations.Inputs.BrokerAuthorizationPropertiesArgs
{
AuthorizationPolicies = new AzureNative.IoTOperations.Inputs.AuthorizationConfigArgs
{
Cache = AzureNative.IoTOperations.OperationalMode.Enabled,
Rules = new[]
{
new AzureNative.IoTOperations.Inputs.AuthorizationRuleArgs
{
BrokerResources = new[]
{
new AzureNative.IoTOperations.Inputs.BrokerResourceRuleArgs
{
Method = AzureNative.IoTOperations.BrokerResourceDefinitionMethods.Connect,
},
new AzureNative.IoTOperations.Inputs.BrokerResourceRuleArgs
{
Method = AzureNative.IoTOperations.BrokerResourceDefinitionMethods.Subscribe,
Topics = new[]
{
"topic",
"topic/with/wildcard/#",
},
},
},
Principals = new AzureNative.IoTOperations.Inputs.PrincipalDefinitionArgs
{
Attributes = new[]
{
{
{ "floor", "floor1" },
{ "site", "site1" },
},
},
ClientIds = new[]
{
"my-client-id",
},
},
StateStoreResources = new[]
{
new AzureNative.IoTOperations.Inputs.StateStoreResourceRuleArgs
{
KeyType = AzureNative.IoTOperations.StateStoreResourceKeyTypes.Pattern,
Keys = new[]
{
"*",
},
Method = AzureNative.IoTOperations.StateStoreResourceDefinitionMethods.ReadWrite,
},
},
},
},
},
},
ResourceGroupName = "rgiotoperations",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.iotoperations.BrokerAuthorization;
import com.pulumi.azurenative.iotoperations.BrokerAuthorizationArgs;
import com.pulumi.azurenative.iotoperations.inputs.ExtendedLocationArgs;
import com.pulumi.azurenative.iotoperations.inputs.BrokerAuthorizationPropertiesArgs;
import com.pulumi.azurenative.iotoperations.inputs.AuthorizationConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var brokerAuthorization = new BrokerAuthorization("brokerAuthorization", BrokerAuthorizationArgs.builder()
.authorizationName("resource-name123")
.brokerName("resource-name123")
.extendedLocation(ExtendedLocationArgs.builder()
.name("qmbrfwcpwwhggszhrdjv")
.type("CustomLocation")
.build())
.instanceName("resource-name123")
.properties(BrokerAuthorizationPropertiesArgs.builder()
.authorizationPolicies(AuthorizationConfigArgs.builder()
.cache("Enabled")
.rules(AuthorizationRuleArgs.builder()
.brokerResources(
BrokerResourceRuleArgs.builder()
.method("Connect")
.build(),
BrokerResourceRuleArgs.builder()
.method("Subscribe")
.topics(
"topic",
"topic/with/wildcard/#")
.build())
.principals(PrincipalDefinitionArgs.builder()
.attributes(Map.ofEntries(
Map.entry("floor", "floor1"),
Map.entry("site", "site1")
))
.clientIds("my-client-id")
.build())
.stateStoreResources(StateStoreResourceRuleArgs.builder()
.keyType("Pattern")
.keys("*")
.method("ReadWrite")
.build())
.build())
.build())
.build())
.resourceGroupName("rgiotoperations")
.build());
}
}
resources:
brokerAuthorization:
type: azure-native:iotoperations:BrokerAuthorization
properties:
authorizationName: resource-name123
brokerName: resource-name123
extendedLocation:
name: qmbrfwcpwwhggszhrdjv
type: CustomLocation
instanceName: resource-name123
properties:
authorizationPolicies:
cache: Enabled
rules:
- brokerResources:
- method: Connect
- method: Subscribe
topics:
- topic
- topic/with/wildcard/#
principals:
attributes:
- floor: floor1
site: site1
clientIds:
- my-client-id
stateStoreResources:
- keyType: Pattern
keys:
- '*'
method: ReadWrite
resourceGroupName: rgiotoperations
The authorizationPolicies property contains rules that match clients and grant permissions. Each rule has a principals section that identifies clients by clientIds or attributes, and a brokerResources section that specifies allowed MQTT operations. The method property controls whether clients can Connect, Publish, or Subscribe; the topics array restricts access to specific topic patterns using MQTT wildcards.
Use attribute-based rules with dynamic topic patterns
IoT deployments often need rules that scale across device fleets without hardcoding each client.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const brokerAuthorization = new azure_native.iotoperations.BrokerAuthorization("brokerAuthorization", {
authorizationName: "resource-name123",
brokerName: "resource-name123",
extendedLocation: {
name: "qmbrfwcpwwhggszhrdjv",
type: azure_native.iotoperations.ExtendedLocationType.CustomLocation,
},
instanceName: "resource-name123",
properties: {
authorizationPolicies: {
cache: azure_native.iotoperations.OperationalMode.Enabled,
rules: [{
brokerResources: [
{
clientIds: ["{principal.attributes.building}*"],
method: azure_native.iotoperations.BrokerResourceDefinitionMethods.Connect,
},
{
method: azure_native.iotoperations.BrokerResourceDefinitionMethods.Publish,
topics: ["sensors/{principal.attributes.building}/{principal.clientId}/telemetry/*"],
},
{
method: azure_native.iotoperations.BrokerResourceDefinitionMethods.Subscribe,
topics: ["commands/{principal.attributes.organization}"],
},
],
principals: {
attributes: [{
building: "17",
organization: "contoso",
}],
usernames: [
"temperature-sensor",
"humidity-sensor",
],
},
stateStoreResources: [
{
keyType: azure_native.iotoperations.StateStoreResourceKeyTypes.Pattern,
keys: [
"myreadkey",
"myotherkey?",
"mynumerickeysuffix[0-9]",
"clients:{principal.clientId}:*",
],
method: azure_native.iotoperations.StateStoreResourceDefinitionMethods.Read,
},
{
keyType: azure_native.iotoperations.StateStoreResourceKeyTypes.Binary,
keys: ["MTE2IDEwMSAxMTUgMTE2"],
method: azure_native.iotoperations.StateStoreResourceDefinitionMethods.ReadWrite,
},
],
}],
},
},
resourceGroupName: "rgiotoperations",
});
import pulumi
import pulumi_azure_native as azure_native
broker_authorization = azure_native.iotoperations.BrokerAuthorization("brokerAuthorization",
authorization_name="resource-name123",
broker_name="resource-name123",
extended_location={
"name": "qmbrfwcpwwhggszhrdjv",
"type": azure_native.iotoperations.ExtendedLocationType.CUSTOM_LOCATION,
},
instance_name="resource-name123",
properties={
"authorization_policies": {
"cache": azure_native.iotoperations.OperationalMode.ENABLED,
"rules": [{
"broker_resources": [
{
"client_ids": ["{principal.attributes.building}*"],
"method": azure_native.iotoperations.BrokerResourceDefinitionMethods.CONNECT,
},
{
"method": azure_native.iotoperations.BrokerResourceDefinitionMethods.PUBLISH,
"topics": ["sensors/{principal.attributes.building}/{principal.clientId}/telemetry/*"],
},
{
"method": azure_native.iotoperations.BrokerResourceDefinitionMethods.SUBSCRIBE,
"topics": ["commands/{principal.attributes.organization}"],
},
],
"principals": {
"attributes": [{
"building": "17",
"organization": "contoso",
}],
"usernames": [
"temperature-sensor",
"humidity-sensor",
],
},
"state_store_resources": [
{
"key_type": azure_native.iotoperations.StateStoreResourceKeyTypes.PATTERN,
"keys": [
"myreadkey",
"myotherkey?",
"mynumerickeysuffix[0-9]",
"clients:{principal.clientId}:*",
],
"method": azure_native.iotoperations.StateStoreResourceDefinitionMethods.READ,
},
{
"key_type": azure_native.iotoperations.StateStoreResourceKeyTypes.BINARY,
"keys": ["MTE2IDEwMSAxMTUgMTE2"],
"method": azure_native.iotoperations.StateStoreResourceDefinitionMethods.READ_WRITE,
},
],
}],
},
},
resource_group_name="rgiotoperations")
package main
import (
iotoperations "github.com/pulumi/pulumi-azure-native-sdk/iotoperations/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := iotoperations.NewBrokerAuthorization(ctx, "brokerAuthorization", &iotoperations.BrokerAuthorizationArgs{
AuthorizationName: pulumi.String("resource-name123"),
BrokerName: pulumi.String("resource-name123"),
ExtendedLocation: &iotoperations.ExtendedLocationArgs{
Name: pulumi.String("qmbrfwcpwwhggszhrdjv"),
Type: pulumi.String(iotoperations.ExtendedLocationTypeCustomLocation),
},
InstanceName: pulumi.String("resource-name123"),
Properties: &iotoperations.BrokerAuthorizationPropertiesArgs{
AuthorizationPolicies: &iotoperations.AuthorizationConfigArgs{
Cache: pulumi.String(iotoperations.OperationalModeEnabled),
Rules: iotoperations.AuthorizationRuleArray{
&iotoperations.AuthorizationRuleArgs{
BrokerResources: iotoperations.BrokerResourceRuleArray{
&iotoperations.BrokerResourceRuleArgs{
ClientIds: pulumi.StringArray{
pulumi.String("{principal.attributes.building}*"),
},
Method: pulumi.String(iotoperations.BrokerResourceDefinitionMethodsConnect),
},
&iotoperations.BrokerResourceRuleArgs{
Method: pulumi.String(iotoperations.BrokerResourceDefinitionMethodsPublish),
Topics: pulumi.StringArray{
pulumi.String("sensors/{principal.attributes.building}/{principal.clientId}/telemetry/*"),
},
},
&iotoperations.BrokerResourceRuleArgs{
Method: pulumi.String(iotoperations.BrokerResourceDefinitionMethodsSubscribe),
Topics: pulumi.StringArray{
pulumi.String("commands/{principal.attributes.organization}"),
},
},
},
Principals: &iotoperations.PrincipalDefinitionArgs{
Attributes: pulumi.StringMapArray{
pulumi.StringMap{
"building": pulumi.String("17"),
"organization": pulumi.String("contoso"),
},
},
Usernames: pulumi.StringArray{
pulumi.String("temperature-sensor"),
pulumi.String("humidity-sensor"),
},
},
StateStoreResources: iotoperations.StateStoreResourceRuleArray{
&iotoperations.StateStoreResourceRuleArgs{
KeyType: pulumi.String(iotoperations.StateStoreResourceKeyTypesPattern),
Keys: pulumi.StringArray{
pulumi.String("myreadkey"),
pulumi.String("myotherkey?"),
pulumi.String("mynumerickeysuffix[0-9]"),
pulumi.String("clients:{principal.clientId}:*"),
},
Method: pulumi.String(iotoperations.StateStoreResourceDefinitionMethodsRead),
},
&iotoperations.StateStoreResourceRuleArgs{
KeyType: pulumi.String(iotoperations.StateStoreResourceKeyTypesBinary),
Keys: pulumi.StringArray{
pulumi.String("MTE2IDEwMSAxMTUgMTE2"),
},
Method: pulumi.String(iotoperations.StateStoreResourceDefinitionMethodsReadWrite),
},
},
},
},
},
},
ResourceGroupName: pulumi.String("rgiotoperations"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var brokerAuthorization = new AzureNative.IoTOperations.BrokerAuthorization("brokerAuthorization", new()
{
AuthorizationName = "resource-name123",
BrokerName = "resource-name123",
ExtendedLocation = new AzureNative.IoTOperations.Inputs.ExtendedLocationArgs
{
Name = "qmbrfwcpwwhggszhrdjv",
Type = AzureNative.IoTOperations.ExtendedLocationType.CustomLocation,
},
InstanceName = "resource-name123",
Properties = new AzureNative.IoTOperations.Inputs.BrokerAuthorizationPropertiesArgs
{
AuthorizationPolicies = new AzureNative.IoTOperations.Inputs.AuthorizationConfigArgs
{
Cache = AzureNative.IoTOperations.OperationalMode.Enabled,
Rules = new[]
{
new AzureNative.IoTOperations.Inputs.AuthorizationRuleArgs
{
BrokerResources = new[]
{
new AzureNative.IoTOperations.Inputs.BrokerResourceRuleArgs
{
ClientIds = new[]
{
"{principal.attributes.building}*",
},
Method = AzureNative.IoTOperations.BrokerResourceDefinitionMethods.Connect,
},
new AzureNative.IoTOperations.Inputs.BrokerResourceRuleArgs
{
Method = AzureNative.IoTOperations.BrokerResourceDefinitionMethods.Publish,
Topics = new[]
{
"sensors/{principal.attributes.building}/{principal.clientId}/telemetry/*",
},
},
new AzureNative.IoTOperations.Inputs.BrokerResourceRuleArgs
{
Method = AzureNative.IoTOperations.BrokerResourceDefinitionMethods.Subscribe,
Topics = new[]
{
"commands/{principal.attributes.organization}",
},
},
},
Principals = new AzureNative.IoTOperations.Inputs.PrincipalDefinitionArgs
{
Attributes = new[]
{
{
{ "building", "17" },
{ "organization", "contoso" },
},
},
Usernames = new[]
{
"temperature-sensor",
"humidity-sensor",
},
},
StateStoreResources = new[]
{
new AzureNative.IoTOperations.Inputs.StateStoreResourceRuleArgs
{
KeyType = AzureNative.IoTOperations.StateStoreResourceKeyTypes.Pattern,
Keys = new[]
{
"myreadkey",
"myotherkey?",
"mynumerickeysuffix[0-9]",
"clients:{principal.clientId}:*",
},
Method = AzureNative.IoTOperations.StateStoreResourceDefinitionMethods.Read,
},
new AzureNative.IoTOperations.Inputs.StateStoreResourceRuleArgs
{
KeyType = AzureNative.IoTOperations.StateStoreResourceKeyTypes.Binary,
Keys = new[]
{
"MTE2IDEwMSAxMTUgMTE2",
},
Method = AzureNative.IoTOperations.StateStoreResourceDefinitionMethods.ReadWrite,
},
},
},
},
},
},
ResourceGroupName = "rgiotoperations",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.iotoperations.BrokerAuthorization;
import com.pulumi.azurenative.iotoperations.BrokerAuthorizationArgs;
import com.pulumi.azurenative.iotoperations.inputs.ExtendedLocationArgs;
import com.pulumi.azurenative.iotoperations.inputs.BrokerAuthorizationPropertiesArgs;
import com.pulumi.azurenative.iotoperations.inputs.AuthorizationConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var brokerAuthorization = new BrokerAuthorization("brokerAuthorization", BrokerAuthorizationArgs.builder()
.authorizationName("resource-name123")
.brokerName("resource-name123")
.extendedLocation(ExtendedLocationArgs.builder()
.name("qmbrfwcpwwhggszhrdjv")
.type("CustomLocation")
.build())
.instanceName("resource-name123")
.properties(BrokerAuthorizationPropertiesArgs.builder()
.authorizationPolicies(AuthorizationConfigArgs.builder()
.cache("Enabled")
.rules(AuthorizationRuleArgs.builder()
.brokerResources(
BrokerResourceRuleArgs.builder()
.clientIds("{principal.attributes.building}*")
.method("Connect")
.build(),
BrokerResourceRuleArgs.builder()
.method("Publish")
.topics("sensors/{principal.attributes.building}/{principal.clientId}/telemetry/*")
.build(),
BrokerResourceRuleArgs.builder()
.method("Subscribe")
.topics("commands/{principal.attributes.organization}")
.build())
.principals(PrincipalDefinitionArgs.builder()
.attributes(Map.ofEntries(
Map.entry("building", "17"),
Map.entry("organization", "contoso")
))
.usernames(
"temperature-sensor",
"humidity-sensor")
.build())
.stateStoreResources(
StateStoreResourceRuleArgs.builder()
.keyType("Pattern")
.keys(
"myreadkey",
"myotherkey?",
"mynumerickeysuffix[0-9]",
"clients:{principal.clientId}:*")
.method("Read")
.build(),
StateStoreResourceRuleArgs.builder()
.keyType("Binary")
.keys("MTE2IDEwMSAxMTUgMTE2")
.method("ReadWrite")
.build())
.build())
.build())
.build())
.resourceGroupName("rgiotoperations")
.build());
}
}
resources:
brokerAuthorization:
type: azure-native:iotoperations:BrokerAuthorization
properties:
authorizationName: resource-name123
brokerName: resource-name123
extendedLocation:
name: qmbrfwcpwwhggszhrdjv
type: CustomLocation
instanceName: resource-name123
properties:
authorizationPolicies:
cache: Enabled
rules:
- brokerResources:
- clientIds:
- '{principal.attributes.building}*'
method: Connect
- method: Publish
topics:
- sensors/{principal.attributes.building}/{principal.clientId}/telemetry/*
- method: Subscribe
topics:
- commands/{principal.attributes.organization}
principals:
attributes:
- building: '17'
organization: contoso
usernames:
- temperature-sensor
- humidity-sensor
stateStoreResources:
- keyType: Pattern
keys:
- myreadkey
- myotherkey?
- mynumerickeysuffix[0-9]
- clients:{principal.clientId}:*
method: Read
- keyType: Binary
keys:
- MTE2IDEwMSAxMTUgMTE2
method: ReadWrite
resourceGroupName: rgiotoperations
Attribute-based rules embed client metadata into topic patterns using {principal.attributes.name} syntax. When a client with building: "17" publishes, the broker evaluates the pattern sensors/{principal.attributes.building}/{principal.clientId}/telemetry/* to determine access. The stateStoreResources section uses the same interpolation for key patterns, letting you scope state store access per client or attribute.
Grant access to broker and state store resources
Applications that use both MQTT messaging and state store need rules covering both resource types.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const brokerAuthorization = new azure_native.iotoperations.BrokerAuthorization("brokerAuthorization", {
authorizationName: "resource-name123",
brokerName: "resource-name123",
extendedLocation: {
name: "qmbrfwcpwwhggszhrdjv",
type: azure_native.iotoperations.ExtendedLocationType.CustomLocation,
},
instanceName: "resource-name123",
properties: {
authorizationPolicies: {
cache: azure_native.iotoperations.OperationalMode.Enabled,
rules: [{
brokerResources: [{
clientIds: ["nlc"],
method: azure_native.iotoperations.BrokerResourceDefinitionMethods.Connect,
topics: ["wvuca"],
}],
principals: {
attributes: [{
key5526: "nydhzdhbldygqcn",
}],
clientIds: ["smopeaeddsygz"],
usernames: ["iozngyqndrteikszkbasinzdjtm"],
},
stateStoreResources: [{
keyType: azure_native.iotoperations.StateStoreResourceKeyTypes.Pattern,
keys: ["tkounsqtwvzyaklxjqoerpu"],
method: azure_native.iotoperations.StateStoreResourceDefinitionMethods.Read,
}],
}],
},
},
resourceGroupName: "rgiotoperations",
});
import pulumi
import pulumi_azure_native as azure_native
broker_authorization = azure_native.iotoperations.BrokerAuthorization("brokerAuthorization",
authorization_name="resource-name123",
broker_name="resource-name123",
extended_location={
"name": "qmbrfwcpwwhggszhrdjv",
"type": azure_native.iotoperations.ExtendedLocationType.CUSTOM_LOCATION,
},
instance_name="resource-name123",
properties={
"authorization_policies": {
"cache": azure_native.iotoperations.OperationalMode.ENABLED,
"rules": [{
"broker_resources": [{
"client_ids": ["nlc"],
"method": azure_native.iotoperations.BrokerResourceDefinitionMethods.CONNECT,
"topics": ["wvuca"],
}],
"principals": {
"attributes": [{
"key5526": "nydhzdhbldygqcn",
}],
"client_ids": ["smopeaeddsygz"],
"usernames": ["iozngyqndrteikszkbasinzdjtm"],
},
"state_store_resources": [{
"key_type": azure_native.iotoperations.StateStoreResourceKeyTypes.PATTERN,
"keys": ["tkounsqtwvzyaklxjqoerpu"],
"method": azure_native.iotoperations.StateStoreResourceDefinitionMethods.READ,
}],
}],
},
},
resource_group_name="rgiotoperations")
package main
import (
iotoperations "github.com/pulumi/pulumi-azure-native-sdk/iotoperations/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := iotoperations.NewBrokerAuthorization(ctx, "brokerAuthorization", &iotoperations.BrokerAuthorizationArgs{
AuthorizationName: pulumi.String("resource-name123"),
BrokerName: pulumi.String("resource-name123"),
ExtendedLocation: &iotoperations.ExtendedLocationArgs{
Name: pulumi.String("qmbrfwcpwwhggszhrdjv"),
Type: pulumi.String(iotoperations.ExtendedLocationTypeCustomLocation),
},
InstanceName: pulumi.String("resource-name123"),
Properties: &iotoperations.BrokerAuthorizationPropertiesArgs{
AuthorizationPolicies: &iotoperations.AuthorizationConfigArgs{
Cache: pulumi.String(iotoperations.OperationalModeEnabled),
Rules: iotoperations.AuthorizationRuleArray{
&iotoperations.AuthorizationRuleArgs{
BrokerResources: iotoperations.BrokerResourceRuleArray{
&iotoperations.BrokerResourceRuleArgs{
ClientIds: pulumi.StringArray{
pulumi.String("nlc"),
},
Method: pulumi.String(iotoperations.BrokerResourceDefinitionMethodsConnect),
Topics: pulumi.StringArray{
pulumi.String("wvuca"),
},
},
},
Principals: &iotoperations.PrincipalDefinitionArgs{
Attributes: pulumi.StringMapArray{
pulumi.StringMap{
"key5526": pulumi.String("nydhzdhbldygqcn"),
},
},
ClientIds: pulumi.StringArray{
pulumi.String("smopeaeddsygz"),
},
Usernames: pulumi.StringArray{
pulumi.String("iozngyqndrteikszkbasinzdjtm"),
},
},
StateStoreResources: iotoperations.StateStoreResourceRuleArray{
&iotoperations.StateStoreResourceRuleArgs{
KeyType: pulumi.String(iotoperations.StateStoreResourceKeyTypesPattern),
Keys: pulumi.StringArray{
pulumi.String("tkounsqtwvzyaklxjqoerpu"),
},
Method: pulumi.String(iotoperations.StateStoreResourceDefinitionMethodsRead),
},
},
},
},
},
},
ResourceGroupName: pulumi.String("rgiotoperations"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var brokerAuthorization = new AzureNative.IoTOperations.BrokerAuthorization("brokerAuthorization", new()
{
AuthorizationName = "resource-name123",
BrokerName = "resource-name123",
ExtendedLocation = new AzureNative.IoTOperations.Inputs.ExtendedLocationArgs
{
Name = "qmbrfwcpwwhggszhrdjv",
Type = AzureNative.IoTOperations.ExtendedLocationType.CustomLocation,
},
InstanceName = "resource-name123",
Properties = new AzureNative.IoTOperations.Inputs.BrokerAuthorizationPropertiesArgs
{
AuthorizationPolicies = new AzureNative.IoTOperations.Inputs.AuthorizationConfigArgs
{
Cache = AzureNative.IoTOperations.OperationalMode.Enabled,
Rules = new[]
{
new AzureNative.IoTOperations.Inputs.AuthorizationRuleArgs
{
BrokerResources = new[]
{
new AzureNative.IoTOperations.Inputs.BrokerResourceRuleArgs
{
ClientIds = new[]
{
"nlc",
},
Method = AzureNative.IoTOperations.BrokerResourceDefinitionMethods.Connect,
Topics = new[]
{
"wvuca",
},
},
},
Principals = new AzureNative.IoTOperations.Inputs.PrincipalDefinitionArgs
{
Attributes = new[]
{
{
{ "key5526", "nydhzdhbldygqcn" },
},
},
ClientIds = new[]
{
"smopeaeddsygz",
},
Usernames = new[]
{
"iozngyqndrteikszkbasinzdjtm",
},
},
StateStoreResources = new[]
{
new AzureNative.IoTOperations.Inputs.StateStoreResourceRuleArgs
{
KeyType = AzureNative.IoTOperations.StateStoreResourceKeyTypes.Pattern,
Keys = new[]
{
"tkounsqtwvzyaklxjqoerpu",
},
Method = AzureNative.IoTOperations.StateStoreResourceDefinitionMethods.Read,
},
},
},
},
},
},
ResourceGroupName = "rgiotoperations",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.iotoperations.BrokerAuthorization;
import com.pulumi.azurenative.iotoperations.BrokerAuthorizationArgs;
import com.pulumi.azurenative.iotoperations.inputs.ExtendedLocationArgs;
import com.pulumi.azurenative.iotoperations.inputs.BrokerAuthorizationPropertiesArgs;
import com.pulumi.azurenative.iotoperations.inputs.AuthorizationConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var brokerAuthorization = new BrokerAuthorization("brokerAuthorization", BrokerAuthorizationArgs.builder()
.authorizationName("resource-name123")
.brokerName("resource-name123")
.extendedLocation(ExtendedLocationArgs.builder()
.name("qmbrfwcpwwhggszhrdjv")
.type("CustomLocation")
.build())
.instanceName("resource-name123")
.properties(BrokerAuthorizationPropertiesArgs.builder()
.authorizationPolicies(AuthorizationConfigArgs.builder()
.cache("Enabled")
.rules(AuthorizationRuleArgs.builder()
.brokerResources(BrokerResourceRuleArgs.builder()
.clientIds("nlc")
.method("Connect")
.topics("wvuca")
.build())
.principals(PrincipalDefinitionArgs.builder()
.attributes(Map.of("key5526", "nydhzdhbldygqcn"))
.clientIds("smopeaeddsygz")
.usernames("iozngyqndrteikszkbasinzdjtm")
.build())
.stateStoreResources(StateStoreResourceRuleArgs.builder()
.keyType("Pattern")
.keys("tkounsqtwvzyaklxjqoerpu")
.method("Read")
.build())
.build())
.build())
.build())
.resourceGroupName("rgiotoperations")
.build());
}
}
resources:
brokerAuthorization:
type: azure-native:iotoperations:BrokerAuthorization
properties:
authorizationName: resource-name123
brokerName: resource-name123
extendedLocation:
name: qmbrfwcpwwhggszhrdjv
type: CustomLocation
instanceName: resource-name123
properties:
authorizationPolicies:
cache: Enabled
rules:
- brokerResources:
- clientIds:
- nlc
method: Connect
topics:
- wvuca
principals:
attributes:
- key5526: nydhzdhbldygqcn
clientIds:
- smopeaeddsygz
usernames:
- iozngyqndrteikszkbasinzdjtm
stateStoreResources:
- keyType: Pattern
keys:
- tkounsqtwvzyaklxjqoerpu
method: Read
resourceGroupName: rgiotoperations
A single rule can define permissions for broker operations and state store key access. The brokerResources section controls MQTT operations; the stateStoreResources section controls state store access. The keyType property determines how keys are matched: Pattern uses wildcards, Binary uses base64-encoded keys. The method property sets whether clients can Read, Write, or ReadWrite.
Beyond these examples
These snippets focus on specific authorization features: client identification (IDs, usernames, attributes), MQTT operation permissions (Connect, Publish, Subscribe), and state store access control (pattern and binary keys). They’re intentionally minimal rather than full broker deployments.
The examples reference pre-existing infrastructure such as IoT Operations instance and broker, Azure Arc CustomLocation, and state store configuration (for relevant examples). They focus on authorization policy configuration rather than provisioning the broker itself.
To keep things focused, common authorization patterns are omitted, including:
- Cache configuration tuning (cache property defaults to Enabled)
- Multiple authorization rules per policy
- Client certificate-based authentication
- Wildcard patterns in clientIds and usernames
These omissions are intentional: the goal is to illustrate how each authorization feature is wired, not provide drop-in security modules. See the BrokerAuthorization resource reference for all available configuration options.
Let's configure Azure IoT Operations Broker Authorization
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Authorization Rules & Permissions
Connect (for client connections), Publish (for publishing messages), and Subscribe (for subscribing to topics).Read (read-only access) and ReadWrite (full access) methods.{principal.attributes.building}, {principal.clientId}, or {principal.attributes.organization} in topics, clientIds, or state store keys. For example, sensors/{principal.attributes.building}/{principal.clientId}/telemetry/* dynamically includes the principal’s building attribute and client ID.authorizationPolicies.cache to Enabled to cache authorization decisions for improved performance, or Disabled to evaluate every request.Pattern Matching & Wildcards
# for multi-level wildcards (e.g., topic/with/wildcard/#).keyType: Pattern, you can use * (multi-character wildcard), ? (single-character wildcard), and character classes like [0-9]. Examples include myotherkey?, mynumerickeysuffix[0-9], and clients:{principal.clientId}:*.Pattern uses string matching with wildcards for flexible key matching, while Binary uses base64-encoded keys for exact binary matching (e.g., MTE2IDEwMSAxMTUgMTE2).Configuration & Lifecycle
authorizationName, brokerName, instanceName, resourceGroupName, and extendedLocation. You must recreate the resource to change these values.pulumi package add azure-native iotoperations [ApiVersion] to generate a local SDK package for versions like 2024-07-01-preview, 2024-08-15-preview, 2024-09-15-preview, 2025-04-01, 2025-07-01-preview, or 2025-10-01.