AWS SDK for Python (Boto3)を使ってパブリックアクセスが可能なS3を作成してみた

2023.05.14

Boto3でS3を作成する必要があったのでブログに残します。

作成したスクリプト

S3を作成するのに使用したスクリプトは以下になります。

import boto3
import datetime

client = boto3.client('s3')

date = datetime.datetime.now()
Bucket_name = 'kobayashi-' + date.strftime('%Y-%m-%d-%H-%M-%S')

client.create_bucket(Bucket=Bucket_name,CreateBucketConfiguration={'LocationConstraint': 'ap-northeast-1'}, ObjectOwnership='ObjectWriter')
client.put_public_access_block(Bucket=Bucket_name, PublicAccessBlockConfiguration={'BlockPublicAcls': False,'IgnorePublicAcls': False,'BlockPublicPolicy': False,'RestrictPublicBuckets': False})
client.put_bucket_acl(ACL='public-read',Bucket=Bucket_name)
client.put_bucket_policy(Bucket=Bucket_name, Policy=f'{{"Version": "2012-10-17", "Statement": [{{ "Sid": "public","Effect": "Allow","Principal": "*", "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::{Bucket_name}/*"] }} ]}}')

参考にしたドキュメントは以下です。
create_bucket

上記のスクリプトを実行するとパブリックアクセスが可能なS3バケット (kobayashi-日時) が作成されます。
client.create_bucketでS3バケットを作成後にclient.put_public_access_blockでパブリックブロックアクセスを無効にしています。
パブリックブロックアクセスを無効にすることでclient.put_bucket_aclでバケットACLの操作が出来るようになるのでpublic-readに設定をしています。
最後にclient.put_bucket_policyでバケットポリシーを設定して外部からGetObjectを許可するようにしています。

実行時に以下のエラーが出る場合はアカウントのパブリックアクセスブロック設定の構成が有効になっている可能性があるので確認してみてください。

botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the PutBucketAcl operation: Access Denied

少し詰まった部分

最初は以下のようなスクリプトを作成していました。

import boto3
import datetime

client = boto3.client('s3')

date = datetime.datetime.now()
Bucket_name = 'kobayashi-' + date.strftime('%Y-%m-%d-%H-%M-%S')

client.create_bucket(ACL=’public-read’, Bucket=Bucket_name,CreateBucketConfiguration={'LocationConstraint': 'ap-northeast-1'}, ObjectOwnership='ObjectWriter')
client.put_bucket_policy(Bucket=Bucket_name, Policy=f'{{"Version": "2012-10-17", "Statement": [{{ "Sid": "public","Effect": "Allow","Principal": "*", "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::{Bucket_name}/*"] }} ]}}')

上記の場合だと以下のエラーが発生します。

botocore.exceptions.ClientError: An error occurred (InvalidBucketAclWithBlockPublicAccessError) when calling the CreateBucket operation: Bucket cannot have public ACLs set with BlockPublicAccess enabled

原因としては以下のドキュメントに記載されている通り、デフォルトでパブリックアクセスブロック設定が有効になっていることでした。
Amazon S3 ストレージへのパブリックアクセスのブロック

2023 年 4 月から、Amazon S3 はすべての新しい S3 バケットの S3 パブリックアクセスブロックとオブジェクト所有権 (ACL 無効) のデフォルト設定を変更します。この更新後に作成された新しいバケットでは、S3 パブリックアクセスブロック設定はすべて有効になり、S3 アクセス制御リスト (ACL) は無効になります。デフォルト設定は、Amazon S3 でデータを保護するために推奨するベストプラクティスです。この設定は、バケットを作成した後に調整できます。詳細については、「 新しい S3 バケットのデフォルト設定に関するよくある質問」および、「AWS ニュースブログ」の「注意事項: 2023 年 4 月に予定されている Amazon S3 のセキュリティ変更」を参照してください。

なので、一旦S3バケットを作成後にput_public_access_block()を使用してパブリックアクセスブロックを無効にすることで解決しました。

さいごに

今回はパブリックアクセスブロックを無効にしたS3バケットを作成しましたが、以下のドキュメントに記載されている通り、有効化しておくことがベストプラクティスとして推奨されているので無効化するのは基本的には行わない方がよいです。
事前のお知らせ: 2023 年 4 月より、Amazon S3 で、すべての新しいバケットに対して自動的に S3 パブリックアクセスブロックが有効化、アクセスコントロールリストが無効化