はじめに
今回、バケットポリシーで使えると便利だけど使い方ではまってしまったNotPrincipalの設定について解説をしたいと思います。
とあるKinesis DataFirehoseからS3へのDirect PUT接続を構築したときのことです。
構築自体は難なく完了。次にセキュリティを高めようと思い、NotPrincipal
を使ったバケットポリシーを以下のように設定してみました。
NotPrincipal
でFirehoseに付与したロール以外からのS3アクセスを拒否したつもりでした。
しかしながら、これを設定した瞬間にS3 Access Denied のアクセスエラーが出てしまいました...
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::<ACCOUNT ID>:role/<ROLE NAME>"
]
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::<BUCKET>",
"arn:aws:s3:::<BUCKET>/*"
]
}
]
}
結論
以下のようにバケットポリシーを設定することで、正しくFirehoseからのデータ連携を受け取ることができるようになりました。以下の例はKinesis DataFirehoseに対応をしていますが、後述のポイント1, 2を見ていただくことで、ご自身の環境に合わせて設定ができるようになります。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:sts::<ACCOUNT ID>:assumed-role/<ROLE NAME>/AWSFirehoseToS3",
"arn:aws:iam::<ACCOUNT ID>:role/<ROLE NAME>",
"arn:aws:iam::<ACCOUNT ID>:root"
]
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::<BUCKET>",
"arn:aws:s3:::<BUCKET>/*"
]
}
]
}
ポイント1 : NotPrincipalの使い方
まずは公式ドキュメントをしっかりと読み込むべきでした。公式にある通り、NotPrincipalを使用するためには以下のように設定する必要があるようです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:sts::<ACCOUNT ID>:assumed-role/<ROLE NAME>/<ROLE SESSION NAME>",
"arn:aws:iam::<ACCOUNT ID>:role/<ROLE NAME>",
"arn:aws:iam::<ACCOUNT ID>:root"
]
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::<BUCKET>",
"arn:aws:s3:::<BUCKET>/*"
]
}
]
}
NotPrincipalの場合は以下3つのARNを含める必要があるので要注意です。
- AssumeRole
- ロール
- ルートユーザ
ポイント2 : ロールセッション名
ポイント1のポリシーの構造がわかったところで、次の壁はAssumeRoleのARNの設定です。特にロールセッション名については記載がなく、Firehoseのロールセッション名が何なのか確認が必要でした。
以下の記事はとても参考になりましたが、EC2とLambdaについて説明されており、自分のケースではうまくいかず...
ワイルドカードの使用を試みましたがポリシー検証でエラー、セッション名をFirehoseのリソース名に設定してみるもFirehoseからのアクセスは拒否されたままの結果でした...
あれこれ悩んだ末、Crondtrailでロールセッション名を確認することができるのではと思い、確認をしてみました。
Croudtrailからイベント名 : AssumeRole
でフィルターをかけると、以下ののようなFirehoseのAssumeRoleの実行履歴を確認することができます。
{
:
:
"requestParameters" : {
"roleArn" : "arn:aws:iam::<ACCOUNT ID>:role/<ROLE NAME>" ,
"roleSessionName" : "AWSFirehoseToS3",
"durationSeconds" : 3600,
"externalId" : "<ACCOUNT ID>"
}
:
:
}
発見!!!
"roleSessionName"をS3のバケットポリシーに設定すると無事疎通しました