2024年7月からインフラの案件に参画しておりますが、今まで理解が不十分だったIAM部分をまとめてみたいと思います。
IAMとは
AWS Identity and Access Management (IAM) は、AWSリソースへのアクセスを安全に制御するための基盤となるサービスです。IAMを使用することで、誰が(認証)、どのAWSリソースに対して、どのような操作を行えるか(認可)を細かく定義できます。
IAMの主要コンポーネント
- ユーザー: AWS環境にアクセスする個人またはアプリケーション
- グループ: 同じ権限を持つユーザーの集合
- ロール: AWSサービスや外部アカウントが一時的に引き受けることができる権限の集合
- ポリシー: 権限を定義するJSONドキュメント
権限の考え方について
AWSでは基本的にあるリソースへのなんらかの行為の許可をポリシーという形で定義しています。実態としては以下のようなJSONなのですが、各要素には重要な意味があります。
ポリシーの基本要素
-
Effect:
Allow(許可)とDeny(拒否)の2択です。混在した場合はDenyが優先されます。 - Principal: リソースへのアクセスを許可または拒否する対象を指定します。(※リソースベースポリシーで使用)
- Action: 許可(or拒否)する操作
- Resource: 実際にActionを許可する対象リソース
- Condition: (オプション)アクセスを許可する条件を指定
実例1: EC2インスタンスの開始・停止権限
下記の例で言うとarn:aws:ec2:region:account-id:instance/instance-idに対して、EC2の開始と停止を許可する、という意味になります。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": [
"arn:aws:ec2:region:account-id:instance/instance-id"
]
}
]
}
実例2: S3バケットへのアップロード権限
例えば下記のようなポリシーだと、ExampleUserがS3バケットexample-bucket内のオブジェクトに対してPutObject(オブジェクトのアップロード)アクションを実行することを許可するものです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/ExampleUser"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::example-bucket/*"
}
]
}
基本的にはこういったポリシー(行為の許可)を特定のロール(役割)に付与させる、というのがAWSの権限管理になります。(一部バケットポリシーなどリソースに直接付与するタイプのものもあります。)
Conditionを使用した高度な制御
Conditionを使用することで、より細かいアクセス制御が可能になります。例えば:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
},
"StringEquals": {
"aws:SecureTransport": "true"
}
}
}
]
}
この例では、特定のIPアドレス範囲からのアクセスで、かつHTTPS経由でのアクセスのみを許可しています。
信頼ポリシーとは
あるリソースがロールを引き受ける場合、ロールを引き受けることができることに対するポリシーが必要になります。(ロール引き受け自体がActionということでしょう・・)
この際、使われるのが「信頼ポリシー」というもので、以下のような形で定義されます。
Lambda関数に対する信頼ポリシーの例
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
これにより、lambdaに任意のロールを付与することができるようになります。
信頼ポリシーの理解を深めるリンク
Lambda関数に権限を付与する流れ
lambdaになんらかの権限を持たせる場合、以下の流れになります:
- 信頼ポリシー(
Lambda.amazonaws.comがAssumeRoleできる)を作成 - 必要な権限を定義したポリシー(例:S3読み取り権限)を作成
- これらのポリシーが付与されたロールを作成
- 作成したロールをLambda関数に付与
サービスロールとは
少し似た概念としてサービスロールを説明します。サービスロールは、特定のAWSサービスが使用するために作成されたロールです。
一般のロールとの違い
- EC2など特定のAWSサービスが他のサービスにアクセスするためのロール
- ユーザーやグループなどではなく、AWSのサービスに割り当てる
- アクセス許可はサービスによって事前に定義されたポリシーのみ
サービスロールの実例
例えば、EC2インスタンスがS3バケットにアクセスする必要がある場合:
- S3読み取り権限を持つサービスロールを作成
- EC2サービスを信頼するように設定
- EC2インスタンスにこのロールを割り当て
これにより、アプリケーションコード内にアクセスキーをハードコーディングする必要がなくなります。
参考リンク
IAMベストプラクティス 2024-2025
最新のセキュリティ動向を踏まえた、IAMのベストプラクティスをご紹介します。
1. 最小権限の原則(Principle of Least Privilege)
最も重要な原則です。ユーザーやサービスには、タスクを実行するために必要な最小限の権限のみを付与します。
実践方法
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-specific-bucket",
"arn:aws:s3:::my-specific-bucket/*"
]
}
]
}
❌ 避けるべき例:
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
2. 一時的な認証情報の使用
長期的な認証情報(アクセスキー)の代わりに、IAMロールを使用した一時的な認証情報を優先します。
3. 多要素認証(MFA)の必須化
MFAは、アカウントのセキュリティを向上させる最もシンプルかつ効果的な方法の一つです。
必須対象
- ルートユーザー: 絶対に必須
- 管理者権限を持つユーザー: 必須
- 機密データにアクセスするユーザー: 強く推奨
4. ルートユーザーの保護
ルートユーザーは完全なアクセス権限を持ち、制限できません。
ルートユーザーのベストプラクティス
- アクセスキーを作成しない(すでにある場合は削除)
- MFAを有効化
- 日常的なタスクには使用しない
- 管理者ロールを持つIAMユーザーを作成し、そちらを使用
ルートユーザーでのみ実行可能なタスク
- アカウントの閉鎖
- 特定の税金請求書の表示
- MFAを必要とするS3バケットの設定変更
- AWS GovCloudへの申し込み
5. IAMグループの活用
個別のユーザーに権限を付与するのではなく、グループを使用します。
グループ設計例
- ReadOnlyGroup: 読み取り専用権限
- DeveloperGroup: 開発環境への完全アクセス
- AdminGroup: 管理者権限(本番環境を含む)
- DataAnalystGroup: データ分析に必要な権限
メリット
- 権限管理が容易
- 一貫性のある権限付与
- 監査が簡単
- 新規ユーザーの追加が迅速
6. 条件キーを使用したコンテキストベースのアクセス制御
より細かい制御のために条件キーを活用します。
実例: 時間制限とIP制限
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
},
"DateGreaterThan": {
"aws:CurrentTime": "2024-01-01T00:00:00Z"
},
"DateLessThan": {
"aws:CurrentTime": "2024-12-31T23:59:59Z"
}
}
}
]
}
よくある落とし穴と対処法
1. ワイルドカード(*)の過度な使用
問題のある例
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
改善例
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}
2. スコープの設定ミス
前述の記事でも触れましたが、pomに依存ライブラリを記述する際と同様に、IAMでもスコープの設定ミスに注意が必要です。
よくあるミス
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-bucket"
}
]
}
このポリシーでは、バケット自体には操作できますが、バケット内のオブジェクトには操作できません。
正しい例
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
3. iam:PassRole の見落とし
iam:PassRole アクションは、他のAWSサービスにロールを渡す権限です。これを不用意に付与すると、権限エスカレーションのリスクがあります。
リスクのある例
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*"
}
推奨例
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789012:role/LambdaExecutionRole",
"Condition": {
"StringEquals": {
"iam:PassedToService": "lambda.amazonaws.com"
}
}
}