AWS IoT Greengrass CoreデバイスとAWSサービス間の認証フローを整理してみた
はじめに
AWS IoT Greengrass(以下、Greengrass)を利用していると、認証・認可のために証明書やらロールやらポリシーやら色々なリソースが出てくるので、権限周りのトラブルシューティングする際にいつも焦って混乱してしまいます。
ということで、今回はGreengrassの認証認可周りを図を使って整理していきたいと思います。
なお、本記事ではGreengrass V2を対象としています。
また、今回はGreengrass CoreデバイスとAWSサービス間の通信にフォーカスしています。
Greengrass Coreデバイスとクライアントデバイス間の通信についてはこの記事では触れていません。
全体像
Greengrass CoreデバイスとAWSの通信で発生する認証認可フローを整理する上で重要なのは、デバイス側とAWS側、それぞれどのようなリソースを持っているか?だと思います。
まずは全体像から。

左側がGreengrass Coreデバイス側、右側がAWS側になります。
全体像だけだと何をしているのかいまいち分かりませんね。
それでは一つずつ紐解いていきましょう。
通信経路
まずはGreengrass CoreデバイスとAWSサービス間の通信において、どのような通信が発生するか確認します。
Greengrass Coreデバイスの認証認可は大きく分けて2つのパターンがあります。
1つ目は、Greengrass CoreデバイスがAWS IoT CoreとMQTT/HTTPS通信するパターンです。

2つ目は、Greengrass CoreデバイスがS3やCloudWatch LogsなどのAWSサービスを直接利用するパターンです。

この2つは利用する認証情報やロールが異なるので、まずはそれぞれの登場人物を整理します。
登場する認証情報とロール
Greengrassの認証認可周りにはいくつかの認証情報とロールが登場します。
デバイス側とAWS側に分けて整理してみます。
デバイス側の登場人物
まずはデバイス側の登場人物です。

| 認証情報 | 種類 | 説明 |
|---|---|---|
| X.509 デバイス証明書 + 秘密鍵 | 証明書 | デバイスの身分証明書。AWS IoT Coreへの接続やAWS認証情報の取得に使う |
| Amazon Root CA 証明書 | 証明書 | AWS IoT Coreのサーバー証明書を検証するためのルート証明書 |
| AWS一時認証情報 | 認証情報 | S3やCloudWatchなどのAWSサービスと通信するための一時認証情報 |
| Token Exchange Service | Greengrassコンポーネント | X.509証明書を使ってIoT Credentials Providerから一時認証情報を取得し、コンポーネントに提供する |
証明書
通常、クライアント端末からAWSへアクセスする際はアクセスキーやシークレットキーが必要ですが、Greengrass CoreデバイスはAWSのアクセスキーやシークレットキーはデバイス上に保存されません。
デバイスの身分証明はすべてX.509証明書+秘密鍵+CA証明書を使った相互認証になっています。
なお、デバイス証明書の発行方法にはAWS IoT CoreのCAによる発行のほか、カスタムCAによる発行(JITP/JITR)やFleet Provisioningなど複数のパターンがありますが、証明書がデバイスに配置された後の認証フローはどのパターンでも同じです。
Token Exchange Serviceと一時認証情報
Token Exchange ServiceはGreengrass CoreデバイスがAWSサービスと直接やりとりするために必要な認証情報を取得するための中継サービスです。
普段あまり意識することはありませんが、Greengrass Coreデバイスをプロビジョニングすると、ローカルサーバーとして実行されます。
Greengrassのマネジメントコンソールを確認するとToken Exchange Serviceが起動していることがわかりますね。

カスタムコンポーネントがAWSサービスを呼び出す際、このToken Exchange Serviceが代わりに一時認証情報を取得してコンポーネントに渡します。
AWS側の登場人物
次にAWS側の登場人物です。
ここが頭を悩ませる部分かもしれません。

