AWS IAM の知っておくべき話と知らなくてもいい話 でチョークトークスタイルで登壇しました #devio2023

「AWS IAM の知っておくべき話と知らなくてもいい話」をしました。当日あまりできなかった「知らなくてもいい話」をこの場で少しだけさせてください。

コンバンハ、千葉(幸)です。

2023/7/7 , 7/8 に行われた Developers IO 2023 にて、「AWS IAM の知っておくべき話と知らなくてもいい話」というタイトルで登壇しました。

AWS IAM の知っておくべき話と知らなくてもいい話

AWS IAMはAWSを利用する上で避けて通れないサービスです。使ったことがない、という方はいないと思います。そんなIAMについて、正解はないけどみんなどんな設計してるの?という話と、つまずきがちな複雑な評価論理の話と、知らなくてもいい裏側の話をします。皆さんのIAMライフをちょっとだけ豊かにすることを目指します。

クラスメソッド株式会社 AWS事業本部コンサルティング部 マネージャー 千葉幸宏(チバユキ)

チョークトークという対話型のセッションで 2回登壇しています。「知っておきべき話」が盛り上がらないと「知らなくてもいい話」を喋り続けることになるな、と思っていました。



ありがたいことに(と同時に少しさびしいことに)「知らなくてもいい話」はする機会がありませんでした。

このブログでは、当日の様子をご紹介しながら、現地で し損ねた「知らなくてもいい話」をちょっとだけしていきます。

登壇の様子

▲ スナップを効かせて右手を上げようとしているわたし

▲ ちょっと半目になりながら「はい!」としているわたし

参加者の方には、挙手 / スケッチブック / マイクを用いた発言 を通じて参加いただきました。

登壇資料

チョークトーク前提なのでいろいろ抜け落ちてますが、雰囲気を感じ取ってください。

資料内の参考リンクは以下です。

ちょっと補足

開始する際に皆さんの IAM レベルを聞いてみました。2~3の方が多かったです。2回のセッションの中で、5 の方が1名だけいらっしゃいました。すごい。

20230708_DevelopersIO2023_chibayuki3

大きく4つのテーマに分け、皆さんの興味が多いものを重点的に取り上げるスタイルにしました。

20230708_DevelopersIO2023_chibayuki1

挙手による投票を行なったところ、2回の登壇とも2番の「ベストプラクティス」が最多票を集めました。

4番の「データプレーンとコントロールプレーンの話」が知らなくてもいい話にあたるわけですが、サクラ票を除くと0~1票に留まりました。そりゃそうか。

2番の「ベストプラクティス」は、独断と偏見で「どの程度対応すべきか」を表現しました。

20230708_DevelopersIO2023_chibayuki2

究極的には「場合による」に収斂してしまうのですが、突き詰めると大変なのでなるべく楽をしたいよね、がわたし個人のスタンスです。場合によります。

当日でた質問とか

当日はいくつか質問をいただきました。そのうち一部を、わたしの記憶に基づいて再編集した上で取り上げます。

Q. Permissions boundary っていつ使うんですか?

A. 使わなくていいと思います。いろいろ複雑になってつらくないですか?

というのは暴論として、使わなくて済むならそれに越したことはないと思います。守るべきセキュリティポリシーがある、それを IAM ポリシーや Organizations SCP では賄えない、という場合には採用することになるでしょう。

以下のように IAM 管理者に権限を委任するケースや、

アプリケーションチーム(開発者)にサービス用のロールの管理を任せたいケースが使い所かと思います。

後者については以下の考え方です。

  • アプリケーション用のロールに設定する Permissions boundary Aを定めておく
  • IAM 管理者は、開発者に以下の権限を与える
    • 「Permissions boundary Aをアタッチする場合のみ IAM ロールを作成できる」

Q. PowerUserAceess と ReadOnlyAccess のちょうどいい中間ないですか?

A. ジョブ機能の AWS 管理ポリシーでちょうどいいのがあれば使ってみては

AWS 管理ポリシーを活用しようとすると、以下がよく出てきます。

  • AdministratorAccess:大抵のことはなんでもできる
  • PowerUserAceess:IAM や Organizations などを除きだいたいのことができる
  • ReadOnlyAccess:だいたいの読み取りだけできる

