【小ネタ】 AWS IoT Core JITPで証明書のステータスが「保留中のアクティベーション」となってしまった際の原因特定
はじめに
こんにちは、コンサルティング部の神野です。
先日の記事で AWS IoT Core の「JITP(Just-In-Time Provisioning)」機能について記載しました。
この機能を使うと、デバイスが初めて接続した時に自動的に証明書の登録から「モノ」の作成、ポリシーの適用まで一連の処理を自動化できて便利なのですが、初回接続して証明書のステータスを見たら保留中のアクティベーション
となっていてJITPに失敗したケースがありました。
ええ、何が原因で失敗したんだろう・・・??と思ったのですが、CloudTrailを見たら早々に解決したので共有したく記事を書きました!
保留中のアクティベーションはどこで起こるのか?
まず、JITPの処理フローを簡単に確認しておきましょう。
JITPでは以下のステップで処理が進みます。
- デバイス証明書を登録し、ステータスを
保留中のアクティベーション
に設定 - プロビジョニングテンプレートに基づいてモノリソースを作成
- ポリシーリソースを作成(または既存のポリシーを使用)
- 証明書にポリシーを添付
- 証明書をモノに添付
- 証明書のステータスを
アクティブ
に更新
問題が発生すると、証明書が保留中のアクティベーション
のステップで止まってしまい、アクティブ
にならないという症状が現れます。これが発生すると、デバイスは正常に接続できず、再接続を試みても同じエラーが繰り返されます。
推測
原因としては、テンプレートに従って各種リソースを作る箇所でエラーになって止まってしまったからアクティブ
に推移しなかったんだろうなと推測できました。
テンプレート自体は問題なく登録できていることから、おそらく権限が怪しいのではと思い、CloudTrailを見た次第です。
公式ドキュメントにも下記記載があるので、CloudTrailを見るのがまずは良さそうですね。
CloudTrail を使用して、JITP テンプレートの問題をトラブルシューティングすることもできます。Amazon CloudWatch に記録されるメトリクスの詳細については、「デバイスプロビジョニングメトリクス」をご覧ください。プロビジョニングテンプレートの詳細については、「プロビジョニングテンプレート」をご覧ください。
原因の切り分け方
この問題に遭遇したとき、まず確認すべきなのは権限不足
の可能性です。JITPのプロビジョニングプロセスは、設定したIAMロールの権限で実行されます。このロールに必要な権限が不足していると、プロビジョニングの途中で失敗します。
CloudTrailのログを確認する
問題の原因を特定するには、CloudTrailのログを確認するのが確実です。CloudTrailでは、JITPで使用するロール(今回ならJitpProvisioningRole
)アクションのログを検索します。
エラーログの例は以下のようなイメージです。
{
"eventVersion": "1.11",
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROA****:IoT-Thing-Provisioning-****",
"arn": "arn:aws:sts::123456789012:assumed-role/JitpProvisioningRole/IoT-Thing-Provisioning-****",
"accountId": "123456789012",
"accessKeyId": "ASIA****",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "AROA****",
"arn": "arn:aws:iam::123456789012:role/JitpProvisioningRole",
"accountId": "123456789012",
"userName": "JitpProvisioningRole"
},
"attributes": {
"creationDate": "2025-05-21T01:38:51Z",
"mfaAuthenticated": "false"
}
},
"invokedBy": "iot.amazonaws.com"
},
"eventTime": "2025-05-21T01:38:51Z",
"eventSource": "iot.amazonaws.com",
"eventName": "RegisterThing",
"awsRegion": "ap-northeast-1",
"sourceIPAddress": "iot.amazonaws.com",
"userAgent": "iot.amazonaws.com",
"errorCode": "ResourceRegistrationFailureException",
"errorMessage": "Register thing workflow execution terminates due to: User: arn:aws:sts::123456789012:assumed-role/JitpProvisioningRole/IoT-Thing-Provisioning-**** is not authorized to perform: iot:CreateThing on resource: arn:aws:iot:ap-northeast-1:123456789012:thing/JitpDevice because no identity-based policy allows the iot:CreateThing action",
"requestParameters": {
"templateBody": "...",
"parameters": {
"AWS::IoT::Certificate::Country": "JP",
"AWS::IoT::Certificate::CommonName": "JitpDevice",
"AWS::IoT::Certificate::Id": "a068****",
"AWS::IoT::Certificate::SerialNumber": "DEVICE123456"
}
}
}
このログからは「iot:CreateThing
アクションを実行する権限がない」というエラーメッセージが記録されています。
JITPプロビジョニングに使用しているIAMロール(JitpProvisioningRole
)に必要な権限が不足していることがわかりました!
その他エラーとしてあり得るとしたら、テンプレートでプロビジョニング時に割り当てるタイプやグループが事前に作成していなければ、エラーになるケースもあります。
CloudWatchメトリクスも確認する
CloudTrailの他に、CloudWatchのメトリクスも確認することもできます。
ProvisionThing.ClientError
というメトリクスが増加していれば、JITPのプロビジョニングが失敗していることが分かります。権限周りのエラーもClientError
に含まれるんだなと今回わかりました。
ただし、CloudWatchメトリクスではエラーの発生は分かりますが、具体的な原因(今回の場合は権限不足)までは分からないため、根本原因の特定にはCloudTrailのログ確認が不可欠かと思います。
他のメトリクスについても公式ドキュメントをご参照ください。
解決方法
問題を解決するには、JITPプロビジョニングに使用しているIAMロールに必要な権限を追加する必要があります。具体的には以下の手順で対応します。
必要な権限を確認する
JITPプロセスでは、プロビジョニングテンプレートに基づいて様々なアクションが実行されます。テンプレートの内容に応じて必要な権限は異なりますが、基本的には以下のアクションが必要となることが多いです。前回の記事の内容で必要だった権限は下記でした。
iot:CreateThing
iot:AttachPolicy
iot:AttachThingPrincipal
iot:UpdateCertificate
iot:AddThingToThingGroup
(モノをグループに追加する場合)iot:RegisterThing
iot:DescribeThing
iot:ListThingGroupsForThing
iot:DescribeCertificate
iot:DescribeThingType
(特定のモノタイプを使用する場合)iot:DescribeThingGroup
(モノをグループに追加する場合)iot:GetPolicy
iot:AttachPrincipalPolicy
iot:CreatePolicy
(テンプレート内で新しいポリシーを作成する場合)
IAMポリシーを修正する
以下のようなポリシーをJITPプロビジョニングロールに追加します。本番環境では必要最小限の権限に絞ることをお勧めしますが、まずは問題の切り分けのために広めの権限で確認するのも一つの方法かと思います。特定できたら必要な権限・リソースに対象を絞りましょう。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:CreateThing",
"iot:AttachPolicy",
"iot:AttachThingPrincipal",
"iot:UpdateCertificate",
"iot:AddThingToThingGroup",
"iot:RegisterThing",
"iot:DescribeThing",
"iot:ListThingGroupsForThing",
"iot:DescribeCertificate",
"iot:DescribeThingType",
"iot:DescribeThingGroup",
"iot:GetPolicy",
"iot:AttachPrincipalPolicy"
],
// 対象リソースは本番環境では要検討
"Resource": "*"
}
]
}
必要に応じてモノタイプやモノグループを事前に作成する
JITPテンプレートで特定のモノタイプやモノグループを指定している場合、それらが事前に作成されていないとエラーになります。テンプレートの内容に応じて、必要なリソースを事前に作成しておきましょう。
例えば、テンプレートが次のような場合は事前に相当するリソース(タイプ、グループ)を作成する必要がございます。
"thing": {
"Properties": {
"ThingName": {
"Ref": "AWS::IoT::Certificate::CommonName"
},
"ThingTypeName": "lightBulb-versionA",
"ThingGroups": [
"v1-lightbulbs",
{
"Ref": "AWS::IoT::Certificate::Country"
}
]
}
}
おわりに
JITPのプロビジョニングで問題が発生した場合は、CloudWatchのメトリクスや、CloudTrailのログを確認して具体的な原因を特定し、必要な対応を行いましょう!
ぼんやりと何で上手くいかないんだろうと思っていたことが、CloudTrailを見ることで一発で解決できました!
今回の記事がみなさんのお役に立てば幸いです!
最後までご覧いただきありがとうございましたー!!