このページの内容は Apigee と Apigee ハイブリッドに該当します。
Apigee Edge のドキュメントを表示する。
このポリシーは、ハッシュベースのメッセージ認証コード(HMAC)を計算し、必要に応じて検証します。HMAC は、SHA-1、SHA-224、SHA-256、SHA-384、SHA-512、MD-5 などの「メッセージ」に適用される暗号ハッシュ関数と秘密鍵を使って、そのメッセージに署名やメッセージ認証コードを生成するものです。鍵付きメッセージ認証コード、鍵付きハッシュなどと呼ばれることもあります。ここでの「メッセージ」という用語は、任意のバイト ストリームを指します。HMAC の一般的な使用例としては、メッセージ送信側がメッセージとその HMAC を受信側に送信します。受信側は、HMAC を共有秘密鍵とともに使用してメッセージを認証できます。
このポリシーは、標準ポリシーであり、任意の環境タイプにデプロイできます。ポリシータイプと各環境タイプで使用可能かどうかは、ポリシータイプをご覧ください。
HMAC の詳細については、HMAC: 鍵付きハッシュ用のメッセージ認証(rfc2104)をご覧ください。
サンプル
HMAC を生成する
<HMAC name='HMAC-1'> <Algorithm>SHA256</Algorithm> <!-- the default encoding of the SecretKey is UTF-8 --> <SecretKey encoding='base64' ref='private.secretkey'/> <IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables> <!-- optional --> <!-- The Message element accepts a template, which means the "message" the policy operates on can include fixed and multiple variable parts, including newlines and static functions. Whitespace, such as newlines and space characters, is significant. --> <Message>Fixed Part {a_variable} {timeFormatUTCMs(timeFormatString1,system.timestamp)} {nonce}</Message> <!-- default encoding is base64 --> <Output encoding='base16'>name_of_variable</Output> </HMAC>
HMAC を検証する
<HMAC name='HMAC-1'> <Algorithm>SHA256</Algorithm> <!-- the default encoding of the SecretKey is UTF-8 --> <SecretKey encoding='base16' ref='private.secretkey'/> <IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables> <!-- optional --> <!-- The Message element accepts a template. This policy verifies an HMAC on the request content. --> <Message>{request.content}</Message> <!-- VerificationValue is optional. Include it to perform an HMAC check. --> <VerificationValue encoding='base16' ref='expected_hmac_value'/> <!-- default encoding of the output is base64 --> <Output encoding='base16'>name_of_variable</Output> </HMAC>
署名の計算とその署名の検証は、同じプロセスで行います。HMAC ポリシーは HMAC を計算し、計算された署名を期待値と照らして任意で検証します。任意で使用可能な VerificationValue
要素(存在する場合)は、計算値を既知の値または指定された値と照合するようポリシーに指示します。
HMAC の要素リファレンス
このポリシー リファレンスでは、HMAC ポリシーの要素と属性について説明します。
最上位の要素に適用される属性
<HMAC name="HMAC" continueOnError="false" enabled="true" async="false">
次の属性は、すべてのポリシーの親要素に共通です。
属性 | 説明 | デフォルト | 要否 |
---|---|---|---|
name |
ポリシーの内部名。名前に使用できる文字は A-Z0-9._\-$ % のみです。ただし、Apigee UI には追加の制限があり、たとえば、英数字以外の文字は自動的に削除されます。必要に応じて、 |
なし | 必須 |
continueOnError |
ポリシーが失敗したときにエラーを返す場合は、false に設定します。これは、ほとんどのポリシーで想定される動作です。ポリシーが失敗した後もフローの実行を続行する場合は、 |
false | 省略可 |
有効 |
ポリシーを適用するには、true に設定します。ポリシーを無効にするには、 |
true | 省略可 |
非同期 | この属性は非推奨となりました。 | false | 非推奨 |
<Algorithm>
<Algorithm>algorithm-name</Algorithm>
HMAC の計算に使用するハッシュ アルゴリズムを指定します。
デフォルト | 該当なし |
要否 | 必須 |
型 | 文字列 |
有効な値 | SHA-1 、SHA-224 、SHA-256 、SHA-384 、SHA-512 、MD-5
ポリシー構成で受け入れられるアルゴリズム名では、大文字小文字の区別や、文字と数字の間にダッシュがあるかないかの区別はありません。たとえば、 |
<DisplayName>
<DisplayName>Policy Display Name</DisplayName>
name 属性に加えて、Apigee UI プロキシ エディタでポリシーを別の自然言語名でラベル付けするために使用します。
デフォルト | この要素を省略した場合、ポリシーの name 属性の値が使用されます。 |
要否 | 省略可 |
型 | 文字列 |
<Message>
<Message>message_template_here</Message> or <Message ref='variable_here'/>
署名するメッセージ ペイロードを指定します。この要素の入力では、メッセージ テンプレート(変数置換)がサポートされているため、タイムスタンプ、ノンス、ヘッダーのリストなど、追加の項目を実行時に含めることができます。次に例を示します。
<Message>Fixed Part {a_variable} {timeFormatUTCMs(timeFormatString1,system.timestamp)} {nonce} </Message>
メッセージ テンプレートには、改行や静的関数など、固定部と変数部を含めることができます。改行やスペース文字などの空白文字は有効な文字と判断されます。
デフォルト | 該当なし |
要否 | 必須 |
型 | 文字列 |
有効な値 | テキスト値には任意の文字列を使用できます。ref 属性を指定すると、テキスト値よりも優先されます。このポリシーは、テキスト値または参照先の変数をメッセージ テンプレートとして評価します。 |
<Output>
<Output encoding='encoding_name'>variable_name</Output>
ポリシーが計算済みの HMAC 値を使用して設定する必要がある変数の名前を指定します。また、出力に使用するエンコードを指定します。
デフォルト |
デフォルトの出力変数は |
要否 | 省略可。この要素が存在しない場合、ポリシーは base64 でエンコードされた値を使用してフロー変数 hmac.POLICYNAME.output を設定します。 |
型 | 文字列 |
有効な値 | エンコードの場合、 値の大文字と小文字は区別されません。
|
<SecretKey>
<SecretKey encoding='encoding_name' ref='private.secretkey'/>
HMAC の計算に使用する秘密鍵を指定します。この鍵は参照先の変数から取得され、特定のエンコードに従ってデコードされます。
デフォルト |
参照先の変数にデフォルト値はありません。
|
要否 | 必須 |
型 | 文字列 |
有効な値 |
エンコード属性を使用すると、UTF-8 の印刷可能な文字の範囲外のバイト数を含む鍵を指定できます。たとえば、次のような構成をポリシー構成に含めるとします。 <SecretKey encoding='hex' ref='private.encodedsecretkey'/>
また、
この場合、鍵のバイト数は [53 65 63 72 65 74 31 32 33] のようにデコードされます(各バイト数は 16 進数で表されます)。別の例として、 |
<VerificationValue>
<VerificationValue encoding='encoding_name' ref='variable_name'/> or <VerificationValue encoding='encoding_name'>string_value</VerificationValue>
(省略可)検証値と、検証値のエンコードに使用されたエンコードを指定します。ポリシーはこのエンコードを使用して値をデコードします。
デフォルト | デフォルトの検証値はありません。要素が存在しても encoding 属性が存在しない場合、ポリシーはデフォルトのエンコード base64 を使用します。 |
要否 | 省略可 |
型 | 文字列 |
有効な値 |
エンコード属性の有効な値は、
|
<IgnoreUnresolvedVariables>
<IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables>
false
に設定すると、ポリシーで指定された参照先の変数を解決できない場合にエラーを返します。true
に設定すると、解決できない変数を空の文字列(null)として扱います。
IgnoreUnresolvedVariables ブール値は、メッセージ テンプレートで参照される変数にのみ影響します。SecretKey
と VerificationValue
は変数を参照できますが、両方とも解決可能である必要があるため、ignore
設定はそれらには適用されません。
デフォルト | false |
要否 | 省略可 |
型 | ブール値 |
有効な値 | true または false |
フロー変数
ポリシーは実行時にこれらの変数を設定できます。
変数 | 説明 | 例 |
---|---|---|
hmac.policy_name.message |
ポリシーは、有効なメッセージ(Message 要素で指定されたメッセージ テンプレートの評価結果)を使用して、この変数を設定します。 |
hmac.HMAC-Policy.message = "Hello, World" |
hmac.policy_name.output |
Output 要素が変数名を指定していない場合に、HMAC 計算の結果を取得します。 |
hmac.HMAC-Policy.output = /yyRjydfP+fBHTwXFgc5AZhLAg2kwCri+e35girrGw4= |
hmac.policy_name.outputencoding |
出力エンコード名を取得します。 | hmac.HMAC-Policy.outputencoding = base64 |
一般的な問題
あるレベルでは、HMAC ポリシーはとても単純に見えます。鍵とメッセージを指定し、計算された HMAC を取得するだけです。しかし、このポリシーで既知のメッセージと鍵の組み合わせを使って取得した HMAC が予期した値と異なる場合は、ストレスを感じるかもしれません。このセクションでは、このような問題に対処するための使用上の注意をいくつか説明します。
検証中に HMAC の不一致を生じさせる一般的な落とし穴は 2 つあります。それは、メッセージ内の空白文字の違いと、エンコードとデコードの違いです。後者は、SecretKey
要素と Output
要素の両方に当てはまります。
空白文字の違い
出力 HMAC 値は、人間が些細に感じるような違いの影響を受けます。たとえば、「Secret123」として表すことができる秘密鍵があるとします。UTF-8 デコードの場合、キーバイトは [53 65 63 72 65 74 31 32 33]
になります。このキーを使用してメッセージ abc
に対する HMAC-SHA256 を計算すると、a7938720fe5749d31076e6961360364c0cd271443f1b580779932c244293bc94
になります。メッセージにスペースを 1 つ追加して abc<SPACE>
にする(<SPACE>
は ASCII 32 を意味します)と、HMAC-SHA256 は 274669b2a85d2532da48e2ce3d8e52ee17346d1bcd1a606d87db1934b5ab294b
になります。
同様に、メッセージを abc<NEWLINE>
にする(<NEWLINE>
は ASCII 10 を意味します)と、HMAC は 0780370844ca07f896066837e8230d3b6a775f678a4ae03e6b5e864c674831f5
になります。メッセージを少し変えただけで、HMAC 値は大きく変化します。これは仕様です。これは HMAC に意図された望ましい動作です。
重要なポイント: 元の HMAC の計算に使用するメッセージ本文と、HMAC の検証に使用されたメッセージ本文が完全に同じになるようにすることが重要です。HMAC の検証ツールが空白文字を追加するかテキストを再フォーマットして、なんらかの方法でメッセージ ペイロードを変更すると、計算された HMAC が変更されます。
ポリシー構成でメッセージ テンプレートを使用する場合は特に注意してください。たとえば、次のポリシー構成フラグメントは問題となる可能性があります。
<HMAC name='HMAC-1'> ... <!-- the result of this message template will include surrounding whitespace --> <Message> {request.content} </Message> ... </HMAC>
<Message>
要素内のこのメッセージ テンプレートの評価結果には、メッセージのコンテンツを囲む改行とスペースが含まれます。これはおそらく、意図されたものではありません。次のような構成の方が適切です。
<HMAC name='HMAC-1'> ... <Message>{request.content}</Message> ... </HMAC>
エンコードの違い
鍵のマテリアルが同じ場合でも異なるデコードが行われると、異なる鍵が生成されます。「U2VjcmV0S2V5MTIz」として表すことができる秘密鍵があるとします。UTF-8 デコードの場合、base16 で表現されるキーバイトは [55 32 56 6a 63 6d 56 30 53 32 56 35 4d 54 49 7a]
になります。base64 デコードでは、キーバイトは [53 65 63 72 65 74 4b 65 79 31 32 33]
になります。ソース マテリアルのデコードが異なると、異なる鍵になり、異なる HMAC 値が生成されます。
重要なポイント: 元の HMAC の計算に使用する鍵のマテリアルと、HMAC の検証に使用する鍵が完全に同じであることを保証することが重要です。これはおそらく、両端で同じキーエンコードを確実に使用することを意味します。HMAC ポリシーでは、SecretKey
要素の encoding
属性を使用してキーエンコードを指定できます。
出力のエンコードについても考えましょう。base16 または hex エンコードで 27f17e11c8ece93844c5eb5e55161d993368628a214f9a51c25d0185e8ea06e2
と表現される HMAC-SHA256 と、base64 エンコード形式で J/F+Ecjs6ThExeteVRYdmTNoYoohT5pRwl0BhejqBuI=
と表現される HMAC-SHA256 は同じです。この 2 つの文字列は異なっているように見えますが、同じ値を表します。最初に計算された HMAC と検証対象の HMAC で、同じエンコードを確実に使用してください。HMAC ポリシーでは、Output
要素の encoding
属性を使用して目的の出力エンコードを指定したり、VerificationValue
要素にある同じ属性を使用して検証ツールのデコード方法を指定したりできます。
エラー リファレンス
このセクションでは、このポリシーによってエラーがトリガーされたときに返される障害コードとエラー メッセージ、Apigee によって設定される障害変数について説明します。これは、障害に対処する障害ルールを作成するうえで重要な情報です。詳細については、ポリシーエラーについて知っておくべきことと障害の処理をご覧ください。
ランタイム エラー
このエラーは、ポリシーの実行時に発生することがあります。
障害コード | HTTP ステータス | 発生条件 |
---|---|---|
steps.hmac.UnresolvedVariable |
401 | このエラーは、HMAC ポリシーで指定された変数が次のいずれかの場合に発生します。
|
steps.hmac.HmacVerificationFailed |
401 | HMAC 検証が失敗しました。指定された検証値が計算値と一致しません。 |
steps.hmac.HmacCalculationFailed |
401 | ポリシーで HMAC を計算できませんでした。 |
steps.hmac.EmptySecretKey |
401 | 秘密鍵の変数の値が空白です。 |
steps.hmac.EmptyVerificationValue |
401 | 検証値を格納する変数が空です。 |
デプロイエラー
以下のエラーは、このポリシーを含むプロキシをデプロイするときに発生することがあります。
エラー名 | HTTP ステータス | 発生条件 |
---|---|---|
steps.hmac.MissingConfigurationElement |
401 | このエラーは、必要な要素または属性が不足している場合に発生します。 |
steps.hmac.InvalidValueForElement |
401 | このエラーは、Algorithm 要素に指定された値が SHA-1 、SHA-224 、SHA-256 、SHA-512 、MD-5 のいずれでもない場合に発生します。 |
steps.hmac.InvalidSecretInConfig |
401 | このエラーは、SecretKey にテキスト値が明示的に指定されている場合に発生します。 |
steps.hmac.InvalidVariableName |
401 | このエラーは、SecretKey 変数に private 接頭辞(private. )が含まれていない場合に発生します。 |
障害変数
ランタイム エラーが発生すると、次の変数が設定されます。詳細については、ポリシーエラーについて知っておくべきことをご覧ください。
変数 | 説明 | 例 |
---|---|---|
fault.name="fault_name" |
fault_name は、上記のランタイム エラーの表に記載されている障害の名前です。障害名は、障害コードの最後の部分です。 | fault.name Matches "UnresolvedVariable" |
hmac.policy_name.failed |
障害が発生した場合、ポリシーによってこの変数が設定されます。 | hmac.HMAC-Policy.failed = true |
エラー レスポンスの例
ベスト プラクティスとして、エラー処理でエラー レスポンスの errorcode
の部分をトラップすることをおすすめします。faultstring
のテキストには依存しないでください。この部分は変更される可能性があります。
障害ルールの例
<FaultRules> <FaultRule name="HMAC Policy Errors"> <Step> <Name>AM-Unauthorized</Name> <Condition>(fault.name Matches "HmacVerificationFailed")</Condition> </Step> <Condition>hmac.HMAC-1.failed = true</Condition> </FaultRule> </FaultRules>