ここで、PowerUserAceessReadOnlyAccessが持つ権限にかなり開きがあるので、そこの中間にあたるようなちょうどいいものがないか、というご質問でした。

実は上記の3つはいずれも「ジョブ機能の AWS 管理ポリシー」に分類されます。ジョブ(職務)に応じて必要となりそうな権限を用意してくれている、というものです。

ここではネットワーク管理者用(NetworkAdministrator)、データベース管理者用(DatabaseAdministrator)といった形である程度決めうちのものがあるので、いったんそれに則ってみるというのもアリかと思います。

用途にマッチしない場合は、ReadOnlyAccessAmazonEC2FullAccessなどサービス単位でのフルアクセス権限を組み合わせていく、それでも広すぎる場合には独自のカスタマー管理ポリシーを作成して割り当てていく、という進め方になるでしょう。

許容されるならなるべく広めの権限をつけたいですね。

Q.オンプレミス用にアクセスキーを払い出すのは避けた方がいいですか?

A. 運用・実装コストなどを鑑みればそれが最適解であることもあると思います。

IAM アクセスキーの払い出しはなるべく避けましょう、というのがベストプラクティスとされています。アクセスキーが流出したことで不正利用される、というケースが多々あるためです。

EC2 上のアプリケーションであればインスタンスプロファイルを使用する、AWS CLI の実行であれば AWS CloudShell を活用する、などアクセスキーの使用を避けられるのであればそれに越したことはありません。

ただ、オンプレミス上のサーバーから AWS API リクエストを実行させたいケースの場合、なかなか代替手段がありません。IAM Roles Anywhere というサービスを活用することでほぼアクセスキーの使用を無くせますが、そのために付随してセットアップする必要が生じるリソースもあります。

理想を言えば IAM Roles Anywhere を使いましょう・になりますが、そこまでパワーをかけられるかというとそうではないケースが多いと思います。「必要以上に権限を持たせない」「一定期間でローテーションする」といった前提を踏まえた上で、オンプレミス用のワークロードにアクセスキーを利用するのは十分妥当な選択肢だと考えます。

他にもたくさん質問いただきました

ここまで取り上げたもの以外にも、たくさん質問をいただきました。また、わたしの方から皆さんに質問することもありました。覚えている限りで、こういった話題が出ましたよというのを羅列します。

  • 管理者、開発者などの役割をどのくらい分けてる?
  • 最小権限どこまで追求してる?
  • IAM の棚卸ってどのくらいの頻度でやるといい?
  • IAM Access Analyzer ってどうやって使うの?
  • IAM Roles Anywhere 使ってる人います?
  • どのくらいのアカウント数になったら Organizations 採用する?
  • 本番環境でAWS 管理ポリシー使ってもいい?
  • 大量の IAM ポリシーを一括で変更するのにいいやり方ある?
  • Organizations SCP とPermissions boundary って併用する?

どのような回答があったかは、参加した方の特権ということでここには書かないでおきます。

AWS IAM の知らなくてもいい話

当日し損ねた話をこの場で供養しておきます。知らなくてもいい話なので、読まなくても特に困りません。


AWS IAM にはコントロールプレーンとデータプレーンという概念があります。「IAM に」というかほぼすべての AWS サービスにはあるんですけどね。多くのサービスではコントロールプレーンが各リージョンに存在するのですが、AWS IAM においてはバージニア北部にのみコントロールプレーンが存在します。コントロールプレーンには IAM ユーザーや IAM ロール、IAM ポリシーといった IAM リソースの情報が格納されています。こういうと IAM グループはどうなるの?と気になるわけですが、IAM グループは (少なくとも狭義の)IAM エンティティではないので、どうなんでしょう。あったとしても IAM ユーザーの情報の一部として解釈されるんじゃないかと勝手に思ってます。IAM グループって結局 IAM ユーザーに IAM ポリシーを配布するための箱でしかないわけですからね。プリンシパルとして IAM グループを指定とかできませんからね。無視しましょう IAM グループのことは。別に嫌いなわけじゃないですよ。でも文脈によっては仲間はずれにしましょうあいつは。

