Skip to content

Latest commit

 

History

History
1143 lines (948 loc) · 35.9 KB

File metadata and controls

1143 lines (948 loc) · 35.9 KB
title Configure MQTT broker authorization
description Configure MQTT broker authorization using BrokerAuthorization.
author sethmanheim
ms.author sethm
ms.subservice azure-mqtt-broker
ms.topic how-to
ms.custom
ignite-2023
ms.date 09/03/2025
ms.service azure-iot-operations

Configure MQTT broker authorization

Authorization policies determine what actions the clients can perform on the broker, such as connecting, publishing, or subscribing to topics. Configure the MQTT broker to use one or multiple authorization policies with the BrokerAuthorization resource. Each BrokerAuthorization resource contains a list of rules that specify the principals and resources for the authorization policies.

How rules are evaluated

  • Policies are allow-only. If no rule explicitly allows an action on a resource for a principal, the action is denied.
  • A rule is defined by three factors: principals (actor), action (Connect/Publish/Subscribe or state store operations), and resource (topics or keys).
  • Principals within a rule are matched with logical OR. For example, any listed username, clientId, or attribute match grants access to the resources in the rule.

Token substitution and wildcards

  • For topics and keys, you can use token substitution to build rules that adapt per client: {principal.username}, {principal.clientId}, and {principal.attributes.<attributeName>}.
  • MQTT topic wildcards + and # are supported in brokerResources.topics.
  • When using token substitution in a topic, the token must be the only text in its path segment. For example, clients/{principal.clientId}/# is valid, but client-{principal.clientId}/# isn't.
  • Connect actions shouldn't include topics.

Link BrokerAuthorization to BrokerListener

To link a BrokerListener resource to a BrokerAuthorization resource, specify the authorizationRef field in the ports setting of the BrokerListener resource. Similar to BrokerAuthentication, the BrokerAuthorization resource can be linked to multiple BrokerListener ports. The authorization policies apply to all linked listener ports. There's one key difference compared with BrokerAuthentication:

Important

To have the BrokerAuthorization configuration apply to a listener port, at least one BrokerAuthentication resource must also be linked to that listener port.

To learn more about BrokerListener, see BrokerListener resource.

Authorization rules

To configure authorization, create a BrokerAuthorization resource in your Kubernetes cluster. The following sections provide examples of how to configure authorization for clients that use usernames, attributes, X.509 certificates, and Kubernetes service account tokens (SATs). For a list of the available settings, see the Broker Authorization API reference.

The following example shows how to create a BrokerAuthorization resource by using both usernames and attributes.

  1. In the Azure portal, go to your IoT Operations instance.

  2. Under Components, select MQTT Broker.

  3. Select the Authorization tab.

  4. Choose an existing authentication policy or create a new one by selecting Create authorization policy.

    :::image type="content" source="media/howto-configure-authorization/authorization-rules.png" alt-text="Screenshot that shows using the Azure portal to create broker authorization rules.":::

Use the az iot ops broker authz apply command to create or change an authorization policy.

az iot ops broker authz apply --resource-group <ResourceGroupName> --instance <AioInstanceName> --broker <BrokerName> --name <AuthenticationResourceName> --config-file <ConfigFilePathAndName>

In this example, assume a configuration file named my-authz-policy.json with the following content stored in the user's home directory:

{
  "authorizationPolicies": {
    "cache": "Enabled",
    "rules": [
      {
        "brokerResources": [
          {
            "clientIds": [],
            "method": "Connect",
            "topics": []
          },
          {
            "clientIds": [],
            "method": "Publish",
            "topics": [
              "odd-numbered-orders"
            ]
          },
          {
            "clientIds": [],
            "method": "Subscribe",
            "topics": [
              "orders"
            ]
          }
        ],
        "principals": {
          "attributes": [
            {
              "group": "authz-sat"
            }
          ],
          "clientIds": [],
          "usernames": []
        }
      }
    ]
  }
}

An example command to create a new authorization policy named my-authz-policy is:

az iot ops broker authz apply --resource-group myResourceGroupName --instance myAioInstanceName --broker default --name my-authz-policy --config-file ~/my-authz-policy.json

To edit an authorization policy, create a .bicep file with the following content. Update the settings as needed, and replace the placeholder values like <AIO_INSTANCE_NAME> with your own.

