いろんな記事がありますが、読んでいて混乱しまくったので自分が使ったケースとそれに対応する設定を残しておきます。
実現したかったこと
オンプレに構築したJenkinsやBambooなどのCIツール(VPCの外)から、VPC内のEC2などのリソースに対してS3経由でデプロイ資材を送り込むケースにおいて、S3上に適切なアクセスコントロールを設定すること。
CIツールのIPアドレスは管理せず、IAMの権限にてアクセスコントロールを行うこと。
S3のアクセスコントロールの考え方
アクセスコントロールの許可/拒否は以下の考え方で適用されます。
- 明示的な拒否 ← Deny
- 許可 ← Allow
- デフォルト拒否 ← Allowされなかった残り
「VPC内からのアクセスのみ許可」をしたいケースでは、厳密には「VPC以外からのアクセスを明示的に拒否」とするのが正しいようです。
「明示的な拒否」は「許可」で上書きできないため、以下の記事ではNOTとANDをうまく使い、その他の条件と結合しています。
http://dev.classmethod.jp/cloud/aws/s3-access-from-specific-ip-and-vpc/
S3のバゲットポリシーの条件部分抜粋
"Condition": { "StringNotEquals": { "aws:sourceVpc": "<<VPC ID>>" }, "NotIpAddress": { "aws:SourceIp": [ "<<VPC外からアクセスする際のIPアドレス>>" ] } }
今回の対応方法
自分のやりたかったことは「明示的拒否」ではなく「デフォルト拒否」です。それを元に考えると以下のようになりました。
- VPC内からのアクセスを「許可」すると、それ以外は自動的に「デフォルト拒否」となる
- VPC外からのアクセスはIAMでの権限を付与しているので「許可」扱いとなり、「デフォルト拒否」に負けない
- オブジェクトのURLでのアクセスは「デフォルト拒否」のため、接続できない
1のS3のバゲットポリシーの内容は以下の通りです。
{
"Version": "2012-10-17",
"Id": "PolicyXXXXX",
"Statement": [
{
"Sid": "StmtXXXXXX",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket-name",
"arn:aws:s3:::my-bucket-name/*"
],
"Condition": {
"StringEquals": {
"aws:SourceVpc": "vpc-XXXXXXX"
}
}
}
]
}
(注意)VPC内からS3へアクセスするためにはVPC内にEndpointの設定も必要となります。このあたりを参考に設定してください。
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-endpoints.html#vpc-endpoints-access
あとはVPC外からS3へのアクセス時に使うIAMユーザの権限を適切に設定してあげればよいです。
所感
アクセスコントロールに関しては、IAMなどでの「許可」が上回るのでセキュリティの観点では弱いですが、保守性を考えるとこれがベストなのかなと考えています。
「デフォルト拒否」はうっかり「許可」されてしまう可能性が高いですし、そもそも考慮できていないこともあるかもしれないのでが注意点ですね。これで運用してみて何かあれば追記しますが、自己責任でお願いします。