0
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?

More than 3 years have passed since last update.

Azure Functions の Easy Auth で Azure REST API をユーザー権限で実行する環境を .NET で作ってみた

0
Posted at

Azure Functions の認証機能を使ってユーザー権限で何かしらの自動化処理を行う場合、Microsoft Graph API なら簡単に利用できます。しかしながら、Azure REST API を使おうとすると scope に設定したい https://management.azure.com/user_impersonation はどこに設定するのかわからなかったので、いろいろ試しながら .NET で検証環境を作ってみました。

ローカルの環境情報

bash
$ func --version
4.0.4629

$ dotnet --version
6.0.300

$ az version
{
  "azure-cli": "2.43.0",
  "azure-cli-core": "2.43.0",
  "azure-cli-telemetry": "1.0.8",
  "extensions": {}
}

Azure Functions を作成

bash
prefix=mnrfuncaad
region=japaneast

az group create \
  --name ${prefix}-rg \
  --location $region

az storage account create \
  --name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --sku Standard_LRS

az functionapp create \
  --name ${prefix} \
  --resource-group ${prefix}-rg \
  --consumption-plan-location $region \
  --runtime dotnet \
  --functions-version 4 \
  --storage-account ${prefix}stor \
  --disable-app-insights \
  --https-only \
  --os-type Linux \
  --assign-identity

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

bash
appid=$(az ad app create \
  --display-name ${prefix} \
  --web-redirect-uris https://${prefix}.azurewebsites.net/.auth/login/aad/callback \
  --enable-id-token-issuance true \
  --sign-in-audience AzureADMyOrg \
  --required-resource-accesse '[
    {
      "resourceAccess": [
        {
          "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
          "type": "Scope"
        },
        {
          "id": "37f7f235-527c-4136-accd-4a02d197296e",
          "type": "Scope"
        },
        {
          "id": "14dad69e-099b-42c9-810b-d002981feec1",
          "type": "Scope"
        },
        {
          "id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
          "type": "Scope"
        }
      ],
      "resourceAppId": "00000003-0000-0000-c000-000000000000"
    },
    {
      "resourceAccess": [
        {
          "id": "41094075-9dad-400e-a0bd-54e686782033",
          "type": "Scope"
        }
      ],
      "resourceAppId": "797f4846-ba00-4fd7-ba43-dac1f8f63013"
    }
  ]' \
  --query appId \
  --output tsv)

apppw=$(az ad app credential reset \
  --id $appid \
  --append \
  --display-name ${prefix} \
  --years 100 \
  --query password \
  --output tsv)

Azure Fnctions の認証設定

bash
az webapp auth config-version upgrade \
  --name ${prefix} \
  --resource-group ${prefix}-rg

az webapp auth microsoft update \
  --name ${prefix} \
  --resource-group ${prefix}-rg \
  --client-id $appid \
  --client-secret $apppw \
  --issuer https://sts.windows.net/$(az account show --query tenantId --output tsv)/v2.0 \
  --yes

az resource update \
  --set properties.globalValidation='{
    "redirectToProvider": "azureactivedirectory",
    "requireAuthentication": true,
    "unauthenticatedClientAction": "RedirectToLoginPage"
  }' \
  --ids $(az webapp auth show \
  --resource-group ${prefix}-rg \
  --name ${prefix} \
  --query id \
  --output tsv)

az resource update \
  --set properties.identityProviders.azureActiveDirectory.login='{
    "disableWWWAuthenticate": false,
    "loginParameters": [
      "response_type=code id_token",
      "scope=email openid profile https://management.azure.com/user_impersonation"
    ]
  }' \
  --ids $(az webapp auth show \
  --resource-group ${prefix}-rg \
  --name ${prefix} \
  --query id \
  --output tsv)

ローカルで Functions を作成

bash
func init ${prefix} --dotnet

cd ${prefix}

func new --name test --template "HTTP trigger" --authlevel "anonymous"

func start

test.cs を編集

test.cs
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Security.Claims;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json.Linq;
using Microsoft.Identity.Web;

namespace mnrfuncaad
{
  public static class test
  {
    [FunctionName("test")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
        ILogger log)
    {
      HttpClient httpClient = new HttpClient();
      httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + req.Headers["X-MS-TOKEN-AAD-ACCESS-TOKEN"]);
      var response = await httpClient.GetAsync("https://management.azure.com/tenants?api-version=2020-01-01");
      var responseMessage = response + "\n";
      if (response.StatusCode == HttpStatusCode.OK)
      {
        JObject tenants = JObject.Parse(await response.Content.ReadAsStringAsync());
        foreach (var value in tenants.GetValue("value"))
        {
          responseMessage = responseMessage + "tenant: " + value["tenantId"] + "\n";
        }
      }

      return new OkObjectResult(responseMessage);
    }
  }
}

必要なパッケージを追加

bash
dotnet add package Microsoft.Identity.Web

func start

Azure Functions にデプロイして動作確認

bash
func azure functionapp publish ${prefix}

open https://${prefix}.azurewebsites.net/api/test
0
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
0
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?