param aioInstanceName string = '<AIO_INSTANCE_NAME>'
param customLocationName string = '<CUSTOM_LOCATION_NAME>'
param policyName string = '<POLICY_NAME>'

resource aioInstance 'Microsoft.IoTOperations/instances@2024-11-01' existing = {
  name: aioInstanceName
}

resource customLocation 'Microsoft.ExtendedLocation/customLocations@2021-08-31-preview' existing = {
  name: customLocationName
}

resource defaultBroker 'Microsoft.IoTOperations/instances/brokers@2024-11-01' existing = {
  parent: aioInstance
  name: 'default'
}

resource brokerAuthorization 'Microsoft.IoTOperations/instances/brokers/authorizations@2024-11-01' = {
  parent: defaultBroker
  name: policyName
  extendedLocation: {
    name: customLocation.id
    type: 'CustomLocation'
  }
  properties: {
    authorizationPolicies: {
      cache: 'Enabled'
      rules: [
        {
          principals: {
            clientIds: [
              'temperature-sensor'
              'humidity-sensor'
            ]
            attributes: [
              {
                city: 'seattle'
                organization: 'contoso'
              }
            ]
          }
          brokerResources: [
            {
              method: 'Connect'
            }
            {
              method: 'Publish'
              topics: [
                '/sensor/{principal.clientId}'
                '/sensor/{principal.attributes.organization}'
              ]
            }
            {
              method: 'Subscribe'
              topics: [
                '/commands/{principal.attributes.organization}'
              ]
            }
          ]
        }
      ]
    }
  }
}

Deploy the Bicep file by using the Azure CLI:

az deployment group create --resource-group <RESOURCE_GROUP> --template-file <FILE>.bicep

[!INCLUDE kubernetes-debug-only-note]

apiVersion: mqttbroker.iotoperations.azure.com/v1
kind: BrokerAuthorization
metadata:
  name: "my-authz-policies"
  namespace: azure-iot-operations
spec:
  authorizationPolicies:
    cache: Enabled
    rules:
      - principals:
          clientIds:
            - "temperature-sensor"
            - "humidity-sensor"
          attributes:
            - city: "seattle"
              organization: "contoso"
        brokerResources:
          - method: Connect
          - method: Publish
            topics:
              - "/sensor/{principal.clientId}"
              - "/sensor/{principal.attributes.organization}"
          - method: Subscribe
            topics:
              - "/commands/{principal.attributes.organization}"

To create this BrokerAuthorization resource, apply the YAML manifest to your Kubernetes cluster.


This broker authorization allows clients with the client IDs temperature-sensor or humidity-sensor, or clients with the attributes organization, with the values contoso and city, and with the value seattle, to:

  • Connect to the broker.
  • Publish messages to topics scoped with their client IDs and organization. For example:
    • temperature-sensor can publish to /sensor/temperature-sensor and /sensor/contoso.
    • humidity-sensor can publish to /sensor/humidity-sensor and /sensor/contoso.
    • some-other-username can publish to /sensor/contoso.
  • Subscribe to /commands/ topics scoped with their organization. For example:
    • temperature-sensor can subscribe to /commands/contoso.
    • some-other-username can subscribe to /commands/contoso.

Use a username for authorization

To use the MQTT username for authorization, specify them as an array under principals.usernames. Depending on the authentication method, the username might not be verified:

  • Kubernetes SAT: Username shouldn't be used for authorization because it's not verified for MQTTv5 with enhanced authentication.
  • X.509: Username matches the common name (CN) from a certificate and can be used for authorization rules.
  • Custom: Username should only be used for authorization rules if custom authentication validates the username.

To prevent security issues, use the MQTT username for broker authorization only when it can be verified.

Tip

To require that MQTT username matches the client ID, use token substitution:

principals:
  usernames:
    - "{principal.clientId}"

Further limit access based on client ID

Because the principals field is a logical OR, you can further restrict access based on client IDs by adding the clientIds field to the brokerResources field. For example, to allow clients with client IDs that start with their building number to connect and publish to topics scoped with their building, use the following configuration:

In the broker authorization rules for your authorization policy, use the following configuration:

