본문 바로가기

AWS IoT/펌웨어

[AWS LED Button] ESP32 (2) : MQTT 프로토콜과 정책, JSON 포맷

MQTT 프로토콜

클라이언트와 사물이 통신을 할 땐 항상 AWS IoT를 매개로 MQTT 프로토콜을 사용하여 통신합니다. 이것은 섀도우 접근도 마찬가지 입니다.

 

 

 

 

통신 주체는 클라이언트와 브로커가 있습니다. 모든 클라이언트는 브로커에 연결되고, 클라이언트끼리는 직접적인 연결이 없습니다. 그리고 모든 데이터는 브로커에 모인 후 필터링되어 다시 적절한 클라이언트들에게 뿌려집니다. 심지어 자기가 보낸 패킷도 조건만 충족되면 다시 돌아옵니다. 모든 데이터는 토픽 단위로 움직입니다. 클라이언트는 데이터를 전송하기 위해 토픽과 이 토픽에 대한 데이터를 브로커에게 발행(Publish)하고, 데이터를 수신하기 위해 브로커로 부터 수신할 토픽을 구독(Subscribe)합니다. 모든 클라이언트는 발행, 구독을 할 수 있습니다. 그리고 토픽과 함께 전송되는 데이터는 여러가지 포맷이 될 수 있지만 AWS IoT는 JSON 포맷을 사용합니다.

 

여기서 브로커를 AWS IoT가 담당합니다. 위에선 클라이언트와 사물이 통신한다고 했는데 IoT(Internet Of Things)에서 사물(Thing)을 강조하기 위한 것일 뿐, 사실 사물도 클라이언트입니다.

 

하지만 모든 클라이언트가 AWS IoT에 연결하고 발행, 구독을 할 수 있는 것은 아닙니다. 이전 포스트에 나와 있지만, AWS IoT에서 생성되고 사물로 다운로드된 인증서에 AWS IoT 정책이 부착(Attach)되어야 합니다.

2018/02/05 - [AWS/LED Button - ESP32] - AWS LED Button 1단계 - ESP32 (1) : 시스템 흐름

정책은 간단하게 권한 리스트라고 보면 됩니다. 이 정책은  JSON 포맷을 사용하여 AWS IoT 콘솔내에서 생성할 수도 있고 CLI를 사용하여 리눅스 콘솔창에서도 생성할 수 있습니다. 전 AWS IoT 콘솔에서 정책을 생성했습니다.

 

JSON 포맷

JSON은 단순히 "키"와 "값"의 집합입니다. 하지만 처음보면 헤깔릴 수 있는데, "값"에 또다시 "키"-"값" 쌍이 올 수 있기 때문입니다. "키"는 항상 큰 따옴표로 감싸져야 합니다. 값은 Integer 또는 bool 또는 string 타입이 될 수 있고, string 타입일 때만 큰 따옴표로 감싸집니다. Integer 타입일 때는 큰 따옴표 없는 정수가 입력되고, bool 타입일 때는 true 또는 false가 입력됩니다. 또한 하나의 "키"에 여러개의 "값"이 올 수 있습니다. 이때는 대괄호([])로 감싸고 "값"은 콤마(,)로 구분합니다.

{
    "key1":{
        "key2":123
    },
    "key3":{
        "key4":[123,456,789],
        "key5":true
    }
}

"키" key1의 입장에선 "key2":123이 모두 "값"이지만, 이 "값"에선 다시 key2가 "키"이 되고 123이 "값"이 됩니다. "키" key3은 "key4":[123,456,789]와 "key5":true라는 두개의 "값"을 갖습니다. 다시 "key4":[123,456,789] 값에서 "키" key4는 123, 456, 789인 3개의 정수형 값을 갖습니다. 그리고 "키" key5는 bool형 true 값을 갖습니다. 

 

제가 생성한 LED Button 정책입니다. <account id>는 개인정보라 가렸습니다.

 

 

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:us-east-1:<account id>:client/LEDButton12345670"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Receive",
      "Resource": [
        "arn:aws:iot:us-east-1:<account id>:topic/LEDButton12345670/command",
        "arn:aws:iot:us-east-1:<account id>:topic/$aws/things/LEDButton12345670/shadow/update/accepted",
        "arn:aws:iot:us-east-1:<account id>:topic/$aws/things/LEDButton12345670/shadow/update/rejected",
        "arn:aws:iot:us-east-1:<account id>:topic/$aws/things/LEDButton12345670/shadow/get/accepted",
        "arn:aws:iot:us-east-1:<account id>:topic/$aws/things/LEDButton12345670/shadow/get/rejected"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": [
        "arn:aws:iot:us-east-1:<account id>:topicfilter/LEDButton12345670/command",
        "arn:aws:iot:us-east-1:<account id>:topicfilter/$aws/things/LEDButton12345670/shadow/update/accepted",
        "arn:aws:iot:us-east-1:<account id>:topicfilter/$aws/things/LEDButton12345670/shadow/update/rejected",
        "arn:aws:iot:us-east-1:<account id>:topicfilter/$aws/things/LEDButton12345670/shadow/get/accepted",
        "arn:aws:iot:us-east-1:<account id>:topicfilter/$aws/things/LEDButton12345670/shadow/get/rejected"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": [
        "arn:aws:iot:us-east-1:<account id>:topic/LEDButton12345670/result",
        "arn:aws:iot:us-east-1:<account id>:topic/$aws/things/LEDButton12345670/shadow/update",
        "arn:aws:iot:us-east-1:<account id>:topic/$aws/things/LEDButton12345670/shadow/get"
      ]
    }
  ]
}

 

 

AWS IoT의 JSON 문서는 "Statement" 키에 정책이 값으로 들어가게 됩니다. 다시 정책은 "Effect", "Action", "Resource" 3개의 키로 구성되어 있습니다. 

 

"Action"의 값은 이 정책이 연결된 인증서를 사용하는 클라이언트가 자신(AWS IoT)에 대해 취할 수 있는 동작이 string 타입으로 입력됩니다. Connect, Publish, Subscribe 모두 여기에 속합니다. 

 

"Resource"는 "Action"이 수행되는 범위 또는 수행될 수 있는 리소스를 의미하며 ARN이 string 타입으로 입력됩니다. ARN은 Amazon Resource Name의 약자로 AWS 내에서 특정 리소스를 표기하는 방법을 의미합니다. 자세한 내용은 여기서 찾을 수 있습니다. 이 리소스의 내용은 "Action"에 따라 달라집니다. "Action"이 Publish일 때는 토픽 ARN 리스트가 입력되며, Subscribe일 때는 토픽 필터 ARN 리스트가 입력됩니다. 참고로 AWS IoT의 ARN은 arn:aws:iot:<Region>:<Account-ID>:<Resource> 형태로 되어 있습니다.

 

"Effect"에는 "Resource"에 대한 "Action"이 허용되면 "Allow"가 거부되면 "Deny"가 입력됩니다.

 

AWS IoT의 JSON 포맷의 형태는 IAM과 동일하지만, IAM 정책에 비해 사용이 제한됩니다. 예를 들면 IAM 정책에선 "Resource" 대신 "NotResource"로 허용되지 않는 리소스를 지정할 수 있는데 AWS IoT에선 "NotResource"를 사용할 수 없습니다. 

 

주의할 점은 사물은 "GetThingShadow"나 "UpdateThingShadow" "Action"으로 사물 섀도우에 대한 접근 권한을 부여받지 않는다는 것입니다. 사물이 AWS IoT의 섀도우를 얻거나 업데이트할 때는 $aws/things/<ThingName>/shadow/<Action>/<Result> 형태의 토픽을 사용합니다.