Boto2 使用の古いシステムを AWS S3 の署名バージョン４に対応させる


# TL;DR

```
$ . your-venv/bin/activate
$ pip install -U boto
$ sudo cat > /etc/boto.cfg <<'^Z'
[s3]
use-sigv4 = True
host = s3.ap-northeast-1.amazonaws.com
^Z
```

# はじめに

間もなく 2019/6/24 に AWS S3 の署名バージョン２が廃止になり、現在署名バージョン２を使って S3 アクセスを行っているシステムに影響が出ます。

【追記】[AWS から発表があり](https://aws.amazon.com/jp/blogs/aws/amazon-s3-update-sigv2-deprecation-period-extended-modified/)、2020/6/24 以降に新規に作成されたバケットのみ署名バージョン４が必須ということにスケジュールと対象が変更されました。引き続き署名バージョン４でのアクセスが推奨されることに変わりはありません。

私が前任者から受け継がされたシステムも古い Boto2 ライブラリ (Python 2.7) を利用し、アップデートもせずに放置されているので、当然署名バージョン２を利用しています。

このシステムは再デプロイのやり方も不明（というかデプロイされた後にサーバー上でいじられた形跡がある）なため、なんとか動作したままライブで署名バージョン４に対応したいところです。

なぜか Boto2 を署名バージョン４に対応させる情報がググってもあまり出てこず、ややはまったのでここに書き記しておきます。

# Boto2 と Boto3

この記事で説明する方法は Boto2 が対象です。Boto3 には当てはまらないので注意してください。

# 署名バージョン２を使っていることを確認する

実際にこのシステムが署名バージョン２を使っていることを確かめるために「[【Amazon S3を利用しているすべての人が安心して2019/06/24を迎えるために】CloudTrailとAthenaを用いたS3の署名バージョンの確認方法 ｜ DevelopersIO](https://dev.classmethod.jp/etc/check-use-your-s3-access-signature-version/)」を参考に署名バージョン２を利用した S3 アクセスを検出しました。

上の記事の最後の Athena に対するクエリを実行すると CSV がダウンロードできるようになります。この CSV（巨大です）を data.csv として、以下のようにすると簡単にインスタンスが特定できます。

```
$ tail -n +2 data.csv | sort -t, -k1r,1 | sort -sut, -k6,6 -k5,5 > data.uniq.csv
$ tail -n +2 data.csv | sort -t, -k1r,1 | sort -st, -k6,6 -k5,5 > data.sorted.csv
```

data.uniq.csv は (S3 バケット名, インスタンスの IP アドレス）が同一のもののうち、最も最近にあったアクセスだけが抽出されます。data.sorted.csv は同一のものを時間順にソートしただけのものです。data.uniq.csv は小さいので見やすいです。詳細（バケット名に加えてキーを見たい場合など）を見たい場合は data.sorted.csv を参照します。

この方法で、修正対象のシステムのインスタンスの IP から確かに署名バージョン２でアクセスがされており、そのユーザーエージェントが `[Boto/2.25.0 Python/2.7.4 Linux/3.4.73-64.112.amzn1.x86_64]` であることが確認できました。Boto2 の 2.25.0 が使われているのが観察できますね。

# 修正方法を調べる

AWS SDK の種類ごとの修正方法が「[署名バージョン 2 から署名バージョン 4 への移行](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/UsingAWSSDK.html#UsingAWSSDK-move-to-Sig4)」に掲載されています。これによると：

| SDK   | Upgrade                      | コード変更が必要 |
|:-:|:-:|:-:|
| Boto2 | Boto2 v2.49.0 にアップグレード | はい |

う～む「コード変更が必要」は困る...

さらに「[リクエスト認証での署名バージョンの指定](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/UsingAWSSDK.html#specify-signature-version)」を見ると：

>boto デフォルト設定ファイルに以下を指定します。

```
[s3] use-sigv4 = True
```

とあります。コード変更といっても設定ファイルの変更だけで済みそうですが、この boto デフォルト設定ファイルってどこにあるの？しかも何この変なフォーマットは

```
[s3]
use-sigv4 = True
```

じゃないの？

# Boto2 の設定ファイル

Boto2 の設定ファイルは「[Boto Config — boto v2.49.0](http://boto.cloudhackers.com/en/latest/boto_config_tut.html)」に書いてあります。 /etc/boto.cfg とか ~/.boto に書けばいいみたい。

あと、やはりフォーマットは ini フォーマットで、`[s3]` の後に改行が必要みたいです。

# 修正作業

材料が揃ったので修正しましょう。今回修正対象のシステムは cron で動作しているので、まずそれを止めます。virtualenv を利用して動いている（よかった...）ので virtualenv 内の boto をアップグレードします。

```
$ cp -a your-venv your-venv-backup  # ← 非常時ロールバック用
$ . your-venv/bin/activate
$ pip install -U boto
$ pip show boto
---
Name: boto
Version: 2.49.0
Location: /home/user/your-venv/lib/python2.7/site-packages
Requires: 
```

Boto2 は依存先が無く他のパッケージを巻き添えにせずにアップグレードできてレガシーシステムにやさしいです。

次に Boto2 設定ファイルを変更します。今回は既存の設定ファイルは無さそうだったので新規で作成します。

```
$ sudo cat > /etc/boto.cfg <<'^Z'
[s3]
use-sigv4 = True
^Z
```

さてテスト実行してみると... S3 に全くアクセスできず！！！... 困った。

# さらなる修正

原因をググってもなかなか探し当てられませんでしたが、それらしきものを発見: [python - Using boto for AWS S3 Buckets for Signature V4 - Stack Overflow](https://stackoverflow.com/questions/27400105/using-boto-for-aws-s3-buckets-for-signature-v4)

この記事には API エンドポイントに `s3.amazonaws.com` ではなく `s3.eu-central-1.amazonaws.com` というリージョン毎のエンドポイントを指定しなくてはならない、と書いてあります。う～ん、これ boto.cfg に書けるのか？

まず東京リージョンの S3 API エンドポイントを調べます: [AWS のリージョンとエンドポイント - アマゾン ウェブ サービス](https://docs.aws.amazon.com/ja_jp/general/latest/gr/rande.html) によると `s3.ap-northeast-1.amazonaws.com` でした。ということで...

```
$ sudo cat > /etc/boto.cfg <<'^Z'
[s3]
use-sigv4 = True
host = s3.ap-northeast-1.amazonaws.com
^Z
```

テスト実行は... うまくいきました。cron を元通りにして終了。

この `[s3]` セクションの設定の公式ドキュメントは一体どこにあるのだろうか？見つからない。