以下の内容はhttps://tech.guitarrapc.com/entry/2016/04/22/042331より取得しました。


Azure FunctionsのAPI Keyを扱ってみる

Azure Functionsを使っていて気になるのが認証制御です。

AWS API Gateway + Lamdbaでは、任意のTokenをつけることができました。それではAzure Functionsはどうでしょうか?

App Service Authentication/Authorizationのような、アカウント連携はあまりに重厚でしょう。単純にAPI Keyで済ませたいものです。

そこで今回はAzure FunctionsでAPI Keyを使った認証について見てみましょう。

API Key認証の例

API Key認証といってもどんなものでしょうか。

AWS

たとえばAPI GatewayではAPI Keysとしてトークンを発行できます。

このトークンを任意のAPIで有効化することで、APIごとに認証トークンがヘッダにないとアクセスできないようにできます。

Azure Functions

翻ってAzure Functionsです。

Azure Functionsを触っていて気づくのが、GitHub WebhookだけURL が違い/GitHub Secretを持つということです。

なんともわかりやすいでしょう。

Function 種類 Function Url フォーマット GitHub Secret サンプル
Empty なし なし
Http Trigger https://{function app name}.azurewebsites.net/api/{function name}?code={api key} なし
Generic Webhook https://{function app name}.azurewebsites.net/api/{function name}?code={api key} なし
GitHub Webhook https://{function app name}.azurewebsites.net/api/{function name} `https://{function app name}.azurewebsites.net/api/{function name}

API Key の詳細

ここ最近アップデートされたドキュメントに概要が説明されています。

https://azure.microsoft.com/en-us/documentation/articles/functions-triggers-bindings/#webhook-triggers

You can use an HTTP or WebHook trigger to call a function in response to an HTTP request. The request must include an API key, which is currently only available in the Azure portal UI.

基本的にはHTTP、WebHookトリガーのいずれもリクエストにAPI Keyを含む必要があります。

さてAPI Keyなどの認証については、Functionの設定に依ります。すなわちFunctionがHTTP TriggerなのかWebhookなのかということです。

Integrateタブからfunction.jsonを見てみましょう。

Advanced Editorから詳細のjsonを操作できます。例えばGenericWebhookなら次のとおりです。

