AWS の API を理解しよう !
上級編 ~新しい発見があるかも ? いろんな機能をご紹介 !
Author : 杉本 圭太
こんにちは!テクニカルトレーナーの杉本圭太です!
最近読んで面白かった漫画は「ビンテイジ」「アフターゴッド」「フールナイト」です。
AWS の API に関する記事を「API を理解する 初級編」「リクエスト署名 や CLI / SDK の仕組みを知る 中級編」と公開してきましたが、連載の最後に “上級編” と題して AWS の API を利用する時に役立つ知識や機能をご紹介していきます !
最後にはこの連載の恒例である、AWS の API に関するクイズも用意していますのでお楽しみに ( ・∀・)=b
ぜひタイトルを見て興味あると感じた部分だけでも良いので読んでみてください !
このシリーズ記事のその他の記事はこちら
- 選択
- 初級編 ~ API の仕組みと利用方法を理解しよう
- 中級編 ~ リクエストの署名や CLI/SDK の中身を覗いてみる
- 上級編 ~ 新しい発見があるかも ? いろんな機能をご紹介 !
エンドポイント Deep Dive
初級編で AWS の API を利用するときの サービスエンドポイント一覧 を紹介しましたが、このエンドポイントに関する知識をより深めてみましょう。
エンドポイントの IP アドレス
サービスエンドポイント一覧は ec2.ap-northeast-1.amazonaws.com のようなドメイン名が記載されていましたが、インターネットでの通信にはグローバル IP アドレスが必要ですので、サービスエンドポイントにもグローバル IP アドレスが割り当てられています。
実はこの AWS の IP アドレスの範囲は JSON 形式で公開 されています。ファイアウォールで通信を許可する IP アドレスの指定が必要な企業などのネットワークから AWS を利用する場合、これを知っていると役に立ちますね !
取得方法は ip-ranges.json にアクセスするだけです。この中身は「AWS が利用している IP アドレスの範囲」「どのリージョンで利用されているか」「(一部ですが) どのサービスで利用されているか」が記載されています。さらに ip-ranges.json から必要な部分を フィルタリングするコマンドのサンプル がドキュメントに載っていますので、特定の AWS リージョンにだけアクセスを許可するファイアウォールを設定したい場合などに便利です。
この IP アドレスの範囲は変更されることもありますが、AWS が用意した SNS トピックにサブスクライブすることで変更通知が受け取れる ようになっています。IP アドレスに更新があると設定変更を自動化させることも可能です ((φ(・д・。)
そして ip-ranges.json には IPv4 だけではなく IPv6 の範囲も記載されています。IPv6 をサポートする AWS サービス に一覧があり、デュアルスタック (IPv4 と IPv6) や IPv6 のみのサポートかどうかなどを確認できます。
AWS で IPv6 を利用した設計のベストプラクティスに関するホワイトペーパー もありますので、興味ある方はこちらもご覧ください !
FIPS エンドポイント
AWS のサービスエンドポイントの中には FIPS エンドポイントというものがあるを知っていますか ? サービスエンドポイントの一覧に <service-code>-fips.<region-code>.amazonaws.com という形式のドメイン名があるのを発見して気になっていた方もいるのではないでしょうか。
ここでの FIPS とは 連邦情報処理標準 (FIPS) 140-2 のことであり、簡単にまとめると「機密情報を保護する暗号化モジュールのセキュリティ要件を規定する米国およびカナダ政府の規格」です。そしてこの FIPS エンドポイントは米国政府とやり取りをする企業で必要とされる場合があり、一部の AWS のサービスが一部のリージョンで利用できます。
FIPS エンドポイントに API をリクエストする方法は AWS CLI や SDK であれば用意されたエンドポイントの指定方法を使用することで可能です。AWS CLI では以下のように --endpoint オプションを使用することで、リージョンとサービス名によって決められるデフォルトのサービスエンドポイントではなく指定のエンドポイントへリクエストできます。
▼ FIPS エンドポイントを利用して AWS Key Management Service (AWS KMS) の API を利用するコマンドの例
aws kms create-key --endpoint-url https://kms-fips.us-west-2.amazonaws.com
このエンドポイントの指定は FIPS エンドポイントを使用する以外にも使い道がありますので、次で紹介します。
開発時に役立つローカルエンドポイントの指定
ここまではグローバル IP を持つ AWS サービスエンドポイントへのアクセスのことばかり紹介していましたが、エンドポイントを指定して切り替えることで、ローカル端末や開発環境として用意している社内サーバーをエンドポイントにすることも可能です !
どんな時に使うかというと、例えば開発中の段階のコードなどを AWS にデプロイする前に試したいなといった経験はありませんか ? そんな時にツールを利用することで、ローカル端末へ AWS の API リクエストをして動作確認するなどができます。
Amaon DynamoDB では DynamoDB ローカル というツールが提供されていて、好きな端末で DynamoDB を動かせます。もちろん本物ではないので 利用に関する注意事項 もありますが、DynamoDB を利用する時にかかるストレージやデータ転送の料金を気にすることなく DynamoDB と連携するアプリケーションのテスト環境を用意できます !
▼ ポート 8000 で DynamoDB ローカルを起動してアクセスする AWS CLI のコマンド例
aws dynamodb list-tables --endpoint-url http://localhost:8000
他にも LocalStack という AWS のエミュレーターを利用してローカルにエンドポイントを用意し、テストで利用する方法もあります。このツールは AWS SDK for Rust の Developer Guide にあるカスタムエンドポイントのページ や .NET アプリケーション開発のホワイトペーパーのテストツールページ でも言及されています。
それ以外の方法だと AWS Serverless Application Model (SAM) を使用すれば Amazon API Gateway や AWS Lambda をローカルで起動 できるので、さっと利用したいサービスの API のモックを作成してエンドポイントに指定することもできます !
リトライとジッターを伴うバックオフ
AWS に限らず API を利用する時には、リクエストがネットワークやサーバー側の障害などのなんらかの要因で失敗してしまうことを考慮しておく必要があります。リクエストの失敗が一時的な問題であれば再試行 (リトライ) で対応することもありますが、リトライをプログラムなどで組み込む時はどんな条件でリトライするかを考えたり、バグが無いように実装したりなど意外とやっかいですよね。しかし AWS CLI や AWS SDK を利用する場合は リトライ機能が実装 されているため、利用する設定になっていれば必要に応じて自動的にリトライをしてくれます !
ですがこのリトライの実装は単純に一定間隔でアクセスを繰り返しているわけではないことをご存知でしょうか ?
実はリトライを効果的にするため、エクスポネンシャルバックオフやジッター (ランダム化された遅延) を使用した工夫がされているのです ! この概念を知っていると AWS の利用以外でも開発に役立つ知識になりますので、これらの特徴を Exponential Backoff And Jitter のブログ や ジッターを伴うバックオフに関する The Amazon Builders' Library の記事 などから抜粋して紹介します ! 詳細を知りたい場合はリンク先をご確認ください。
バックオフ
まず「バックオフ」というのは、リクエストが失敗した時にリトライする間隔を少し空けることで呼び出されるシステムに負荷を集中させにくくする仕組みです。バックオフを利用しない場合、サーバー側はエラー発生時に受け付けるリクエストが増加することで負荷も増加しやすくなり、クライアント側も失敗するリクエストを何度もリクエストし続けることになるので不要なリソース消費に繋がります。
さらにバックオフの仕組みを工夫して、リトライの回数が増える度にリトライ間隔を徐々に増やして効率的にするパターンを「エクスポネンシャルバックオフ」と呼びます。Lambda の非同期呼び出し でエラーがあった場合も「再試行間隔は、最初の試行後 1 秒から最大 5 分まで指数関数的に増加します。」と書かれている通り、この考え方が採用されています。
しかし一時的な障害が起きているサーバーに対してクライアントが多数いる場合、全てのクライアントがエクスポネンシャルバックオフを行った場合でも増加していくリトライ間隔が同じであれば、結局一定の間隔でサーバーに負荷が集中してしまいやすいという問題も抱えています。この問題を緩和するための一つの方法にジッターの利用があります。
(クリックすると拡大します)
ジッター
リトライで利用する「ジッター」はバックオフにある程度のランダム性を追加して、リトライ間隔を分散させることです。こうすることで多くのクライアントがバックオフを行いながらもサーバー側の負荷を分散させやすくなります。
(クリックすると拡大します)
API のリトライ時だけではなく、複数のクライアントがスケジューリングされた定期的なジョブを実行するような場面にもジッターを利用すると負荷分散に効果的です。
さらにジッターの実装方法にもいくつか種類があることが Exponential Backoff And Jitter のブログ に紹介されているため、記載されている特徴を簡単にまとめてみました。
種類 | 特徴 | 呼び出し回数 (*) | 完了時間 (*) |
Full Jitter | エクスポネンシャルバックオフによりリトライ回数を踏まえて計算されたリトライ間隔に、ランダムな値を掛け合わせる。 | 3 つの中で同率で 1 番少ない | 3 つの中で 1 番長い |
Equal Jitter | ランダムな値を掛け合わせるが、非常に短いリトライ間隔になるのは避けつつリトライ間隔がある程度短くなるようにする。 | 3 つの中で同率で 1 番少ない | 3 つの中で 2 番目に短い |
Decorrlated Jitter | Full Jitter に似ているが、前回のリトライ間隔も利用してランダムな値を算出する。 | 3 つの中で 1 番多い | 3 つの中で 1 番短い |
(*) 多数のクライアントが並列する場合
ブログにはジッターの簡易的な計算式も記載されているので、バックオフを自分で実装する機会があれば参考にしてみてください。
AWS CLI のリトライ
AWS CLI のリトライ には現在以下の 3 つのモードがあり、設定で選択できます。
- レガシー
- 標準 (AWS CLI バージョン 2 のデフォルト)
- アダプティブ
これらはリトライ対象のレスポンスやバックオフの時間が異なります。それぞれの設定の特徴にはバックオフに関する記述などがありますが、今回の説明によって少し理解できるようになったのではないでしょうか !
curl コマンドでリクエストの署名ができる --aws-sigv4 オプション
AWS CLI や AWS SDK を利用すると面倒なリクエスト署名のプロセスやリトライを自分で実装せずに AWS の API を利用できますが、逆に言うとこれらのツールを利用すると AWS の API をそのまま利用することはできません。しかし開発中の検証やテストなどで実際の HTTP レスポンスを受け取って確認したいこともありますよね ?
このような場面で AWS の API を直接利用する方法はいくつかありますが、開発でお世話になってる方も多い curl コマンドでは 2021 年 2 月にリリースされた curl 7.75.0 から --aws-sigv4 オプションが利用できるようになり、認証情報をコマンドのパラメーターで渡せば署名バージョン 4 (SigV4) でリクエスト署名をしてリクエストしてくれるようになっています !
--aws-sigv4 オプションの使い方は こちら に記載されていますが、コマンド実行例を乗せてみましたので参考にしてみてください。
▼ 利用する認証情報
- アクセスキー ID : AKIAIOSFODNN7EXAMPLE
- シークレットアクセスキー : wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
▼ --aws-sigv4 オプションを利用した curl コマンドの実行例
# IAM の ListUsers を curl でリクエスト
curl -L "https://iam.amazonaws.com/?Action=ListUsers&Version=2010-05-08" \
--aws-sigv4 "aws:amz:us-east-1:iam" \
--user "AKIAIOSFODNN7EXAMPLE:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
# IAM ロールを利用した一時的な認証情報の場合は X-Amz-Security-Token ヘッダーも必要
curl -L "https://iam.amazonaws.com/?Action=ListUsers&Version=2010-05-08" \
--aws-sigv4 "aws:amz:us-east-1:iam" \
--user "AKIAIOSFODNN7EXAMPLE:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
-H "X-Amz-Security-Token: AQoDYXdzEJr...<remainder of token>"
# profile に認証情報を設定している場合はアクセスキーなどを毎回手動で入力せずにこんな方法も可能
curl -L "https://iam.amazonaws.com/?Action=ListUsers&Version=2010-05-08" \
--aws-sigv4 "aws:amz:us-east-1:iam" \
--user "$(aws configure get aws_access_key_id):$(aws configure get aws_secret_access_key)"
署名付き URL
中級編で紹介したリクエストの署名は認証情報の所有者自身が AWS の API を利用する用途で紹介しましたが、Amazon Simple Storage Service (Amazon S3) には自分以外のユーザーへ認証情報を発行せずに期限付きでオブジェクトの取得やアップロードを利用できるようにする「署名付き URL」という機能があります。S3 で署名付き URL を使用することで、URL を知っているユーザーだけに S3 バケットの特定のドキュメントや動画へアクセスさせられるため、料金を支払っている一部のユーザーだけにデータへ配布したい場合などに便利です。
そしてこの S3 の署名付き URL は AWS のリクエストの署名 を利用しているため、仕組みを理解していればどのようにアクセス制御をしているかがわかって面白いですので、その観点を踏まえて見てみましょう !
S3 の署名付き URL 生成
まずは基本から確認します。S3 の署名付き URL 生成に必要なのは以下の 3 つです。
- 認証情報 (IAM ユーザーのアクセスキーや IAM ロールのトークンなど)
- S3 のバケット名とオブジェクトキー
- 有効期限 (利用する認証情報によって設定できる最大有効期限は異なります)
オブジェクトの取得、アップロード それぞれの署名付き URL 生成は AWS CLI や AWS SDK を使用できます。2022 年 1 月にはマネジメントコンソールでオブジェクト取得の署名付き URL を生成できるようにもなりました ! 詳細はドキュメントを確認していただきたいのですが、生成方法の例を記載しておきます。
▼ AWS CLI で署名付き URL 生成をする場合の例
# 有効期限は 3600 秒で、バケット名: EXAMPLE-BUCKET、オブジェクトキー: movie.mp4 の場合
aws s3 presign s3://EXAMPLE-BUCKET/movie.mp4 --expires-in 3600
▼ AWS SDK for Python (Boto3) で署名付き URL 生成をする場合の例
# 有効期限は 3600 秒で、バケット名: DEXAMPLE-BUCKET、オブジェクトキー: movie.mp4 の場合
import boto3
from botocore.config import Config
url = boto3.client('s3', config=Config(signature_version='v4')).generate_presigned_url(
ClientMethod='get_object',
Params={'Bucket': 'EXAMPLE-BUCKET', 'Key': 'movie.mp4'},
ExpiresIn=3600
)
print(url)
ちなみに署名付き URL の生成自体は AWS の API アクションを呼び出している訳ではないため、上記のコマンドやコードの実行時に AWS のサービスエンドポイントへ通信は発生していません。
S3 の署名付き URL の中身
では生成した署名付き URL の中身を見てみましょう。IAM ユーザーか IAM ロールのどちらの認証情報を使うかや、使用する設定で URL のパラメーターは異なりますが、今回は IAM ユーザーの認証情報で SigV4 を利用して URL を生成した場合を例にします。
▼ 署名付き URL 生成に利用した IAM ユーザーの認証情報
- アクセスキー ID : AKIAIOSFODNN7EXAMPLE
- シークレットアクセスキー : wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
▼ 生成された署名付き URL の例
https://s3.ap-northeast-1.amazonaws.com/EXAMPLE-BUCKET/movie.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20221101%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20221101T091530Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
生成された URL を見ると X-Amz-Expires 以外は SigV4 のプロセスに必要な要素とほとんど同じであり、 X-Amz-Credential にはリクエスト署名の生成で使用したアクセスキー ID が入っていることがわかります。つまり署名付き URL を渡して他のユーザーに使用してもらうというのは、URL の生成者自身の認証情報を利用して署名した URL を配布して使用してもらっているということです。第三者へアクセスキー ID を渡していることにもなるので、その認識は持っておきましょう !
そして署名付き URL を利用した場合に対象のオブジェクトへアクセスできるかは、URL 生成に利用した認証情報に紐づく IAM ポリシーにオブジェクトへのアクションが許可されているかで決まります。そのため、他の AWS の API と同じようにアクセスがある度にオブジェクト取得やアップロードなどのアクションが認可されているかを判断しているため、署名付き URL を生成した時に認証情報に紐づくポリシーに許可があるかどうかは URL 使用に関係がありません。
署名付き URL を生成した後に認証情報を無効化したり、オブジェクト取得に必要なポリシーを削除してしまうと URL は期限関係なく利用できなくなるということですね !
Amazon CloudFront の署名付き URL
Amazon CloudFront にも署名付き URL や 署名付き Cookie という機能があるのですが、こちらの署名は 現在推奨されている方法 である 信頼されたキーグループのキーペア を使用します。S3 と同じ「署名付き URL」という名前ですが、S3 の署名付き URL のように IAM ユーザーや IAM ロールの認証情報を利用した署名とはプロセスが異なっています。利用方法はドキュメントをご確認ください。
AWS Cloud Control API
AWS の API はサービスエンドポイントごとに複数のアクションが用意されていて、それぞれでパラメーターやリクエスト・レスポンスの形式は様々です。例えば「AWS のリソースを作成するアクション名はどんな単語から始まるかを思い浮かべてください」と言われたら、あなたは何を思い浮かべますか?
実は RunXXX や CreateXXX などがあり、リソース作成のアクション名だからと言って統一はされていません。他にもリソースの情報を取得するアクション名は GetXXX や DescribeXXX などですし、リソースを削除するアクションの HTTP メソッドもサービスによって異なります。
クエリ API
本題には関係ありませんが Amazon Elastic Compute Cloud (Amazon EC2) や AWS Identity and Access Management (IAM) などいくつかのサービスの API は クエリ API と呼ばれて います。クエリ API は全てのアクションを GET もしくは POST のどちらでも可能な仕様です。非クエリ API 形式のサービスはそれぞれで仕様が決まっており、RESTful API のようにアクションごとに GET / POST / PUT / DELETE メソッドを使い分けるようなサービスもあります。
Cloud Control API (対応サービス追加中)
このように様々な形式の API を共通の形式で利用するために、2021 年 9 月に AWS Cloud Control API がリリースされました。これは既存のサービスごとの API はそのまま利用できるのに加えて、Cloud Control API をサポートしているリソースタイプ では作成、読み取り、更新、削除、および一覧表示 (CRUDL) のための API が CreateResource、GetResource、UpdateResource、DeleteResource、ListResource の共通したアクションで操作できるようになっています。Cloud Control API の全てのアクションは API リファレンス をご覧ください。現在は全ての AWS サービスのリソースがサポートされてはいませんが、AWS サービスやサードパーティのサービスは今後も追加予定とされています。
利用方法は Cloud Control API がリリースされた時の ブログ にわかりやすくまとまっており、冪等性のためのトークン利用や、データソースの中心には CloudFormation Public Registry があることなども記載されていて興味深い内容になっています。
AWS CLI や AWS SDK を利用してる場合は「今すぐこれが役に立つぞ !」という方は少ないかもしれませんが、AWS の API に関する面白い機能なので紹介してみました。
まとめ
トレーニングで紹介するために AWS の API をまとめる記事を 1 つ書こうとして始めたのですが、思っていた以上に伝えたいことがたくさん出てきて 3 部作になりました !
これにて連載は完結ですが、AWS の API はまだまだ奥が深く、どんどんアップデートもされていきますので、もし番外編を書く機会があればまたお会いしましょう ! みなさんも AWS の API の動向をウォッチしてみてください !
クイズ
もしかすると知っていれば役に立つかもしれない、そんな内容のクイズを AWS の API に関する範囲で作ってみました ! 問題の下をスクロールすると正解がありますので、少し考えたり調べたりしてから確認してみてください !
問題
- リクエストの署名を使わない AWS の API は何があるでしょうか ?
- 署名バージョン 2 (SigV2) と SigV4 の違いはどのようなものがあるでしょうか ?
- IAM ポリシーの Action 要素に記載するアクション名と API の Action の名前は同じものが多いのですが、いくつか異なるものもあります。何があるでしょうか ?
↓ (正解はこちら) ↓
正解
- Amazon Cognito の SignUp、ConfirmSignUp、InitiateAuth や AWS Security Token Service の AssumeRoleWithWebIdentity など
- SigV2 の要素に入るアクセスキーは AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE の形式で、SigV4 のような Credential=AKIDEXAMPLE/20150830/us-east-1/iam/aws4_request ではなかったり、サポートされるリージョンやサービス が限定されているなど
AWSAccessKeyId=XXX が URL に含まれている場合は SigV2 を利用してると判断できますね ! - ポリシーの Action に s3:ListBucket と記載した場合、対応する API の Action は S3 の ListObjectsV2、ポリシーでの記載が s3:ListAllMyBuckets に対する API の Action は S3 の ListBuckets など
このシリーズ記事のその他の記事はこちら
- 選択
- 初級編 ~ API の仕組みと利用方法を理解しよう
- 中級編 ~ リクエストの署名や CLI/SDK の中身を覗いてみる
- 上級編 ~ 新しい発見があるかも ? いろんな機能をご紹介 !
筆者プロフィール
杉本 圭太
アマゾン ウェブ サービス ジャパン合同会社
トレーニングサービス本部 テクニカルトレーナー
新しいことを知るのが好きなので、多くの人に「AWS を知るのは面白い ! もっと学んでみよう ! 活用しよう !」と思っていただけるよう工夫しながらテクニカルトレーナーをしています。
最近は面白い漫画が増えすぎていて、時間が足りなくて困っています。
AWS を無料でお試しいただけます