話は戻って AWS IAM のコントロールプレーンはバージニア北部リージョンにあります。言ってみればここに保管されているのがプライマリです。レプリカ相当の情報は、各リージョンに存在するデータプレーンに伝播されます。ちなみにデータプレーンは各リージョンで 3 つ以上の AZ にまたがるように構成されています。具体的な数字は見つけられませんでしたが、数千台、あるいはもっと大規模なマシンによってホストされているのではないでしょうか。AWS IAM のデータプレーンが何をしているかというと、認証・認可です。当該リージョンのサービスを対象に行われた API リクエストに対して認証・認可を行います。

例えば東京リージョンで RDS DB インスタンスを起動したいとします。(別に RDS である必要はないので他のサービスでもいいですよ。)せっかくなので AWS CLI で実行するとしましょう。AWS CLI を通じて、API リクエストはまず東京リージョンの RDS サービスエンドポイントに到達します。次に、RDS サービスエンドポイントから 東京リージョンの AWS IAM データプレーンにリクエストがパスされます。「パス」って何、と思うかも知れませんが、AWS 公式での表現が「パス」だったのでそのまま使っています。サービスエンドポイントと AWS IAM データプレーンの間には IAM エンドポイントというものが存在します。リクエストは IAM エンドポイントを通じて AWS IAM データプレーンに到達します。カスタマー側では意識する必要はないですが、そう言ったものがあるんだと考えると楽しいですね。IAM エンドポイントは数百万のマシンによってホストされているそうです。2021 年の AWS re:Invent のキーノートで話されていました。

AWS サービスによって「リクエストコンテキスト」が生成される、という表現がされます。AWS サービスエンドポイントから IAM エンドポイントにパスするタイミングで生成されているのではないかと想像します。AWS IAM データプレーンでは、AWS enforcement code によって認証・認可が行われます。認証はまず「誰がリクエストを実行してきたか」を判断するプロセスです。リクエストに含まれる署名を見て判断しています。ここで言う署名とは、Sigv4 とか呼ばれるそういったものです。昔は v2 とかありましたね。(v3 は……ありましたっけ?)今回は AWS CLI による操作を例にしていますが、AWS CLI はリクエストに署名を含めるのを勝手にやってくれています。AWS CLI を永続的なアクセスキーを用いて実施しているなら IAM ユーザーの認証情報が、それ以外であれば IAM ロールの一時的な認証情報などが含まれていることでしょう。

認可のプロセスもあります。「何をしていいか」を判断するものですね。「リクエストコンテキスト」と「評価対象のポリシー」を突き合わせて、最終的に評価論理で Allow になればリクエストは成功します。「評価対象のポリシー」はいわゆる IAM ポリシーに限定されず、リソースベースポリシーやPermissions boundary、Organizations SCP、セッションポリシー、VPCエンドポイントポリシーを含みます。「評価対象のポリシー」を AWS enforcement code がどう判断するか、そこにもリクエストコンテキストが関わっています。リクエストコンテキストに含まれる情報から実行元のプリンシパルが誰、というのが分かればそこにアタッチされた IAM ポリシーが評価対象だと判明しますし、そのプリンシパルが Organizations 所属しているということであれば SCP も評価対象になってきます。リクエストコンテキストに含まれる「対象リソース」「アクション」「プリンパル」「環境データ(実行元IPアドレスや実行時刻、ユーザーエージェントなど)」などの情報と、評価対象のポリシーの合算を突き合わせて許可/拒否の判断が行われます。認可が行われる、とも言い換えられます。この認可における評価論理がまたね、ややこしいんですよね。ややこしいんでこの場では話さないですけど。ひとまず評価論理フローチャートを眺めてください。AWS ドキュメントに載ってますので。評価論理フローチャートを見ると全部答えが……わかるわけではないんですよ。特にリソースベースポリシーの部分が鬼門でね。リソースベースポリシーにおけるプリンシパルとして何を指定するかによって評価論理がちょっと変わったりします。まぁその話は置いておきましょう。データプレーンの話でした。

AWS IAM のデータプレーンが何をしているかのイメージはついたでしょうか。AWSサービスエンドポイントからその裏の AWS IAM データプレーンにパスされるリクエストは秒間で 10 億回もの規模にのぼるそうですよ。これは全リージョンあわせての数字だと思いますが、すごい規模ですね。