[
  {
    "brokerResources": [
      {
        "clientIds": [
          "{principal.attributes.building}*"
        ],
        "method": "Connect",
        "topics": []
      },
      {
        "clientIds": [],
        "method": "Publish",
        "topics": [
          "sensors/{principal.attributes.building}/{principal.clientId}/sensor"
        ]
      }
    ],
    "principals": {
      "attributes": [
        {
          "building": "building22"
        },
        {
          "building": "building23"
        }
      ]
    }
  }
]

Use the az iot ops broker authz apply command to create or change an authorization policy.

az iot ops broker authz apply --resource-group <ResourceGroupName> --instance <AioInstanceName> --broker <BrokerName> --name <AuthenticationResourceName> --config-file <ConfigFilePathAndName>

In the broker authorization rules for your authorization policy, create a configuration file named client-id-policy.json with the following configuration stored in the user's home directory:

{
  "authorizationPolicies": {
    "cache": "Enabled",
    "rules": [
      {
        "brokerResources": [
          {
            "clientIds": [
              "{principal.attributes.building}*"
            ],
            "method": "Connect",
            "topics": []
          },
          {
            "clientIds": [],
            "method": "Publish",
            "topics": [
              "sensors/{principal.attributes.building}/{principal.clientId}/sensor"
            ]
          }
        ],
        "principals": {
          "attributes": [
            {
              "building": "building22"
            },
            {
              "building": "building23"
            }
          ]
        }
      }
    ]
  }
}

An example command to create a new authorization policy named client-id-authz-policy is:

az iot ops broker authz apply --resource-group myResourceGroupName --instance myAioInstanceName --broker default --name my-authz-policy --config-file ~/client-id-authz-policy.json

To edit an authorization policy, create a .bicep file with the following content. Update the settings as needed, and replace the placeholder values like <AIO_INSTANCE_NAME> with your own.

param aioInstanceName string = '<AIO_INSTANCE_NAME>'
param customLocationName string = '<CUSTOM_LOCATION_NAME>'
param policyName string = '<POLICY_NAME>'

resource aioInstance 'Microsoft.IoTOperations/instances@2024-11-01' existing = {
  name: aioInstanceName
}

resource customLocation 'Microsoft.ExtendedLocation/customLocations@2021-08-31-preview' existing = {
  name: customLocationName
}

resource defaultBroker 'Microsoft.IoTOperations/instances/brokers@2024-11-01' existing = {
  parent: aioInstance
  name: 'default'
}

resource brokerAuthorization 'Microsoft.IoTOperations/instances/brokers/authorizations@2024-11-01' = {
  parent: defaultBroker
  name: policyName
  extendedLocation: {
    name: customLocation.id
    type: 'CustomLocation'
  }
  properties: {
    authorizationPolicies: {
      cache: 'Enabled'
      rules: [
        {
          principals: {
            attributes: [
              {
                building: 'building22'
              }
              {
                building: 'building23'
              }
            ]
          }
          brokerResources: [
            {
              method: 'Connect'
              clientIds: [
                '{principal.attributes.building}*' // client IDs must start with building22
              ]
            }
            {
              method: 'Publish'
              topics: [
                'sensors/{principal.attributes.building}/{principal.clientId}/sensor'
              ]
            }
          ]
        }
      ]
    }
  }
}

Deploy the Bicep file by using the Azure CLI:

az deployment group create --resource-group <RESOURCE_GROUP> --template-file <FILE>.bicep

[!INCLUDE kubernetes-debug-only-note]

apiVersion: mqttbroker.iotoperations.azure.com/v1
kind: BrokerAuthorization
metadata:
  name: "my-authz-policies"
  namespace: azure-iot-operations
spec:
  authorizationPolicies:
    cache: Enabled
    rules:
    - principals:
        attributes:
          - building: "building22"
          - building: "building23"
      brokerResources:
      - method: Connect
        clientIds:
          - "{principal.attributes.building}*" # client IDs must start with building22
      - method: Publish
        topics:
          - "sensors/{principal.attributes.building}/{principal.clientId}/sensor"

Here, if the clientIds weren't set under the Connect method, a client with any client ID could connect as long as it had the building attribute set to building22 or building23. When you add the clientIds field, only clients with client IDs that start with building22 or building23 can connect. This designation ensures that the client has the correct attribute and that the client ID matches the expected pattern.

Authorize clients that use X.509 authentication

You can authorize clients that use X.509 certificates for authentication to access resources based on X.509 properties present on their certificate or their issuing certificates up the chain.

