次の方法で共有


TypeScript Function API を使用して Azure リソース グループを管理する

このチュートリアルでは、API を使用してローカル TypeScript Azure Function アプリを作成し、Azure リソース グループを管理し、アプリを Azure にデプロイします。

特徴と機能:

  • Visual Studio Code でローカルの TypeScript Azure Function アプリ プロジェクトを作成する
  • Visual Studio Code で関数 API 定型コードを作成する
  • Visual Studio Code から Azure Function にデプロイする
  • Azure CLI でサービス プリンシパルを作成する
  • Visual Studio Code を使用してローカルおよびリモートのアプリケーション設定を構成する
  • パスワードなしの接続には、ローカル環境とリモート環境の両方で DefaultAzureCredential を使用します。
  • Azure Identity と Azure Resource Management SDK を使用して Azure リソースを管理します
  • ローカルとクラウドの API を使用して、サブスクリプション内のリソース グループを作成、削除、および一覧表示する

警告

このチュートリアルは迅速な導入を目的としており、"既定でセキュリティ保護" の要件には従っていません。 "既定でセキュリティ保護" という目標を持つこのシナリオの詳細については、「セキュリティに関する考慮事項」を参照してください。

ソース コードは TypeScript で記述されますが、ソース コードは単純です。 async/await を使用する最新の JavaScript に慣れている場合は、このコードには見覚えがあるでしょう。

前提条件

アプリケーションのアーキテクチャ

アプリでは、次の API エンドポイントが提供されます。

メソッド URL 説明
POST、DELETE http://localhost:7071/api/resourcegroup リソースグループを追加または削除します。 追加するときに、後でグループの目的を特定するためにタグ (キーと値のペア) を含めます。
GET http://localhost:7071/api/resourcegroups サブスクリプションに含まれるすべてのリソース グループを一覧表示します。
GET http://localhost:7071/api/resources サブスクリプションやリソース グループ内のすべてのリソースを一覧表示します。

これらのエンドポイントはパブリックですが、実際の環境に展開する前に、API エンドポイントを認証と承認で保護 する必要があります

サービス プリンシパルの作成時に指定されたスコープであるため、このアプリはサブスクリプションに限定されます。

1. 環境を準備する

Azure Identity SDK を使用するには、ローカルとクラウドの環境を準備する必要があります。

Azure CLI へのサインイン

bash ターミナルで、次のコマンドを使用して Azure CLI にサインインします。

az login

Azure サブスクリプション ID を取得する

  1. bash ターミナルでサブスクリプションを取得し、使用するサブスクリプション ID を見つけます。 次のクエリは、サブスクリプション ID、サブスクリプション名、およびテナント ID をサブスクリプション名で並べ替えて返します。

    az account list --query "sort_by([].{Name:name, SubscriptionId:id, TenantId:tenantId}, &Name)" --output table
    
  2. サブスクリプション ID を先ほどの一時ファイルにコピーします。 この設定は後で必要になります。

Azure サービス プリンシパルを作成する

Azure サービス プリンシパルでは、個人のユーザー資格情報を使用することなく Azure へのアクセスが提供されます。 このチュートリアルでは、サービス プリンシパルはローカル環境とクラウド環境の両方で使用できます。 エンタープライズ環境では、環境ごとに個別のサービス プリンシパルが必要になります。

  1. 後でサービス プリンシパル を簡単に見つけられるように、サービス プリンシパル名 の形式を決定します。 たとえば、形式のアイデアとしては次のものがあります。

    • プロジェクトと所有者: resource-management-john-smith
    • 部署と日付: IT-2021-September
  2. bash ターミナルで、 az ad sp create-for-rbac を使用してサービス プリンシパルを作成します。 <SUBSCRIPTION-ID> は、サブスクリプション ID で置き換えてください。

    az ad sp create-for-rbac --name YOUR-SERVICE-PRINCIPAL-NAME --role Contributor --scopes /subscriptions/<SUBSCRIPTION-ID>
    
  3. 出力結果全体を一時ファイルにコピーします。 これらの設定は後で必要になります。

    {
      "appId": "YOUR-SERVICE-PRINCIPAL-ID",
      "displayName": "YOUR-SERVICE-PRINCIPAL-NAME",
      "name": "http://YOUR-SERVICE-PRINCIPAL-NAME",
      "password": "YOUR-SERVICE-PRINCIPAL-PASSWORD",
      "tenant": "YOUR-TENANT-ID"
    }
    