AWS IAM コントロールプレーンと AWS IAM データプレーンの関係についても考える必要があります。先ほど述べた通り、コントロールプレーン上のリソースとデータプレーン上の情報は、プライマリとレプリカのような関係にあります。プライマリに対して行われた変更は、少しの遅延とともにレプリカに伝播されます。ここでのプライマリの変更とは、新しい IAM ユーザーや IAM ロールの変更であるとか、既存のエンティティに IAM ポリシーをアタッチ/デタッチしたりポリシーの内訳を変更するなどことを指します。AWS IAM では結果整合性が採用されているため、変更内容の即時反映を期待してはいけません。「伝播の遅延」を構成する要素としては、単純にリージョン間でのデータ転送の時間もありますし、データプレーンをホストするサーバーのレプリケーションの時間もあります。IAM ではパフォーマンス向上のためにキャッシュを使用しているため、そのデータアウトまでの時間がかかることもあるそうです。権限のチューニングのために頻繁に IAM コントロールプレーンへの変更を行う際は、この遅延を考慮する必要があります。IAM ポリシー自体を変更するのではなく AssumeRole などで都度セッションを生成し直し、その際に指定するセッションポリシーの内訳を変更することで結果整合性の影響を避けるという考え方もあります。セッションポリシーっていつ使うんだろう?使ってる人いるのか?と思っていたのですが、こんな使い方もあるんですね。(ちなみにチョークトークセッションでアンケートを取ったらセッションポリシーを使ってる方が一人だけいらっしゃいました。)

AWS IAM のコントロールプレーン、データプレーンの障害についてもちょっと考えてみましょう。ここで問題ですが、統計的にコントロールプレーンとデータプレーンのどちらがより障害発生率が高いか分かるでしょうか。これは AWS IAM に限定した話ではなく、AWS サービス全体の話です。そうですね、正解はコントロールプレーンです。データプレーンはコントロールプレーンと比較してシンプルな構造をとるよう構成されています。そしてコントロールプレーンとデータプレーンは独立しており、一方の障害に影響を受けないように構成されています。静的安定性というやつです。

「AWS IAM で障害が発生した」、という話があった場合、多くはコントロールプレーンにおける障害を指すでしょう。新規に作成した IAM ユーザーがなかなかコンソール上で確認できなかったり、IAM ポリシーの変更がなかなか反映されない、という影響が考えられます。わたしも実際に直面したことがあります。IAM ロールを含んだ構成一式を CloudFormation スタックをデプロイしたのですが、途中で「必要な IAM ロールが存在しない」というエラーが出てしまうんですね。いやいやスタックデプロイのイベントを追っていくときちんと IAM ロールの作成が成功しているじゃないか、どういうことだろう、なんつってね。CloudFormation としては IAM ロール作成リクエストが正常に終了したので次にステップに進んだ。ところが IAM ロールが実際にコントロールプレーンに作成される、というプロセスに時間がかかっており、当該 IAM ロールを必要とするリソースの作成が失敗した、ということのようでした。そんなことあるんだーってね。

バージニア北部リージョンで障害があった、となると AWS IAM のコントロールプレーンへの影響がないかドキドキします。AWS IAM の他にも、コントロールプレーンをバージニア北部リージョンにのみ持つサービスがいくつかあるので、そちらへの影響も気になります。バージニア北部で障害があった場合には、新規リソースの作成や既存リソースの更新といったアクションは控えた方が安心でしょう。とはいえ、先述の通りコントロールプレーンとデータプレーンは独立しています。コントロールプレーンで障害があったとしても、データプレーンは機能し続けることが期待できます。AWS IAM で言えば、各リージョンにおける認証・認可プロセスは引き続き行われている状態です。

