署名付き AWS API リクエストを作成する - AWS Identity and Access Management

署名付き AWS API リクエストを作成する

重要

AWS SDK (「サンプルコードとライブラリ」を参照) または AWS Command Line Interface (AWS CLI) ツールを使用して API リクエストを AWS に送信する場合、SDK および CLI クライアントが指定したアクセスキーを使用してリクエストを認証するため、このセクションをスキップできます。正当な理由がない限り、常に SDK または CLI を使用することをお勧めします。

複数の署名バージョンをサポートするリージョンでは、リクエストに手動で署名する場合、使用する署名バージョンを指定する必要があります。マルチリージョンアクセスポイントにリクエストを送信すると、SDK と CLI は Signature Version 4A の使用に自動的に切り替えます。追加の設定は不要です。

AWS SigV4 署名プロトコルを使用して、AWS API リクエストを署名付きで作成できます。

  1. リクエストの詳しい情報に基づいて正規リクエストを作成します。

  2. 自分の AWS 認証情報を使用して署名を計算します。

  3. 求めた署名を認証ヘッダーとしてリクエストに追加します。

AWS は、このプロセスをレプリケートして署名を検証し、検証結果に応じてアクセスを許可または拒否します。

AWS SigV4 を使用して API リクエストに署名する方法を確認する場合は、「リクエスト署名の例」を参照してください。

以下の図は、SigV4 署名プロセスを示しています。このように、署名に作成する文字列にはさまざまなコンポーネントがあります。

正規リクエスト、署名する文字列、署名キー、および署名の各部分を示す画像。

次の表では、図に示されている関数について説明します。これらの関数のコードを実装する必要があります。詳細については、「AWS SDK のサンプルコード」を参照してください。

機能 説明

Lowercase()

文字列を小文字に変換します。

Hex()

16 進数の小文字エンコード。

SHA256Hash()

セキュアハッシュアルゴリズム (SHA) 暗号化ハッシュ関数。

HMAC-SHA256()

指定した署名キーで SHA256 アルゴリズムを使用して HMAC を計算します。これが最後の署名です。

Trim()

先頭または末尾の空白をすべて削除します。

UriEncode()

すべてのバイトが URI でエンコードされます。UriEncode() は、以下のルールを適用する必要があります。

  • 非予約文字 (「A」-「Z」、「a」-「z」、「0」-「9」、「-」、「.」、「_」および「~」) を除くすべてのバイトが URI でエンコードされます。

  • スペース文字は予約文字であるため、「+」ではなく「%20」としてエンコードする必要があります。

  • URI で エンコードされた各バイトは、「%」とそのバイトの 2 桁の 16 進値で構成されています。

  • 16 進値の文字は大文字である必要があります (例:「%1A」)。

  • オブジェクトキー名以外では、フォワードスラッシュ文字「/」がエンコードされます。例えば、オブジェクトキー名が photos/Jan/sample.jpg の場合、キー名のフォワードスラッシュはエンコードされません。

重要

開発プラットフォームが提供する標準の UriEncode 関数は、実装の違いや基礎となる RFC のあいまいさにより動作しない場合があります。エンコードが確実に機能するように、独自のカスタム UriEncode 関数を作成することをお勧めします。

Java での UriEncode 関数の例については、GitHub ウェブサイトで「Java Utilities」を参照してください。

注記

リクエストに署名するときは、AWS Signature Version 4 または AWS Signature Version 4A のいずれかを使用できます。これら 2 つの大きな違いを決定づけるのは、署名の計算方法です。AWS Signature Version 4A では、署名にはリージョン固有の情報は含まれず、署名の計算には AWS4-ECDSA-P256-SHA256 アルゴリズムが使用されます。

一時的なセキュリティ認証情報でリクエストに署名する

リクエストに署名するために長期的に認証情報を使用する代わりに、AWS Security Token Service (AWS STS) から提供された一時的なセキュリティ認証情報を使用できます。

一時的なセキュリティ認証情報を使用するときは、認証ヘッダーに X-Amz-Security-Token を追加するか、それをクエリ文字列に含めてセッショントークンを保持する必要があります。一部のサービスでは、正規リクエストに X-Amz-Security-Token を追加する必要があります。その他のサービスでは、署名の計算後に、X-Amz-Security-Token を末尾に追加するだけです。特定の要件については、AWS サービスごとのドキュメントを確認してください。