2. Visual Studio Code でローカルの Azure 関数アプリを作成する

Visual Studio Code で Azure 関数アプリを作成して Azure のリソース グループを管理します。

Function App の作成

Visual Studio Code を使用して、ローカルの関数アプリを作成します。

  1. Bash ターミナルで、新しいディレクトリを作成し、変更します。

    mkdir my-function-app && cd my-function-app
    
  2. Bash ターミナルで、Visual Studio Code を開きます。

    code .
    
  3. Visual Studio Code のコマンド パレット Ctrl + Shift + pを開きます。

  4. Azure Functions: create new project」と入力します。 プロンプトに入力するには、次の表を使用します。

    プロンプト Value
    関数プロジェクトを含むフォルダーを選択します デフォルト (現在の) ディレクトリを選択します
    言語を選択する [TypeScript] を選択します。
    TypeScript プログラミング モデルを選択する モデル V4 (プレビュー)を選択します。
    Select a template for your project's first function (プロジェクトの最初の関数のテンプレートを選択してください) [HTTP トリガー] を選択します。
    新しい HTTP トリガーを作成する API 名 resourcegroups を入力します。
    承認レベル [匿名] を選択します。 この記事の後にこのプロジェクトを続行する場合は、承認レベルを関数に変更してください。 関数レベルの認可の詳細を参照してください。

    プロジェクトのボイラープレートが作成され、依存関係がインストールされます。

local.settings.json ファイルにサービス プリンシパル設定を追加する

  1. プロジェクトのルート ディレクトリにある ./local.settings.json ファイルを開き、次の 5 つの環境変数を含む VALUES セクションを追加します。

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "",
        "FUNCTIONS_WORKER_RUNTIME": "node",
        "AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
        "AZURE_CLIENT_ID": "REPLACE-WITH-SERVICE-PRINCIPAL-APPID",
        "AZURE_CLIENT_SECRET": "REPLACE-WITH-SERVICE-PRINCIPAL-PASSWORD",
        "AZURE_SUBSCRIPTION_ID":"REPLACE-WITH-SUBSCRIPTION-ID",
        "AZURE_TENANT_ID":"REPLACE-WITH-SERVICE-PRINCIPAL-TENANT",
        "NODE_ENV":"development"
      }
    }
    
  2. 前のセクションの設定を参照して値を追加します。 これらの環境変数は、 DefaultAzureCredential を使用するためのコンテキストで必要です

    • AZURE_TENANT_ID: 上記のサービス プリンシパルの出力からの tenant
    • AZURE_CLIENT_ID: 上記のサービス プリンシパルの出力からの appId
    • AZURE_CLIENT_SECRET: 上記のサービス プリンシパルの出力からの password
  3. サブスクリプション ID も設定する必要があります。 リソース管理には Azure SDK を使用する必要があります。

    • AZURE_SUBSCRIPTION_ID: リソース グループを含む既定のサブスクリプション。

誤ってソース コードにコミットすることがないように、この local.settings.json ファイルはローカルの git では意図的に無視されます。

Azure ID とリソース管理のための npm 依存関係をインストールする

Visual Studio Code の 統合 bash ターミナルで、Azure ID とリソース管理のための Azure SDK の依存関係をインストールします。

npm install @azure/identity @azure/arm-resources

