Slide 1

Slide 1 text

boto3からの解放。 python3の標準ライブラリのみで AWSサービスを取り扱うには ⼩板橋 由誉 2022/1/27

Slide 2

Slide 2 text

Who am I ? ⼩板橋 由誉 / Yoshitaka Koitabashi u KDDI株式会社 アジャイル開発部 ソフトウェア技術2G 所属チーム u AR/VRなどxR向けの コンテンツ管理システム(CMS)の開発 好きなAWSサービス u AWS App Runner

Slide 3

Slide 3 text

ある⽇・・・ n ある⽇こんな要望が舞い降りてきました。 n 「python3の標準ライブラリのみでAWSサービスに対して操作 (今回は、S3に対するCRUD操作-GetとPostに限定)できるようにして欲しいな。」

Slide 4

Slide 4 text

n AWSの各サービスをさわる⽅法は、いくつかあります。 l AWSマネジメントコンソールからの操作 l AWS SDKや、AWS CLIなどのAWSツールを使う⽅法 l blabla・・ AWSの各サービスをさわるには︖

Slide 5

Slide 5 text

n Boto3というのは、AWS SDK for Pythonの別称であり、 Pythonを介してAWSを操作するためのライブラリ n Boto3を⼊れるのは、簡単でpipでインストールできる n Boto3の由来ちょっと気になって調べてみたら、アマゾン川に⽣息する アマゾンカワイルカにちなんでつけたよう https://github.com/boto/boto3/issues/1023 n ドキュメント: (https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart .html#installation) Boto3 is 何︖

Slide 6

Slide 6 text

Boto3は便利 • 各AWS内のサービスについての 操作ドキュメントがしっかりしている • 各methodも使いやすい

Slide 7

Slide 7 text

こんな便利なboto3を使⽤しないで、 どうやってPythonからAWSの各サービスをさわればいいのーーー?

Slide 8

Slide 8 text

n boto3を使わないとなると、まずやらなければならないのはboto3が 何を隠蔽してくれているのかを確認する必要がある。 n まあ、単純に⾔えばBoto3がどんなREST APIのリクエストを 投げているのかを確認すればよい n そこで、Boto3でDEBUGログを出⼒してあげると 簡単にREST APIのリクエストの内容が確認できます。 Boto3のDEBUGログ

Slide 9

Slide 9 text

DEBUGログの設定 boto3.set_stream_loggerでログ出⼒の設定ができる。

Slide 10

Slide 10 text

DEBUGログのデモ

Slide 11

Slide 11 text

REST APIのリクエストの中⾝が分かったの で、ここからBoto3を使⽤せずに、S3に対す るCRUD操作-GetとPostをしていきます

Slide 12

Slide 12 text

n まず、AWSへのAPIリクエストを⾏う場合 (AWS SDKや、AWS CLIなどのAWSツールを使わない場合)、 リクエストの署名するためのコードを含める必要があります。 n 基本的には、この署名を気にすることはありません。 l AWS SDK、AWS CLIなどのAWSツールは、 ツール設定時に指定するアクセスキーを使⽤して APIリクエストに⾃動で署名します S3に対するGet処理

Slide 13

Slide 13 text

そもそも何で署名が必要なの︖︖

Slide 14

Slide 14 text

n 簡単に⾔えば、署名によってリクエストの セキュリティ確保をしたい為です。 n AWSのリクエストに対する署名では次の点でセキュリティの確保を ⾏なっています。 署名が必要な理由

Slide 15

Slide 15 text

n リクエストのIDの確認 l 署名により、有効なアクセスキーを持っている⼈がリクエストを送信したことを 確認できる n 送信中のデータの保護 l 送信中のリクエストの改ざんを防ぐために、リクエストの要素からハッシュ値を 計算し、得られたハッシュ値をリクエストの⼀部として含めます。 l AWSがリクエストを受け取ると、同じ情報を使⽤してハッシュを計算し、 リクエストに含まれているハッシュ値と⽐較します。 ハッシュ値が⼀致しない場合、AWSはリクエストを拒否します。 => Canonical Request この時、HTTP Authorization ヘッダーを使⽤します。 n 潜在的なリプレイ攻撃の防⽌ l リクエストに含まれるタイムスタンプの5分以内にAWSに到達する必要がある。 その条件を満たさない場合、AWSはリクエストを拒否します。 セキュリティ確保項⽬

Slide 16

Slide 16 text

つまりこの項⽬をboto3を使わないな ら、⾃分で実装しないといけない

Slide 17

Slide 17 text

やってやりましょう

Slide 18

Slide 18 text

n 署名のバージョン l AWSでは、署名バージョン4と署名バージョン2がサポートされている。 AWS CLI, AWS SDKは、署名バージョン4をサポートする すべてのサービスに対して⾃動で署名バージョン4を使⽤します。 n なので今回は、使⽤する署名のバージョンは署名バージョン4にします。 実装前の確認

Slide 19

Slide 19 text

S3におけるCanonical Requestでは何が必要︖︖ 参照元: https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/API/sig- v4-header-based-auth.html#canonical-request

Slide 20

Slide 20 text

