ちょっと話題の記事

【IAM TIPS】S3バケット毎に権限を分けるためのIAM権限設計

2015.06.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

望月@シアトルです。

今日はAmazon S3を複数名で利用するときの、IAM権限制御に関するTIPSのご紹介です。

想定する環境

S3は安価かつ高耐久性のストレージとして、AWS上でシステムが稼働しているかどうかに関わらず利用することが可能です。また、単純な保存領域としてだけでなく、S3 Static Website Hostingと呼ばれる機能を利用すれば、S3にHTMLなどの静的ファイルを配置しておくだけで簡単にWEBサイトを作れます。 この機能により、可用性・対障害性の高いWEBサーバを非常に安価(〜10円/月)でホスティングできます。

Static Website Hostingを利用する時には、S3にファイルを配置するだけで外部への公開ができますが、気にしなければならないことの一つに権限の管理があります。S3へのアップロード権限はAWS Identity and Access Management (IAM)で制御することになりますが、ここでS3の管理者権限をユーザに与えてしまうと、例えばStatic Website Hostingで複数のWEBサイトを管理することになった場合、それぞれのサイトで管理者が全く違う、ということはよくあると思います。

そういった時には、各人が担当するS3バケットのみ操作できるような権限設定が必要になります。

単純に実装

つまり、要求としてはあるIAMアカウントに、特定のバケットに対する操作のみを許可するIAMユーザを量産したい、ということになります。 単純に実装すると、以下のようなIAM Policyを準備すればよいでしょう。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::*"
    },
    {
      "Action": "*" ,
      "Effect":"Allow",
      "Resource": [
        "arn:aws:s3:::<bucketname>",
        "arn:aws:s3:::<bucketname>/*"
      ]
    }
  ]
}

Statementは2つあり、1つめのStatementは、CloudBerry ExplorerなどのS3用GUIツールで操作する時に必要な権限になります。これについての詳細は以下のブログを参照ください。

2つめのStatementが、S3バケットごとに権限を割り当てている部分になります。Resourcesで、操作対象のバケットの指定をしているので、実際に操作したいバケットのバケット名に置換して下さい。 あとはこのPolicyを作成したユーザごとに割り当てていけばいいのですが、ユーザ毎にIAM Policyを割り当ててしまうと、ポリシーの更新・修正時に全てのユーザのポリシーを修正しなければならず、管理が煩雑になります。今回の例にかぎらず、IAMで権限設定をする時は可能な限りIAM GroupにPolicyを紐付けるほうが好ましいでしょう。

一方で、今回の例でGroupにIAM Policyを記載する方針とすると、上記で指定した<bucketname>の部分がユーザごとに与えられなくなる問題が発生します。これはIAM Policy Variablesを利用することで解決できます。

IAM Policy Variables

IAM Policy Variablesは、そのIAM Policyの評価時、つまりAPIの実行時にパラメータとして渡される変数で、例えばAPI実行元のIPアドレスを指定するaws:SourceIpなどもこの一種です。用途は以下のブログでも触れられています。

このブログ内でも触れられている${aws:username}変数を利用して、今回の要望を実装してみます。先ほどのIAM Policyを以下の用に変更します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::*"
    },
    {
      "Action": "*" ,
      "Effect":"Allow",
      "Resource": [
        "arn:aws:s3:::${aws:username}",
        "arn:aws:s3:::${aws:username}/*"
      ]
    }
  ]
}

このIAM Policyを、新しく作成したIAM Group(例: S3UploaderGroup)に割り当てます。あとは、バケット名と同じ名前のIAMユーザを作成すれば、そのユーザの権限では自分自身と同じ名前のバケットしか操作できなくなります。例えば、www.example.comというWEBサイトを公開する場合には、S3バケット「www.example.com」を作成した後に、IAMユーザ「www.example.com」を作成し、先ほど作成したIAM Groupに紐づけてあげればOKです。

この方法の欠点は、IAM Userと操作対象のバケットが1:1になることです。つまり、複数のS3バケットを操作可能なIAM Userを作ることができません。この問題の綺麗な解決策がありましたらぜひコメントやTwitterなどで教えて頂けると嬉しいです!

まとめ

S3に限らず、IAMによる権限設定は結構複雑ですが、AWSのと直結する部分なので、それぞれのIAMユーザには適切な権限を与えて上げる必要があります。今回利用したIAM Policy Variablesを利用すれば柔軟にIAMの権限設定をできますので、一度IAMについてのドキュメントを読んでみてください。

参考