しばやん雑記

ASP.NET とメイドさんが大好きなフリーランスのプログラマーのブログ

Managed Service Identity を利用して Kudu に用意された REST API を実行してみる

あまり弄ってなかったのですが、Managed Service Identity を使うと ARM の API とかいろいろと使いやすくなって素晴らしいという話をぶちぞう RD のブログで読んでました。

そういえば、ちょっと前に GA になったみたいなので安心して使えるようになりました。

Managed Service Identity (Preview) | ブチザッキ

ARM を使うと App Service のいろんな設定を変更したり、新しくリソースを作ったりも出来ますが Kudu に用意されている REST API は直接扱うことは出来ないみたいでした。

Kudu の REST API は結構な数が用意されていて、ARM の API と組み合わせることで何でも出来るようになるので夢が膨らみます。

ARM では実行できないファイルシステム系の API も用意されていて使ってみたかったので、Managed Service Identity で取得した認証情報を使って叩けるようにしました。

とりあえず Azure Functions と Web App を作成して、Azure Functions 側の Managed Service Identity を有効化するところから始めます。

f:id:shiba-yan:20180706003645p:plain

有効化すると Access control から権限を割り当てることが出来るようになります。この辺りは UI が MSI 向けに最適化されていて非常に楽でした。

今回は Web App 向けの API を叩きたいので、Website Contributor を割り当てます。

f:id:shiba-yan:20180706003817p:plain

これで Azure Functions から MSI を使って ARM の API を叩けるようになりました。

Kudu の API を叩くためには 2 種類の認証情報が用意されていますが、Site Credentials に関しては ARM を使って取得できるので、それを利用して Kudu の API を利用します。

Deployment credentials · projectkudu/kudu Wiki · GitHub

今回はサンプルとして VFS API を利用して、Azure Functions からファイルを作成してみます。

実際に用意した Azure Functions のコードは以下のようになります。やっていることは極めて単純です。

public static class Function1
{
    [FunctionName("Function1")]
    public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, TraceWriter log)
    {
        var subscriptionId = "***";
        var resourceGroupName = "***";

        // ARM 向けに AccessToken を取得する
        var tokenProvider = new AzureServiceTokenProvider();

        var accessToken = await tokenProvider.GetAccessTokenAsync("https://management.azure.com/");

        var websiteClient = new WebSiteManagementClient(new TokenCredentials(accessToken))
        {
            SubscriptionId = subscriptionId
        };

        // Site credentials を取得する
        var credentials = await websiteClient.WebApps.ListPublishingCredentialsAsync(resourceGroupName, "kudu-api-test");

        // Site credentials を使って Kudu REST API を利用する
        var httpClient = new HttpClient();

        httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{credentials.PublishingUserName}:{credentials.PublishingPassword}")));

        // VFS API を使ってファイルを生成してみる
        await httpClient.PutAsync("https://kudu-api-test.scm.azurewebsites.net/api/vfs/site/wwwroot/samplefile.txt", new StringContent(DateTime.Now.ToString()));

        return new OkObjectResult($"OK");
    }
}

AzureServiceTokenProvider を使って AccessToken が取れてしまえば、後は対象の Web App の Site credentials を取得して Kudu REST API を叩くだけです。API に関しては Wiki にまとまっています。

作成した Function を実行すると、Web App に新しくファイルが作成されているはずです。

f:id:shiba-yan:20180706005551p:plain

VFS API 以外にも Zip Deploy やコマンド実行など、割と何でも出来るようになるので使い勝手がありそうです。ただし、くれぐれも認証情報の扱いには注意したいところです。

Managed Service Identity のおかげで、ようやく ARM API を使ってみようという気力が湧いてきました。