署名手順の概要

正規リクエストを作成する:

リクエストのコンテンツ (ホスト、アクション、ヘッダーなど) を標準的な正規形式に変換します。正規リクエストは、署名文字列を作成するために使用される入力の 1 つです。正規リクエストの作成の詳細については、「AWS API リクエスト署名の要素」を参照してください。

正規リクエストのハッシュを作成する

ペイロードのハッシュを作成する際に使用したのと同じアルゴリズムを使用して、正規リクエストをハッシュ化します。正規リクエストのハッシュは、小文字の 16 進数文字の文字列として表す必要があります。

署名文字列を作成する

正規リクエストに加えてアルゴリズム、リクエスト日、認証情報スコープ、正規リクエストのハッシュなどの追加情報を使用して、署名文字列を作成します。

署名キーを取得する

最初のハッシュ操作のキーとして AWS のシークレットアクセスキーを使用して、リクエスト日、リージョン、およびサービスに対する一連のキー付きハッシュ操作 (HMAC) を実行します。

署名を計算する

取得した署名キーをハッシュキーとして使用して、署名文字列に対してキー付きハッシュ操作 (HMAC) を実行します。

リクエストヘッダーに署名を追加する

算出した署名をリクエストの HTTP ヘッダーまたはクエリ文字列に追加します。

正規リクエストを作成する

正規リクエストを作成するには、次の文字列を改行文字で区切って連結します。これにより、自分で計算する署名と AWS が計算する署名とが必ず一致するようになります。