サブスクリプションに含まれる全リソース グループを JavaScript で一覧表示する

  1. ./src/functions/resourcegroups.ts ファイルを開き、その内容を次のものに置き換えます。

    import { ResourceGroup } from '@azure/arm-resources';
    import {
      app,
      HttpRequest,
      HttpResponseInit,
      InvocationContext
    } from '@azure/functions';
    import {
      createResourceGroup,
      deleteResourceGroup
    } from '../lib/azure-resource-groups';
    import { processError } from '../lib/error';
    
    export async function resourcegroup(
      request: HttpRequest,
      context: InvocationContext
    ): Promise<HttpResponseInit> {
      try {
        console.log(JSON.stringify(request.query));
        console.log(JSON.stringify(request.params));
    
        const name: string = request.query.get('name');
        const location: string = request.query.get('location');
        console.log(`name: ${name}`);
        console.log(`location: ${location}`);
    
        switch (request.method) {
          case 'POST': // wait for create to complete before returning
            if (!name || !location) {
              return { body: 'Missing required parameters.', status: 400 };
            }
    
            if (request.headers.get('content-type') === 'application/json') {
              // create with tags
    
              const body: Record<string, unknown> =
                (await request.json()) as Record<string, string>;
              const tags: Record<string, string> = body?.tags
                ? (body?.tags as Record<string, string>)
                : null;
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                tags
              );
              return { jsonBody: resourceGroup, status: 200 };
            } else {
              // create without tags
    
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                null
              );
              return { jsonBody: resourceGroup, status: 200 };
            }
    
          case 'DELETE': // wait for delete to complete before returning
            if (!name) {
              return { body: 'Missing required parameters.', status: 400 };
            }
            await deleteResourceGroup(name);
            return { status: 204 };
        }
      } catch (err: unknown) {
        return processError(err);
      }
    }
    
    app.http('resourcegroup', {
      methods: ['DELETE', 'POST'],
      authLevel: 'anonymous',
      handler: resourcegroup
    });
    

    このファイルは、 /api/resourcegroups への API リクエストに応答し、サブスクリプション内のすべてのリソース グループのリストを返します。

  2. srclib という名前のサブディレクトリを作成し、そのディレクトリに azure-resource-groups.ts という名前の新しいファイルを作成します。

  3. 次のコードを ./src/lib/azure-resource-groups.ts ファイルにコピーします。

    // Include npm dependencies
    import {
      ResourceGroup, ResourceManagementClient
    } from '@azure/arm-resources';
    import { DefaultAzureCredential } from '@azure/identity';
    import { getSubscriptionId } from './environment-vars';
    
    const subscriptionId = getSubscriptionId();
    
    // Create Azure authentication credentials
    const credentials = new DefaultAzureCredential();
    
    // Create Azure SDK client for Resource Management such as resource groups
    const resourceManagement = new ResourceManagementClient(
      credentials,
      subscriptionId
    );
    
    // all resources groups in subscription
    export const listResourceGroups = async (): Promise<{
      list: ResourceGroup[];
      subscriptionId: string;
    }> => {
      const list: ResourceGroup[] = [];
      for await (const resourceGroup of resourceManagement.resourceGroups.list()) {
        list.push(resourceGroup);
      }
      return {
        subscriptionId,
        list
      };
    };
    export const createResourceGroup = async (
      resourceGroupName: string,
      location: string,
      tags: { [propertyName: string]: string }
    ): Promise<ResourceGroup> => {
      const resourceGroupParameters = {
        location: location,
        tags
      };
    
      return await resourceManagement.resourceGroups.createOrUpdate(
        resourceGroupName,
        resourceGroupParameters
      );
    };
    export const deleteResourceGroup = async (
      resourceGroupName: string
    ): Promise<void> => {
      return await resourceManagement.resourceGroups.beginDeleteAndWait(
        resourceGroupName
      );
    };
    

    このファイルによって、以下が実行されます。

    • サブスクリプション ID を取得します
    • DefaultAzureCredential コンテキストを作成します
    • リソース管理 SDK を使用するために必要な ResourceManagementClient を作成します。
    • サブスクリプション内のすべてのリソース グループを取得します。
  4. ./src/lib ディレクトリに environment-vars.ts という名前の新しいファイルを作成し、そのファイルに次のコードをコピーします。

    export const checkAzureAuth = () => {
      // The following code is only used to check you have environment
      // variables configured. The DefaultAzureCredential reads your
      // environment - it doesn't read these variables.
      const tenantId = process.env['AZURE_TENANT_ID'];
      if (!tenantId)
        throw Error('AZURE_TENANT_ID is missing from environment variables.');
      const clientId = process.env['AZURE_CLIENT_ID'];
      if (!clientId)
        throw Error('AZURE_CLIENT_ID is missing from environment variables.');
      const secret = process.env['AZURE_CLIENT_SECRET'];
      if (!secret)
        throw Error('AZURE_CLIENT_SECRET is missing from environment variables.');
    };
    
    export const getSubscriptionId = (): string => {
      checkAzureAuth();
    
      // Get subscription from environment variables
      const subscriptionId = process.env['AZURE_SUBSCRIPTION_ID'];
      if (!subscriptionId)
        throw Error('Azure Subscription is missing from environment variables.');
      return subscriptionId;
    };
    

    このファイルは、サブスクリプション ID を返す前に環境変数を確認します。

  5. ./src/lib ディレクトリに error.ts という名前の新しいファイルを作成し、そのファイルに次のコードをコピーします。

    export function processError(err: unknown): any {
      if (typeof err === 'string') {
        return { body: err.toUpperCase(), status: 500 };
      } else if (
        err['stack'] &&
        process.env.NODE_ENV.toLowerCase() !== 'production'
      ) {
        return { jsonBody: { stack: err['stack'], message: err['message'] } };
      } else if (err instanceof Error) {
        return { body: err.message, status: 500 };
      } else {
        return { body: JSON.stringify(err) };
      }
    }
    

    このファイルは、エラー メッセージとともに 500 エラーを返します。 NODE_ENV 変数が productionに設定されていない場合、スタックが返されます。