n Canonical Requestでは、次のStepで署名の検証が⾏われる。 l ①: 署名するための⽂字列を決める。 l ②: 署名キーを使⽤して、署名する⽂字列のHMAC-SHA256ハッシュを 計算する。 l ③: s3は認証されたリクエストを受信すると、署名を計算しリクエストで 指定した署名と⽐較する。 u そのため、s3と同じ⽅法で署名を計算する必要がある => ここで、署名のために合意された形式でリクエストを送信するプロセスは、 正規化と呼ばれます。 ⾔語化すると

Slide 21

Slide 21 text

実装じゃ

Slide 22

Slide 22 text

①:Canonical Requestの作成 まず、下記にあるのがS3におけるcanonical requestのフォーマット

Slide 23

Slide 23 text

n HTTPMethod : GET/PUT/HEAD/DELETE等のHTTPメソッドの1つです。 n CanonicalURI : URIのURIエンコードバージョンです。 ドメイン名に続く「/」で始まり、⽂字列末尾まで、 または疑問符⽂字( '︖')までのすべてを指定します。 n CanonicalQueryString : URIエンコーディングされたクエリパラメータを指定します。 n CanonicalHeaders : リクエストヘッダーとその値のリストです。 個々のヘッダー名と値のペアは、改⾏⽂字( "¥ n")で区切られます。 ヘッダー名は⼩⽂字にする必要があります。 また、CanonicalHeadersは下記のものを必ず含めなければなりません。 l HTTPホストヘッダー l Content-Typeヘッダーがリクエストに存在する場合は、追加 l リクエストに含める予定のx-amz-*ヘッダーも追加。たとえば、⼀時的なセキュリティ クレデンシャルを使⽤している場合は、リクエストにx-amz-security-tokenを含める 必要があります。 Canonical Requestの詳細(説明割愛)

Slide 24

Slide 24 text

n SignedHeaders : アルファベット順にソートされたセミコロンで 区切られた⼩⽂字のリクエストヘッダー名のリストです。 リスト内のリクエス トヘッダーは、CanonicalHeaders⽂字列に含めたものと同じヘッダーです。 n HashedPayload : リクエストペイロードのSHA256ハッシュの16進値です。 l ちなみに、GETリクエストを使⽤してオブジェクトを取得する場合、空の⽂字列ハッ シュを計算します。 Canonical Requestの詳細(説明割愛)

Slide 25

Slide 25 text

CanonicalHeadersだけ説明 CanonicalHeaders : リクエストヘッダーとその値のリスト • また、CanonicalHeadersは下記のものを必ず含めなければなりませ ん。 • HTTPホストヘッダー • Content-Typeヘッダーがリクエストに存在する場合は、 追加リクエストに含める予定のx-amz-*ヘッダーも追加。 たとえば、⼀時的なセキュリティクレデンシャルを使⽤している場合 は、リクエストにx-amz-security-tokenを含める必要がある。 ↑Cognitoの認証tokenとかが該当 CanonicalHeadersのサンプル

Slide 26

Slide 26 text

②: 署名する⽂字列を作成 • AWS4-HMAC-SHA256: ハッシュアルゴリズムHMAC-SHA256を 使⽤していることを⽰します。 • timeStamp : ISO8601形式の現在のUTC時刻を⼊れます。 • Scope : 結果の署名を特定の⽇付、AWSリージョン、およびサービス名を 連結したものを⼊れます。 結果の署名は、特定の地域および特定のサービスでのみ機能し、 署名は指定された⽇付から7⽇間有効です。

Slide 27

Slide 27 text

n AWS署名バージョン4では、AWSアクセスキーを使⽤してリクエストに署 名する代わりに、最初に特定のリージョンとサービスを対象と する署名キーを作成します。 ③: 署名を計算

Slide 28

Slide 28 text

S3の特定のbucketに対してGetするサンプルコード

Slide 29

Slide 29 text

ここまでがGetの実装 次からは、POSTの実装

Slide 30

Slide 30 text

n S3に対するアップロードの処理で気をつけなければならないのは、アッ プロードするデータの種類を固定させるわけにはいかない n 複合データ型(=multipart)を扱える、multipart/form-dataとい う形式でアップロードしなければならない。 S3に対するPost処理

Slide 31

Slide 31 text

n multipart/form-dataは、複数の種類のデータを⼀度に扱える形式。 n 気をつけなければならないのは、 下記のようにboundaryをコンテンツの境界を⽰す⽂字列として ⼊れてあげなければならない。 multipart/form-dataでの送信

Slide 32

Slide 32 text

あれ・・・ そういえばmultipartでの送信って、 Python3の標準ライブラリで簡単にできるっけ︖

Slide 33

Slide 33 text

n 今回は、Python3の標準ライブラリのみを使⽤して、 s3に対してアップロードしたい。 n 外部ライブラリで有名なrequestsというものがありますが、 こちらを使うと簡単にmultipart/form-data形式の送信ができますが、今 回はurllibで頑張って実装していきます。 ちなみにrequestを使うと、1⾏でできる笑 requests.post(url, data=form, files={"file": file}, verify=verify) ということで・・

Slide 34

Slide 34 text

urllibでmultipart/form-data送信する

Slide 35

Slide 35 text

Postの実装をまとめると あとは、作成したクラスを使⽤しS3に対してmultipart/form-dataで アップロードを実⾏してあげれば完成

Slide 36

Slide 36 text

まとめ PythonでAWSサービスを扱う時可能なら、 boto3を使うべき

Slide 37

Slide 37 text

コード等はQiitaに掲載中