【Azure】VMの起動/シャットダウンができるカスタムロールを割り当てつつAutomationをデプロイ(ARMテンプレート編)Tech TIPS

Azure AutomationアカウントでVMの起動やシャットダウンを自動化したい場合、対象のVMを操作するためのアクセス許可を与える必要がある。それには「カスタムロール」にアクセス許可をまとめてAutomationに割り当てればよい。その方法と注意点を説明する。

» 2024年05月08日 05時00分 公開
[島田広道デジタルアドバンテージ]
「Tech TIPS」のインデックス

連載目次

Azure Automationにカスタムロールを割り当ててVM操作

対象: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を構成する。

役割(カスタムロール)と操作元(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

【Bicep】カスタムロールを作成する(roledefine.bicep)
※Microsoftのレファレンス:Microsoft.Authorization roleDefinitionstargetScopeguid()アクセス許可の名称

 「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アカウントをデプロイする際に指定する必要がある。

カスタムロール生成時に出力される「ロールID」をメモしておく カスタムロール生成時に出力される「ロールID」をメモしておく

●生成したカスタムロールを確認する

 生成したカスタムロールを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
  }
}

【Bicep】カスタムロールを割り当てつつAutomationアカウントを生成する(main.bicep)
※Microsoftのレファレンス:Microsoft.Automation automationAccountsmoduledeployment()

 ロールの割り当ては、拡張機能リソースとして生成する必要がある。そのスコープは操作対象リソース側になり、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 // 定義済みロール
  }
}

【Bicep】実際にロールを割り当てるためのテンプレート(roleassign.bicep)
※Microsoftのレファレンス:Microsoft.Authorization roleAssignmentsresourceGroup()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テンプレート編)」を参照していただきたい。

「Tech TIPS」のインデックス

Tech TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。