Use attributes

To create rules based on properties from a client's certificate, its root CA, or intermediate CA, define the X.509 attributes in the BrokerAuthorization resource. For more information, see Certificate attributes.

With client certificate subject common name as username

To create authorization policies based on the client certificate subject CN only, create rules based on the CN.

For example, if a client has a certificate with the subject CN = smart-lock, its username is smart-lock. From there, create authorization policies as normal.

Authorize clients that use Kubernetes service account tokens

Authorization attributes for SATs are set as part of the service account annotations. For example, to add an authorization attribute named group with the value authz-sat, run the command:

kubectl annotate serviceaccount mqtt-client aio-broker-auth/group=authz-sat

Attribute annotations must begin with aio-broker-auth/ to distinguish them from other annotations.

As the application has an authorization attribute called authz-sat, there's no need to provide a clientId or username value. The corresponding BrokerAuthorization resource uses this attribute as a principal, for example:

In the broker authorization rules for your authorization policy, use the following configuration:

[
  {
    "brokerResources": [
      {
        "clientIds": [],
        "method": "Connect",
        "topics": []
      },
      {
        "clientIds": [],
        "method": "Publish",
        "topics": [
          "odd-numbered-orders"
        ]
      },
      {
        "clientIds": [],
        "method": "Subscribe",
        "topics": [
          "orders"
        ]
      }
    ],
    "principals": {
      "attributes": [
        {
          "group": "authz-sat"
        }
      ]
    }
  }
]

Use the az iot ops broker authz apply command to create or change an authorization policy.

az iot ops broker authz apply --resource-group <ResourceGroupName> --instance <AioInstanceName> --broker <BrokerName> --name <AuthenticationResourceName> --config-file <ConfigFilePathAndName>

In this example, assume a configuration file named my-authz-policy.json with the following content stored in the user's home directory:

{
  "authorizationPolicies": {
    "cache": "Enabled",
    "rules": [
      {
        "brokerResources": [
          {
            "clientIds": [],
            "method": "Connect",
            "topics": []
          },
          {
            "clientIds": [],
            "method": "Publish",
            "topics": [
              "odd-numbered-orders"
            ]
          },
          {
            "clientIds": [],
            "method": "Subscribe",
            "topics": [
              "orders"
            ]
          }
        ],
        "principals": {
          "attributes": [
            {
              "group": "authz-sat"
            }
          ],
          "clientIds": [],
          "usernames": []
        }
      }
    ]
  }
}

An example command to create a new authorization policy named my-authz-policy is:

az iot ops broker authz apply --resource-group myResourceGroupName --instance myAioInstanceName --broker default --name my-authz-policy --config-file ~/my-authz-policy.json

To edit an authorization policy, create a .bicep file with the following content. Update the settings as needed, and replace the placeholder values like <AIO_INSTANCE_NAME> with your own.

param aioInstanceName string = '<AIO_INSTANCE_NAME>'
param customLocationName string = '<CUSTOM_LOCATION_NAME>'
param policyName string = '<POLICY_NAME>'

resource aioInstance 'Microsoft.IoTOperations/instances@2024-11-01' existing = {
  name: aioInstanceName
}

resource customLocation 'Microsoft.ExtendedLocation/customLocations@2021-08-31-preview' existing = {
  name: customLocationName
}

resource defaultBroker 'Microsoft.IoTOperations/instances/brokers@2024-11-01' existing = {
  parent: aioInstance
  name: 'default'
}

resource brokerAuthorization 'Microsoft.IoTOperations/instances/brokers/authorizations@2024-11-01' = {
  parent: defaultBroker
  name: policyName
  extendedLocation: {
    name: customLocation.id
    type: 'CustomLocation'
  }
  properties: {
    authorizationPolicies: {
      rules: [
        {
          principals: {
            attributes: [
              {
                group: 'authz-sat'
              }
            ]
          }
          brokerResources: [
            {
              method: 'Connect'
            }
            {
              method: 'Publish'
              topics: [
                'odd-numbered-orders'
              ]
            }
            {
              method: 'Subscribe'
              topics: [
                'orders'
              ]
            }
          ]
        }
      ]
    }
  }
}

Deploy the Bicep file by using the Azure CLI:

az deployment group create --resource-group <RESOURCE_GROUP> --template-file <FILE>.bicep

