Azure Cloud Services (Classic) を REST API から操作する

#はじめに
この記事は、昔々 Azure が Windows Azure と呼ばれていた頃に使われていた Azure Service Management (ASM) という、太古のテクノロジーに関する話題です。本記事の著者も久しぶりに触る機会があり、昔のことを忘れていて結構悩みました。なので、いま知識を残しておかないと、今後ほかにも突然保守を任された方などが苦労されるかも…と思い、メモ書き程度に残しています。

Azure Resource Manager モデルで同じようなことをやろうとする際には、ここに書いてある内容では全く上手くいきませんので、[こちら](https://docs.microsoft.com/en-us/rest/api/azure/) の記事を参考にして頑張ってください。

#Azure Service Management (ASM) とは
Azure が出来た当初に利用されていた Azure のサービス管理とデプロイメントの管理の仕組みです。現行の Azure Resource Manager (ARM) と対比して、クラシックデプロイモデル、なんて言われることもあります。
2014年に Azure Resource Manager が出た後は、着々と Azure 上のサービスの ARM 対応が進められてきており、今では ASM の利用は非推奨となっていますので、今を生きる人はこのあたりで回れ右で OK です。

但し、Azure Cloud Services など、ごく一部のサービスで ASM での管理にしか対応していないものがあり、このあたりの操作には必然的に ASM を利用する必要があります。

#ASM でデプロイされたサービスを REST API から操作するには？
ARM のリソースをプログラムから弄るときには、サービスプリンシパルを作ってやるのが一般的ですが、ASM にはそういったオシャレなものは用意されていません。

ではどうするのか？というと「管理証明書」をサブスクリプションに登録し、その「管理証明書」を REST API 呼び出しのクライアント証明書につけることで、ユーザー認証を行っています。

#手順
##サブスクリプションに管理証明書を登録するには
まずは、自己署名証明書で良いので、何らかの証明書を作る必要があります。

PowerShell で作るならこんな感じ。

```MakeOreOre.ps1
$cert = New-SelfSignedCertificate -Subject "適当に名前をつける" -CertStoreLocation "cert:\CurrentUser\My" -KeyLength 2048 -KeySpec "KeyExchange"
$password = ConvertTo-SecureString -String "パスワード" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath ".\my-cert-file.pfx" -Password $password
Export-Certificate -Type CERT -Cert $cert -FilePath .\my-cert-file.cer
```

これで作った my-cert-file.cer を以下の手順で管理対象の Cloud Services が存在するサブスクリプションに登録します。

[Azure サービス管理証明書のアップロード](https://docs.microsoft.com/ja-jp/previous-versions/azure/azure-api-management-certs)

##Cloud Services を REST API で操作するには
まずは以下のリファレンスを読みましょう。

[Cloud Services REST Api](https://docs.microsoft.com/ja-jp/rest/api/compute/cloudservices/)

例えば、あるデプロイメントの情報を取得するとしたら、以下のドキュメントに従ってリクエストを ASM REST API に投げればいいことになります。

[Get Deployment](https://docs.microsoft.com/ja-jp/rest/api/compute/cloudservices/rest-get-deployment)

###Get Deployment REST API の呼び出しを C# のコードからやるとしたら
HttpWebRequest を使ってリクエストを投げてやるのが簡単だと思います。
こんな感じ。
応答は時代を感じさせる XML で返ってきますのでご注意ください。

```ASMSample.cs
string subscriptionId = "サブスクリプション ID";
string cloudserviceName = "クラウドサービス名";
string slot = "production"; //production か staging

//証明書を読み込む
cert = new X509Certificate2("pfxファイルのパス", "PFXファイルのパスワード");

//リクエストの組み立て
Uri uri = new Uri(string.Format(
    "https://management.core.windows.net/{0}/services/hostedservices/{1}/deploymentslots/{2}",
    subscriptionId, cloudserviceName, slot));

HttpWebRequest request =
    (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "GET";
request.ClientCertificates.Add(cert);
request.Headers.Add("x-ms-version", "2009-10-01");

//リクエスト出す
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

//Status == OK なら呼び出し成功している
if (response.StatusCode == HttpStatusCode.OK)
{
    XElement body = XElement.Load(response.GetResponseStream());
    XNamespace nspace = body.Name.Namespace;
    //ここまできたら、body のなかに応答の XML が入っているので煮るなり焼くなりご自由に。
    //クエリをかけるときには、名前空間付きの XML であることに要注意です。
}
```

ここまでわかってしまえば、ほかの API もこれの応用でどうにかなります。

#まとめ
太古の Azure のテクノロジーをこの 2021 年にやらなければいけなくなってしまった人の手助けになりますように…。

#補足
Azure Service Management は、現在着々と機能縮小が進んでいます。
例えば、ASM を使ってデプロイされたクラシックデプロイモデルに基づく仮想マシンは、2023/3/1 までに ARM へ移行することが求められています。
[2023 年 3 月 1 日までに IaaS リソースを Azure Resource Manager に移行する](https://docs.microsoft.com/ja-jp/azure/virtual-machines/classic-vm-deprecation)
是非、これから Azure でサービスをご利用される方は、この記事を参考にしないようにご注意ください。
（基本的には、ポータルからはちょっと変な操作をしないと出てこないところに引っ込んでいるので、普通にポータルから仮想マシンを作る、とかはやっちゃって全然 OK です。そしたら ARM モデルになってますので。）