ローカル関数をテストする

  1. Visual Studio Code 統合ターミナルで、ローカル プロジェクトを実行します。

    npm start
    
  2. 実行中の関数の URL が統合 bash ターミナルに表示されるまで待機します。

    Azure 関数がローカルで実行されていて、関数アプリの API のローカル URL が表示されている、Visual Studio Code の統合 bash ターミナルの部分的なスクリーンショット。

  3. Visual Studio Codeで2つ目の統合bashターミナルを開き、 Ctrl + Shift + 5、以下の GET cURLコマンドを使ってAPIを使用します。

    curl http://localhost:7071/api/resourcegroups
    

    サブスクリプションに多数のリソース グループがある場合は、簡単に確認できるように出力をファイルにパイプすることをお勧めします。

    curl http://localhost:7071/api/resourcegroups > resourcegroups.json
    
  4. 応答には、そのサブスクリプション内のすべてのリソース グループの subscriptionIdlist が含まれます。

    {
      "subscriptionId": "ABC123",
      "list": [
            {
              "id": "/subscriptions/ABC123/resourceGroups/vmagelo-cloudshell",
              "name": "jsmith-cloudshell",
              "type": "Microsoft.Resources/resourceGroups",
              "properties": {
                "provisioningState": "Succeeded"
              },
              "location": "westeurope"
            },
            ... REMOVED FOR BREVITY ...
        ]
    }
    

トラブルシューティング

この記事を完了できない場合は、次の表で問題を調べてください。 問題が表に記載されていない場合は、このドキュメント ページでイシューを開いてください。

問題点 解決策
アプリが開始されなかった。 エラーを確認します。 必要な依存関係がインストールされていることを確認してください。
アプリが開始されたが、200 応答を取得できない。 curl コマンドが正しいローカル ルートから要求されていることを確認します。
API によって 200 応答が返されたが、結果が返されなかった。 Azure リソース用の Visual Studio Code 拡張機能を使用して、サブスクリプションにリソース グループがあることを確認します。 リソース グループが表示されなくても、問題ありません。 このチュートリアルでは、サブスクリプション内のリソース グループを作成および削除するための API を追加します。 この API は、ソース コードを Azure に最初にデプロイした後に追加されるため、コードを再デプロイする方法を学習できます。

