VPC エンドポイントポリシーで S3 バケットを制限する際の落とし穴
状況設定
AWS の VPC エンドポイントポリシーで VPC 内部から Amazon S3 バケットへのアクセスを制限するために,以下のようなエンドポイントポリシーを設定するとします。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-xxxxxxxxxxx"
}
}
}
]
}
上記の例では aws:PrincipalOrgID
を用いて特定の Organization 配下のバケットに限定していますが,特定のアカウント配下のバケットに限定するなら aws:PrincipalAccount
を用います。
実際に検証してみると,確かに限定されたバケットにはアクセスできるようになりました。
問題発生
ところが,その VPC 内で構築していた Amazon EKS クラスタでなぜか一部のコンテナイメージを pull できなくなりました。
pull できないコンテナイメージは大別すると以下のレジストリでホストされているものでした。
- Amazon ECR プライベートレジストリ
- registry.k8s.io
原因
一部のコンテナレジストリはパブリックな Amazon S3 バケットをバックエンドにしてそこから pull させているようです。
Amazon ECR プライベートレジストリ
ECR プライベートレジストリはプライベートという名前がついていますが,自分のアカウントの VPC ではなく,AWS が管理するアカウントに存在する S3 バケットにイメージのレイヤーが保存されています。
バケットの ARN は以下の形式です。region
にはレジストリが存在する AWS のリージョン名が入ります。
arn:aws:s3:::prod-region-starport-layer-bucket
ちなみに ECR Public(Public Gallery でホストされている,public.ecr.aws から始まるイメージを pull するときに使う)はクライアントから S3 バケットの存在が見えず,アクセス許可は不要でした。
registry.k8s.io
Kubernetes のコンテナレジストリは k8s.gcr.io から registry.k8s.io に移行しましたが,AWS からアクセスする場合は S3 バケットにリダイレクトされる挙動になりました。
移行に関する AWS のブログ記事にはその旨がさらっとしか書かれていませんでしたが,こちらの Issue にバケット名が記載されていました。
arn:aws:s3:::prod-registry-k8s-io-region
同様に region
にはリージョン名が入ります。
解決策
それぞれのコンテナレジストリの背後にいる S3 バケットへのアクセスを別途許可します。ap-northeast-1 リージョンの場合は以下の Statement を追加します。
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::prod-ap-northeast-1-starport-layer-bucket/*",
"arn:aws:s3:::prod-registry-k8s-io-ap-northeast-1/*"
]
}
もし他にも S3 バケットへのアクセスを必要とするコンテナレジストリがありましたら,コメント欄でご教示いただけると助かります。
余談
ECR プルスルーキャッシュに registry.k8s.io を設定できるようになっています。
ECR のプルスルーキャッシュ設定は実体はプライベートレジストリなので,registry.k8s.io をそこ経由にすれば,prod-region-starport-layer-bucket の許可だけで pull できる気がします。イメージ指定の書き換えが大変そうですが,試してみた方がいらっしゃいましたらコメントください。
Discussion