以前、Azure FunctionsへのアクセスにAPIキーを必須にしてみたことがあったが、このAzure Functionsの呼び出しをAPI Managementを経由して行うこともできる。
今回は、Azure API Managementを経由して、APIキーが必要なAzure Functionsを呼び出してみたので、その手順を共有する。
なお、Azure FunctionsへのアクセスにAPIキーを必須にする対応については、以下の記事を参照のこと。
前提条件
下記記事の実装が完了していること。
また、以下の記事のPostmanをインストール済であること。
やってみたこと
作成したサンプルプログラム(Azure Functions側)の内容
作成したサンプルプログラム(Azure Functions側)の構成は以下の通り。

なお、上記の赤枠は、前提条件のプログラムから変更したプログラムである。また、App Service側のソースコードは修正していない。
ハンドラークラスの内容は以下の通りで、権限レベル(authLevel )をANONYMOUSからFUNCTIONに変更している。
package com.example;
import java.util.Optional;
import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
import com.example.model.SearchParam;
import com.example.model.SearchResult;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
public class CallFunctionApiHandler extends FunctionInvoker<SearchParam, SearchResult> {
/**
* HTTP要求に応じて、DemoAzureFunctionクラスのcallFunctionApiメソッドを呼び出し、
* その戻り値をボディに設定したレスポンスを返す.
* @param request リクエストオブジェクト
* @param context コンテキストオブジェクト
* @return レスポンスオブジェクト
*/
@FunctionName("callFunctionApi")
public HttpResponseMessage execute(
@HttpTrigger(name = "request", methods = HttpMethod.POST
, authLevel = AuthorizationLevel.FUNCTION)
HttpRequestMessage<Optional<String>> request,
ExecutionContext context) {
// リクエストオブジェクトからパラメータ値を取得し、検索用パラメータに設定する
ObjectMapper mapper = new ObjectMapper();
String jsonParam = request.getBody().get();
jsonParam = jsonParam.replaceAll("\\[", "").replaceAll("\\]", "");
SearchParam searchParam = new SearchParam();
try {
searchParam = mapper.readValue(jsonParam
, new TypeReference<SearchParam>() {
});
} catch (Exception ex) {
throw new RuntimeException(ex);
}
// handleRequestメソッド内でDemoAzureFunctionクラスのcallFunctionApiメソッドを呼び出し、
// その戻り値をボディに設定したレスポンスを、JSON形式で返す
return request.createResponseBuilder(HttpStatus.OK)
.body(handleRequest(searchParam, context))
.header("Content-Type", "text/json").build();
}
}その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/azure/tree/master/api-management-api-key-functions/demoAzureFunc
また、ソースコードを修正後、Azure上にデプロイする。なお、Azure Functionsにデプロイする過程は、以下の記事の「Azure FunctionsへのSpring Bootを利用したJavaアプリケーションのデプロイ」を参照のこと。
Azure環境でのAzure FunctionsのAPI呼出し
Postmanを利用して、Azure環境でのAzure FunctionsやAPI ManagementのAPIを呼び出した結果は、以下の通り。
1) 以下のように、Headerにx-functions-keyの値を指定しないでAzure環境でのAzure FunctionsのAPIを呼び出すと、401エラーが発生する。

なお、このとき指定するAPIの「https://azurefuncdemoapp.azurewebsites.net」の部分は、Azure Portal上のAzure FunctionsのURLから確認できる。

2) 以下のように、Headerにx-functions-keyの値を指定してAzure環境でのAzure FunctionsのAPIを呼び出すと、正常にレスポンスが返ることが確認できる。

なお、このときのx-functions-keyに指定する値は、以下の画面から確認できる。

3) HeaderにOcp-Apim-Subscription-Keyの値を指定して 、Azure環境でAPI Management経由でAzure FunctionsのAPIを呼び出すと、正常にレスポンスが返ることが確認できる。なお、Ocp-Apim-Subscription-Keyの値については、前提条件の記事と同じ指定をしている。

なお、このときのOcp-Apim-Subscription-Keyの値は、以下の画面の主キーを表示することによって確認できる。

また、指定するAPIの「https://azureapipurinit.azure-api.net/azureFuncDemoApp」の部分は、Azure Portal上のAPI Managementの「Base URL」から確認できる。

さらに、リクエストボディには、Azure FunctionsのAPI呼出時と同じように、paramの値を指定している。

4) Azure環境でAPI Management経由でAzure FunctionsのAPIを呼び出す際、前提条件の記事と同じ指定で正常にレスポンスが返却される背景としては、API Management上に追加した「callFunctionApi」APIで、「set-backend-service」ポリシーが追加されているためである。


なお、「set-backend-service」ポリシーについては、以下のサイトを参照のこと。
https://docs.microsoft.com/ja-jp/azure/api-management/api-management-transformation-policies#SetBackendService
サンプルプログラムの実行結果
修正したサンプルプログラムの実行結果は、以下の通り。
1) Azure App ServiceのURL「https://azureappdemoservice.azurewebsites.net/」とアクセスすると以下の画面が表示されるため、「ファンクション呼び出し」ボタンを押下する。

なお、上記URLは、下記Azure App ServiceのURLから確認できる。

2) callFunctionApi関数が呼び出され、以下の画面に遷移する。その後「戻る」ボタンを押下する。

要点まとめ
- Azure API Managementを経由して、APIキーが必要なAzure Functionsを呼び出すことができる。このとき、API Managementの設定変更は不要である。