[!INCLUDE kubernetes-debug-only-note]

apiVersion: mqttbroker.iotoperations.azure.com/v1
kind: BrokerAuthorization
metadata:
  name: "my-authz-policies"
  namespace: azure-iot-operations
spec:
  authorizationPolicies:
    cache: Enabled
    rules:
      - principals:
          attributes:
            - group: "authz-sat"
        brokerResources:
          - method: Connect
          - method: Publish
            topics:
              - "odd-numbered-orders"
          - method: Subscribe
            topics:
              - "orders"

To learn more with an example, see Set up Authorization Policy with Dapr Client.

State store

The MQTT broker provides a state store that clients can use to store state. You can also configure the state store to be highly available.

To set up authorization for clients that use the state store, provide permissions for protocol topics and keys:

  • Publish requests to: statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke.
  • Subscribe to the response topic you set on publish, commonly: clients/{principal.clientId}/services/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke/response/#.
  • Grant key access under stateStoreResources per the guidance below.

State store keys

The state store is accessed over the MQTT broker on the topic statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke. Because clients have access to the topic, you can specify keys and access levels under the stateStoreResources section of the MQTT broker brokerResources configuration.

The stateStoreResources section format consists of access level, a pattern indicator, and the pattern.

Include the stateStoreResources section in the rules for your authorization policy.

"stateStoreResources": [
  {
    "method": "", // Values: read, write, readwrite 
    "keyType": "", //Values: string, pattern, binary. Default is pattern
    "keys": [
      // List of patterns to match
    ]
  },
]

Include the stateStoreResources section in the rules for your authorization policy.

"stateStoreResources": [
  {
    "method": "", // Values: read, write, readwrite 
    "keyType": "", //Values: string, pattern, binary. Default is pattern
    "keys": [
      // List of patterns to match
    ]
  },
]

In Bicep, include the stateStoreResources section in your authorization policy.

stateStoreResources: [
  {
    method: '' // Values: read, write, readwrite 
    keyType: '' //Values: string, pattern, binary. Default is pattern
    keys: [
      // List of patterns to match
    ]
  }
  {
    method: 'ReadWrite'
    keyType: 'Binary'
    keys: [
      'xxxxxxxxxxxxxxxxxxxx'
    ]
  }
]

[!INCLUDE kubernetes-debug-only-note]

In your custom resource definition, include the stateStoreResources section in your authorization policy.

stateStoreResources:
  - method:  # Values: read, write, readwrite 
    keyType: # Values: string, pattern, binary. Default is pattern
    keys:
      - # List of patterns to match

The method field specifies the access level:

  • Read access is specified with read. Write access is specified with write. Read and write access is specified with readwrite.
  • Access level is required.
  • Read access level implies the actions of get and keynotify.
  • Write access level implies the actions of set, del, and vdel.

The keyType field specifies the type of key matching:

  • pattern: Used for glob-style pattern matching.
  • string: Used to do exact match, for example, when a key contains characters that might be otherwise matched as a pattern (*, ?, [0-9]).
  • binary: Used to match a binary key.

The keys field specifies the keys to match. You can specify the keys as glob-style patterns, token substitutions, or exact strings.

  • Glob style examples:

    • colors/*: All keys under the "colors/" prefix
    • number[0-9]: Any key from "number0" to "number9"
    • char?: Any key with the prefix "char" and a single digit suffix, like "charA"
    • *: Full access to all keys
  • State store keys also support token substitution when key type is pattern and curly braces are reserved for this purpose. Token substitution examples:

    • clients/{principal.clientId}/*
    • usernames/{principal.username}/*
    • rooms/{principal.attributes.room}/*

Here's an example of how you might author your state store resources.

In the broker authorization rules for your authorization policy, add a similar configuration:

[
  {
    "brokerResources": [
      {
        "clientIds": [
          "{principal.attributes.building}*"
        ],
        "method": "Connect"
      },
      {
        "method": "Publish",
        "topics": [
          "sensors/{principal.attributes.building}/{principal.clientId}/sensor/*"
        ]
      },
      {
        "method": "Subscribe",
        "topics": [
          "commands/{principal.attributes.organization}"
        ]
      }
    ],
    "principals": {
      "attributes": [
        {
          "building": "17",
          "organization": "contoso"
        }
      ],
      "usernames": [
        "temperature-sensor",
        "humidity-sensor"
      ]
    },
    "stateStoreResources": [
      {
        "method": "Read",
        "keyType": "Pattern",
        "keys": [
          "myreadkey",
          "myotherkey?",
          "mynumerickeysuffix[0-9]",
          "clients/{principal.clientId}/*"
        ]
      },
      {
        "method": "ReadWrite",
        "keyType": "Binary",
        "keys": [
          "xxxxxxxxxxxxxxxxxxxx"
        ]
      }
    ]
  }
]

In this example, assume a configuration file named state-store-authz-policy.json in the user's home directory. In the broker authorization rules for your authorization policy, add a similar configuration:

{
  "authorizationPolicies": {
    "cache": "Enabled",
    "rules": [
      {
        "brokerResources": [
          {
            "clientIds": [
              "{principal.attributes.building}*"
            ],
            "method": "Connect"
          },
          {
            "method": "Publish",
            "topics": [
              "sensors/{principal.attributes.building}/{principal.clientId}/sensor/*"
            ]
          },
          {
            "method": "Subscribe",
            "topics": [
              "commands/{principal.attributes.organization}"
            ]
          }
        ],
        "principals": {
          "attributes": [
            {
              "building": "17",
              "organization": "contoso"
            }
          ],
          "usernames": [
            "temperature-sensor",
            "humidity-sensor"
          ]
        },
        "stateStoreResources": [
          {
            "method": "Read",
            "keyType": "Pattern",
            "keys": [
              "myreadkey",
              "myotherkey?",
              "mynumerickeysuffix[0-9]",
              "clients/{principal.clientId}/*"
            ]
          },
          {
            "method": "ReadWrite",
            "keyType": "Binary",
            "keys": [
              "xxxxxxxxxxxxxxxxxxxx"
            ]
          }
        ]
      }
    ]
  }
}

An example command to create a new authorization policy named state-store-authz-policy is:

az iot ops broker authz apply --resource-group myResourceGroupName --instance myAioInstanceName --broker default --name my-authz-policy --config-file ~/state-store-authz-policy.json

To edit an authorization policy, create a .bicep file with the following content. Update the settings as needed, and replace the placeholder values like <AIO_INSTANCE_NAME> with your own.

param aioInstanceName string = '<AIO_INSTANCE_NAME>'
param customLocationName string = '<CUSTOM_LOCATION_NAME>'
param policyName string = '<POLICY_NAME>'

resource aioInstance 'Microsoft.IoTOperations/instances@2024-11-01' existing = {
  name: aioInstanceName
}

resource customLocation 'Microsoft.ExtendedLocation/customLocations@2021-08-31-preview' existing = {
  name: customLocationName
}

resource defaultBroker 'Microsoft.IoTOperations/instances/brokers@2024-11-01' existing = {
  parent: aioInstance
  name: 'default'
}

resource brokerAuthorization 'Microsoft.IoTOperations/instances/brokers/authorizations@2024-11-01' = {
  parent: defaultBroker
  name: policyName
  extendedLocation: {
    name: customLocation.id
    type: 'CustomLocation'
  }
  properties: {
    authorizationPolicies: {
      cache: 'Enabled'
      rules: [
        {
          principals: {
            usernames: [
              'temperature-sensor'
              'humidity-sensor'
            ]
            attributes: [
              {
                city: 'seattle'
                organization: 'contoso'
              }
            ]
          }
          brokerResources: [
            {
              method: 'Connect'
            }
            {
              method: 'Publish'
              topics: [
                '/sensor/{principal.username}'
                '/sensor/{principal.attributes.organization}'
              ]
            }
            {
              method: 'Subscribe'
              topics: [
                '/commands/{principal.attributes.organization}'
              ]
            }
          ]
          stateStoreResources: [
            {
              method: 'Read'
              keyType: 'Pattern'
              keys: [
                'myreadkey'
                'myotherkey?'
                'mynumerickeysuffix[0-9]'
                'clients/{principal.clientId}/*'
              ]
            }
            {
              method: 'ReadWrite'
              keyType: 'Binary'
              keys: [
                'xxxxxxxxxxxxxxxxxxxx'
              ]
            }
          ]
        }
      ]
    }
  }
}

Deploy the Bicep file by using the Azure CLI:

az deployment group create --resource-group <RESOURCE_GROUP> --template-file <FILE>.bicep

[!INCLUDE kubernetes-debug-only-note]

stateStoreResources:
  - method: Read # Read includes Get, Notify
    keyType: "pattern" # string, pattern, binary
    keys:
      - "myreadkey" # explicit read access on key: myreadkey
      - "myotherkey?" # single digit wildcard
      - "mynumerickeysuffix[0-9]" # single digit number range
      - "clients/{principal.clientId}/*" # use token substitution and a wildcard for per-client sandboxing
  - method: ReadWrite  # ReadWrite access includes Get, Notify, Set, Del
    keyType: "binary" # binary keys have exact match, no patterns
    keys:
      - "xxxxxxxxxxxxxxxxxxxx"  # base-64 encoded binary key.

Update authorization

You can update broker authorization resources at runtime without restart. All clients connected at the time of the update of policy are disconnected. Changing the policy type is also supported.

kubectl edit brokerauthorization my-authz-policies

Caching behavior

To reduce authorization overhead on high-throughput topics, enable in-memory caching with authorizationPolicies.cache: Enabled.

  • Decisions are cached per tuple of client, action, and resource. Repeated operations hit the cache.
  • Highly variable resources (for example, unique topic segments per message) lower cache hit rate.
  • The cache grows with the number of unique tuples. Monitor memory for very high churn patterns.

Disable authorization

  1. In the Azure portal, go to your IoT Operations instance.
  2. Under Components, select MQTT Broker.
  3. Select the broker listener you want to edit from the list.
  4. On the port where you want to disable authorization, select None in the authorization dropdown.

Use the az iot ops broker listener port add command to disable authorization for a port. To disable authentication, don't include the --authz-ref parameter.

az iot ops broker listener port add --resource-group <ResourceGroupName> --instance <AioInstanceName> --broker default --listener <ListenerName> --port <ListenerServicePort>

The following example disables authorization for port 8884 to the listener named aio-broker-loadbalancer:

az iot ops broker listener port add --resource-group myResourceGroupName --instance myAioInstanceName --broker default --listener aio-broker-loadbalancer --authn-ref default --port 8884

To disable authorization, omit authorizationRef in the ports setting of your BrokerListener resource.

[!INCLUDE kubernetes-debug-only-note]

To disable authorization, omit authorizationRef in the ports setting of your BrokerListener resource.


Unauthorized publish in MQTT 3.1.1

With MQTT 3.1.1, when publish is denied, the client receives PUBACK with no error because the protocol version doesn't support returning error code. MQTTv5 returns PUBACK with reason code 135 (Not authorized) when publish is denied.

Troubleshooting

Validate rules

  1. Review your BrokerAuthorization YAML/JSON for schema issues.
  2. Check output when applying the config; schema errors are reported by the API server.
  3. Set frontend pod logs to debug or trace, restart pods, and inspect for entries tagged with authz that show parsed and effective rules.

Example healthy logs (abridged):

<7>2025-02-10T16:28:31.986Z aio-broker-frontend-0 [mq@311 tid="1" module="authz"] - adding broker config ... and store config ...
<6>2025-02-10T16:28:31.986Z aio-broker-frontend-0 [mq@311 tid="1"] - starting broker authorization engine with basic rules. Cache enabled: true
<7>2025-02-10T16:28:31.987Z aio-broker-frontend-0 [mq@311 tid="1" module="authz"] - set broker authorization engine data: {"rules":[{...}]}

MQTT broker operations

Denied publish example:

<7>2025-02-10T16:32:19.398Z aio-broker-frontend-0 [mq@311 tid="15" module="authz"] - checking authorization for {"action":"publish","clientId":"test-publisher","topic":"test"}
<7>2025-02-10T16:32:19.411Z aio-broker-frontend-0 [mq@311 tid="15" module="authz"] - publish from client 'test-publisher' was denied ... reason_code: NotAuthorized

State store operations

Denied get example:

<7>2025-02-10T16:41:31.314Z aio-broker-frontend-0 [mq@311 tid="8" module="authz"] - checking authorization for {"action":"get","clientId":"statestore-cli","key":"dGVzdA=="}
<7>2025-02-10T16:41:31.322Z aio-broker-frontend-0 [mq@311 tid="8" module="authz"] - cached new authorization result ...: Denied("no rule matched")

Next steps