| リソース | 種類 | 用途 |
|---|---|---|
| デバイス証明書 | 証明書 | デバイス側のX.509証明書と同一の証明書。IoT Coreに登録され、相互認証時にデバイスの身元を検証する |
| AWS IoT ポリシー | IoTポリシー | IoT CoreやGreengrassのデータプレーン操作(MQTT接続、Pub/Sub等)を認可する |
| ロールエイリアス | ロールエイリアス | デバイス証明書とIAMロールを紐づける |
| IAM Role (Token Exchange Role) |
IAMロール | デバイスがAWSサービス(S3、CloudWatch Logs等)を利用する際の権限 |
| AWS IoT Core credential provider | IoT Coreの機能 | Token Exchange Serviceからのリクエストを受け取り、AWS STSと連携して一時認証情報を発行する |
| AWS Security Token Service(AWS STS) | AWSサービス | AWS IoT Core credential providerからの要求に応じて、IAM Roleに基づく一時認証情報を発行する |
| Greengrass Service Role | IAMロール | Greengrassサービス自体がAWSリソースにアクセスする際の権限 |
特に混乱しやすいのが、IoTポリシー・IoT Role Alias・IAM Roleの関係性です。
「どこで何を認可しているのか、なぜ3つも必要なのか」がわかりにくいポイントです。
IoTポリシー
IoT Coreへの接続やMQTTのPub/Subなど、IoT Coreとの通信を認可するポリシーです。
IoTポリシーは1つの証明書に複数のポリシーをアタッチすることができます。
ロールエイリアス
X.509証明書の世界とIAMの世界をつなぐ橋渡し役です。「この証明書を持つデバイスはこのIAM Roleを使ってよい」という対応を定義します。
S3などの一般的なAWSサービスはX.509証明書を理解できないため、一度IAM(STSの一時認証情報)に変換してやる必要があります。
そのためにRole Aliasが必要になります。

ちょっと細かい話ですが、IoTポリシーとロールエイリアスが直接紐づいているわけではなく、IoTポリシーはロールエイリアスを「Resource(操作対象)」として指定し、そのロールエイリアスをAssumeする(iot:AssumeRoleWithCertificate)ことを許可している。という関係性になります。
IAM Role(Token Exchange Role)
S3やCloudWatch LogsなどのAWSサービスへのアクセスを認可するロールです。
IAMポリシーをアタッチして権限を定義します。
IoTポリシーはIoT Coreの世界での認可、IAM RoleはAWSサービスの世界での認可、そしてその2つをつなぐのがIoT Role Aliasという役割分担になっています。
Greengrass Service Role
Greengrass Service RoleはCoreデバイスとAWSサービス間の通信では意識する必要はありませんが、Greengrassのサービスロールであり、AWS IoT GreengrassがAWSサービスのリソースにアクセスする際に利用されています。
ドキュメントと実際のサービスロールのポリシーを見る限りでは、クライアントデバイスがGreengrass Coreデバイスと接続する際に、Greengrassサービス(クラウド側)が裏方で使うロールという印象です。
主にクライアントデバイス側の話になるので、今回は深掘りはしません。
なお、表に記載したIoT Credentials ProviderとSTSについては、後述するToken Exchangeの流れの中で説明します。
では、ここで紹介した登場人物が実際にどう連携してどう利用されているのか、接続方式ごとに見ていきます。
AWS IoT Coreとの通信(TLS相互認証)
まずはGreengrass CoreデバイスとAWS IoT Coreの間の通信です。
この通信はIoT Coreとの接続やMQTTメッセージのPublish/Subscribeなど、Greengrass Coreデバイスの基本的な操作に使われます。
認証認可の流れ
それでは実際に認証認可の流れを見てみましょう。

- Greengrass CoreデバイスがX.509デバイス証明書と秘密鍵を使ってAWS IoT Coreに接続
- AWS IoT Core側もサーバー証明書を提示(デバイスはRoot CA証明書で検証)
- 双方の証明書が正しいことを確認
- 接続後の操作はデバイス証明書にアタッチされたIoTポリシーで認可
Greengrass CoreデバイスとAWS IoT Coreの間の通信はそんなに難しいことはありませんね。
デバイス証明書で誰を判断して、デバイス証明書に紐づくIoTポリシーで何ができるを定義しているだけです。
IoTポリシーで制御するアクション
IoTポリシーではIoT CoreとGreengrassそれぞれのアクションを制御します。
最低限、以下のポリシーが必要になります。
参照: AWS IoT Greengrass V2 policy actions
IoT Core系のアクション
| アクション | 説明 |
|---|---|
iot:Connect |
IoT Coreへの接続 |
iot:Publish |
MQTTトピックへのパブリッシュ |
iot:Subscribe |
MQTTトピックのサブスクライブ |
iot:Receive |
MQTTメッセージの受信 |
iot:AssumeRoleWithCertificate |
Token Exchange用の一時認証情報取得(※後述するAWSサービスとの通信で必要) |
Greengrass系のアクション
| アクション | 説明 |
|---|---|
greengrass:GetComponentVersionArtifact |
コンポーネントアーティファクトのダウンロード |
greengrass:ResolveComponentCandidates |
デプロイ時のコンポーネント依存解決 |
greengrass:GetDeploymentConfiguration |
デプロイ設定の取得 |
greengrass:ListThingGroupsForCoreDevice |
Thing Group階層の取得 |
AWSサービスとの通信
次に、Greengrass CoreデバイスがS3やCloudWatch LogsなどのAWSサービスを直接利用する際の通信です。
ここが特に混乱しやすいポイントかなと思います。
ベースは先ほどのIoT Coreとの通信と同じですが、AWSサービスへ直接アクセスする際には認証情報が必要になります。
AWSサービスとの通信ではこの認証情報をどのように取得しているか?が重要なポイントになります。
なぜToken Exchange Serviceが必要なのか
先ほど登場人物を整理する際にも少し触れましたが、AWSサービスへアクセスするための認証情報を取得するにはToken Exchange Serviceが必要です。
ではなぜToken Exchange Serviceが必要なのでしょうか。
S3やCloudWatch Logsなどの一般的なAWSサービスは、IoT CoreのようにX.509証明書による認証をサポートしていません。
これらのサービスを呼び出すにはAWSの認証情報(アクセスキー、シークレットキー、セッショントークン)が必要です。
とはいえ、デバイスにアクセスキーを埋め込むのはセキュリティ的にやりたくないですよね。
ということで、X.509証明書から一時的なAWS認証情報を取得するToken Exchangeという仕組みが用意されています。
では具体的にToken Exchange Serviceを使ってどのようにAWSサービスに接続しているのかみていきましょう。
一時認証情報の取得
全体の流れとしてはこんな感じです。

