IAM + STS — 権限管理
概要
IAM (Identity and Access Management) は AWS の認証認可サービス。 User / Group / Role / Policy で構成され、「誰が何にどうアクセスできるか」をすべてここで決めます。 STS (Security Token Service) は IAM と組み合わせて使う一時認証情報の発行サービスで、AssumeRole / OIDC / MFA Session を扱います。
IAM は AWS で最も重要なサービス。設計が雑だと事故・侵害の温床になります。 逆に「最小権限の原則」を貫けると、セキュリティだけでなく運用安定性も上がります。
主な構成要素
- User — 人 or アプリ単位の長期 ID。AccessKey を持てる。
- Group — User をまとめる単位。共通ポリシーを Group に attach 可能。
- Role — 「引き受けられる役割」。短命な認証情報で動く。EC2 / Lambda / OIDC で頻出。
- Managed Policy — 独立リソース化されたポリシー。複数 user/role に attach 可能、バージョン管理あり。
- Inline Policy — 特定 user/role/group に埋め込みのポリシー。再利用不可だが運命共同体。
- Trust Policy — Role の「誰が AssumeRole できるか」宣言。Principal で AWS / Service / Federated を指定。
- Permissions Boundary — Role/User の最大権限の上限。委譲先が過剰な権限を attach しないよう制限。
- SCP (Service Control Policy) — Organizations の OU/Account 単位の禁止条項。IAM より上位。
- STS API — AssumeRole / AssumeRoleWithWebIdentity / GetSessionToken。
「最小権限の原則」の実践
- 長期 AccessKey は人間用に作らない — IAM Identity Center / SSO / OIDC で短命認証へ移行。
- Action は具体的に書く —
s3:*ではなくs3:GetObject/s3:PutObject。 - Resource を絞る —
*ではなくarn:aws:s3:::my-bucket/*。 - Condition で追加制約 —
aws:SourceIp,aws:MultiFactorAuthPresent,aws:SourceArn。 - Permissions Boundary で上限 — 委譲する Role に上限を設けて事故防止。
使うべきパターン
- EC2 / Lambda の認証 — Instance Profile / Execution Role でコードに認証情報を書かない。
- GitHub Actions の AWS デプロイ — OIDC + AssumeRoleWithWebIdentity で長期 AccessKey 不要。
- マルチアカウント — 各アカウントの Role を AssumeRole でジャンプ。SSO 統合可。
- クライアント側コード — Cognito Identity Pool 経由で一時認証。
使わない方が良いパターン
- 長期 AccessKey を CI に直書き — OIDC へ移行。
- AdministratorAccess の濫用 — 開発初期はやむを得ないが、本番は最小権限化。
- 1 Role を全用途で使い回す — 用途別に分ける。事故時の影響範囲を局所化。
Terraform 最小サンプル(GitHub Actions OIDC Role)
# GitHub OIDC Provider (アカウントに 1 個だけ)
resource "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"]
}
# Trust Policy: 特定 repo の特定 branch のみ assume 許可
data "aws_iam_policy_document" "github_trust" {
statement {
effect = "Allow"
principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.github.arn]
}
actions = ["sts:AssumeRoleWithWebIdentity"]
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:iigtn/iigtn-platform:*"]
}
}
}
resource "aws_iam_role" "github_deploy" {
name = "github-actions-deploy"
assume_role_policy = data.aws_iam_policy_document.github_trust.json
}
# 最小限のデプロイ権限
data "aws_iam_policy_document" "deploy_perms" {
statement {
actions = [
"s3:PutObject", "s3:DeleteObject", "s3:ListBucket",
"cloudfront:CreateInvalidation",
]
resources = ["arn:aws:s3:::my-site/*", "arn:aws:s3:::my-site"]
}
}
resource "aws_iam_role_policy" "deploy" {
role = aws_iam_role.github_deploy.id
policy = data.aws_iam_policy_document.deploy_perms.json
}
用語集
- User vs Role
- User = 長期 ID (AccessKey 持てる)。Role = 引き受けられる役割で短命。CI/CD は Role 推奨。
- Managed Policy / Inline Policy
- Managed = 独立リソースで再利用可・バージョン管理あり。Inline = 特定 user/role/group 埋め込み。
- Trust Policy
- Role の「誰が AssumeRole できるか」宣言。Principal + Action: sts:AssumeRole。
- Permissions Policy
- Role/User の「何ができるか」宣言。Allow/Deny + Action + Resource + Condition。
- Permissions Boundary
- Role/User の最大権限の上限。委譲先が過剰権限を attach しないよう制限。
- SCP
- Service Control Policy。Organizations 配下の OU/Account 全体に強制する禁止条項。
- STS
- Security Token Service。一時認証情報を発行するサービス。AssumeRole 系 API。
- OIDC Provider
- 外部 ID プロバイダ (GitHub Actions / GitLab / EKS) を AWS に登録した仕組み。AssumeRoleWithWebIdentity の前提。
- Condition Keys
- Policy で使える条件キー。aws:SourceIp / aws:MultiFactorAuthPresent / aws:SourceArn 等。
- Access Analyzer
- 外部公開リソース (S3 / IAM Role / KMS 等) を検出する AWS マネージド分析。