【Azure】VMの起動/シャットダウンができるカスタムロールを割り当てつつAutomationをデプロイ(ARMテンプレート編):Tech TIPS
Azure AutomationアカウントでVMの起動やシャットダウンを自動化したい場合、対象のVMを操作するためのアクセス許可を与える必要がある。それには「カスタムロール」にアクセス許可をまとめてAutomationに割り当てればよい。その方法と注意点を説明する。
対象:Azure Automation、カスタムロール、ARMテンプレート(Bicep)
Tech TIPS「【Azure】Automation RunbookにGitHub上のPowerShellスクリプトをインポートする(ARMテンプレート編)」で解説した手順でPowerShellスクリプトをRunbookとしてAutomationアカウントに組み込んでも、それだけでは実際にVMなど他のリソースの制御はできない。
Automationアカウントで他のリソースを操作するには、そのための「アクセス許可」をAutomationアカウントに割り当てる必要がある。
そこで本Tech TIPSでは、VMの起動/シャットダウンを例として、リソース操作の許可を与えつつAutomationアカウントを生成する方法を説明する。デプロイにはBicepで記述したARM(Azure Resource Manager)テンプレートを使用する。
■執筆時の各種ツール/APIのバージョン
- Azure CLI: Ver. 2.60.0
- Bicep CLI: Ver. 0.27.1
- Bicepでのデプロイ時のAPIバージョン: 2023-11-01(Automationアカウント)、2022-04-01(ロールの生成と割り当て)
Automationアカウントとカスタムロール、VMとの関係
使用するARMテンプレートを具体的に解説する前に、AutomationアカウントにVMを操作するための許可を与える方法について、簡単に説明しておく。
Azureのリソースを操作するには、その操作元(リソースあるいはユーザー、グループなど)に対象リソースを制御するための「アクセス許可」を与える必要がある。アクセス許可の内容は、「ロールベースのアクセス制御(RBAC)」という仕組みにのっとって、あらかじめ細かく決まっている。VMなら、起動やシャットダウン、割り当て解除、再起動などがそれぞれ別々のアクセス許可として取り扱える。
リソース操作に必要な複数のアクセス許可をまとめてセットにしものが「Azureロール」といえる。最初から用意されている(組み込み済みの)Azureロールとして、「所有者」「閲覧者」などを目にしたことがあるのではないだろうか。
組み込み済みのロールとは別に、個々のアクセス許可を自由にまとめられる「カスタムロール」も利用できる。本Tech TIPSでは、VMの起動/シャットダウンなどの許可をまとめたカスタムロールを作成し、それをAutomationアカウントに割り当てることで、AutomationによるVMの自動制御を実現する。
具体的には下図のような位置付けでカスタムロールとAutomationアカウント、VMを構成する。
カスタムロールはサブスクリプション内ならどのリソースでも利用できるように生成する(他のサブスクリプションからは利用できない)。
一方、実際に操作するVMは特定のリソースグループ内だけに制限する(上図では「リソースグループA」内のVMのみ操作可能)。無制限、すなわちサブスクリプション内の全VMを操作できるようにすると、誤って別のプロジェクトのVMを止めてしまった、といった事故が生じかねないからだ。
さて、以下では説明を簡単にするために、操作対象のVMはデプロイ済みとする。また、各リソースを生成する前に、「az account set」コマンドを以下のように実行して、デフォルトのサブスクリプションを適切に選択しておく。
az account set -s <サブスクリプション名>
掲載しているAzure CLIのコマンドラインは、Windows OSのコマンドプロンプトで実行することを前提としている。
【Bicep】カスタムロールを作成する
ここからは、各リソースを生成するARMテンプレートについて説明していく。
まずは、VMの起動/シャットダウンなどの許可をまとめたカスタムロールを作成(定義)する。その際、サブスクリプションレベルでカスタムロールを作成するための許可(組み込み済みのロールなら「所有者」など)が与えられているユーザーでデプロイすること。
// ファイル名: roledefine.bicep
targetScope = 'subscription' // デプロイ時のデフォルトのサブスクリプションレベルでロール定義
param roleName string // このロールの名前
param description string // このロールの説明文
// 許可する操作の一覧
param actions array = [
'Microsoft.Compute/virtualMachines/read' // VMの情報の読み取り
'Microsoft.Compute/virtualMachines/start/action' // VMの起動
'Microsoft.Compute/virtualMachines/deallocate/action' // VMの割り当て解除
'Microsoft.Compute/virtualMachines/powerOff/action' // VMのシャットダウン
'Microsoft.Compute/virtualMachines/restart/action' // VMの再起動
]
var permissions = [
{
actions: actions
notActions: []
}
]
var roleDefineScope = subscription() // デプロイ時のデフォルトのサブスクリプション
var roleDefineName = guid(roleDefineScope.id, roleName) // テナント間で一意なGUIDを指定
var assignableScopes = [
roleDefineScope.id // サブスクリプション内に割り当て可能
]
var roleType = 'customRole' // カスタムロール
// 拡張機能リソース生成: ロール定義
resource roleDefine 'Microsoft.Authorization/roleDefinitions@2022-04-01' = {
name: roleDefineName
properties: {
roleName: roleName
description: description
assignableScopes: assignableScopes
permissions: permissions
type: roleType
}
}
// 定義したロールのIDを出力(割り当て時に利用)
output definedRoleId string = roleDefine.name
※Microsoftのレファレンス:Microsoft.Authorization roleDefinitions、targetScope、guid()、アクセス許可の名称
「targetScope = 'subscription'」は、スコープをサブスクリプションにする、すなわちサブスクリプションに対してリソース(カスタムロール)をデプロイすることを意味する。
アクセス許可はパラメーター「actions」の配列に列挙する。「Microsoft.」から始まる各アクセス許可の名称については、Microsoft Learn「Azure のアクセス許可」にレファレンスが掲載されている。他の許可を追加する場合は、このページを参照していただきたい。
パラメーター「roleName」で指定するカスタムロールの名前には、スペースが含まれていてもよい。パラメーター「description」の説明文についても同様だ。
上記のテンプレートでカスタムロールを生成するには、「az deployment sub create」コマンドを以下のように実行する。
az deployment sub create -l <リージョン名> -f roledefine.bicep -p "roleName=<このロールの名前>" "description=<このロールの説明文>"
デプロイが完了したら、出力されたJSONの「properties.outputs.definedRoleId.value」に記載のGUID(以下、「ロールID」)をメモしておく。これは後ほどAutomationアカウントをデプロイする際に指定する必要がある。
●生成したカスタムロールを確認する
生成したカスタムロールをAzure CLIで確認するには、「az role definition list」コマンドを以下のように実行する。
az role definition list --custom-role-only
前述のロールIDは「name」に出力されるはずだ。
Azureポータルの場合は、以下のようにサブスクリプションの「アクセス制御(IAM)」ページで確認できる。
上記のように作成したカスタムロールは、以後、同じサブスクリプション内であれば使い回すことが可能だ。
【Bicep】カスタムロールを割り当てつつAutomationアカウントを生成する
カスタムロールのデプロイが完了したら、Automationアカウントを生成する。以下では、主にAutomationアカウントを生成する「main.bicep」と、作成したカスタムロールをAutomationアカウントに割り当てる「roleassign.bicep」という2つのテンプレートファイルに分割して例示している。
// ファイル: main.bicep
param automationAccountName string // Automationアカウント名
param location string = resourceGroup().location
param publicNetworkAccess bool = true // パブリックネットワークからのアクセスの可否
param disableLocalAuth bool = false // ローカル認証の可否
var identity = {
type: 'SystemAssigned' // マネージドID: システム割り当て
}
var sku = {
name: 'Basic' // SKU: Basic
}
var encryption = {
keySource: 'Microsoft.Automation' // 暗号化: デフォルトのまま
identity: {}
}
// リソース生成: Automationアカウント
resource automationAccount 'Microsoft.Automation/automationAccounts@2023-11-01' = {
name: automationAccountName
location: location
identity: identity
properties: {
publicNetworkAccess: publicNetworkAccess
disableLocalAuth: disableLocalAuth
sku: sku
encryption: encryption
}
}
////////////////////////////////////////
param definedRoleId string // カスタムロールのロールID
param roleAssignDesc string // このロール割り当ての説明文
// このロール割り当てのスコープ指定
param VMsResourceGroupName string // 操作対象のVMが所属するリソースグループ名
var roleAssignScope = resourceGroup(VMsResourceGroupName) // VMと同じリソースグループに生成
// このロールの割り当て先(ここではAutomationアカウント)の指定
var assignedPrincipalId = automationAccount.identity.principalId // プリンシパルID
var assignedPrincipalType = 'ServicePrincipal' // ↑のIDの種別
// モジュール: ロール割り当て
module roleAssignModule './roleassign.bicep' = {
name: '${deployment().name}-roleAssign'
scope: roleAssignScope
params: {
description: roleAssignDesc
definedRoleId: definedRoleId
principalId: assignedPrincipalId
principalType: assignedPrincipalType
}
}
※Microsoftのレファレンス:Microsoft.Automation automationAccounts、module、deployment()
ロールの割り当ては、拡張機能リソースとして生成する必要がある。そのスコープは操作対象リソース側になり、Automationアカウントとは異なることがよくある。その場合、ロール割り当てとAutomationアカウントの生成は単一のテンプレートファイルには記述できない(デプロイ時にエラーが生じる)。そのため、ロール割り当ては別のテンプレート(roleassign.bicep)に記述し、main.bicepからはモジュールで呼び出している。
Automationアカウント生成でのポイントは、マネージドIDを有効化して、それによって生成された「プリンシパルID(オブジェクトID)」をロールの割り当て先(モジュールのパラメーター「principalId」)として指定していることだ。上記テンプレートでは、手軽な「システム割り当て」を選んでいる(Microsoftは「ユーザー割り当て」を推奨している)。
カスタムロールの生成時にメモしたロールIDは、パラメーター「definedRoleId」に指定すること。また操作対象のVMが所属するリソースグループ名を、パラメーター「VMsResourceGroupName」に指定する必要もある。
以下は、ロール割り当てのテンプレートである。
// ファイル: roleassign.bicep
// 既存リソース: 定義済みのロール
param definedRoleId string // これから割り当てる定義済みロールのID
var definedRoleScope = subscription() // サブスクリプションレベルで定義
resource definedRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
name: definedRoleId // 定義済みロールのID
scope: definedRoleScope
}
////////////////////////////////////////
param principalId string // ロール割り当て先を表すID
@allowed([
'Device'
'ForeignGroup'
'Group'
'ServicePrincipal' // システム割り当てのマネージドID
'User'
])
param principalType string // ↑の種別
param description string = '' // このロール割り当ての説明文
var roleAssignScope = resourceGroup() // このロール割り当ての適用範囲
// テナント間で一意なGUIDを生成
// スコープ(=リソースグループ)、マネージドID、ロールの各IDを利用
var roleAssignName = guid(roleAssignScope.id, principalId, definedRole.id)
// 拡張機能リソース生成: ロール割り当て
resource roleAssign 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: roleAssignName // 生成したGUIDを指定
scope: roleAssignScope
properties: {
description: description
principalId: principalId // 割り当て先
principalType: principalType
roleDefinitionId: definedRole.id // 定義済みロール
}
}
※Microsoftのレファレンス:Microsoft.Authorization roleAssignments、resourceGroup()、subscription()、guid()
割り当て先としてマネージドIDを指定する場合は、パラメーター「principalType」に「ServicePrincipal」を指定すること。
ロール割り当てリソースの「name」には、テナント間で一意な(重複していない)GUIDを指定する必要がある。ここではguid()関数を用いて、スコープ(VM所属のリソースグループ)とプリンシパルID(Automationアカウント)、カスタムロールの各IDから生成したハッシュ値を指定している。
上記のテンプレートからデプロイするには、「az deployment group create」コマンドを以下のように実行する。
az deployment group create -g <リソースグループ名> -f main.bicep -p automationAccountName=<Automationアカウント名> definedRoleId=<定義したロールのGUID> VMsResourceGroupName=<VMのリソースグループ名> "roleAssignDesc=<ロール割り当ての説明文>"
以上で、特定のVMを起動/シャットダウンできるAutomationアカウントがデプロイできるはずだ。
実際にVMを操作するには、Tech TIPS「【Azure】Automation RunbookにGitHub上のPowerShellスクリプトをインポートする(ARMテンプレート編)」で説明しているように、VMの起動やシャットダウンをするためのPowerShellスクリプトをRunbookとして登録する必要もある。
さらに多くの場合、そのRunbookを定期的に実行するスケジュールを組む必要もあるだろう。その方法については、Tech TIPS「【Azure】AutomationアカウントでVMの起動/停止を定期的に繰り返すスケジュールを組む(ARMテンプレート編)」を参照していただきたい。
■関連リンク
- Azureロールベースのアクセス制御(Azure RBAC)とは(Microsoft Learn)
- Azureのアクセス許可 - Azure RBAC(Microsoft Learn)
- Azure ロールの定義について - Azure RBAC(Microsoft Learn)
- Azure Resource Managerテンプレートを使用してAzureカスタムロールを作成または更新する - Azure RBAC(Microsoft Learn)
- Bicepを使用してサブスクリプションにリソースをデプロイする - Azure Resource Manager(Microsoft Learn)
- Bicepを使用してAzureでのロールを割り当てる - Azure RBAC(Microsoft Learn)
- 特定のユーザーへ仮想マシンの起動/停止/再起動のみの操作を許可する方法(Japan Azure IaaS Core Support Blog)
Copyright© Digital Advantage Corp. All Rights Reserved.