📓

AzureVMを起動/停止/再起動/状態確認するAzure Automation

に公開

はじめに

AzureでVMの起動停止などの操作をユーザにさせる場合、都度カスタムロールを作成/修正して割り当てる方法があります。

運用者にロールの編集権限を与えておくのは危険なので、Azure Automationを使って何とか作ってみました。

概要

以下のようなAutomationアカウントを作成します。

  • 変数に、操作させたいVMのリソースIDを指定
    • 運用者が指定する想定です。
  • 操作するRunbookから上記の変数を取得して、入力時に指定したVMが操作してよいVMかどうかを確認

権限については以下のように運用します。

  • 操作者に対して、上記AutomationアカウントのAutomation オペレーターの権限を作成
    • 運用者には、上記の権限を付与だけできるようにしておく

参考

https://www.tama-negi.com/2022/03/06/azure-cli-powershell-vm/

作成

Azure Automation アカウント・ランタイム作成

過去の記事と同じものを作成します。ランタイムも現時点で最新版のPowerShell7.4で作ります。
https://zenn.dev/arbr/articles/19994b62d63ea3#automationアカウント作成

デフォルトのランブックの削除

作成時にデフォルトでランブックがありますので、消しておきます。

ランブック作成

作成の仕方は以前の記事を参照ください。
https://zenn.dev/arbr/articles/19994b62d63ea3#ランブックを作成して実行する

スクリプトは以下になります。

param(
    [Parameter(Mandatory=$true)][string]$executionId,
    [Parameter(Mandatory=$true)][string]$ResourceId,
    [Parameter(Mandatory=$true)][ValidateSet("GetVmInfo","Start", "Stop", "Restart")][string]$Action
)

$ErrorActionPreference = "Stop" # エラーが発生したらスクリプトを終了

# connect to Azure
try {
    Write-Output "Trying to connect to Azure with a system assigned Identity..."
    $null = Connect-AzAccount -Identity
}catch {
    $ErrorMessage = "Error connecting to Azure: " + $_.Exception.message
    Write-Error $ErrorMessage
}

# 変数取得
try{
    $retVar = Get-AutomationVariable -Name $executionId
}catch {
    $ErrorMessage = "指定したexecutionId: $($executionId) が存在しません。`r`n "
    $ErrorMessage += "Error connecting to Azure: " + $_.Exception.message
    Write-Error $ErrorMessage
}

# リソースIDが定義されているか確認し実行
if( ($retVar -split ',' ).Contains($ResourceId) ){

    # リソースIDから各引数を抽出
    $AryResourceId = $ResourceId.Split('/')
    $SubscriptionId = $AryResourceId[2]
    $RgName = $AryResourceId[4]
    $VmName = $AryResourceId[-1]

    # リソースIDからサブスクリプションIDを取得し、プロファイルを取得
    try{
        Write-Output "サブスクリプションID $($SubscriptionId) のプロファイルを取得します."
        $TargetProfile = Set-AzContext -SubscriptionId $SubscriptionId
    }catch {
        $ErrorMessage = "エラーが発生しました.サブスクリプションID: $($SubscriptionId) のプロファイルが取得できません。`r`n "
        $ErrorMessage += $_.Exception.message
        Write-Error $ErrorMessage
    }

    try {
        Write-Output "リソースID $($ResourceId) に対して、$($Action) 実行中..."
        switch ($Action) {
            "GetVmInfo" { 
                (Get-AzVM -ResourceGroupName $RgName -Name $VmName -DefaultProfile $TargetProfile -status).Statuses[1].Code }
            "Start" { Start-AzVM -ResourceGroupName $RgName -Name $VmName -DefaultProfile $TargetProfile }
            "Stop" { Stop-AzVM -ResourceGroupName $RgName -Name $VmName -Force -DefaultProfile $TargetProfile }
            "Restart" { Restart-AzVM -ResourceGroupName $RgName -Name $VmName -DefaultProfile $TargetProfile }
        }
        Write-Output "処理は終了しました。"
    }catch {
        $ErrorMessage = "エラーが発生しました: " + $_.Exception.message
        Write-Error $ErrorMessage
    }
}else {
    $ErrorMessage = "リソースID $($ResourceId) は変数で未定義のため、実行は許可されていません "
    Write-Error $ErrorMessage
}

Errorについては何も設定しないと処理を続けてしまうので、以下を参考にしました。
https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7.5#erroractionpreference

カスタムロール作成・割り当て

Automation アカウントに紐づけるカスタムロールを作成します。
スコープはサブスクリプション全体で、アクションは 起動/割り当て解除/再起動/読み取り を持つロールを作成します。

JSONだと以下のようになります。

{
    "properties": {
        "roleName": "cr-operateVm",
        "description": "",
        "assignableScopes": [
            "/subscriptions/[対象のサブスクリプションID]"
        ],
        "permissions": [
            {
                "actions": [
                    "Microsoft.Compute/virtualMachines/start/action",
                    "Microsoft.Compute/virtualMachines/read",
                    "Microsoft.Compute/virtualMachines/restart/action",
                    "Microsoft.Compute/virtualMachines/deallocate/action"
                ],
                "notActions": [],
                "dataActions": [],
                "notDataActions": []
            }
        ]
    }
}

作成したカスタムロールを、作成したAutomation アカウントに割り当てます。
今回はマネージドIDから割り当ててみます。IDからシステム割り当て済み よりAzureロールの割り当てをクリックします。

ロールの割り当ての追加から、サブスクリプションスコープで作成したロールを割り当てます。

操作者用の権限作成

操作者には都度、このAutomationアカウントへのオペレータ権限を付与します。
運用者には、ユーザアクセス管理者として、Automation オペレータの権限を付与できるようにしておきます。


設定・実行

使い方は変数として許可するVMのリソースIDを定義していきます。

変数設定

変数から、名前に実行IDを、値に操作させたいVMのリソースIDをカンマ区切りで指定します。実行IDはユーザの名前など、任意の文字列を指定できます。制限はこちらを確認ください。

実行

実行する際は、先ほど変数で指定した内容と処理を引数として指定します。

ACTIONには、GetVmInfo/Start/Stop/Restart を指定してください。

出力タブで、結果を確認します。

おわりに

今回はAzure Automationを用いて、権限を編集する権限を使わないでAzureVMの操作を行えるような仕組みを考えてみました。
AWSのようにカスタムロールの中でcondition句を使えないので、このような形にしました。

この記事がどなたかのお役に立ちましたら幸いです。

Discussion