Azure REST API を Postman で操作する

Azure にリソースをデプロイしたり、設定を変更する際には Azure REST API が使われる。PowerShell や Azure CLI はこれらの API をラップしている。どのようなケースで Azure REST API をそのまま使用するのだろうか？

* 最新の API を使用したい場合
* API の挙動を理解したい場合

PowerShell, Azure CLI、各種の Azure SDK はすべての API をサポートしているわけではない。Azure に対して操作を行いたいときに、APIには存在するのに、PowerShell などが対応していないケースも多い。
そのようなケースでも、REST API を使えば問題なくアクセスできる。また、インターネットのブログや、ドキュメントの情報が古い場合もあるが、REST API を見てみれば現在の状況がわかるので、最も信頼性の高いリソースといえる。

REST API を CLIやSDK経由ではなく、素で使用することで、どのような仕様になっているのか、どのような挙動になっているかを理解できる。Azure のリソースに対するプログラミングをする場合、仕様と挙動を理解することにより正確さとスピードを向上させることができる。

# 2 つのフロー

Azure REST API にアクセスするには、以下のいずれかのフローを使って、トークンを取得する必要がある。

* OAuth 2.0 Code glant flow
* OAuth 2.0 Client credentials flow

最初の Flow は、Web ブラウザを使って認証を行いトークンを発行する方法であり、２つ目の Flow は、クライアントのクレデンシャルで認証する方法である。今回は Postman を使うので、あまり Web Browser を使いたくない。自動で接続してほしい。ユーザのインタラクションを必要せずに、トークンが欲しい場合は `Client credentials flow` を使うとよい。今回のユースケースでは、`Client credentials` の Flow がフィットしているのでそちらで検証する。

# Azure REST API を使用するステップ

