Azure REST APIでリソース監視!
2019-12-19
azblob://2022/11/11/eyecatch/2019-12-18-azure-rest-api-000.png

こんにちは、bot作成おじさんの石川です。このブログを運営するにあたりAzureのリソースを触ってみるためのサブスクリプションが存在するんですが、ここのコスト管理等々の作業も発生します。ここを効率化した話をします。

もくじ

  1. Azure REST APIとは
  2. Azure REST APIを触ってみる
    1. サービスプリンシパルの作成
    2. REST APIを叩いてみる
  3. Slackのbotにする
    1. Azure Functionsを作成
    2. Functionを作成
  4. まとめ

1. Azure REST APIとは

Azure REST APIはAzureのリソースに対して操作を行えるREST APIで、様々なリソースに対してCRUDをはじめとする各種操作を行えるものになっています。

具体的には「VMを作成」したり「SQL DBを削除」したりと、Azureリソースに対してあらゆることができる代物です。

それゆえ、取扱注意だったりもします。。。

詳細はこちら( https://docs.microsoft.com/ja-jp/rest/api/azure/ ) をご覧ください。

2. Azure REST APIを触ってみる

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

リソースの操作を行うためのものなのでAzure ADアプリとしての作成が必要となります。作成には共同作成者以上のロールが必要です。

AzureポータルからAzure Active Directoryを開き、アプリの登録を開きます。

「新規登録」より登録していきましょう。

  • 名前: AADアプリの表示名 ポータルから見えるのみなので識別できればOK
  • サポートされているアカウントの種類: シングルテナントを選択
  • リダイレクト URI: 空欄でOK

作成できたら以下の情報をメモります。

  • アプリケーションID
  • テナントID
  • アプリが所属しているサブスクリプションID

メモったら左のメニュー(概要等並んでいる列)から「証明書とシークレット」を開きます。

新しいクライアントシークレットをクリックし、クライアントシークレットを発行します。

期限はお好みのものをどうぞ。

「追加」をクリックするとクライアントシークレットが生成されます。

生成時しか値が確認できないので忘れずにメモります。

メモる必要があるものをまとめると

  • アプリケーションID
  • テナントID
  • アプリが所属しているサブスクリプションID
  • 生成したクライアントシークレット

の4つです。

2.2. REST APIを叩いてみる

必要な4つの情報がそろったところで実際にREST APIを叩いてみましょう。

とはいえ、Azure REST APIは認証にJWTトークンが必要です。まず、先ほどメモした情報を基にJWTトークンを取得しましょう。

AzureのJWTトークンは

https://login.microsoftonline.com/<テナントID>/oauth2/token

のエンドポイントにパラメータを付加しapplication/x-www-form-urlencodedの形式でPOSTしてあげることで得られます。

パラメータは以下の通りです。

  "grant_type": "client_credentials",
  "resource" : "https://management.core.windows.net",
  "client_id" : <アプリケーションID>,
  "client_secret" : <クライアントシークレット>

実際にトークンを取得してみます。

無事トークンが取れました。

これをHeaderのAuthorizationにBearerトークンとして付加してリソース一覧を取得してみます。

エンドポイントは

https://management.azure.com/subscriptions/<サブスクリプションID>/resources?api-…

です。

では叩いてみましょう。

無事に値が取れていますね。ちょっと中身を見てみます。

{
    "id": "/subscriptions/<サブスクリプションID>/resourceGroups/rg-techblog/providers/Microsoft.Web/sites/ResourceMonitoringBot",
    "name": "ResourceMonitoringBot",
    "type": "Microsoft.Web/sites",
    "kind": "functionapp",
    "location": "japaneast",
    "tags": {}
}

一番下のリソースの情報を取り出してみました。

リソース名やリソースのタイプ、リージョンなどの情報が取得できているのが確認できますね。

3. Slackのbotにする

3.1. Azure Functionsを作成

今回はAzure FunctionsのTimer Triggerを使い、毎朝10時に存在しているリソースを取得。それをSlackに通知するようにしてみようと思います。

ポータルからAzure Functionsを作成します。大量にぶん回すわけじゃないので従量課金で立てても無料枠分で全然事足ります。

3.2. Functionを作成

以下のような感じで適当にコードを書きます。

private static HttpClient httpClient = new HttpClient();

[FunctionName("bot")]
public async Task Run([TimerTrigger("0 0 1 * * 1-5")]TimerInfo timer, ILogger log)
{
  var resources = await GetAzureResources();
  await SendSlack(resources);
}

public async Task<Resources> GetAzureResources()
{
  var token = await GetAccessToken();
  var endpoint = "https://management.azure.com/subscriptions/" + Environment.GetEnvironmentVariable("SubscriptionId") + "/resources?api-version=2019-08-01;
  httpClient.DefaultRequestHeaders.Authorization = AuthenticationHeaderValue("Bearer", token);
  var response = await httpClient.GetAsync(endpoint);
  if (response.StatusCode == System.Net.HttpStatusCode.OK)
  {
    var resString = await response.Content.ReadAsStringAsync();
    var resources = JsonConvert.DeserializeObject<Resources>();
    return resources;
  }
  else
  {
    //エラー処理
  }
}

public async Task<string> GetAccessToken()
{
  //省略
}

public async Task SendSlack()
{
  //省略
}

出来上がったものがこちら。

なにもないとこんな感じ。

なにかあるとこんな感じで通知してくれます。

4. まとめ

さっくりとリソース監視するbotができました。シャドーIT防止とかに使いたいですね。

と、まとめようと思ったんですが

発見してしまった………。

時間を見つけてこれ使って書き直します…………。