{
  "bindings": [
    {
      "webHookType": "genericJson",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ],
  "disabled": false
}

プロパティのの説明は、ドキュメントにあるとおりです。

HTTP Requestのプロパティです。

プロパティ Webhookトリガーの場合 HTTPトリガーの場合
name Function コード内でリクエストオブジェクトを示す変数名として利用されます。*1
resにしたならコードでもresとして受けるということです。
同左
type 必ずhttpTriggerとします。 同左
direction 必ずinとします。 同左
webHookType 正当な入力値はgithub, github, githubのいずれかです。 WebHook ではないのでこのプロパティを空文字githubとします。
authLevel Webhookトリガーの場合無視され適用されません。 API Keyについて制御できます。
functionとすることでAPI Keyを必須とできます。
functionとすることで API Keyを無視します。
functionとすることで、master API Key を必須とします。

HTTP Responseのプロパティです。

プロパティ 説明
name レスポンスオブジェクトを示す変数名です。
reqにしたならコードでもreqで返す必要があります。
type 必ずhttpとします。
direction 必ずoutとします。

API Key の保存場所

API Keyは、D:\home\data\Functions\secretsに保存されています。

Kuduで見てみましょう。

host.json

最も大事な master key は、host.jsonに書かれています。

host.jsonに書かれた2つのキーを説明します。

キー 説明
masterkey FunctionApp 内の全てのFunctionで利用できます。無効のFunctionもトリガー実行できません。
function.json でauthLevelauthLevelにすることで必須にできます。
functionkey FunctionApp 内の全てのFunctionで利用できます。無効のFunctionはトリガー実行できません。

しかしこのhost.jsonの鍵は権限が強すぎます。Wehookのプロバイダと共有なんてもっての他です。

もっと対象のFunctionだけに働きかけられる鍵はないでしょうか。

Functionごとの鍵

実際の利用を考えた場合、host.jsonではなく、各ファンクションを作った際に自動的に生成される<Function名>.jsonの鍵を使いましょう。例えば<Function名>.jsonというFunctionを作成したら<Function名>.jsonがその鍵をもつファイルです。

この鍵のkeyプロパティの値が、対象Functionを叩くためのAPI Keyです。

またこの鍵は、Functionを作成した時のFunction Urlで、クエリ文字列に埋め込まれています。

トリガーによるAPI Key 必須選択と渡し方

ドキュメントにある通りです。WehookトリガーではAPI Keyは必須です。HTTPトリガーでは選択可能です。

To trigger a WebHook function the HTTP request must include an API key. For non-WebHook HTTP triggers, this requirement is optional.

API Key の埋め込み方

API Keyは2つの埋め込み方があります。

  1. codeという名前で、クエリ文字列に含める
  2. x-functions-keyという、HTTPリクエストヘッダに埋める*2

もちろんHTTPトリガーに関しては、function.jsonfunction.jsonanonymous にすることでAPI Keyがなくても問題なくできます。

簡単なメソッドで検証してみましょう。1つはクエリ文字列でキーを渡します。もう1つはx-functions-keyヘッダで渡します。

https://gist.github.com/guitarrapc/39ddc7900c7f9846e9a294ce75a2c737

Webhook トリガー

HTTP Requestは、API Key をクエリ文字列で含んでいる必要があります。

クエリ文字列にAPI Keyがなかったり、間違っているとBadRequestが返ります。

https://gist.github.com/guitarrapc/68c967dde2cbd9c4485dc33c55d82f72

https://gist.github.com/guitarrapc/c13356698604134d4f9b28e984037481

正しいAPI Keyを含めると、jsonが判定されて応答が返ってきます。

https://gist.github.com/guitarrapc/ebd1994b7255eef984e574295826a682

また、ヘッダにx-functions-keyでキーを渡してもダメなのが特徴的です。

https://gist.github.com/guitarrapc/b620244f99c4816c728a801a58a26286

HTTP トリガー

API Keyはオプショナルです。この指定するのが、先ほどのfunction.jsonのHTTP RequestにあるauthLevelプロパティです。

authLevelが省略 or authLevel

もしfunction.jsonでauthLevelが省略された場合はfunction相当、となるためAPI Keyが必須となります。

クエリ文字列にAPI Keyがなかったり、間違っているとUnauthorizedが返ります。

https://gist.github.com/guitarrapc/e300a491e2584ec823e70da4f5825e8a

https://gist.github.com/guitarrapc/cebdbd8b59130d7a74a131a250f139e8

クエリ文字列に正しいAPI Keyを含めると、jsonが判定されて応答が返ってきます。

https://gist.github.com/guitarrapc/3afa4fcd5f9349b1d8ce3e03151ea664

Webhookと違い、ヘッダにx-functions-keyでキーを渡することでも認証ができます。

https://gist.github.com/guitarrapc/44f9f858b2a61dfb3b60950266aed0df

authLevelauthLevel

匿名認証のためAPI Keyは無視されます。URLさえ正しく叩ければいい状態です。

https://gist.github.com/guitarrapc/d695f39a9852bfeb928ae5a875284fc9

authLevelauthLevel

host.jsonのmasterKey以外の鍵では呼べなくなります。host.jsonのfunctionKeyでも実行できません。

https://gist.github.com/guitarrapc/25003798887556401a5cbdd7b9bfc0ce

鍵の変更

もしAPI Keyを変更したくなったどうしましょうか?

ドキュメントに記述がありませんが、D:\home\data\Functions\secretsの鍵を書き換えれば更新されます。

変更前 :

変更後 :

変更が確認できましたね

https://gist.github.com/guitarrapc/463bcb75fa52b3ec9ac92e7f024800ab

まとめ

これに気づかず、独自ヘッダ認証を組み込んでからドキュメントが発行されました。

Azure functionsで作成するとデフォルトでAPI Keyが必須です。HTTPSであることからも、安全がある程度担保されているので、いい感じに扱えますね。

APIの更新も含めて、うまく使う目処がそろそろ立つのではないでしょうか?

*1:あるいは、Node.js の場合はリクエストボディとして扱われます。

*2:HTTP Triggerでのみ利用可能のようです




以上の内容はhttps://tech.guitarrapc.com/entry/2016/04/22/042331より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14