AWSで全ユーザーに割り当てる権限

こんにちは、AWS担当のwakです。AWSで新しくIAMユーザーを作ったときに割り当てるべきポリシーを整理したので書くことにします。

f:id:nurenezumi:20151002173222j:plain

大好物の高級かりかり欲しさに芸をするかわいい猫

ポリシーの内容

まずポリシーの内容を記載します。3つのパートに分けています。

1. 各種読み取り権限

弊社でよく利用しているサービスで状態読み取りを許可しています。この権限だけで、稼働中の各種インスタンスについてはどのような構成になっているかまでは分かることになります。またrds:DownloadDBLogFilePortionを指定しているのでRDSのログファイルの取得も可能です。スロークエリをファイルに保存するようにしている場合にはファイルを取得するためにこの権限が必要です。

{
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:Describe*",
                "autoscaling:Describe*",
                "elasticloadbalancing:Describe*",
                "cloudwatch:List*",
                "cloudwatch:Get*",
                "cloudwatch:Describe*",
                "autoscaling:Describe*",
                "rds:Describe*",
                "rds:ListTagsForResource",
                "logs:Get*",
                "logs:Describe*",
                "logs:TestMetricFilter",
                "sns:Get*",
                "sns:List*"
            ],
            "Resource": "*"
        }
    ]
}

2. 認証情報

アカウント上に存在する全IAMユーザー一覧取得、自分自身のパスワード変更、自分自身の仮想MFAデバイス(要するにスマートホンのアプリ)を使った2段階認証追加・再同期を許可しています。ここでは無効化は許可していないので、別の端末に2段階認証を移動したい場合(機種変したときなど)には管理者が一度2段階認証を削除し、ユーザーが再度追加する必要があります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:ChangePassword",
                "iam:EnableMFADevice",
                "iam:ListMFADevices",
                "iam:ResyncMFADevice"
            ],
            "Resource": "arn:aws:iam::999999999999:user/${aws:username}"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:DeleteVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::999999999999:mfa/${aws:username}"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:ListUsers",
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "*"
        }
    ]
}
  • 999999999999AWSのアカウントIDに置き換えてください。ダッシュボードや毎月の請求書(PDFファイル)で確認できます。
  • ${aws:username}はIAMユーザー名に置換される変数です。つまりarn:aws:iam::999999999999:user/${aws:username}は「IAMユーザー自分自身のARN*1」を示します。
  • 仮想MFAデバイスの無効化権限を与えない場合でも、iam:DeleteVirtualMFADeviceは必須です。
    • 「MFAデバイスの管理」→「仮想MFAデバイス」をクリックした時点で内部的には仮想MFAデバイスが作成されているようで、ここでキャンセルしてしまうと未アクティベーションの仮想MFAデバイスが残ってしまいます。これは次に仮想MFAデバイス追加をやり直した際に自動的に削除されるのですが、iam:DeleteVirtualMFADeviceの権限がないと先に進めなくなります。
    • 管理者が仮想MFAデバイスを無効化した後、ユーザーが再度仮想MFAデバイスを追加する場合も同じくiam:DeleteVirtualMFADeviceが必要です。
    • IAMユーザーが自分で仮想MFAデバイスの無効化を行うためにはiam:DeactivateMFADeviceが必要です。

3. S3バックアップフォルダ

最後はS3です。ユーザー個人のファイル置き場(他ユーザーからは参照不可)として、S3にバックアップ用バケットを作成し、この中に/Personal/USERNAME*2というフォルダを作成してあります。ここに読み書きする権限を与えます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Action": "s3:ListBucket",
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::backup-test-sanwasystem",
            "Condition": {
                "StringEquals": {
                    "s3:prefix": [
                        "",
                        "Personal/"
                    ],
                    "s3:delimiter": "/"
                }
            }
        },
        {
            "Action": "s3:ListBucket",
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::backup-test-sanwasystem",
            "Condition": {
                "StringLike": {
                    "s3:prefix": "Personal/${aws:username}/*"
                }
            }
        },
        {
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::backup-test-sanwasystem/Personal/${aws:username}/*"
        }
    ]
}

それぞれ上から順に、

  • バケットのリストを取得するための権限
  • 指定したバケット/Personal直下を見るための権限
  • 指定したバケット/Personal/USERNAMEを見るための権限
  • 指定したバケット/Personal/USERNAME以下を読み書きするための権限

となります。

説明

これだけだと格好がつかないので、ポリシーについて簡単に解説を加えます。AWSの操作には、

……といったように、すべてに名前が付いています*3。IAMユーザーには、これらを許可するか禁止するかを個別に設定することができます。また、ec2:Describe*rds:*のようにワイルドカードを利用することもできます。

明示的な禁止

"Effect":"Allow"のかわりに"Effect":"Deny"と書くと、そのユーザーはその操作が決して許されなくなります。「決して」というのはつまり、

  • rds:*(RDSに対するすべての操作)を許可
  • rds:DeleteDBInstance(RDSのインスタンス削除)を禁止

というルールを両方設定したとしても禁止の方が勝つということです。

条件

さらに条件をつけて絞ることもできます。

  • 「Groupタグが特定の値なら」という条件で、Groupタグが特定の値を持つEC2インスタンスに対しての操作のみ許可する
  • 「ARNが特定の値なら」という条件で、特定のEC2インスタンスに対しての操作は受け付けないように禁止する
  • 「操作元IPアドレスが特定の値なら」という条件で、社内からの操作のみ受け付ける
  • 「操作が発生した時刻が特定の期間内なら」という条件で、本番リリースまでの間だけ環境構築のための操作を受け付ける
  • 「S3でキーが特定のパターンから始まるなら」という条件で、S3の特定のフォルダ以下の読み書きを受け付ける

最後のパターンを「3. S3バックアップフォルダ」にあるCondition句で使っています。

グループ

管理上の都合から、一般的にはIAMユーザーに対して直接権限を与える(ポリシーをアタッチする)ことは推奨されていません。AWSにはIAMユーザーをまとめて管理するためのIAMグループという機能が用意されているので、

  1. IAMグループを作る
  2. IAMグループに対してポリシーをアタッチする
  3. IAMユーザーを任意のグループに追加する(複数可)

という手順に従うのがベストプラクティスだとされています。このため、IAMユーザー間に上位・下位関係を持たせるようなロールはありません。

まとめ

このようにIAMユーザーの権限は細かくかつ柔軟に設定できますが、あまり「必要最低限」にこだわると、使うサービスやユーザー増えてきたときに管理が難しくなると感じています。何か緊急時にいちいち管理者の対応が必要になるような体制にしてしまうとAWSのメリットが薄れてしまいますし、CloudTrailで操作ログも取ることができます。「お前を信じて…これ(PowerUserAccessポリシー)を……渡す! 受け取れ!!」といった信頼(と割り切り)は大切かもしれません。

*1:ARNとはAmazon Resource Nameの略で、EC2インスタンス、RDSインスタンス、IAMユーザーなど、AWSの全てのリソースに対して振られた一意のIDです。

*2:USERNAMEはユーザーのアカウント名。弊社の運用ルールでは、Slack・Backlogのアカウント名、会社のメールアドレスの先頭部分でもあります。

*3:つまりAPIの名前だと思えばいいです。Management Consoleの操作と1:1では対応していません。1回のクリックや画面遷移で複数の操作が行われることもあります。