3. クラウドベースの Azure Function アプリを作成する

  1. Visual Studio Code で、[Azure] アイコンを選択して Azure Explorerを開きます。

  2. + アイコンを選択して、Azure クラウドに新しい Azure Function アプリを作成します。

    Azure Function アプリのアイコンが強調表示された、Visual Studio Code の Azure Explorer のスクリーンショット。

  3. [Azure で関数アプリを作成] を選択します。

  4. 新しい関数アプリに グローバルに一意の名前 を入力します。 名前は、すべての Azure 関数にわたって一意である必要があります。 たとえば、 jsmith-rg-managementのようにします。

  5. ローカル関数アプリの作成時に選択したものと同じ Node.js 18+ LTS ランタイム を選択します。

  6. 米国西部 3など、自分に近い地理的な 場所 を選択します。

  7. リソースが作成されるまで待ちます。 詳細については、 Azure: アクティビティ ログ をご覧ください。

    リソースの作成ステータスを示す Visual Studio Code の Azure アクティビティ ログのスクリーンショット。

4. クラウドベースの Azure Function アプリを構成する

Azure 関数アプリに接続するように Azure アプリ設定を構成する必要があります。 ローカルでは、これらの設定は local.settings.json ファイルにあります。 このプロセスによって、これらの値がクラウド アプリに追加されます。

  1. Visual Studio Code の Azure エクスプローラーの [リソース] セクションで、 関数アプリ を展開し、関数アプリを選択します。

  2. [アプリケーションの設定] を右クリックし、 [Add New Setting]\(新しい設定の追加\)を選択します。

  3. local.settings.json から 4 つの値を追加します (同じ名前と値を正確に使用してください)。

    • AZURE_TENANT_ID: 上記のサービス プリンシパルの出力からの tenant
    • AZURE_CLIENT_ID: 上記のサービス プリンシパルの出力からの appId
    • AZURE_CLIENT_SECRET: 上記のサービス プリンシパルの出力からの password
    • AZURE_SUBSCRIPTION_ID: リソース グループを含む既定のサブスクリプション。
    • AzureWebJobsFeatureFlags:EnableWorkerIndexing

Visual Studio Code の Azure 用エクスプローラーの部分的なスクリーンショット。リモート/クラウド関数のアプリ設定が表示されています。

5. Resource Manager 機能アプリをデプロイする

Visual Studio Code で Azure Function アプリをデプロイして、Azure リソース グループを管理します。

Visual Studio Code 拡張機能を使用してホスティング環境にデプロイする

  1. VS Code で、 local.settings.json ファイルを開いて表示します。 これにより、これらの名前と値をコピーする次の手順が簡単になります。

  2. Azure ロゴを選択して Azure Explorer を開き、 関数 でクラウド アイコンを選択してアプリをデプロイします。

    クラウド展開アイコンが強調表示された Visual Studio Code のローカル ワークスペース領域のスクリーンショット。

    または、 Ctrl + Shift + p を押して コマンド パレット を開き、 deploy to function appと入力して、 Azure Functions: Function App にデプロイ コマンドを実行してデプロイすることもできます。

  3. [関数アプリにデプロイ] を選択します。

  4. 前のセクションで作成した Function App 名を選択します。

  5. デプロイするかどうかを確認するメッセージが表示されたら、 [デプロイ]を選択します。

  6. Azure Functions の VS Code の [出力] パネルに進行状況が表示されます。 デプロイ時には関数アプリケーション全体がデプロイされるため、すべての個別の関数に対する変更が一度にデプロイされます。

ブラウザーを使用して関数アプリが使用可能なことを確認する

  1. 引き続き Visual Studio Code で、 Azure Functions エクスプローラーを使用して、Azure サブスクリプションのノードを展開し、関数アプリのノードを展開し、 [関数 (読み取り専用)] を展開します。 関数名を右クリックし、 [Copy Function Url]\(関数の URL をコピーする\)を選択します。

    Visual Studio Code の Azure 用エクスプローラーの部分的なスクリーンショット。関数の URL をコピーする場所が表示されています。

  2. URL をブラウザに貼り付け、 Enter を押して、クラウド API からリソース グループ リストを要求します。

6. 関数アプリに API を追加し、Azure に再デプロイする