<HTTPMethod>\n <CanonicalURI>\n <CanonicalQueryString>\n <CanonicalHeaders>\n <SignedHeaders>\n <HashedPayload>
  • HTTPMethod – GETPUTHEADDELETE などの HTTP メソッド。

  • CanonicalUri – 絶対パスコンポーネント URI の URI エンコード版 (ドメイン名の後の / から始まり、文字列の末尾まで、またはクエリ文字列パラメータがある場合は疑問符文字 (?) まで)。絶対パスが空値の場合は、フォワードスラッシュ文字 (/) を使用します。以下の例の URI (/examplebucket/myphoto.jpg) は絶対パスであるため、絶対パス内の / をエンコードしないでください。

    http://s3.amazonaws.com/examplebucket/myphoto.jpg
  • CanonicalQueryString – URI エンコードされたクエリ文字列パラメータ。それぞれの名前と値を個別に URI エンコードします。また、正規クエリ文字列内のパラメータをキー名のアルファベット順にソートする必要があります。ソートはエンコード後に行われます。次のサンプル URI のクエリ文字列は次のとおりです。

    http://s3.amazonaws.com/examplebucket?prefix=somePrefix&marker=someMarker&max-keys=2

    正規クエリ文字列は次のとおりです (この例では、読みやすいように改行が追加されています)。

    UriEncode("marker")+"="+UriEncode("someMarker")+"&"+ UriEncode("max-keys")+"="+UriEncode("20") + "&" + UriEncode("prefix")+"="+UriEncode("somePrefix")

    リクエストがサブリソースをターゲットにしている場合、対応するクエリパラメータ値は空の文字列 ("") になります。例えば、次の URI は examplebucket バケット上の ACL サブリソースを特定してします。

    http://s3.amazonaws.com/examplebucket?acl

    この場合、CanonicalQueryString は以下のようになります。

    UriEncode("acl") + "=" + ""

    URI に ? が含まれていない場合は、リクエストにクエリ文字列が存在しないため、正規クエリ文字列を空の文字列 ("") に設定します。この場合も、改行文字 ("\n") を含める必要があります。

  • CanonicalHeaders – リクエストヘッダーとその値のリスト。個々のヘッダー名と値のペアは改行文字 ("\n") で区切られます。以下は正規ヘッダーの例です。

    Lowercase(<HeaderName1>)+":"+Trim(<value>)+"\n" Lowercase(<HeaderName2>)+":"+Trim(<value>)+"\n" ... Lowercase(<HeaderNameN>)+":"+Trim(<value>)+"\n"

    CanonicalHeaders リストには以下が含まれている必要があります。

    • HTTP host ヘッダー。

    • Content-Type ヘッダーがリクエスト内に存在する場合は、それを CanonicalHeaders リストに追加する必要があります。

    • リクエストに含める予定の x-amz-* ヘッダーも追加する必要があります。例えば、一時的なセキュリティ認証情報を使用している場合は、リクエストに x-amz-security-token を含める必要があります。このヘッダーを CanonicalHeaders リストに追加する必要があります。

    注記

    x-amz-content-sha256 ヘッダーは Amazon S3 AWS リクエストに必要です。これにより、リクエストペイロードのハッシュが指定されます。ペイロードがない場合は、空の文字列のハッシュを指定する必要があります。

    各ヘッダー名は次の条件を満たす必要があります。

    • 小文字が使用されていること。

    • アルファベット順に表示されていること。

    • 後にコロン (:) が指定されていること。

    値については、次の操作を行う必要があります。

    • 先頭または末尾のスペースをすべて削除する。

    • 連続するスペースを 1 つのスペースに変換する。

    • 複数値ヘッダーの値をカンマで区切る。

    • host ヘッダー (HTTP/1.1) または :authority  ヘッダー (HTTP/2)、および任意の x-amz-* ヘッダーを署名に含める必要があります。署名には、content-type のような他の標準ヘッダーを指定することもできます。

    この例で使用されている関数 Lowercase() と Trim() は、前のセクションで説明されています。

    以下は CanonicalHeaders 文字列の例です。ヘッダー名は小文字で、ソートされています。

    host:s3.amazonaws.com x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20130708T220855Z

    注記

    認証署名を計算する目的では、host ヘッダーと任意の x-amz-* ヘッダーだけが必要です。ただし、データの改ざんを防ぐために、すべてのヘッダーを署名計算に含めることを検討する必要があります。

  • SignedHeaders – アルファベット順にソートされ、セミコロンで区切られた小文字のリクエストヘッダー名のリスト。リスト内のリクエストヘッダーは、CanonicalHeaders 文字列に含めたヘッダーと同じです。前の例の場合、SignedHeaders の値は次のようになります。

    host;x-amz-content-sha256;x-amz-date
  • HashedPayload — HTTP リクエスト本文のペイロードをハッシュ関数への入力として使用して作成された文字列。この文字列には小文字の 16 進数文字を使用します。

    Hex(SHA256Hash(<payload>>))

    リクエストにペイロードがない場合は、空の文字列のハッシュを計算します。例えば、GET リクエストを使用してオブジェクトを取得する場合、ペイロードには何もありません。

    Hex(SHA256Hash(""))
    注記

    Amazon S3 の場合、正規リクエストを作成するときにはリテラル文字列 UNSIGNED-PAYLOAD を含め、リクエストを送信するときには x-amz-content-sha256 ヘッダー値と同じ値を設定します。

    Hex(SHA256Hash("UNSIGNED-PAYLOAD"))

正規リクエストのハッシュを作成する

ペイロードのハッシュを作成する際に使用したのと同じアルゴリズムを使用して、正規リクエストのハッシュ (ダイジェスト) を作成します。正規リクエストのハッシュは、小文字の 16 進数文字の文字列として表す必要があります。

署名文字列を作成する

署名文字列を作成するには、以下の文字列を改行文字で区切って連結します。この文字列は改行文字で終わらせないようにしてください。

Algorithm \n RequestDateTime \n CredentialScope \n HashedCanonicalRequest
  • Algorithm — 正規リクエストのハッシュを作成するために使用されるアルゴリズム。SHA-256 では、アルゴリズムは AWS4-HMAC-SHA256 です。

  • RequestDateTime — 認証情報のスコープで使用される日付と時刻。この値は、ISO 8601 形式の現在の UTC 時刻です (例: 20130524T000000Z)。

  • CredentialScope - 認証情報スコープ。つまり、こうして生成した署名を指定されたリージョンとサービスに制限します。文字列の形式は YYYYMMDD/region/service/aws4_request です。

  • HashedCanonicalRequest - 前のステップで計算した正規リクエストのハッシュ。