![ARMWithPostman.jpg](https://qiita-image-store.s3.amazonaws.com/0/3470/8fdede31-e9ed-a899-afba-dbc055ae68df.jpeg)


Azure REST API を使用するには次の３つのステップが必要になる

1. Service Principal の作成
2. Token の取得
3. REST API の呼び出し

また、Token が Expire した場合は、 code grant flow だと refresh token を使うが、このフローでは、リフレッシュはないため、再度トークンを取得すればよい。

# Service Principal の作成

Postman から Azure REST API にアクセスするために、クライアントクレデンシャルを事前に Azure AD に登録しておく必要がある。クライアントを表す `Application`、 そして`Service Principal` という、クライアントが、どのような権限で対象のリソースにアクセスできるかを割り当てるオブジェクトの２つを作る必要がある。それらを作り、Application に設定したクレデンシャル (Password や 証明書)を使うと、Azure のリソースにアクセスできるようになる。

具体的な方法として最も簡単なのは、Azure CLI を用いる方法だろう。Azure CLI を入れていない人はインストールをお勧めする。

```
az ad sp create-for-rbac --name ServicePrincipalName
```

上記のコマンドを実行すると、自動で `Application` と `Service Principal` を作成してくれる。さらに、設定に必要な項目だけを返してくれる。

```
>az ad sp create-for-rbac --name ABCDE
{
  "appId": "c5c23df7-0ad6-4a1d-8a7c-64a5b3336b77",
  "displayName": "ABCDE",
  "name": "http://ABCDE",
  "password": "ef89fc9b-64e3-4f3d-8440-386d5472a33e",
  "tenant": "99f722bf-77f3-52ab-99ab-2d7cd011db43"
}
```

この一番簡単な方法で `Application` と `Service Principal` を作ると、あなたのサブスクリプションのすべてのリソースにアクセス可能な、Service Principal ができてしまうので注意が必要だ。制限をかけたい場合は次のリンクを参照されたい。上記の サンプルはでたらめのデータなので、上記の情報で次に述べるTokenの取得のAPIにアクセスしても権限がなく 401でエラーになる。

* [Create an Azure service principal with Azure CLI 2.0](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest)

# Token の取得

Service Principal を取得したのち、アクセストークンを取得するためにリクエストを投げる。

`https://login.microsoftonline.com/{{tenantId}}/oauth2/token` の `{{tenantId}}` を先ほどの Service Prinipal の `tenat` で埋めて、`POST` のリクエストと次の値を、`x-www-form-urlencoded` の形式で、POST の BODY として送信する。

| Name | Description | sample |
|---|---|---|
| URL | Endpoint | https://login.microsoftonline.com/{{tenantId}}/oauth2/token |
| Method | Request Method | POST |
| grant_type | client_credentials 固定 | client_credentials |
| client_id | Application Id |  c5c23df7-0ad6-4a1d-8a7c-64a5b3336b77|
| client_secret | Secret (password) |  ef89fc9b-64e3-4f3d-8440-386d5472a33e|
| resource | Target Resource | https://management.azure.com/ |

上記のリクエストを投げると、access token が `access_token` という名前で返ってくる。

```
{
    "token_type": "Bearer",
    "expires_in": "3599",
    "ext_expires_in": "0",
    "expires_on": "1536978531",
    "not_before": "1536974631",
    "resource": "https://management.azure.com/",
    "access_token": "eyJ0eX....."
}
```

# REST の呼び出し

REST API を呼ぶときに先ほど獲得した `access_token` を ヘッダに渡してあとは、仕様通りにREST API をコールするとよい。`access_token` は `JWT token` の形式になっている。

## Header

Azure REST API に必要なヘッダは次の通り

| name | description | sample |
|------|------|-----|
| Content-Type | Content Type。application/json である必要がある | application/json|
| Authorization | Bearer トークン。 | Bearer eyJ0eX.... |

## URL 

URL の形式は次の通り。当然のことだが、API のバージョンによって使える内容が異なるので、最新のバージョンを見てみるとよい。

```
https://management.azure.com//subscriptions/{{subscriptionId}}/resourceGroup/{{resourceGroupName}}/providers/{{ResourceProvider}}/{{resourceType}}/{{ResourceName}}/{{optional}?api-version={{api-version}}
```

## 概念の説明

API の概念としては、次の階層になっている。

* Subscription
* Resource Group
* Resource Provider
* Resource Type
* API Version

Azure REST API の classic ではないのものは、`ARM API` とも呼ばれる。`ARM API` は Rsource Group の単位でリソースを管理する。リソースは、Resource Provider から割り当てられる。各リソースは 複数の API バージョンを持っている。

### Resource Provider 

Resource Provider はリソースのプロバイダで、次の PowerShell Command let でどのようなものが使えるかを取得できる。

```
 Get-AzureRmResourceProvider | `
>> Select-Object ProviderNamespace, ResourceTypes |`
>> Sort-Object ProviderNamespace

ProviderNamespace               ResourceTypes
-----------------               -------------
Microsoft.ADHybridHealthService {services, addsservices, configuration, operations...}
Microsoft.Advisor               {suppressions, configurations, recommendations, generateRecommendations...}
Microsoft.ApiManagement         {service, validateServiceName, checkServiceNameAvailability, checkNameAvailability...}
Microsoft.Authorization         {roleAssignments, roleDefinitions, classicAdministrators, permissions...}

```

### Resource Type

Resource Provider には、各種のリソースタイプが存在し、それ毎にリクエストを投げることができる。各リソースタイプは、サブスクリプションによって使えるリージョンが異なってくる。また、いくつかのリソースタイプは、リソースの使用にあたって、Registration が必要になることがある。


```
Get-AzureRmResourceProvider -ProviderNamespace Microsoft.Comput
e |`
>> Select-Object ResourceTypes, Locations | `
>> Sort-Object ResourceTypes

ResourceTypes                                               Locations
-------------                                               ---------
{virtualMachines/diagnosticSettings}                        {East US, East US 2, West US, Central US...}
{virtualMachines/metricDefinitions}                         {East US, East US 2, West US, Central US...}
{sharedVMImages}                                            {West Central US, South Central US, East US 2, Southeast...
{restorePointCollections/restorePoints}                     {Southeast Asia, East US 2, Central US, West Europe...}
{locations/publishers}                                      {East US, East US 2, West US, Central US...}
```

### バージョンの取得

リソースプロバイダ毎に使用できる API バージョンを取得するためには、次の PowerShell を実行するとよい。

```
 ((Get-AzureRmResourceProvider -ProviderNamespace Microsoft.Web)
.ResourceTypes | Where-Object {$_.ResourceTypeName -eq 'sites'}).ApiVersions

2018-02-01
2016-08-01
2016-03-01
2015-08-01-preview
2015-08-01
2015-07-01
  :
```

## REST API のサンプル

リソースの構造は対象リソースによって異なる。たとえば WebApp の Config のパートなら下記の通り。

```
GET https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/config/web?api-version=2016-08-01
```

詳細はこちらのページでAPIを確認するとよい。

* [Azure REST API Reference](https://docs.microsoft.com/en-us/rest/api/azure/#create-the-request)

## 更新

基本的に更新したい場合は、GET でオブジェクトを取得して、更新して、`PUT`すればよい。ARM template は部分的に更新ができたが REST では知らないので聞いてみる。


# まとめ

本フローを用いると、簡単に Azure REST API を呼び出すことができる。

# リソース

今回の目的に最も最短だったブログ。Postman のコンフィグレーションも参考になる

* [Azure REST APIs with Postman in 2 Minutes](https://blog.jongallant.com/2017/11/azure-rest-apis-postman/)

サービスから Azure REST API を呼ぶ方法について

* [Service to service calls using client credentials (shared secret or certificate)](https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-client-creds-grant-flow#request-an-access-token)

Resource Providers と Resource Types の解説

* [Resource Providers and types](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-supported-services)

REST API のリファレンス。トップページに使い方がまとまっている。すべてのリソースも参照できる。

* [Azure REST API Reference](https://docs.microsoft.com/en-us/rest/api/azure/#create-the-request)

Client Credential Flow についての全体的な説明

* [Azure Active Directory v2.0 and the OAuth 2.0 client credentials flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow)