AWSのS3バケットの作成、削除、タグ付与、ポリシー設定をコマンドラインから操作する

2019-03-09Amazon, AWS, Bash, Linux

S3のバケット作成、削除、ポリシー設定をWeb上から操作することが多いです。
Web操作の解説も多いです。

でも、コマンドラインからの実行を解説しているケースはさほど多くないですね。。

S3はバックアップデータ置き場、ログ置き場として使うことが多いが、特に検証時に作っては消し、また作るを繰り返す...
繰り返しが疲れてきたのでコマンドラインでのやり方をまとめてみました。

ここではよく使用される aws s3 コマンドではなく aws s3api コマンドについてできるだけ触れてみます。

aws-cli (AWSコマンドの利用可能な環境づくり)

AWSコマンドを使うための環境をDockerを使って構築(Mac/Linux/WindowsでもPythonなしで動くよ) | ゲンゾウ用ポストイット を参照。

上記記事では Mac、Linux、Windowsの環境の差異を無視できるよう、またPythonなしでも動作するように Docker を利用しました。

S3バケットの作成 ( aws s3api create-bucket / aws s3 mb )

aws s3api create-bucket コマンドを使う。

ここでは genzouw-test-bucket というバケット名で作成してみます。

$ aws s3api create-bucket \
  --bucket genzouw-test-bucket \
  --create-bucket-configuration "LocationConstraint=ap-northeast-1"

# 環境変数 AWS_DEFAULT_REGION が設定されていれば、以下のコマンドでも良い。
## aws s3api create-bucket \
##   --bucket genzouw-test-bucket \
##   --create-bucket-configuration "LocationConstraint=${AWS_DEFAULT_REGION}"

何度か --create-bucket-configuration オプション無しで実行してみたが、以下のようなエラーが発生しました。
AWS_DEFAULT_REGION の設定があったとしても指定が必要な模様。

An error occurred (IllegalLocationConstraintException) when calling the CreateBucket operation: The unspecified location constraint is incompatible for the region specific endpoint this request was sent to.

※ちなみに、以下のコマンドでもいける 。実はこちらの方はリージョンのデフォルト設定が効いてくれるので楽。

$ aws s3 mb s3://genzouw-test-bucket

S3バケットの一覧表示 ( aws s3api list-buckets / aws s3 rb )

正しくバケットが作成されたかどうかは以下のコマンドを実行すれば確認できます。

$ aws s3api list-buckets
{
    "Owner": {
        "DisplayName": "xxxxxxxxxxx",
        "ID": "yyyyyyyyyyyyyy"
    },
    "Buckets": [
        {
            "CreationDate": "2019-02-23T05:53:31.000Z",
            "Name": "genzouw-test-bucket"
        }
    ]
}

※ちなみに、以下のコマンドでもいける

$ aws s3 ls
2019-02-23 14:53:31 genzouw-test-bucket

S3バケットの削除 ( aws s3api delete-bucket )

バケットが不要になった場合は以下のコマンドで削除できます。

$ aws s3api delete-bucket \
  --bucket genzouw-test-bucket

※この場合はリージョンの指定はなくても動作します。

※ちなみに、以下のコマンドでもいける

$ aws s3 rb s3://genzouw-test-bucket

すでにファイルが存在している場合は消せないので、 --force オプションを付ける。

$ aws s3 rb s3://genzouw-test-bucket --force

S3バケットにファイルをアップロード ( aws s3 cp )

対象バケットにファイルをアップロードしてみます。

# まずはからであることを確認
$ aws s3 ls s3://genzouw-test-bucket

# ファイルを作成
$ echo "hello world." >> first.txt

# アップロード
$ aws s3 cp first.txt s3://genzouw-test-bucket/
upload: ./first.txt to s3://genzouw-test-bucket/first.txt

# ファイルが存在している
$ aws s3 ls s3://genzouw-test-bucket
2019-02-23 15:14:33         26 first.txt

アップロードされたファイルが公開されている場合には、以下のURLで閲覧できます。

# わかりやすく変数に代入したが、変数を使わずべた書きしてもいい
$ BUCKET_NAME=genzouw-test-bucket
$ FILEPATH=first.txt

$ curl -L "https://${BUCKET_NAME}.s3.amazonaws.com/${FILEPATH}"

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>8878BF29A528BC9D</RequestId><HostId>+oi6UYV9MHiplWgImb8cTxzOceIp3bnrCkXfcYztVSDJqgJgJsIkbvs/eaGXvwFWXMXp1eKOMVA=</HostId></Error>%

幸い、 アクセス権限はないよ! と怒られてしまいました。
外部から見えて問題が発生、というケースが最近後をたたないので。

S3バケットのファイルを一時的に公開 ( aws s3 presign )

維持的に公開する方法があります。

# わかりやすく変数に代入したが、変数を使わずべた書きしてもいい
$ BUCKET_NAME=genzouw-test-bucket
$ FILEPATH=first.txt

# 60秒だけアクセスを許す( `--expires-in` オプション無しだと 3600秒アクセス可能 )
$ aws s3 presign "s3://${BUCKET_NAME}/${FILEPATH}" --expires-in 60
https://genzouw-test-bucket.s3.amazonaws.com/first.txt?AWSAccessKeyId=AKIAJH2H7TNAY63LTXRA&Signature=PNbboO7Ciawjxc7w7Zww44qv4qA%3D&Expires=1550907814

# 60秒間だけアクセスできる
$ curl -L "https://genzouw-test-bucket.s3.amazonaws.com/first.txt?AWSAccessKeyId=AKIAJH2H7TNAY63LTXRA&Signature=PNbboO7Ciawjxc7w7Zww44qv4qA%3D&Expires=1550907814"

# 60秒をすぎるとエラー
$ curl -L "https://genzouw-test-bucket.s3.amazonaws.com/first.txt?AWSAccessKeyId=AKIAJH2H7TNAY63LTXRA&Signature=PNbboO7Ciawjxc7w7Zww44qv4qA%3D&Expires=1550907814"
EsgHhk=</HostId></Error><?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Request has expired</Message><Expires>2019-02-23T07:43:34Z</Expires><ServerTime>2019-02-23T07:43:43Z</ServerTime><RequestId>33885186804B8BE5</RequestId><HostId>VJQm2IV5YDKNpZLCYpr/xWqzxSICB8nW7tIQxWLemOMfTb0lCMbBi0bno+9nKk/1jRfrto+Cjuw=</HostId></Error>

S3バケットのファイルを読み取り専用で公開 ( `aws s3 pub-object-acl )

デフォルトは非公開状態であるバケット上のファイルを公開状態に設定する方法。

# --key というのはS3上のファイルパスのこと
$ aws s3api put-object-acl --bucket genzouw-test-bucket --acl public-read --key first.txt

# わかりやすく変数に代入したが、変数を使わずべた書きしてもいい
$ BUCKET_NAME=genzouw-test-bucket
$ FILEPATH=first.txt

# 読めるかどうか確認。。。みれた!
$ curl -L "https://${BUCKET_NAME}.s3.amazonaws.com/${FILEPATH}"
hello world.

ビビリなので、このあとに追加されたファイルまで公開されてしまうことなったりしないか確認してみました。

$ echo "hello genzouw." >> second.txt

# アップロード
$ aws s3 cp second.txt s3://genzouw-test-bucket/
upload: ./second.txt to s3://genzouw-test-bucket/second.txt

# ファイルが存在している
$ aws s3 ls s3://genzouw-test-bucket
2019-02-23 17:03:19         13 first.txt
2019-02-23 17:12:24         15 second.txt

# 読めませんように。。。
$ BUCKET_NAME=genzouw-test-bucket
$ FILEPATH=second.txt
$ curl -L "https://${BUCKET_NAME}.s3.amazonaws.com/${FILEPATH}"
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>10F8A6F402403DA1</RequestId><HostId>uojYIx7674U6z+Wp4lqkgRCJjA+ejE3Nmf+mBOZh/USmuOYtTV6XuXvQ5m5n/wrzrwEFQYyYH98=</HostId></Error>

大丈夫そうです。

ひとこと

検証のためにS3バケットを作って、消して、ファイルを追加してはコマンドだけで何度も行けそう。
負荷テストもできそうです。

頻繁に使うコマンドは、 s3api じゃなくても s3 コマンドで十分網羅されているようでした。

2019-03-09Amazon, AWS, Bash, Linux