1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Azure Functions ( Node.js ) から Azure Resource Graphの実行結果を取得したメモ

Posted at

概要

Node.jsを使ってAzure Resource Graphの実行結果を取得した

この時点のソース

環境

ローカル

  • Windows 11
  • Core Tools Version: 4.0.7030 Commit hash: N/A +bb4c949899cd5659d6bfe8b92cc923453a2e8f88 (32-bit)
    Function Runtime Version: 4.1037.0.23568

Functions

  • オペレーティング システム: Linux
  • App Service プラン: JapanEastLinuxDynamicPlan (Y1: 0)
  • ランタイム バージョン: 4.1038.400.1
  • Node.js バージョン: Node.js 20 LTS

ポータルでクエリの確認

resources
| where type == 'microsoft.storage/storageaccounts'
| where resourceGroup  == 'async-ttrpg'

image.png

2件取得できた。

組み込みロールの確認

Azure 組み込みロール

組み込みのロール 説明 ID
Reader すべてのリソースを表示しますが、変更を加えることはできません。 acdd72a7-3385-48ef-bd42-f606fba81ae7

日本語のポータルから見ると「Reader」が「閲覧者」と訳されている。
わかりにくい。

image.png

ローカル実行用に組み込みロールの設定

自分で作成したリソースグループだと共同編集者権限を持っているのでこの作業は不要

基本的なやりかたはAzure Functionsをローカル実行してマネージドIDを使った認証でBlobStorageにアクセスしたメモと同様。選ぶロールが異なる。

image.png

ソースコード

パッケージのインストール。@azure/arm-resourcegraphのlatestの4.2.1だとNodeのfetchのエラーが出たのでaplpha版v5を選ぶ。

npm i @azure/arm-resourcegraph@5.0.0-alpha.20250506.1 @azure/identity
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
import { DefaultAzureCredential } from '@azure/identity';
import { Hono } from 'hono';

const app = new Hono().post('/', async (c) => {
  const creds = new DefaultAzureCredential();

  const client = new ResourceGraphClient(creds);
  const result = await client.resources({
    query: `
resources
| where type == 'microsoft.storage/storageaccounts'
| where resourceGroup  == 'async-ttrpg'
    `,
  });
  return c.json(result);
});
export default app;
サンプルコードの記法

npm のサンプルコードの書きかたをすると型エラーとなるのでコメントで回避している。
型エラーとなっても動作はした。私の環境ではsubscriptionIdを入れても入れなくとも結果は変わらなかった。

import { ResourceGraphClient } from '@azure/arm-resourcegraph';
import { DefaultAzureCredential } from '@azure/identity';
import { Hono } from 'hono';

const subscriptionId = '00000000-0000-0000-0000-000000000000';
const app = new Hono().post('/', async (c) => {
  const creds = new DefaultAzureCredential();

  // @ts-expect-error subscriptionId is not a valid parameter
  const client = new ResourceGraphClient(creds, subscriptionId);
  const result = await client.resources({
    query: `
resources
| where type == 'microsoft.storage/storageaccounts'
| where resourceGroup  == 'async-ttrpg'
    `,
  });
  return c.json(result);
});
export default app;

ローカル実行

ローカルで起動して問い合わせてみる。

post http://localhost:7071/api/sdk-test

実行結果

下記のような形で2件取れる。

