Configure Azure IoT Operations Broker Authorization

The azure-native:iotoperations:BrokerAuthorization resource, part of the Pulumi Azure Native provider, defines authorization policies for an Azure 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 and topic authorization, attribute-based access control, and state store key patterns.

Authorization resources belong to a broker within an IoT Operations instance. 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 principals block identifies clients by clientIds or attributes (key-value pairs like site and floor). The brokerResources array defines what those clients can do: the method property specifies MQTT operations (Connect, Subscribe, Publish), and the topics array lists allowed topic patterns. Wildcards like # match multiple topic levels. The stateStoreResources block grants read-write access to all state store keys using the * pattern.

Use attribute-based rules with dynamic topic patterns

IoT deployments often need rules that scale across device fleets without hardcoding every client ID.

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 reference client properties at runtime using template syntax like {principal.attributes.building} and {principal.clientId}. The principals block defines required attributes (building: “17”, organization: “contoso”) and usernames (temperature-sensor, humidity-sensor). The brokerResources array uses these attributes in topic patterns, so each client publishes to a unique path based on its identity. The stateStoreResources block demonstrates two access patterns: pattern-based keys using wildcards and character classes ([0-9]), and binary keys encoded as base64 strings.

Grant state store access with pattern matching

Applications using the broker’s state store need rules that control which keys clients can access.

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

The stateStoreResources block defines access rules for the broker’s state store. The keyType property determines how keys are matched: Pattern uses wildcards and literals, while Binary expects base64-encoded key names. The keys array lists patterns or exact keys, and the method property specifies Read, Write, or ReadWrite permissions. Pattern matching lets you grant access to key families without listing every key individually.

Beyond these examples

These snippets focus on specific authorization features: client authentication and topic authorization, attribute-based access control with dynamic patterns, and state store key access rules. They’re intentionally minimal rather than full broker deployments.

The examples reference pre-existing infrastructure such as Azure IoT Operations instance and broker, and Azure Arc custom location for edge deployment. They focus on configuring authorization policies rather than provisioning the broker itself.

To keep things focused, common authorization patterns are omitted, including:

  • Username-based principal matching (usernames property)
  • Multiple authorization rules per policy
  • Cache configuration tuning beyond enabled/disabled
  • Binary key types for state store access

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 FREE

Frequently Asked Questions

Authorization Rules & Principals
How do I use principal attributes dynamically in authorization rules?
Use the syntax {principal.attributes.attributeName} or {principal.clientId} in clientIds, topics, or state store keys. For example, sensors/{principal.attributes.building}/{principal.clientId}/telemetry/* creates dynamic topic patterns based on the principal’s building attribute and client ID.
Can I define multiple authorization rules for different principals?
Yes, the authorizationPolicies.rules property accepts an array of authorization rules. Each rule can specify different principals (by attributes, clientIds, or usernames) and their allowed broker resources and state store access.
How do I specify which principals an authorization rule applies to?
Configure the principals property with attributes (key-value pairs like building: “17”), clientIds (MQTT client IDs), or usernames. Principals matching any of these criteria will be subject to the rule.
State Store Access Control
What pattern matching is supported in state store keys?
When using keyType: Pattern, you can use * (matches any characters), ? (matches single character), and [0-9] (matches character ranges). Examples: myotherkey?, mynumerickeysuffix[0-9], clients:{principal.clientId}:*.
What's the difference between Pattern and Binary keyTypes for state store resources?
Pattern keyType uses string patterns with wildcards (like mykey* or key[0-9]). Binary keyType uses base64-encoded binary keys (like MTE2IDEwMSAxMTUgMTE2).
How do I grant read-only vs read-write access to state store keys?
Set the method property to Read for read-only access or ReadWrite for full access. You can define multiple state store resource rules with different methods for different key patterns.
MQTT Broker Operations
How do I authorize MQTT connect, publish, and subscribe operations?
Configure brokerResources with the appropriate method: Connect for client connections, Publish for publishing to topics, or Subscribe for subscribing to topics. Specify topics for Publish and Subscribe methods, and optionally clientIds for Connect.
Can I use wildcards in MQTT topic authorization patterns?
Yes, use # for multi-level wildcards in topic patterns, such as topic/with/wildcard/#. You can also combine wildcards with dynamic principal attributes like sensors/{principal.attributes.building}/#.
Resource Configuration
What properties can't I change after creating a BrokerAuthorization?
The following properties are immutable and require resource replacement if changed: extendedLocation, authorizationName, brokerName, instanceName, and resourceGroupName.

Using a different cloud?

Explore security guides for other cloud providers: