IoT custom authorizer not allowing subscribing and receiving messages

0

We're using IoT as a communication channel for a web app. The clients are not registered things, but rather we authorize using tokens and custom lambda authorizer. Our clients that use the app only receive messages by subscribing to topics of interest.

I have the lambda authorizer setup and everything works when I return the following policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "iot:Connect",
      "Effect": "Allow",
      "Resource": [
        "*"
      ]
    },
    {
      "Action": "iot:Subscribe",
      "Effect": "Allow",
      "Resource": [
        "arn:aws:iot:eu-west-1:ACCOUNT_ID:topicfilter/*"
      ]
    },
    {
      "Action": [
        "iot:Receive"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:iot:eu-west-1:ACCOUNT_ID:topic/*"
      ]
    }
  ]
}

An example topic that the client would subscribe to would be /resource/RESOURCE_ID/event.

The moment I try to restrict the policy more than having just *, it just stops working. For example even if I just add the resource/* to the end of the topic & topicfilter like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "iot:Connect",
      "Effect": "Allow",
      "Resource": [
        "*"
      ]
    },
    {
      "Action": "iot:Subscribe",
      "Effect": "Allow",
      "Resource": [
        "arn:aws:iot:eu-west-1:ACCOUNT_ID:topicfilter/resource/*"
      ]
    },
    {
      "Action": [
        "iot:Receive"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:iot:eu-west-1:ACCOUNT_ID:topic/resource/*"
      ]
    }
  ]
}

Now the client no longer receives any messages.

I've logged the policies, the topics we publish to and subscribe to, and they're 100% correct and identical everywhere. I enabled IoT logging and I found this stuff from logs (removed the non-relevant properties):

{
  "status": "Success",
  "eventType": "Subscribe",
  "topicName": "/resource/RESOURCE_ID/event",
  "subscriptions": [
    {
      "topicName": "/resource/RESOURCE_ID/event",
      "reasonCode": 135
    }
  ]
}

Looking at AWS IoT docs, reason code 135 means "Not authorized". Changing the /resource/* to just /* makes it work.

1 Answer
1
Accepted Answer

And just after I wrote this, I realized that topic names don't need to start with /, and including that in the policy fixes the issue. 🤦

So this works:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "iot:Connect",
      "Effect": "Allow",
      "Resource": [
        "*"
      ]
    },
    {
      "Action": "iot:Subscribe",
      "Effect": "Allow",
      "Resource": [
        "arn:aws:iot:eu-west-1:ACCOUNT_ID:topicfilter//resource/*"
      ]
    },
    {
      "Action": [
        "iot:Receive"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:iot:eu-west-1:ACCOUNT_ID:topic//resource/*"
      ]
    }
  ]
}
reko
answered 7 months ago
  • Good catch! Yes, it's one of those things where specific positioning of the leading slash is important. Another one is the mixing of topic (used by iot:Publish and iot:Receive) and topicfilter (used by iot:Subscribe).

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions