AWS - JITR,Just-in-Time Registration,即時註冊。

春麗 S.T.E.M.
12 min readFeb 22, 2024

--

目錄
1
. 前情提要
2. 複習 Lambda
3. 裝置首次連線
3-1 Arduino 呈現狀態
4. 最終流程

⦿ 前情提要
⦿ 複習 Lambda
⦿ 裝置首次連線
⦿ Arduino 呈現狀態
⦿ 最終流程

前情提要

前一篇文章,我們知道設備(裝置)要與 AWS 交互時有更簡便的方法 —— JITP,JITP 允許設備第一次連線 AWS 時,註冊設備憑證,並為設備憑證附加政策、產生 Thing⋯⋯,這樣在 AWS IoT Core 中就不會有多餘的、預先產生的憑證佔據頁面,並且也不好追蹤及管理。

不過使用 JITP 仍然有一些限制,沒辦法很靈活地做一些想要做的其他事,像是設備第一次連線時,在產生 Thing 的當下,為 Thing 一個帥氣卻保有規則的字,於此同時產生 Shadow,為了將來能夠同步設備與手機 APP 中的狀態

關於 Shadow 可以參考下面的文章:

而在另一篇文章中,我們使用了 Lambda,在設備已經設置憑證private key 的時候,對特定的 Topic 傳送訊息,以訊息內容驅動 Lambda 為設備產生 Thing,於此同時產生 Shadow 以及其他種種。

這個方法其實相當不錯,不過每次連線都得朝特定 Topic 發送特定訊息,這會不會出問題?例如一個憑證產生多個 Thing 或多個 Shadow,所幸,AWS 的 Thing 與 Shadow 的名稱是不能重複的,這即是說即便多次驅動 Lambda,最終仍只會產生一個 Thing 與特定的 Shadow,缺點是在於 Lambda Function 的驅動計費可能會不斷地增加。

而為了做出更靈活的事情,AWS 也提供了一個相當不錯的作法 —— JITR,Just-in-Time Registration,即時註冊。即時註冊實現的方法也是透過 Lambda Function 的驅動,來為設備憑證產生 Thing、Shadow 等,差別僅是當設備憑證首次連線自動註冊時,會朝 AWS 預留的 Topic(含有 $ 做開頭的 Topic) 發送相關訊息。

融合 JITP 的優點,我們這篇文章來講講 JITR,由於會使用到 Lambda Function,所以下面我們也先來複習 Lambda Function。

回目錄

繼續閱讀|回目錄

複習 Lambda

我們參考關於 Lambda 的文章:

首先,進到 AWS Lambda 的服務中,建立函式,並選擇你要用來撰寫函式的語言,接著,點選組態 => 許可 => 為你的執行角色加入權限,由於這個權限是以 IoT Core 特定的 Topic 做為 Trigger,所以加入 IoT 相應權限,最後,加入 Trigger,選擇 IoT,以 SQL 設定特定 Topic。

前置作業就完成了!

我們看到範例程式碼:

import json
import boto3
from botocore.exceptions import BotoCoreError, ClientError

iot = boto3.client('iot')
iot_data = boto3.client('iot-data', region_name='ap-southeast-2')

def lambda_handler(event, context):
mac_address = event['mac']
thing_name = f'sensor_{mac_address}'
group_name = 'Sensor'

try:
# Activates the certificate
iot.update_certificate(
certificateId=event['cid'],
newStatus='ACTIVE'
)

# Creates a new Thing
iot.create_thing(
thingName=thing_name
)

# Attaches the certificate to the Thing
iot.attach_thing_principal(
principal=event['carn'],
thingName=thing_name
)

# Adds the Thing to the Thing Group
iot.add_thing_to_thing_group(
thingGroupName=group_name,
thingName=thing_name
)

# Interacts with the named shadows to create them
iot_data.update_thing_shadow(
thingName=thing_name,
payload=json.dumps({
'state': {
'desired': {
'info': 'Initial info shadow message'
}
}
}),
shadowName=f'sensor_{mac_address}_factory'
)

iot_data.update_thing_shadow(
thingName=thing_name,
payload=json.dumps({
'state': {
'desired': {
'LED': 'off'
},
'reported': {
'LED': 'off'
}
}
}),
shadowName=f'sensor_{mac_address}_event'
)

print('JITR process completed successfully for', thing_name)

return {
'statusCode': 200,
'body': 'Success'
}

except (BotoCoreError, ClientError) as error:
print(error)

return {
'statusCode': 400,
'body': str(error)
}

在這段程式碼中,接收到訊息有三個,分別是 MACCIDCARN,即是 MAC Address,還有 Certificate 的 ID 與 ARN,這是由設備發出的,event[‘mac’]event[‘cid’]event[‘carn’] 就是從事件讀取而來的三個訊息。

MAC 被組成 Thing Name,而 Group 是在 IoT Core 上設置的實物群組,所以在 Lambda Handler 中,我們 try 了,iot.update_certificate 更新憑證狀態為 ACTIVE;iot.create_thing 產生 Thing,Thing Name 包含 MAC;iot.attach_thing_principal 將憑證與 Thing 關聯起來;iot.add_thing_to_thing_group 將 Thing 加入特定實物群組;iot_data.update_thing_shadow 產生兩個 Shadow,一個用來打設備初始資訊,一個用來打設備初始狀態,兩者的名稱皆包含 MAC。

後面則是成功驅動印出成功訊息失敗也印出錯誤訊息

回目錄

繼續閱讀|回目錄

裝置首次連線

AWS 告訴我們,如果 CA 憑證已經 AWS 認證過,並且 CA 憑證設為 ACTIVE自動註冊也打開,而當裝置憑證註冊時,沒有將憑證狀態設為 ACTIVE,那麼,當裝置使用裝置憑證進行首次連線,憑證的狀態會變成 PENDING_ACTIVATION

實際例子如下:

這個憑證會處於等待啟用(PENDING_ACTIVATION)的狀態。

此外,憑證還會朝特定的、AWS 保留的 Topic 發送訊息,這個預留的 Topic 是 $aws/events/certificates/registered/<caCertificateId>,後面即是你用來簽署這個裝置憑證的 CA Certificate 的 ID。

測試時可以訂閱這個預留的 Topic,裝置第一次連線時,AWS 就會從這個 Topic 收到訊息:

而我收到的訊息如下:

{
"certificateId": "9f9b7fbab5d86559943826bbb255d7c65ffd3323b8318b00550dc2edb7654e38",
"caCertificateId": "6b271c84e220102e4a9594bd7b9eea4a9fd28536b06a1537e13c4705f91d929c",
"timestamp": 1708501227363,
"certificateStatus": "PENDING_ACTIVATION",
"awsAccountId": "123456789012",
"certificateRegistrationTimestamp": null,
"sourceIp": "XX.XX.XX.XX"
}

你可以看到裝置憑證的 ID,也有 CA 憑證的 ID,事實上有這兩個 ID 等於也有了兩者的 ARN,因為我們說 ARN 裡面就包含了 ID,訊息也告訴我們,裝置憑證的狀態是等待啟用。

接著,我們就可以更改 Lambda 的 Trigger 為 $aws/events/certificates/registered/<caCertificateId> 這個 Topic,如下:

即是將原本打到 mcu/esp32/fakedata/tap 的這個動作,改成打到 AWS 預留的 Topic,並且經過實測,裝置無論連線幾次,只會朝這 Topic 打一次相關訊息,這就變成了有效的單次 Trigger Lambda Function 的設計。

Arduino 呈現狀態

接著,我們來看看 PENDING_ACTIVATION 的狀態實際發生情況,看到 Arduino Monitor 如下:

第一個已註冊並且作用中的憑證嘗試連線,但該憑證並無相應權限(附加正確政策)而得到的結果,就是說這是一個看起來正常卻沒辦法正常以 MQTT 方式連接到 AWS IoT Core 的憑證。

解決辦法當然是幫憑證附加上正確的政策

第二個初次連線的憑證處於 PENDING_ACTIVATION,等待 Lambda 被 Trigger,設置憑證為作用中,附加政策、產生 Thing & Shadow⋯⋯等,實際上我在 Arduino 的寫法是,那個「⋯⋯」若在沒有正確連上 AWS 時會不斷地嘗試連線,也就是「⋯⋯」會一直延續下去,而這次卻在中間斷掉了,這即是處於 PENDING_ACTIVATION 造成的結果。

當然 Trigger Lambda 後,後續就會成為正常的連線憑證。

回目錄

繼續閱讀|回目錄

最終流程

那麼,在 JITP、JITR,以及 Trigger Lambda 這些組合技中,可能就有一個不錯的解決方案,我們試著順過裝置憑證註冊流程。

  1. 乾淨模板,或不使用模板的情況下,向 AWS 註冊自簽 CA 憑證,當然,憑證必須設定為作用中,並且自動註冊必須打開
  2. 以 CA 憑證簽署裝置憑證,但不去更改裝置憑證的狀態,所以預設為非作用中,在首次連線 AWS 時會變成 PENDING_ACTIVATION
  3. 首次連線,自動會將憑證相關資訊發到 AWS 預設 MQTT Topic:$aws/events/certificates/registered/<caCertificateId>
  4. Trigger Lambda,改動憑證的狀態為 ACTIVE、附加政策、產生 Thing、將 Thing 與憑證關聯起來、產生兩種 Shadow(一個裝出廠資訊,一個裝裝置初始狀態)

以此流程設計憑證產出,將會簡化許多步驟,我們不用將裝置韌體加入程式碼,讓它朝特定 MQTT Topic 去打相關資訊,而是 AWS 在 INACTIVE 狀態的憑證初次連上線時,自動將狀態改為 PENDING_ACTIVATION,並且該憑證會自動朝 AWS 預留的 Topic 發送相關訊息,其中重要資訊為 Certificate ID,有了 ID 就有 ARN,有 ARN 就可以做相應操作(設置狀態、附加政策、產生 Thing⋯⋯)。

那麼,我們就對 IoT 產線流程,或說產線流程部份多了些概念,以便找到適合你企業的解決方案。

這次就分享到這,感謝您的閱讀。

回目錄

繼續閱讀|回目錄

Reference:

--

--

春麗 S.T.E.M.
春麗 S.T.E.M.

Written by 春麗 S.T.E.M.

Do not go gentle into that good night, Old age should burn and rave at close of day; Rage, rage, against the dying of the light.

No responses yet