ちょっと話題の記事

システム開発プロジェクトにおけるIAMポリシー権限はどうしたらいいですか

システム開発プロジェクトにおける IAM ポリシー権限付与を考えてみたいと思います。
2021.06.11

こんにちは。
ご機嫌いかがでしょうか。
"No human labor is no human error" が大好きな ネクストモード株式会社 の吉井です。

AWS 上でシステム開発および運用を行ううえで IAM ポリシー権限をどのように割り当ててよいかという相談を受けることが多く感じています。
ベストプラクティスでは「最小権限を付与」なのですが、どこまでが最小なの? の答えは誰も持っていないと思います。

今回はシステム開発プロジェクトにおける IAM ポリシー権限付与を考えてみたいと思います。

前提

AWSアカウントの分離

権限を考える前に前提として 実行環境ごとに AWS アカウントは分ける ことを私はお勧めしています。
タグに実行環境名を設定してタグベースの権限制御をすることは可能ですが、複雑なポリシーを記述しないとならず完全なコントロールは難しいですし事故の可能性もあると思います。
確実に実行環境を保護、特に本番環境を保護するためにも AWS アカウントは分ける方針を採用します。

本エントリでは3つの実行環境を想定しました。
もちろんこれが正解ではありません。ご自身の管理しているシステムに最適な実行環境を構築ください。

  • 開発環境
  • ステージング環境
    • 本番デプロイ前に動作確認をする
    • 本番で発生した障害の再現テスト
  • 本番環境
    • サービスを提供する

IaC

現代のシステム構築において IaC は欠かせないものとなりつつあります。
今回の内容でも IaC が前提となります。
特に本番環境は人間が極力触らないことを想定しています。

役割

今回は単純化して4つの役割を想定しました。

  • 管理者
    • AWS アカウントという意味での管理者、root アカウントを管理している方々
  • アプリチーム
    • アプリケーションを開発、デプロイする方々
  • インフラチーム
    • AWS リソースを作成削除変更する方々
  • 運用チーム
    • 本番稼働後の維持管理をする方々

ガードレールの導入

CloudTrail、Config、Access Analyzer、GuardDuty、SecurityHub を有効にすることが最低限です。
誰が何をしたか、思わぬ「穴」はないかをチェックすることが必要です。
SecurityHub ではセキュリティベストプラクティスに沿った構成になっているかを確認可能な状態にしておきます。

AWS OrganizationsとAWS Control Tower が使えるようであれば是非検討してみてください。

IAM ポリシー権限付与

前提を書き終わったところで肝心の IAM ポリシー権限付与について考えます。

開発環境

役割 権限
管理者 root アカウントは普段使いしない、MFAで保護
アプリチーム 必要な権限を広めで
インフラチーム Admin 相当
運用チーム 運用の範囲次第

アプリチーム

アプリチームには広めの権限を与えます。
使うリソースごとの FullAccess を付与することもありです。
AWS CDK や Serverless Framework 等を使う場合は AdminstratorAccess を求められるかもしれませんが、円滑なアプリ開発のために許容しましょう。

強い権限を直接付与することに抵抗がある場合は、Cloud9 を活用します。
Cloud9 でインスタンスプロファイルをアタッチすることでアプリ開発者に直接強い権限を付与しなくて済みます。
【レポート】AWS Cloud9 の紹介 #reinvent #DEV320
Calling AWS services from an environment in AWS Cloud9

AdminstratorAccess を与える場合でも、Permissions Boundary を正しく設定し禁止する操作を定義します。
例えば CloudTrail 削除、Config 削除、インフラチームの IAM 操作を禁止します。