次の API を追加して、Visual Studio Code に Azure Function アプリを再デプロイします。

  • リソース グループを追加および削除する
  • リソース グループまたはサブスクリプション内のリソースを一覧表示します。

チュートリアルのこの時点では、サブスクリプションのリソース グループを一覧表示する 1 つの API を使用してローカル関数アプリを作成し、そのアプリを Azure にデプロイしました。 Azure 開発者として、リソース グループを作成または削除することがプロセス自動化パイプラインの一部として必要になることがあります。

関数アプリのリソースグループ API を作成する

Azure Functions の Visual Studio Code 拡張機能を使用して、TypeScript ファイルを関数アプリに追加し、リソース グループを作成および削除します。

  1. Visual Studio Code のコマンド パレット Ctrl + Shift + pを開きます。

  2. Azure Functions: Create Function」と入力し、Enter キーを押してプロセスを開始します。

  3. 次の表を使用して、 /api/resourcegroup API を作成します。

    プロンプト
    Select a template for your function (関数のテンプレートを選択してください) HTTP トリガー
    Provide a function name (関数名を指定してください) resourcegroup
    承認レベル [匿名] を選択します。 このプロジェクトを続行する場合は、権限レベルを関数に変更してください。 関数レベルの認可の詳細を参照してください。
  4. ./src/functions/resourcegroup.ts を開き、ファイル全体を次のソース コードに置き換えます。

    import { ResourceGroup } from '@azure/arm-resources';
    import {
      app,
      HttpRequest,
      HttpResponseInit,
      InvocationContext
    } from '@azure/functions';
    import {
      createResourceGroup,
      deleteResourceGroup
    } from '../lib/azure-resource-groups';
    import { processError } from '../lib/error';
    
    export async function resourcegroup(
      request: HttpRequest,
      context: InvocationContext
    ): Promise<HttpResponseInit> {
      try {
        console.log(JSON.stringify(request.query));
        console.log(JSON.stringify(request.params));
    
        const name: string = request.query.get('name');
        const location: string = request.query.get('location');
        console.log(`name: ${name}`);
        console.log(`location: ${location}`);
    
        switch (request.method) {
          case 'POST': // wait for create to complete before returning
            if (!name || !location) {
              return { body: 'Missing required parameters.', status: 400 };
            }
    
            if (request.headers.get('content-type') === 'application/json') {
              // create with tags
    
              const body: Record<string, unknown> =
                (await request.json()) as Record<string, string>;
              const tags: Record<string, string> = body?.tags
                ? (body?.tags as Record<string, string>)
                : null;
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                tags
              );
              return { jsonBody: resourceGroup, status: 200 };
            } else {
              // create without tags
    
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                null
              );
              return { jsonBody: resourceGroup, status: 200 };
            }
    
          case 'DELETE': // wait for delete to complete before returning
            if (!name) {
              return { body: 'Missing required parameters.', status: 400 };
            }
            await deleteResourceGroup(name);
            return { status: 204 };
        }
      } catch (err: unknown) {
        return processError(err);
      }
    }
    
    app.http('resourcegroup', {
      methods: ['DELETE', 'POST'],
      authLevel: 'anonymous',
      handler: resourcegroup
    });
    
  5. ./src/lib/azure-resource-groups.ts ファイルには、リソース グループを追加および削除するコードがすでに含まれています。

関数アプリのリソース API を作成する

