VPCエンドポイント構成でS3バケットへのアクセスを制限するには?

記事タイトルとURLをコピーする

こんにちは。takada@福岡オフィスです。
ポケモンGOをやってます。深夜、近所のポケストップを一人で徘徊していると、カップルから「あの人、一人でポケモンGOやってる。ヤバくない」と指さされました。
家に返って「ヤバイ」辞書を調べたら、どうやら否定的な意味と、「凄い」「のめり込みそうなくらい魅力的」といった肯定的な意味の2つの意味があるらしく、「あーなるほど。あのカップルは後者の意味で使ってたのだ」と腑に落ちたのでした。そう、何事も調べることが大事。
今回は、VPCエンドポイント構成でS3バケットへのアクセスを制限する方法を調べてみました。

 

VPCエンドポイント is 何?

ブリを産んだ魚、じゃなくて人のブログに書かれております。ここ読めワンワン。
以下抜粋。


VPCと別のAWSサービスとの間でプライベート接続を作成できるようになります。
つまり、S3にアクセスする際にも、インターネットを経由しなくてよくなるんですね。

ほーほー。

VPCエンドポイント構成で、S3へのアクセス制限をかける意味

 VPCエンドポイントのつかいどころとしては、当然VPCの内側からS3へのアクセスをするケースとなります。
多くの場合、以下のように、EC2からS3へのアクセスが利用用途となるでしょう。

VPCE_S3

例えば、特定のS3バケット「hoge」にVPC内のEC2からのみアクセスを許可したいケースを考えてみます。

 EC2からS3へのアクセス制限をかける場合、S3バケットへのアクセスを許可したIAMポリシーを紐付けたIAMロールを作成し、EC2に付与するのがベストです。
理由は以下の2つです。

  • EC2の内部に認証情報(IAMアカウントのシークレットアクセスキー)を保つ必要がない
  • IAMポリシーは「デフォルト拒否」の動作となるため、実質的にこのバケットにアクセスできるのは、IAMロールを付与されたEC2のみとなる

ただし、これは、S3バケットへアクセスするEC2内で動作するアプリケーション("aws cli"など)がIAMロールに対応している場合に限ります。

 IAMロールに対応していないアプリケーションからS3バケットへアクセスする場合は、やはり、IAMユーザーのシークレットアクセスキーを払い出して、EC2内部にもたせる必要があります。このケースですと、万が一、シークレットアクセスキーが漏れてしまった場合、S3バケット「hoge」にはインターネット側からもアクセスが可能となります。
これを防ぐため、払いだしたIAMユーザに対して接続元をVPC内に制限するポリシーを割り宛てる必要がでてきます。

送信元をVPCのCIDRで制限してみた。

こんな感じのIAMポリシーを作って、IAMユーザーに適応してみました。


{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "arn:aws:s3:::*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "10.0.0.0/16"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::hoge",
                "arn:aws:s3:::hoge/*"
            ],
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "10.0.0.0/16"
                }
            }
        }
    ]
}

結果、効きません。該当バケットにアクセスできない状態になります。なぜでしょう

答えはドキュメントに

書いてありました。辞書とドキュメントは調べるに限ります。

「Amazon S3 エンドポイントを使用する場合、バケットポリシーまたは IAM ポリシーを使用して VPC CIDR 範囲(プライベート IP アドレス範囲)からのアクセスを許可することはできません。VPC CIDR ブロックは重複または同じになる場合があり、それによって予期しない結果が発生する可能性があります。代わりに、バケットポリシーを使用して特定のエンドポイントまたは特定の VPC へのアクセスを制限するか、ルートテーブルを使用して、エンドポイント経由で Amazon S3 のリソースにアクセスできるインスタンスを制御できます。」
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-endpoints.html#vpc-endpoints-limitations

なるほど、VPC内部のプライベートアドレス帯はAWSアカウントごと、もしくはAWSアカウント内で重複して設定が可能なので、制限する条件となり得ないということですね。
代わりに、VPCエンドポイントIDもしくはVPC IDを使用して制限する必要があります。
マニュアルでは、「バケットポリシー」の例が記載されていますが、確認したところ、IAMポリシーを使用した制限も可能です。

ちなみに、IAMポリシーとバケットポリシーの違いですが、IAMポリシーは操作主体(IAMユーザあるいはEC2インスタンス)に付与するポリシーとなり、
バケットポリシーは、操作対象(S3バケット)に付与するポリシーとなります。
バケットポリシーに設定した場合、操作主体(IAMユーザあるいはEC2インスタンス)を問わず、制御がかかることになります。
今回のケースですと、バケットポリシーで設定した場合は、S3バケットへのアクセスはいかなる操作主体(IAMユーザあるいはEC2インスタンス)であっても、VPC内部からしかアクセスできません。
一方、IAMポリシーの場合は、設定した"操作主体(IAMユーザあるいはEC2インスタンス)のみ、S3バケットへのアクセスがVPC内部のみに制限されることになります。

以下、前述のIAMポリシーをVPCエンドポイントIDを使用するように変更したものになります。


{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "arn:aws:s3:::*",
            "Condition": {
                "StringEquals": {
                    "aws:sourceVpce": [
                        "vpce-xxxxxxxx"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::hoge",
                "arn:aws:s3:::hoge/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:sourceVpce": [
                        "vpce-xxxxxxxx"
                    ]
                }
            }
        }
    ]
}

まとめ

以下、まとめです。

VPCエンドポイント構成でEC2からS3バケットへのアクセス制限をかける場合は、

  • IAMロールとIAMポリシーを使用するのがベストです。
  • アクセスキーを使用する場合は、バケットポリシーもしくはIAMポリシーで、VPC IDかVPCエンドポイントIDで制限を行いましょう。

ちなみに、連日の深夜徘徊のおかげで、ポケモンGOのトレーナーレベルが22になりました。
決して、ヒマなのではありません。ではでは。