Permissions Boundary サンプル
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "All",
            "Action": [
                "*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Sid": "DenyBoundaryDelete",
            "Action": [
                "iam:DeleteUserPermissionsBoundary",
                "iam:DeleteRolePermissionsBoundary",
                "iam:PutRolePermissionsBoundary",
                "iam:PutUserPermissionsBoundary"
            ],
            "Effect": "Deny",
            "Resource": "*"
        },
        {
            "Sid": "DenyCloudTrailAndConfigChange",
            "Action": [
                "cloudtrail:DeleteTrail",
                "cloudtrail:PutEventSelectors",
                "cloudtrail:StopLogging",
                "cloudtrail:UpdateTrail",
                "config:DeleteConfigurationRecorder",
                "config:DeleteDeliveryChannel",
                "config:DeleteRetentionConfiguration",
                "config:PutConfigurationRecorder",
                "config:PutDeliveryChannel",
                "config:PutRetentionConfiguration",
                "config:StopConfigurationRecorder"
            ],
            "Effect": "Deny",
            "Resource": "*"
        },
        {
            "Sid": "DenyAnyActionsAdminUser",
            "Action": [
                "iam:Add*",
                "iam:Attach*",
                "iam:ChangePassword",
                "iam:Create*",
                "iam:Delete*",
                "iam:Detach*",
                "iam:Enable*",
                "iam:PassRole",
                "iam:Put*",
                "iam:Remove*",
                "iam:Reset*",
                "iam:Resync*",
                "iam:Set*",
                "iam:Update*"
            ],
            "Effect": "Deny",
            "Resource": "インフラチームの IAM User ARN"
        }
    ]
}

アプリケーション内でアクセスキーが必要な場合は、人間とは別にアプリケーション用 IAM ユーザーを作成します。
開発者個人が発行したアクセスキーをアプリケーション内で使わないように留意します。
権限コントロールが難しい、離任時削除しにくい、不正利用された場合の調査が難しいなどといったデメリットがあります。

インフラチーム

リソース作成、IAM 作成等プロジェクトに必要な操作を行うことになるので AdminstratorAccess を付与します。
くれぐれも普段プロジェクト作業をしない人に権限を付けないよう気を付けてください。
「そのうち使うから」「部長 or 課長だから」という理由で権限付与しないようご注意ください。

運用チーム

本番の維持管理をするチームであれば開発環境の権限は要らないと思います。
プロジェクト組織ごとにご判断いただければと思います。

ステージング環境

ステージング環境は人が触らなくてもメンテナンスが可能な仕組み作りをしておくことをお勧めします。
CloudFormation、Terraform、AWS CDK や Serverless Framework 等のコードを Git のどこかのブランチに push するとデプロイが実行される仕組みです。(こちら側の権限管理が発生します)
デプロイは Code シリーズ、GitHub Actions、GitLab CI/CD などのツールを活用して実施します。

役割 権限
管理者 root アカウントは普段使いしない、MFAで保護
アプリチーム ログを読む権限程度
インフラチーム Admin 相当
運用チーム 運用の範囲次第

アプリチーム

CloudWatch、ログ格納 S3 バケットの読み取り権限のみで問題ないかと思います。

インフラチーム

初期構築のために AdminstratorAccess が必要です。
構築完了後は、普段使いは ReadOnlyAccess、メンテナンスだけ AdminstratorAccess を持ったロールにスイッチといった運用でよいかと思います。

運用チーム

開発環境と同じく本番の維持管理をするチームであれば権限は不要ですが、
本番障害の再現、原因追求に使うのであれば CloudWatch、ログ格納 S3 バケットの読み取り権限を付与します。

本番環境

極力人は触らないようにします。
思い出してください。"No human labor is no human error" です。
こちらもステージング環境に記載したと同様にコード化、自動実行化が必須です。

役割 権限
管理者 root アカウントは普段使いしない、MFAで保護
アプリチーム ログを読む権限程度
インフラチーム Admin 相当
運用チーム 運用作業に必要な権限

アプリチーム

CloudWatch、ログ格納 S3 バケットの読み取り権限のみで問題ないかと思います。

インフラチーム

初期構築のために AdminstratorAccess が必要です。
構築完了後は、読み取り権限のみで基本は OK ですが、運用チームとの役割分担によっては AdminstratorAccess へのスイッチロール権限を残しておくことも考えます。

運用チーム

普段使いは ReadOnlyAccess、メンテナンスだけ AdminstratorAccess を持ったロールにスイッチといった運用がよいと思います。

まとめ

誰にでも強い権限を与えるのは抵抗があります。が、権限が必要な都度払い出しをお願いする運用は負荷が大きいと感じます。
強い権限はシステムの裏側で使うように工夫をして、人間は極力権限を持たないような仕組みが理想だと考えます。
マルチアカウント時代の権限管理は難しいテーマだと感じました。

以上、吉井 亮 がお届けしました。