Azure Functions の Visual Studio Code 拡張機能を使用して、TypeScript ファイルを関数アプリに追加し、リソース グループ内のリソースを一覧表示します。

  1. Visual Studio Code のコマンド パレット Ctrl + Shift + pを開きます。

  2. Azure Functions: Create Function」と入力し、Enter キーを押してプロセスを開始します。

  3. 次の表を使用して、 /api/resources API を作成します。

    プロンプト
    Select a template for your function (関数のテンプレートを選択してください) HTTP トリガー
    Provide a function name (関数名を指定してください) resources
    承認レベル [匿名] を選択します。 このプロジェクトを続行する場合は、権限レベルを関数に変更してください。 関数レベルの認可の詳細を参照してください。
  4. ./src/functions/resources.ts を開き、ファイル全体を次のソース コードに置き換えます。

    import {
      app,
      HttpRequest,
      HttpResponseInit,
      InvocationContext
    } from '@azure/functions';
    import {
      listResourceByResourceGroup, listResourceBySubscription
    } from '../lib/azure-resource';
    import { processError } from '../lib/error';
    
    export async function resources(
      request: HttpRequest,
      context: InvocationContext
    ): Promise<HttpResponseInit> {
      try {
        const resourceGroupName: string = request.query.get('resourceGroupName');
        context.log(`resourceGroupName: '${resourceGroupName}'`);
    
        if (resourceGroupName) {
          const resourcesByName = await listResourceByResourceGroup(
            resourceGroupName
          );
          return { jsonBody: resourcesByName };
        } else {
          const resourcesBySubscription = await listResourceBySubscription();
          return { jsonBody: resourcesBySubscription };
        }
      } catch (err: unknown) {
        return processError(err);
      }
    }
    app.http('resources', {
      methods: ['GET'],
      authLevel: 'anonymous',
      handler: resources
    });
    
  5. ./src/lib/azure-resource.ts ファイルを作成し、次のコードをそのファイルにコピーして、リソース グループ内のリソースを一覧表示します。

    // Include npm dependencies
    import { Resource, ResourceManagementClient } from '@azure/arm-resources';
    import { DefaultAzureCredential } from '@azure/identity';
    import { getSubscriptionId } from './environment-vars';
    
    const subscriptionId = getSubscriptionId();
    
    // Create Azure authentication credentials
    const credentials = new DefaultAzureCredential();
    
    // Create Azure SDK client for Resource Management such as resource groups
    const resourceManagement = new ResourceManagementClient(
      credentials,
      subscriptionId
    );
    
    // all resources groups in subscription
    export const listResourceBySubscription = async (): Promise<{
      list: Resource[];
      subscriptionId: string;
    }> => {
      const list: Resource[] = [];
    
      for await (const resource of resourceManagement.resources.list()) {
        list.push(resource);
      }
    
      return {
        subscriptionId,
        list
      };
    };
    // all resources groups in resource group
    export const listResourceByResourceGroup = async (
      resourceGroupName: string
    ): Promise<{
      list: Resource[];
      subscriptionId: string;
      resourceGroupName: string;
    }> => {
      const list: Resource[] = [];
    
      for await (const resource of resourceManagement.resources.listByResourceGroup(
        resourceGroupName
      )) {
        list.push(resource);
      }
    
      return {
        subscriptionId,
        resourceGroupName,
        list
      };
    };
    

ローカル関数アプリを起動し、新しい API をテストする

  1. Visual Studio Code 統合ターミナルで、ローカル プロジェクトを実行します。

    npm start
    
  2. 実行中の関数の URL が統合 bash ターミナルに表示されるまで待機します。

    Visual Studio Code の統合 bash ターミナルの部分的なスクリーンショット。Azure 関数がローカルで実行されていて、関数アプリの API のローカル URL が表示されています。

  3. 別の統合 bash ターミナルで次のcurl コマンドを使用して API を呼び出し、リソース グループをサブスクリプションに追加します。 任意の名前付け規則を使用して、リソース グループの名前を変更します。

    curl -X POST 'http://localhost:7071/api/resourcegroup?name=my-test-1&location=westus'
    
    curl -X POST 'http://localhost:7071/api/resourcegroup?name=my-test-1&location=westus' \
      -H 'content-type: application/json' \
      -d '{"tags": {"a":"b"}}'
    
  4. 次の Curl コマンドを使用して、サブスクリプションにリストされている新しいリソース グループを表示します。

    curl http://localhost:7071/api/resource-groups
    
  5. 次の Curl コマンドを使用して、追加したリソース グループを削除します。

    curl -X DELETE 'http://localhost:7071/api/resourcegroup?name=my-test-1' \
      -H 'Content-Type: application/json'
    