データプレーンはシンプルゆえに障害が起こりづらい、という側面はありつつも、全く起こらないというわけではありません。2021年6月に、ストックホルムリージョンで IAM のデータプレーンでの障害と思われる事象がありました。複数のサービス(EC2、S3、ELBなど)で、1時間ほど「API 実行の IAM 認証で失敗した」とイベントが記録されました。おさらいをすると AWS サービスエンドポイントへのリクエストは IAM エンドポイントを経由して AWS IAM データプレーンで認証・認可が行われます。この「サービスエンドポイントから IAM エンドポイントにパス」以降のプロセスで障害が発生していたのでは、と推測します。こういった事象の最中には各サービスにおいて「新規リソースの作成」「既存リソースの更新」は避けた方が良いでしょう。一方で、サービスごとにデータプレーンは独立しているはずなので、AWS IAM データプレーンで障害があっても同一リージョンの別サービス(例えば EC2)のデータプレーンは正常に機能し続けていることが期待されます。(もちろんまとめて障害になるケースもあるとは思いますが。)EC2 のデータプレーンが正常に機能していれば、既存インスタンスの変更はエラーが発生しても(変更リクエストが IAM のデータプレーンで評価される際にエラー)、既存インスタンスの稼働は正常のまま(ステータスチェックに失敗せず、OS以上のレイヤも影響を受けない)となっていることが期待されます。こういった形で障害の影響範囲を分けて考えるとスッキリしそうです。ダメな時はもう全部ダメだと思いますけど。

最後に、派生キーの話をして終わりたいと思います。認証プロセスに関わりが深いものです。認証情報のうち特に重要なものと言えばそう、シークレットアクセスキーですね。IAM リソースのプライマリはコントロールプレーンに保管されているという話をしましたが、シークレットアクセスキーも同じくコントロールプレーンに保管されています。原本であるシークレットアクセスキーはコントロールプレーンにのみ存在し、その派生キーが各リージョンのデータプレーンに生成されます。派生キーは日付の情報とともに生成され、結果的にデータプレーンに存在する派生キーは「リージョン」「日付」固有のものになります。今日生成された派生キーは今日だけ有効、ということです。おそらく日次で派生キーのローテーションが行われているのではないでしょうか。AWS IAM のグローバルエンドポイントと通信できない障害があったとしても少なくとも24時間は STS リージョナルエンドポイント経由で一時的な認証情報が生成できる、という話が AWS ドキュメントに書かれており、これは AWS IAM データプレーンに保管された派生キーの有効期限と関係しているのではと考えています。

派生キーからさらなる派生キーが生成されます。ややこしくなるので、ここまで取り上げてきた派生キーを「リージョン/日付 固有派生キー」と呼びます。API リクエストがサービスエンドポイントを通じて IAM エンドポイントにパスされたタイミングで、「リージョン/日付 固有派生キー」に「ユーザー」「サービス」固有の情報を付加したさらなる派生キーが生成されます。この派生キーを「いい感じ派生キー」と呼びます。「いい感じ派生キー」はユーザーとサービス固有であることから想像できるように、とにかくたくさん生成されます。そして IAM エンドポイントでキャッシュされます。色々絞り込んだ結果「固有」度が高まったキーはどんどん使いまわそう、ということですね。派生キーの情報と、API リクエストに不可された署名情報を突き合わせて認証が行われます。秒間 10 億、というとんでもないリクエストが到達する IAM エンドポイントではこのような派生キーのキャッシュなどを活用して捌いているということです。すごいですね。すごい。


ほら、知らなくてもよかったですね。(上記の話はだいたい先述の参考リンク先に書かれています。)

7/8 当日、発表後の懇親会で話しかけてくださった方がおり、上記のコントロールプレーンとデータプレーンの話をちょっとだけできました。その節はありがとうございました。

終わりに

Developers IO 2023 で登壇しました、という話でした。

オフラインでの登壇は久しぶりで、とても満足感がありました。一方的に発表するのではなく参加者の方の反応をもとに展開していく、というのが大変でもあり楽しさがありました。参加いただいた皆様ありがとうございました。

ブログ読んでますよ、と話しかけていただいたことが嬉しかったです。

DevelopersIO 2023 7/7,7/8の後も各地で開催されており、本日(2023/7/27)時点ではまだ沖縄での開催を残しています。

また、ビデオセッションも続々と投稿されていますので、ぜひチェックしてみてください。

参加できなかったけど興味出た、という方はぜひ Developers IO 2024 でお会いしましょう。

以上、 チバユキ (@batchicchi) がお送りしました。