今回はGreengrass上にデプロイしたコンポーネントが、S3やCloudWatch Logsにデータを送信することを想定します。
1つずつ順を追ってみていきましょう。
-
Greengrass上のコンポーネントがAWS SDKでAWSサービスを呼び出す
-
AWS SDKが環境変数
AWS_CONTAINER_CREDENTIALS_FULL_URIを参照し、Token Exchange Serviceに認証情報をリクエスト

-
Token Exchange ServiceがX.509デバイス証明書を使ってIoT Credentials ProviderにHTTPSリクエスト

-
IoT Credentials Providerが証明書を検証し、Role Aliasに紐づくIAMロール(Token Exchange Role)を特定

-
IoT Credentials ProviderがSTSの
AssumeRoleを実行し、一時認証情報を取得

-
一時認証情報がToken Exchange Service経由でコンポーネントに返却される

-
コンポーネントはこの認証情報を使ってSigV4署名でAWSサービスを呼び出す

少し複雑ではありますが、要はIoT Core(IoT Credentials Provider)に接続して、認証情報を取得する。
そして、その認証情報を使ってAWSサービスにアクセスしているということです。
もしAWSサービスの接続に関するトラブルシューティングが必要な場合は、まずToken Exchange RoleにアタッチされたIAMポリシーを確認しましょう。
Token Exchange Roleのデフォルトの権限は最小限で、CloudWatch Logsへのログ出力とS3のバケットロケーション取得程度です。
よくある権限エラーはS3からコンポーネントアーティファクトをデプロイする場合に権限が不足しているパターンです。
S3にあるアーティファクトをデプロイする場合は別途s3:GetObjectの権限を追加する必要があります。
デバイスに紐づく証明書、ポリシー、ロールエイリアス、IAMロールを調べる
実際に権限周りでエラーが起きた際に、まずデバイスに紐づく証明書やポリシー、ロールエイリアス、IAMロールを確認すると思います。
しかし、意外に何が何に紐づいているか、どこで確認すればいいか焦って分からなくなることがあるので、AWSマネジメントコンソールでの確認方法を見ていきます。
証明書
AWS IoT コンソール画面 > 全てのデバイス > 対象のデバイスを選択 > 証明書
証明書は1デバイスに複数アタッチされている場合があります。
IoTポリシー
AWS IoT コンソール画面 > 全てのデバイス > 対象のデバイスを選択 > 証明書 > 対象の証明書を選択
IoTポリシーは1デバイスに複数アタッチされている場合があります。
ロールエイリアス
AWS IoT コンソール画面 > 全てのデバイス > 対象のデバイスを選択 > 証明書 > 対象の証明書を選択 > ポリシーアクションに iot:AssumeRoleWithCertificate がアタッチされたポリシーを探す(ポリシー名にTESやToken Exchange Serviceと付けておくとわかりやすい) > ポリシーリソースに記載されているrolealias以降の文字列

IAMロール
AWS IoT コンソール画面 > セキュリティ > ロールエイリアス > ロールエイリアスの手順で取得したロールエイリアスを選択 > ロール


証明書から一つずつ芋づる方式に確認が必要です。
いきなりIAMロールやロールエイリアスから探そうとすると、何と紐づいているか分からないため、証明書から辿るようにしましょう。
まとめ
今回はGreengrass Coreデバイスの認証認可周りを整理してみました。
認証認可の経路は2つあり、どのAWSサービスと通信するか次第で認証認可の方法が変わります。
トラブルシューティングの際も「IoTポリシーの問題なのかIAMポリシーの問題なのか」の切り分けがしやすくなるので、頭の片隅に入れておくと役立つかもしれません。