新しい API を含む関数アプリを Azure に再デプロイする

  1. VS Code で コマンドパレットCtrl + Shift + pで開き、 deploy to function appを入力して Azure Functions: Deploy to Function App コマンドを実行します。

  2. アプリの一覧から関数アプリを選択します。

  3. ポップアップ ウィンドウから [デプロイ] を選択します。

  4. デプロイが完了するまで待機します。

ブラウザーを使用して関数 API を検証する

前の cURL コマンドを使用して、ローカルホスト アドレス http://localhost:7071https://myfunction.azurewebsites.netなどのAzure Function リソース名に置き換えます。

7. 関数アプリのログを表示してクエリを実行する

Azure portal で Azure Function App のログを表示およびクエリします。

Azure 関数ログに対してクエリを実行する

Azure portal を使用して、関数ログを表示してクエリを実行します。

  1. VS Code で、Azure ロゴを選択して Azure エクスプローラーを開き、 [Functions]\(関数\) で関数アプリを右クリックし、 [ポータルで開く] を選択します。

    これにより、Azure portal が開き、Azure 関数が表示されます。

  2. [設定] の [Application Insights] を選択し、 [Application Insights データの表示] を選択します。

    メニューの選択肢を示すブラウザのスクリーンショット。 [設定] から [Application Insights] を選択し、[Application Insights データの表示] を選択します。

    このリンクを使用すると、VS Code で Azure 関数を作成したときに作成された個別のメトリック リソースに移動します。

  3. [監視] セクションで、 [ログ] を選択します。 [クエリ] ポップアップ ウィンドウが表示された場合、ポップアップの右上隅にある [X] を選択して閉じます。

  4. [スキーマとフィルター] ペインの [テーブル] タブで、 traces テーブルをダブルクリックします。

    これにより Kusto クエリtraces がクエリ ウィンドウに入力されます。

  5. API 呼び出しを検索するようにクエリを編集します。

    traces 
    | where message startswith "Executing "
    
  6. [実行] を選択します。

    ログに結果が表示されない場合、原因として考えられるのは、Azure 関数への HTTP 要求から Kusto でログが利用できるようになるまでに数分の遅延があることです。 数分待って、クエリを再度実行します。

    Trace テーブルについての Azure portal Kusto クエリ結果を示すブラウザーのスクリーンショット。

    Azure Function App の作成時に Application Insights リソースが追加されたため、このログ情報を取得するために追加の操作を行う必要はありません。

    • 関数アプリによって、 ユーザー用の Application Insights が追加されました。
    • クエリ ツールは、Azure portal に含まれています。
    • Kusto クエリ を記述してログから最小情報を取得する方法について学習する必要はなく、代わりに traces を選択することができます。

8. Azure リソースをクリーンアップする

リソース グループを削除します

  1. VS Code で、Azure ロゴを選択して Azure Explorer を開き、[関数] の下の関数アプリを右クリックし、[ポータルで開く] を選択します。これにより、Azure ポータルが開いて Azure 関数が表示されます。

  2. [概要] セクションで、リソース グループ名を見つけて選択します。 この操作により、Azure portal のリソース グループが表示されます。

  3. リソース グループ ページには、このチュートリアルに関連するすべてのリソースがリストされます。

  4. 一番上のメニューで、 [リソース グループの削除] を選択します。

  5. サイド メニューで、リソース グループの名前を入力し、 [削除]を選択します。

サービスプリンシパルを削除する

サービス プリンシパルを削除するには、次のコマンドを実行します。 <YOUR-SERVICE-PRINCIPAL-NAME> をサービス プリンシパルの名前に置き換えます。

az ad sp delete --id <YOUR-SERVICE-PRINCIPAL-NAME>

サンプル コード

セキュリティに関する考慮事項

このソリューションは初心者向けチュートリアルであり、"既定でセキュリティ保護" のためのプラクティスは示していません。 ここではソリューションのデプロイを成功させることが目的であるため、意図的にそのようにしています。 リソースのセキュリティ保護は、デプロイが成功した後の次の手順になります。 このソリューションでは 3 つの Azure サービスが使用され、それぞれに独自のセキュリティ機能と、"既定でセキュリティ保護" の構成に関する考慮事項があります。

次のステップ