AzureのSubscriptionを MSアカウントに紐づけている場合のPowerShell 自動実行

# MSアカウントでは、AzurePowerShellの自動化に対応できない?
組織アカウントではなくMSアカウントでの自動化をやりたいという要望を頂きました。
ざっと下調べしてみると、組織アカウント云々とかAzureAD云々とかばかりで、MSアカウントでは **無理** ですという記述ばかりなんですね。どうも、**MSアカウントでAzurePowerShellの自動実行はできません**ってのが定説なようです。

# 調べてみた
定説が本当に正しいのかどうか調べ~~るのは楽しい~~てみたところ、こんな感じの記述でイケることがわかりました。
事前にプロファイル情報を保存し、CronやTask SchedulerでPowerShellスクリプトを実行する際にプロファイル情報を呼び出せば、Azure関連のcmdletを正常に利用可能です。Get-AzureRmSubscription実行時に**Unable to acquire token for tenant 'Common'**という警告が出ますが、これは気にしても仕方ないようです。Commonという名のTenantを作成すればよいのかもしれませんが、未調査です。

```:プロファイル情報の保存
$Path = "${env:USERPROFILE}\AppData\Roaming\Windows Azure Powershell"
$Prof = "$Path\apf.json"
if(!(Test-Path $Path)) {
    New-Item $Path -ItemType Directory | Out-Null
}
Login-AzureRmAccount
Save-AzureRmProfile -Path $Prof -Force
```
```:プロファイル情報の呼び出し
$Path = "${env:USERPROFILE}\AppData\Roaming\Windows Azure Powershell"
$Prof = "$Path\apf.json"
Select-AzureRmProfile -Path $Prof | Out-Null
```

# いくつか怪しげな挙動あり
試験的にしばらく稼働させてみると、以下のような制限事項と思われる挙動や、よくわからない怪しげな挙動、仕様と思われる事象が見つかりました。

* Select-AzureRmSubscriptionが正常に行われないケースがある
* サブスクリプションの増減があると、プロファイル情報が無効になるケースあり
* 14日でプロファイル情報の寿命が尽きる
* プロファイル情報が無効になったことが分かりにくい
* Invoke-RestMethod使用不可

### Select-AzureRmSubscription対策
あれこれ試してみたところ、Select-AzureRmProfileでプロファイル情報を呼び出した後、一回しかSelect-AzureRmSubscriptionでのサブスクリプション切替ができないようです。原因を特定できていませんし、頭の悪いAdHocな解決方法ですが、Select-AzureRmSubscriptionを実行する前に毎回Select-AzureRmProfileを叩けば問題はありませんでした。
ダブルでAdHocですが、Select-AzureRmSubscriptionの代わりにこれを使うのが手っ取り早いでしょうね。

```:代替Select-AzureRmSubscription
function Select-Subscription {
    param($sub)

    if((Get-AzureRmContext).Subscription.SubscriptionId -ne $sub) {
        Select-AzureRmProfile -Path $Prof | Out-Null
        Select-AzureRmSubscription -SubscriptionId $sub
    }
}
```

### サブスクリプションの増減があると、プロファイル情報が無効になるケース
MSアカウントに紐づいているサブスクリプションが増減した場合、プロファイル情報を呼び出しても認証エラーが発生してAzure関連cmdletを正常に利用できないケースがありました。これについては、任意にテストを繰り返すことができていないので**参考情報**です。
この場合、プロファイル情報を再作成する以外の解決方法は見つかっていません。おそらく、それ以外の解決方法は無いでしょう。

ちなみに、以下のような傾向が見られます。

|追加/削除|サブスクリプションの払い出し元|挙動|
|:---:|:---:|:--:|
|追加|同一EA契約|問題なし。但し、追加されたサブスクリプションは選択できない|
|追加|別のEA契約|問題あり。認証されず。|
|削除|別のEA契約|警告は表示されるが、問題なし|

### 14日でプロファイル情報の寿命が尽きる
プロファイル情報は、保存後きっちり14日で寿命が尽きます。当然ですが、寿命が尽きたプロファイル情報は利用不能です。
無効になったプロファイル情報は、再作成してリフレッシュする必要があります。

### プロファイル情報が無効になったことが分かりにくい
寿命などの理由で無効になったプロファイル情報ですが、Select-AzureRmProfileで呼び出してもこれといったエラーは出ません。裏でAzureのREST APIを叩くcmdletを実行するまで、プロファイル情報が無効であることはハンドリングできないようですが、ここは深掘りしていないのであまりよくわかっていません。

### Invoke-RestMethod使用不可
Linux版PowerShellを試していて気付いたのですが、Invoke-RestMethodを実行するための準備としてクレデンシャルの作成を行うとLogin-AzureRmAccount相当の処理が行われるようです。
実験に使用したLinux版PowerShellでは、Get-AzureRmVM等の主要cmdletが使用できなかったのでInvoke-RestMethodで代用を試みたのですが、上記の通りでしたので目論見は崩れ去りました。

# 制限事項
Save-AzureRmProfile及びSelect-AzureRmProfileですが、AzureRM.Profile 2.2.0以前でのみ利用可能なようです。
[MSの公式文書](https://docs.microsoft.com/en-us/powershell/module/azurerm.profile/select-azurermprofile)には、AzureRM.Profile 3.8.0でも利用可能と記載されているようですが、3.x系には含まれていませんでした。ざっくりまとめると、下表のようになります。

|バージョン|公式|実態|
|:---:|:---:|:--:|
|2.x|○|○|
|3.x|○|×|
|4.x|×|×|

# 総括
色々と問題が多く、かつ新しいAzureRM.Profileには含まれていないため、これを利用できるシチュエーションはさほど多くはないと考えています。
ただ、要件によっては制約条件を承知の上で使いたいというケースもあるのではないかと思い、私自身のチャレンジをザックリとですがまとめてみました。

以上、ご参考まで。