【小ネタ】S3バケットのバケットポリシーを一括でいい感じに取得する #AWSCLI

2017.08.31

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

AWS CLIを使って S3バケットのバケットポリシーを取得するには、get-bucket-policy コマンドを使用します。

でもこの場合、バケットポリシー自体はエスケープされた状態で出力されてしまいます。
例えばこんな感じに(backet-xxxxxxxxがバケット名):

$ aws s3api get-bucket-policy --bucket backet-xxxxxxxx
{
    "Policy": "{\"Version\":\"2008-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::1234nnnn5678:role/xxxx-default-role\"},\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::backet-xxxxxxxx/*\"},{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::backet-xxxxxxxx/*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":[\"13.112.23.xxx/32\",\"13.112.23.yyy/32\"]}}}]}"
}

これでもバックアップという意味では悪くないんですが、いまひとつ読みにくいのと、
マネジメントコンソールに貼り付けたり、作業の前後や他のバケットポリシーと比較する用途では使いにくいのも困りものです。

実は help に書いてあるのですが、
下記のように--query --output両オプションを指定することで、エスケープされない状態のバケットポリシー (JSON) を取得できます。

$ aws s3api get-bucket-policy --bucket backet-xxxxxxxx --query Policy --output text
{"Version":"2008-10-17","Statement":[{"Sid":"","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::1234nnnn5678:role/xxxx-default-role"},"Action":"s3:*","Resource":"arn:aws:s3:::backet-xxxxxxxx/*"},{"Sid":"","Effect":"Allow","Principal":{"AWS":"*"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::backet-xxxxxxxx/*","Condition":{"IpAddress":{"aws:SourceIp":["13.112.23.xxx/32","13.112.23.yyy/32"]}}}]}

ここまでくれば、あとはもうちょっと整形された状態にしたくなりますね。

せっかくなので、存在する全 S3バケットのバケットポリシーを取得してファイルに書き出すワンライナーを書いてみました。

#!/bin/bash
for backet in $(aws s3api list-buckets | jq -r .Buckets[].Name)
do
  echo "* ${backet}"
  aws s3api get-bucket-policy --bucket ${backet} --query Policy --output text | jq . --indent 4 > policy_${backet}.json
done

AWS_DEFAULT_PROFILE環境変数など、AWS CLIが使用できる状態で実行してください。

forからdoneまでをターミナルにコピペしてもいいですし、
何か適当な名前で保存してシェルスクリプトにしても大丈夫です。

実行すると、policy_(バケット名).jsonという名前でファイルが作成されます。

バケットポリシーが設定されていない S3バケットがあると、エラーメッセージとともに 0バイトのファイルができてしまいますがご了承ください。
エラーメッセージはこんな感じです:

An error occurred (NoSuchBucketPolicy) when calling the GetBucketPolicy operation: The bucket policy does not exist

この実行にはjqコマンドが必要になりますが、CLIでJSONを扱う時には非常に便利なので、是非いれておいてください。

また、マネジメントコンソールで修正する際のフォーマットにそろえるために、jqのオプションでインデントを 4にしています。

作成されたファイルは下記のようになります。

$ cat policy_backet-xxxxxxxx.json
{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::1234nnnn5678:role/xxxx-default-role"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::backet-xxxxxxxx/*"
        },
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::backet-xxxxxxxx/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "13.112.23.xxx/32",
                        "13.112.23.yyy/32"
                    ]
                }
            }
        }
    ]
}

特記事項

何度か実行していて気づいたのですが、
バケットポリシー内のArray部分([])の順番がどうも不定であるように見えます。

なので作業前後で差分を確認すると、修正していないのに差分が出てびっくりすることがあります。その部分はいまひとつ使いにくいものの、気をつけていれば支障のない範囲ですので、バケットポリシー修正作業の際にはご活用ください。