🔐
EC2にS3操作権限を持つIAMロールを割り当てる。それ、terraformでやる
背景
EC2インスタンスから他のAWSサービス(S3など)にアクセスする必要がある場合、認証方法として以下の2つの選択肢があります。
アクセスキー方式(非推奨)
私はEC2にロールを割り当てることができるというのを知らずに、この方法を採用していました。。。今思うと、よくこんな面倒なことをやっていたなと思います。
- アクセスキーとシークレットアクセスキーをEC2に設定
- デメリット:
- キーがEC2上のファイルに保存されるためセキュリティリスクが高い
- キーのローテーション管理が必要
- キーが流出すると不正アクセスのリスクがある
IAMロール方式(推奨)
- EC2インスタンスにIAMロールを割り当て
- メリット:
- 一時的な認証情報が自動的に発行・更新される
- アクセスキーをEC2上に保存する必要がない
- 権限管理がシンプルで安全
本記事では、IAMロール方式でEC2にS3操作権限を付与する方法をTerraformで実装します。
IAMロールとインスタンスプロファイルの関係
EC2にIAMロールを割り当てるには、以下の3つのリソースが必要です:
| リソース | 役割 |
|---|---|
| IAMロール | 権限の定義と信頼ポリシーを持つエンティティ |
| IAMポリシー | 具体的な操作権限(S3への読み書きなど)を定義 |
| インスタンスプロファイル | EC2インスタンスとIAMロールを紐付けるコンテナ |
Terraformでの実装
ステップ1: IAMロールの作成
まず、EC2インスタンスが引き受ける(AssumeRole)ことができるIAMロールを作成します。
resource "aws_iam_role" "ec2_s3_role" {
name = "ec2-s3-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}
-
assume_role_policy: このロールを誰が引き受けられるかを定義(信頼ポリシー) -
Principal.Service = "ec2.amazonaws.com": EC2サービスがこのロールを使用できることを許可 -
Action = "sts:AssumeRole": ロールの引き受けを許可
ステップ2: S3操作ポリシーの定義
S3に対する操作権限を定義したIAMポリシーを作成します。
resource "aws_iam_policy" "s3_policy" {
name = "EC2S3Policy"
description = "Policy for EC2 instance to operate only on S3"
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = [
"s3:*"
],
Resource = "*"
}
]
})
}
-
Action = "s3:*": S3に対するすべての操作を許可 -
Resource = "*": すべてのS3バケットに対して許可
ステップ3: ロールにポリシーをアタッチ
作成したIAMポリシーをIAMロールに関連付けます。
resource "aws_iam_role_policy_attachment" "attach_s3_policy" {
role = aws_iam_role.ec2_s3_role.name
policy_arn = aws_iam_policy.s3_policy.arn
}
ポイント:
-
role: アタッチ先のロール名 -
policy_arn: アタッチするポリシーのARN
ステップ4: インスタンスプロファイルの作成
EC2インスタンスとIAMロールを紐付けるインスタンスプロファイルを作成します。
resource "aws_iam_instance_profile" "ec2_s3_instance_profile" {
name = "ec2-s3-instance-profile"
role = aws_iam_role.ec2_s3_role.name
}
ステップ5: EC2インスタンスにプロファイルを割り当て
EC2インスタンスのリソース定義で、インスタンスプロファイルを指定します。
resource "aws_instance" "this" {
ami = "ami-0a6fd4c92fc6ed7d5"
instance_type = "t3.nano"
disable_api_termination = false
monitoring = true
# ... 省略 ...
iam_instance_profile = aws_iam_instance_profile.ec2_s3_instance_profile.name
}
ポイント:
-
iam_instance_profile: 作成したインスタンスプロファイルの名前を指定
EC2インスタンスでの確認
確認方法
EC2インスタンスにSSHログインし、以下のコマンドで認証情報の取得元を確認します:
aws configure list
ロール割り当て前の状態
IAMロールを割り当てる前は、access_keyとsecret_keyが<not set>になっています。
aws configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key <not set> None None
secret_key <not set> None None
region ap-northeast-1 imds
ロール割り当て後の状態
IAMロールを割り当てると、Typeがiam-roleになり、一時的な認証情報が自動的に設定されます。
aws configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key CN5X iam-role
secret_key KCNh iam-role
region ap-northeast-1 imds
-
Type列がiam-roleになっている → IAMロールから認証情報を取得していることを示す -
access_keyとsecret_keyが表示されている → 一時的な認証情報が自動発行されている - これらの認証情報は定期的に自動更新される
動作確認
S3へのアクセスが可能か確認します:
# S3バケット一覧の取得
aws s3 ls
# 特定バケットへのファイルコピー
aws s3 cp test.txt s3://my-bucket/
まとめ
| 項目 | 内容 |
|---|---|
| 目的 | EC2インスタンスにS3操作権限を安全に付与 |
| 推奨方法 | IAMロール方式(アクセスキー方式は非推奨) |
| 必要なリソース | IAMロール + IAMポリシー + インスタンスプロファイル |
| セキュリティ | 一時認証情報の自動更新、キー流出リスクなし |
実装のポイント
- IAMロール: EC2サービスが引き受け可能なロールを作成
- IAMポリシー: S3操作権限を定義(本番環境では特定バケットに制限推奨)
- ポリシーアタッチ: ロールとポリシーを関連付け
- インスタンスプロファイル: EC2とIAMロールを紐付ける中間リソース
- EC2に割り当て:
iam_instance_profileパラメータで指定
IAMロールを使用することで、アクセスキーを管理する手間がなくなり、セキュアなAWS環境を構築できます。
Discussion