以下は署名する文字列の例です。

"AWS4-HMAC-SHA256" + "\n" + timeStampISO8601Format + "\n" + <Scope> + "\n" + Hex(SHA256Hash(<CanonicalRequest>))

署名キーを取得する

署名キーを取得するには、最初のハッシュ操作のキーとして AWS のシークレットアクセスキーを使用して、リクエスト日、リージョン、およびサービスに対する一連のキー付きハッシュ操作 (HMAC) を実行します。

各ステップで、必要なキーとデータを使用してハッシュ関数を呼び出します。ハッシュ関数を呼び出すたびに、その結果はハッシュ関数への次の呼び出しの入力になります。

以下の例は、この手順の次のセクションで使用する SigningKey を取得する方法を示しています。入力内容は、この順序で連結されてハッシュ化されます。HMAC-SHA256 は、以下に示すようにデータをハッシュ化する場合に使用されるハッシュ関数です。

DateKey = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>") DateRegionKey = HMAC-SHA256(<DateKey>, "<aws-region>") DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>") SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")
入力必須
  • Key、シークレットアクセスキーが含まれている文字列。

  • Date、認証情報スコープで使用される日付が含まれている YYYYMMDD 形式の文字列。

  • Region、リージョンコードが含まれている文字列 (例えば、us-east-1)。

    リージョン文字列のリストについては、「AWS 全般のリファレンス」の「リージョンとエンドポイント」を参照してください。

  • Service、サービスコードが含まれている文字列 (例えば、ec2)。

  • 上記の手順で作成したトピックを選択します。

署名キーを取得するには
  1. "AWS4" とシークレットアクセスキーを連結します。データとしてのキーおよび日付文字列として、連結した文字列を備えたハッシュ関数を呼び出します。

    DateKey = hash("AWS4" + Key, Date)
  2. データとしてのキーおよびリージョン文字列として、前回の結果を備えたハッシュ関数を呼び出します。

    DateRegionKey = hash(kDate, Region)
  3. データとしてのキーおよびサービス文字列として、前回の結果を備えたハッシュ関数を呼び出します。

    サービスコードは、サービスによって定義されます。AWS Pricing CLI で get-products を使用して、サービスのサービスコードを返すことができます。

    DateRegionServiceKey = hash(kRegion, Service)
  4. データとしてのキーおよび「aws4_request」として、前回の結果を備えたハッシュ関数を呼び出します

    SigningKey = hash(kService, "aws4_request")

署名を計算する

署名キーを取得したら、署名文字列にキー付きハッシュ操作を実行して、署名を計算します。取得した署名キーを、この操作のハッシュキーとして使用します。

署名を計算するには
  1. データとしての署名用キーおよび文字列として、前回の結果を備えたハッシュ関数を呼び出します。その結果、署名はバイナリ値になります。

    signature = hash(SigningKey, string-to-sign)
  2. 署名を 2 進数から 16 進数表現に、小文字に変換します。

リクエストヘッダーに署名を追加する

算出した署名をリクエストに追加します。

例: 認証ヘッダー

以下の例は、DescribeInstances アクションに対する Authorization ヘッダーを示しています。読みやすいように、この例では改行でフォーマットされています。コードでは、これは連続した文字列である必要があります。アルゴリズムと Credential の間にカンマはありません。ただし、他の要素はカンマで区切られている必要があります。

Authorization: AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request, SignedHeaders=host;x-amz-date, Signature=calculated-signature
例: クエリ文字列に認証パラメータを含むリクエスト

次の例は、認証情報を含む DescribeInstances アクションのクエリを示しています。読みやすいように、この例は改行でフォーマットされており、URL はエンコードされていません。コードでは、クエリ文字列は URL エンコードされた連続した文字列である必要があります。

https://ec2.amazonaws.com/? Action=DescribeInstances& Version=2016-11-15& X-Amz-Algorithm=AWS4-HMAC-SHA256& X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request& X-Amz-Date=20220830T123600Z& X-Amz-SignedHeaders=host;x-amz-date& X-Amz-Signature=calculated-signature