このページは 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 に設定します。ポリシーを「turn off」するには、 |
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 要素にある同じ属性を使用して検証ツールのデコード方法を指定したりできます。
Error reference
This section describes the fault codes and error messages that are returned and fault variables that are set by Apigee when this policy triggers an error. This information is important to know if you are developing fault rules to handle faults. To learn more, see What you need to know about policy errors and Handling faults.
Runtime errors
These errors can occur when the policy executes.
| Fault code | HTTP status | Occurs when |
|---|---|---|
steps.hmac.UnresolvedVariable |
401 | This error occurs if a variable specified in the HMAC policy is either:
|
steps.hmac.HmacVerificationFailed |
401 | The HMAC verification failed; the verification value provided does not match the calculated value. |
steps.hmac.HmacCalculationFailed |
401 | The policy was unable to calculate the HMAC. |
steps.hmac.EmptySecretKey |
401 | The value of the secret key variable is empty. |
steps.hmac.EmptyVerificationValue |
401 | The variable holding the verification value is emtpy. |
Deployment errors
These errors can occur when you deploy a proxy containing this policy.
| Error name | HTTP status | Occurs when |
|---|---|---|
steps.hmac.MissingConfigurationElement |
401 | This error occurs when a required element or attribute is missing. |
steps.hmac.InvalidValueForElement |
401 | This error occurs if the value specified in the Algorithm element is not
one of the following values: SHA-1, SHA-224, SHA-256,
SHA-512, or MD-5. |
steps.hmac.InvalidSecretInConfig |
401 | This error occurs if there is a text value explicitly provided for SecretKey. |
steps.hmac.InvalidVariableName |
401 | This error occurs if the SecretKey variable does not contain the
private prefix (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>