{
  "totalRecords": 2,
  "count": 2,
  "resultTruncated": "false",
  "data": {
    "0": {
      "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-resource-group/providers/Microsoft.Storage/storageAccounts/examplestorageaccount1",
      "name": "examplestorageaccount1",
      "type": "microsoft.storage/storageaccounts",
      "tenantId": "00000000-0000-0000-0000-000000000000",
      "kind": "StorageV2",
      "location": "eastasia",
      "resourceGroup": "example-resource-group",
      "subscriptionId": "00000000-0000-0000-0000-000000000000",
      "managedBy": "",
      "sku": {
        "name": "Standard_LRS",
        "tier": "Standard"
      },
      "plan": null,
      "properties": {
        "provisioningState": "Succeeded",
        "publicNetworkAccess": "Enabled",
        "encryption": {
          "keySource": "Microsoft.Storage",
          "services": {
            "blob": {
              "enabled": true,
              "lastEnabledTime": "2025-01-01T01:00:00.0000000Z",
              "keyType": "Account"
            },
            "file": {
              "enabled": true,
              "lastEnabledTime": "2025-01-01T01:00:00.0000000Z",
              "keyType": "Account"
            }
          }
        },
        "privateEndpointConnections": [],
        "supportsHttpsTrafficOnly": true,
        "allowBlobPublicAccess": true,
        "allowCrossTenantReplication": false,
        "minimumTlsVersion": "TLS1_2",
        "primaryEndpoints": {
          "blob": "https://examplestorageaccount1.blob.core.windows.net/",
          "file": "https://examplestorageaccount1.file.core.windows.net/",
          "table": "https://examplestorageaccount1.table.core.windows.net/",
          "queue": "https://examplestorageaccount1.queue.core.windows.net/",
          "web": "https://examplestorageaccount1.z11.web.core.windows.net/",
          "dfs": "https://examplestorageaccount1.dfs.core.windows.net/"
        },
        "statusOfPrimary": "available",
        "primaryLocation": "eastasia",
        "keyCreationTime": {
          "key2": "2025-01-01T01:00:00.0000000Z",
          "key1": "2025-01-01T01:00:00.0000000Z"
        },
        "creationTime": "2025-01-01T01:00:00.0000000Z",
        "networkAcls": {
          "virtualNetworkRules": [],
          "defaultAction": "Allow",
          "ipv6Rules": [],
          "ipRules": [
            {
              "value": "0.0.0.1",
              "action": "Allow"
            },
            {
              "value": "0.0.0.2",
              "action": "Allow"
            },
            {
              "value": "0.0.0.3",
              "action": "Allow"
            }
          ],
          "bypass": "AzureServices",
          "resourceAccessRules": []
        },
        "accessTier": "Hot"
      },
      "tags": {},
      "identity": null,
      "zones": null,
      "extendedLocation": null
    },
    "1": {
      "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-resource-group/providers/Microsoft.Storage/storageAccounts/examplestorageaccount2",
      "name": "examplestorageaccount2",
      "type": "microsoft.storage/storageaccounts",
      "tenantId": "00000000-0000-0000-0000-000000000000",
      "kind": "StorageV2",
      "location": "eastasia",
      "resourceGroup": "example-resource-group",
      "subscriptionId": "00000000-0000-0000-0000-000000000000",
      "managedBy": "",
      "sku": {
        "name": "Standard_LRS",
        "tier": "Standard"
      },
      "plan": null,
      "properties": {
        "provisioningState": "Succeeded",
        "encryption": {
          "keySource": "Microsoft.Storage",
          "services": {
            "blob": {
              "enabled": true,
              "lastEnabledTime": "2024-01-01T01:00:00.0000000Z",
              "keyType": "Account"
            },
            "file": {
              "enabled": true,
              "lastEnabledTime": "2024-01-01T01:00:00.0000000Z",
              "keyType": "Account"
            }
          }
        },
        "privateEndpointConnections": [],
        "supportsHttpsTrafficOnly": true,
        "allowBlobPublicAccess": false,
        "allowCrossTenantReplication": false,
        "minimumTlsVersion": "TLS1_0",
        "primaryEndpoints": {
          "blob": "https://examplestorageaccount2.blob.core.windows.net/",
          "file": "https://examplestorageaccount2.file.core.windows.net/",
          "table": "https://examplestorageaccount2.table.core.windows.net/",
          "queue": "https://examplestorageaccount2.queue.core.windows.net/",
          "web": "https://examplestorageaccount2.z11.web.core.windows.net/",
          "dfs": "https://examplestorageaccount2.dfs.core.windows.net/"
        },
        "statusOfPrimary": "available",
        "primaryLocation": "eastasia",
        "keyCreationTime": {
          "key2": "2024-01-01T01:00:00.0000000Z",
          "key1": "2024-01-01T01:00:00.0000000Z"
        },
        "creationTime": "2024-01-01T01:00:00.0000000Z",
        "networkAcls": {
          "virtualNetworkRules": [],
          "defaultAction": "Allow",
          "ipv6Rules": [],
          "ipRules": [],
          "bypass": "AzureServices"
        },
        "accessTier": "Hot"
      },
      "tags": {},
      "identity": null,
      "zones": null,
      "extendedLocation": null
    }
  },
  "facets": []
}

組み込みロールの設定

Functionsにロールの設定が不足していると下記エラーとなる。

Access is denied to the requested resource. The user might not have enough permission.

設定してみる。

image.png

設定が完了すると、エラーが発生しなくなった。

5分ほどまつとロール割り当てに下記のように表示されることを確認できる。(作成されたと通知されても、ここに反映されるまでにはラグがあった)

image.png

Bicepで設定

infra/biceps/rbacToFunction.bicep
@description('Specifies the role definition ID used in the role assignment.')
param roleDefinitionID string

@description('Specifies the principal ID assigned to the role.')
param functionAppName string

resource functionApp 'Microsoft.Web/sites@2024-04-01' existing = {
  name: functionAppName
}

var roleAssignmentName= guid(functionAppName, roleDefinitionID, resourceGroup().id)
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: roleAssignmentName
  properties: {
    roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionID)
    principalId: functionApp.identity.principalId
  }
}
infra/bin/rbac-to-function.bin
#!/bin/bash

BIN_DIR=$(cd $(dirname $0) && pwd)
BICEP_DIR=$(cd $BIN_DIR/../biceps && pwd)

# 環境変数読み込み
source $BIN_DIR/.env

# Reader ( 閲覧者 ) のロールを割り当てる
cd $BICEP_DIR && az deployment group create \
  --name frontendDeployment \
  --template-file rbacToFunction.bicep \
  --parameters roleDefinitionID=acdd72a7-3385-48ef-bd42-f606fba81ae7 \
  functionAppName=$APP_NAME \
  -g $RESOURCE_GROUP_NAME
infra/bin/.env
APP_NAME=hogehoge

image.png

手動で行ったときに比べ、リソース名がリソースグループになったが、問題なく動いた。

参考

npm @azure/arm-resourcegraph ... TypeError: Expected signal to be an instanceof AbortSignalが発生。おそらく古くてNodeのfetchの仕様変更についていけていない
npm @azure/arm-resourcegraph 5.0.0-alpha.20250506.1 ... こちらだとAbortSignalは発生せず。
@azure/arm-resourcegraph package
@azure/arm-resourcegraph package ResourceGraphClient resources
Azure Resource Graph (ARG) に馴染んでみる
訳あってMicrosoft Graph API調べてみた
Resource Graph API で Azure のリソース情報を取得する
Azure Resource Graph で Azure リソースの変更を検知して通知する
Azure Resource GraphでAzureリソースを可視化する!
Azure Resource Graphで簡単にリソースを検索する方法
Azure Functionsをローカル実行してマネージドIDを使った認証でBlobStorageにアクセスしたメモ
Azure FunctionsのマネージドIDを有効化してBlobStorageにアクセスしたメモ
Azure 組み込みロール

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?