tech.guitarrapc.cóm

C#, PowerShell, Unity, Cloud, Serverless Technical Update and Features

Azure Functions の API Key を扱ってみる

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

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

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

f:id:guitarrapc_tech:20160422022100p:plain

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

目次

API Key認証の例

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

AWS

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

f:id:guitarrapc_tech:20160422022558p:plain

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

Azure Functions

翻って Azure Functions です。

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

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

Function 種類 Function Url フォーマット Github Secret サンプル
Empty なし なし f:id:guitarrapc_tech:20160422023705p:plain
Http Trigger https://{function app name}.azurewebsites.net/api/{function name}?code={api key} なし f:id:guitarrapc_tech:20160422023740p:plain
Generic Webhook https://{function app name}.azurewebsites.net/api/{function name}?code={api key} なし f:id:guitarrapc_tech:20160422022750p:plain
Github Webhook `https://{function app name}.azurewebsites.net/api/{function name} {api key} f:id:guitarrapc_tech:20160422022803p:plain

API Key の詳細

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

azure.microsoft.com

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 を見てみましょう。

f:id:guitarrapc_tech:20160422030028p:plain

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

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

f:id:guitarrapc_tech:20160422030107p:plain

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

HTTP Request のプロパティです。

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

HTTP Response のプロパティです。

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

API Key の保存場所

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

Kudu で見てみましょう。

f:id:guitarrapc_tech:20160422033431p:plain

host.json

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

f:id:guitarrapc_tech:20160422033534p:plain

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

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

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

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

Functionごとの鍵

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

f:id:guitarrapc_tech:20160422034200p:plain

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

またこの鍵は、Functionを作成した時の Function Url で、クエリストリングに埋め込まれています。

f:id:guitarrapc_tech:20160422034555p:plain

トリガーによる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.jsonauthLevelanonymous にすることで API Key がなくても問題なくできます。

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

gist.github.com

Webhook トリガー

HTTP Request は、API Key をクエリストリングで含んでいる必要があります。

クエリストリングにAPI Key がなかったり、間違っていると BadRequest が返ります。

gist.github.com

gist.github.com

f:id:guitarrapc_tech:20160422034923p:plain

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

gist.github.com

f:id:guitarrapc_tech:20160422035425p:plain

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

gist.github.com

f:id:guitarrapc_tech:20160422040728p:plain

HTTP トリガー

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

authLevel が省略 or function

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

クエリストリングにAPI Key がなかったり、間違っているとUnauthorized が返ります。

gist.github.com

gist.github.com

f:id:guitarrapc_tech:20160422035250p:plain

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

gist.github.com

f:id:guitarrapc_tech:20160422035515p:plain

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

gist.github.com

f:id:guitarrapc_tech:20160422040924p:plain

authLevelanonymous

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

gist.github.com

f:id:guitarrapc_tech:20160422041245p:plain

authLeveladmin

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

gist.github.com

f:id:guitarrapc_tech:20160422041537p:plain

鍵の変更

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

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

変更前 :

f:id:guitarrapc_tech:20160422041641p:plain

変更後 :

f:id:guitarrapc_tech:20160422041723p:plain

変更が確認できましたね

f:id:guitarrapc_tech:20160422041801p:plain

gist.github.com

f:id:guitarrapc_tech:20160422041953p:plain

まとめ

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

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

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

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

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