Azure Bastionの自動起動停止方法(作成削除をスケジュール実行)

2022-04-29Azure,Bastion,Logic Apps,PowerShell/Azure CLI

Azure PowerShellやREST APIを利用した、Azure Bastionリソース作成、削除手順です。

Azure Bastionホストは起動停止できません。
仮想マシン(Azure VM)の起動状況や接続しているかどうかに関わらず継続して課金が発生します。
仮想マシンを停止している場合や、接続しない時間帯にAzure Bastionホストを起動しておくことは無駄に課金が掛かる事になります。

Azure Bastionの価格

停止させて課金を抑えたい所ですが、Azure Bastion自体の起動停止は出来ません。
削除するしか課金を停止手段はありません。
それなら使う時のみ、リソースを作成して削除するようにしようという事で手順をまとめてみました。

Azure PowerShellを使った方法と、REST APIを使った方法を確認してみました。
REST APIはLogic Apps(ロジックアプリ)のワークフローを利用する事でスケジュール化できるようにしています。

※Azure PowerShellの動作確認は、AutomationアカウントのRunbook(PowerShell(7.2))で実施しています。
※Developer SKUは無料で利用できます。
※本手順は検証利用を目的として確認しています。利用する場合は十分にご注意ください。

スポンサーリンク

PowerShellを使ったAzure Bastion作成、削除

Azure Bastionに関するPowerShellコマンドレット

Azure Bastionのリソース作成などで利用する、主なPowerShellコマンドレットは4つです。
作成、情報取得、更新、削除です。
リソース作成時にはAzure Portalと同じ項目を設定します。
リソース名、リソースグループ名、ロケーション、仮想ネットワークのリソース情報、パブリックIPのリソース情報、SKUなどを指定します。

処理 Azure PowerShell
作成 New-AzBastion
取得 Get-AzBastion
更新 Set-AzBastion
削除 Remove-AzBastion

作成したAzure Bastionの設定内容

作成したリソースの設定内容です。
Azure BastionのSKUはStandardを想定しています。
パブリックIPはAzure Bastionのリソースと同時に作成しています。
事前に作成されている、仮想ネットワークやサブネットを利用する想定としています。

要素 項目 設定値
パブリックIP 名前 bas-pip-01
SKU Standard
仮想ネットワーク 仮想ネットワーク名 test-vnet-01
アドレス空間 10.0.0.0/16
サブネット名 AzureBastionSubnet
ループ回数 10.0.255.0/26
Bastion 名前 bas-01
SKU Standard
インスタンス数 2
詳細設定 すべてにチェック
(セッションの記録除く)

※セッションの記録はStandard SKUでは利用できません。
※課金が掛かるリソースのみ(パブリックIPやAzure Bastion)を新規作成する想定としています。

Azure Portalを利用したBastionホストの作成はこちら。

PowerShellを使ってAzure Bastionを作成

Azure PowerShellを利用してAzure Bastionのリソースを作成します。
最初にAzure Bastionのリソースを作成する仮想ネットワーク、サブネットの情報を取得します。
次にパブリックIPアドレス作成、最後にAzure Bastionのリソースを作成しています。

Get-AzVirtualNetwork:仮想ネットワークの情報を取得
New-AzPublicIpAddress:パブリックIPのリソースを作成
New-AzBastion:Azure Bastionのリソースを作成

パブリックIPアドレスのSKUはStandardを指定します。
Azure Bastionの機能は個別に有効、無効を指定します。

※Automationアカウントで利用する想定としています。利用環境に応じてManagedIDの認証処理やサブスクリプションの指定等を削除してください。
※すべてのリソースが、同じリソースグループにある想定になっています。異なるリソースグループを利用する場合は変数の指定を追加、変更してください。

Azure Bastionのリソースを作成するPowerShell
###変数設定(Standardの場合)###

# リソースグループ名
$rgname = “test-rg-01"
# リージョン
$location = “japaneast"
# 仮想ネットワーク名
$vnetname = “test-vnet-01"
# パブリックIP名
$pipname = “bas-pip-01"
# パブリックIPのSKU
$pipsku = “Standard"
# Bastion名
$basname = “bas-01"
# BastionのSKU
$bassku = “Standard"
# Bastionのユニット数(デフォルト値は2)
$basscaleunit = 2
# コピー/貼り付け(許可する場合はFalse)
$bascopypaste = [System.Convert]::ToBoolean(“False")
# IPベースの接続(許可する場合はTrue)
$basipconnect = [System.Convert]::ToBoolean(“True")
# Kerberos 認証(許可する場合はTrue)
$baskerberos = [System.Convert]::ToBoolean(“True")
# ネイティブ クライアント サポート(許可する場合はTrue)
$bastunneling = [System.Convert]::ToBoolean(“True")
# 共有可能なリンク(許可する場合はTrue)
$basshareablelink = [System.Convert]::ToBoolean(“True")

# ManagedID 認証処理
Disable-AzContextAutosave -Scope Process
$AzureContext = (Connect-AzAccount -Identity).context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext

# サブスクリプションID
$subscription = “サブスクリプションID"

# サブスクリプション指定
Set-AzContext -SubscriptionId $subscription

# 仮想ネットワーク情報取得
$vnet = Get-AzVirtualNetwork -Name $vnetname `
-ResourceGroupName $rgname

# パブリックIPのリソースを作成
$pip = New-AzPublicIpAddress -Name $pipname `
-ResourceGroupName $rgname `
-Location $location `
-AllocationMethod Static `
-IpAddressVersion “IPv4" `
-Sku $pipsku

# Azure Bastionのリソースを作成
New-AzBastion -Name $basname `
-ResourceGroupName $rgname `
-PublicIpAddress $pip `
-VirtualNetwork $vnet `
-Sku $bassku `
-ScaleUnit $basscaleunit `
-EnableKerberos $baskerberos `
-DisableCopyPaste $bascopypaste `
-EnableTunneling $bastunneling `
-EnableIpConnect $basipconnect `
-EnableShareableLink $basshareablelink

Automationアカウントのリソース作成から仮想マシン起動を例にしたRunbook作成手順についてはこちらで紹介しています。

Runbookのスケジュール設定についてはこちらの記事で紹介しています。

PowerShellを使ってAzure Bastionを削除する

Azure PowerShellを利用してAzure Bastionのリソースを削除します。
使用したコマンドレットです。

Remove-AzBastion:Azure Bastionのリソースを削除
Remove-AzPublicIpAddress:パブリックIPのリソースを削除

仮想ネットワークやサブネットはそのまま残しています。

※課金が発生するパブリックIPとAzure Bastionのリソースのみ削除しています。

Azure Bastionのリソースを削除するPowerShell
###変数設定(Standardの場合)###

# リソースグループ名
$rgname = “test-rg-01"
# パブリックIP名
$pipname = “bas-pip-01"
# Bastion名
$basname = “bas-01"

# ManagedID 認証処理
Disable-AzContextAutosave -Scope Process
$AzureContext = (Connect-AzAccount -Identity).context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext

# サブスクリプションID
$subscription = “サブスクリプションID"

# Azure Bastionのリソースを削除
Remove-AzBastion -Name $basname `
 -ResourceGroupName $rgname `
 -Force

# パブリックIPのリソースを削除
Remove-AzPublicIpAddress -Name $pipname `
 -ResourceGroupName $rgname `
 -Force

作成したリソースの設定内容を確認

PowerShellで作成したAzure Bastionのリソースを確認します。
設定にある構成のメニューで確認します。
レベル(SKU)や機能が指定通り有効化されているのが確認できました。

作成したリソースの設定内容を確認

左側のメニューで構成を選択します。
レベルや機能が指定通りになっている事が確認できました。

Azure Bastionの構成画面で、作成したリソースの設定内容を確認

—広告—

REST APIを使ってAzure Bastionを作成、削除(Logic Appsを利用)

Azure BastionのREST API

REST APIを利用してAzure Bastionのリソース作成や削除などの操作ができます。

Bastion Hosts(REST API)

Logic AppsをREST APIのスケジュール実行環境として利用

今回、REST APIをスケジュール実行させる環境としてLogic Appsを利用します。
従量課金(消費)(マルチテナント)のプランで2つのリソースを作成しています。

logic-bas-start-01:リソースを作成
logic-bas-stop-01:リソースを削除

Logic Appsのリソース作成手順についてはこちらの記事で紹介しています。
トリガーやアクションの概要についてもこちらで紹介しています。

Logic Appsでシステム割り当てマネージドIDを設定

Logic AppsのワークフローでAzureのリソース操作を行うために認証が必要となる事があります。
HTTPやAzure Resource Managerのコネクタで認証が必要となります。

今回の手順では、認証にシステム割り当てマネージドIDを利用しています。
Logic Appsのリソースに対して、Azure Bastionのリソース作成に必要なロールを割り当てます。

※割り当ては必要なロールのみに制限する事が推奨されます。

Logic AppsのマネージドID設定

IDのメニューで有効化、Azure ロールの割り当て設定します。
今回はリソースグループに対して、共同作成者のロールの割り当てます。

 

 

Logic Appsのシステム割り当て済みマネージドID設定を有効化
Logic Appsに共同作成者のロールを割り当て
Logic Appsのシステム割り当て済みマネージドIDに共同作成者のロールを割り当てた時の画面表示例

Logic AppsのワークフローからREST APIを実行してAzure Bastionを作成

ロジックアプリデザイナーを利用してワークフローを作成します。
PowerShellの場合と同様に仮想ネットワークやサブネットは事前にあるリソースを利用しています。
パブリックIPアドレスとAzure Bastionのリソースを作成しています。

    • 主なワークフローの流れ
      • スケジュール設定
      • サブスクリプションの読み取り
      • 変数設定
      • HTTPのアクションでパブリックIPアドレスを作成
      • リソースの読み取り
      • HTTPのアクションをでAzure Bastionを作成

リソースの読み取りでは作成したパブリックIPアドレスや仮想ネットワークのリソースIDを取得しています。

Azure Bastionホストを作成
トリガーを追加します。
ScheduleコネクタにあるRecurrenceのアクションを選択します。
毎朝9時30分(日本時間)に実行されるように設定します。
scheduleのトリガーを追加(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
毎朝9時30分に実行するスケジュール設定例(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

Azure Resource Managerコネクタにあるサブスクリプション読み取るアクションでサブスクリプションIDを取得します。

Azure Resource Managerコネクタを利用する場合は接続の作成が必要になります。
今回は認証にマネージドIDを利用した接続を作成しています。

サブスクリプション読み取るのアクションを選択(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
システム割り当てマネージドIDを使った接続の作成(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
サブスクリプションを読み取るのアクション設定(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

Variablesのコネクタを利用して変数を設定します。
initialize variable(変数の初期化)のアクションを選択します。
変数名を指定します。
TypeにはObjectを指定します。
リソース作成時の設定値を指定します。

※アクションの名前は変更できます。分かりやすい名前で設定します。

Variablesのアクション設定でinitialize variableを選択(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

Azure Bastionのリソース設定値をObjectの変数として設定した画面例(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

【変数の設定内容】

{
 “rg": {
  “rgname": “test-rg-01",
  “location": “japaneast"
 },
 “vnet": {
  “vnetname": “test-vnet-01"
 },
 “pip": {
  “pipname": “bas-pip-01",
  “pipsku": “Standard"
 },
 “bas": {
  “basname": “bas-01",
  “bassku": “Standard",
  “basscaleunit": “2",
  “bascopypaste": “False",
  “basipconnect": “True",
  “baskerberos": “True",
  “bastunneling": “True",
  “basshareablelink": “True"
 }
}

REST APIを利用してパブリックIPアドレスのリソースを作成します。

HTTPのコネクタから、REST APIを利用できます。
HTTPのアクションで実行するREST APIのURI、Method、bodyなどを指定します。
URIや指定するパラメーターについてはこちらを参照します。

Public IP Addresses – Create Or Update

URIで作成するパブリックIPのリソース名を指定してます。
SKUなどはbodyで指定しています。

認証の設定も行います。
設定値は変数から取得しています。

HTTPのアクションを選択(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
HTTPのアクション設定画面例(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
パブリックIPアドレスを作成するREST APIをHTTPのアクションに設定した例(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
詳細パラメーターでAuthentication(認証)を追加します。
認証の種類にはマネージドIDを指定します。
マネージドIDにはシステム割り当てマネージドIDを指定します。
詳細パラメーター設定でAuthenticationを選択(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
Authenticationでシステム割り当てマネージドIDを選択(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

設定した変数や値を利用します。
動的なコンテンツの挿入を選択すると、前のアクションの値を利用できます。
サブスクリプションを読み取るのサブスクリプションIDを指定しています。

式の挿入から関数を利用できます。
関数を利用して変数から値を取得できます。
variables関数を利用してobjectの変数から値を取得しています。

HTTPアクションのURI設定画面例(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
サブスクリプションを読み取るで取得したサブスクリプションIDを設定(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
# 設定した変数"basvariables"からリソースグループ名を取得
variables('basvariables’)['rg’]['rgname’] 
# 設定した変数"basvariables"からパブリックIP名を取得
variables('basvariables’)['pip’]['pipname’]
# 設定した変数"basvariables"からパブリックIPのSKUを取得
variables('basvariables’)['pip’]['pipsku’]
#設定した変数"basvariables"からリソースを作成するリージョンを取得
variables('basvariables’)['rg’]['location’] 
 
【リソースグループ名の例】(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

【パブリックIPアドレス名の例】(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

仮想ネットワークとパブリックIPのリソースIDを取得します。
Azure Resource Managerコネクタにあるリソースを読み取るアクションを利用します。
短いリソースIDに指定するリソース名は変数から取得しています。

【短いリソースIDの指定例】
publicIPAddresses/bas-pip-01

取得したリソースIDはBastionのリソース作成時に利用します。

Azure Resource Managerのリソースを読み取るのアクションで仮想ネットワークのリソースIDを取得(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
Azure Resource Managerのリソースを読み取るのアクションでパブリックIPのリソースIDを取得(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

REST APIを利用してAzure Bastionのリソースを作成します。
HTTPのアクションから、REST APIを利用します。
実行するREST APIのURI、Method、bodyなどを指定します。
こちらを参照して、URIやパラメーターを指定します。

Bastion Hosts – Create Or Update

認証の設定も行います。
設定値は変数から取得しています。

※設定後のコードビューの値も記載しています。設定内容の詳細はこちらを参照ください。
※関数や式などを設定している時に"/"が抜けてエラーになる事があります。エラーになった場合はまず"/"が抜けてないか確認しましょう。

HTTPのアクションを選択(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
Azure Bastionのリソースを作成するようURIにREST APIの設定(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
Azure Bastionのリソースを作成するようBodyにBastionのリソース設定値を指定(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

bodyで指定するパブリックIPやサブネットのリソースIDは取得した値を利用しています。
サブネットのリソースIDは仮想ネットワークのリソースIDを利用して作成しています。
URIやbodyで使用する設定値は変数から取得して利用しています。

 

 

仮想ネットワークのリソースIDを指定(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
パブリックIPのリソースIDを指定(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

【変数の設定例】

# 設定した変数"basvariables"からリソースグループ名を取得
variables('basvariables’)['rg’]['rgname’] 
# 設定した変数"basvariables"からリソースを作成するリージョンを取得
variables('basvariables’)['rg’]['location’]

# 設定した変数"basvariables"からAzure Bastionの名を取得
variables('basvariables’)['bas’]['basname’]
# 設定した変数"basvariables"からAzure BastionのSKUを取得
variables('basvariables’)['bas’]['bassku’]

【コードビューの表示結果】

{
  “type": “Http",
  “inputs": {
    “uri": “https://management.azure.com/subscriptions/@{body('サブスクリプションを読み取る’)?['subscriptionId’]}/resourceGroups/@{variables('basvariables’)['rg’]['rgname’]  }/providers/Microsoft.Network/bastionHosts/@{variables('basvariables’)['bas’]['basname’]  }?api-version=2023-11-01",
    “method": “PUT",
    “headers": {
      “Content-Type": “application/json"
    },
    “body": {
      “name": “@{variables('basvariables’)['bas’]['basname’]}",
      “location": “@{variables('basvariables’)['rg’]['location’]}",
      “sku": {
        “name": “@{variables('basvariables’)['bas’]['bassku’]}"
      },
      “properties": {
        “scaleUnits": “@variables('basvariables’)['bas’]['basscaleunit’]",
        “disableCopyPaste": “@variables('basvariables’)['bas’]['bascopypaste’]",
        “enableTunneling": “@variables('basvariables’)['bas’]['bastunneling’]",
        “enableIpConnect": “@variables('basvariables’)['bas’]['basipconnect’]",
        “enableShareableLink": “@variables('basvariables’)['bas’]['basshareablelink’]",
        “enableKerberos": “@variables('basvariables’)['bas’]['baskerberos’]",
        “ipConfigurations": [
          {
            “name": “bastionHostIpConfiguration",
            “properties": {
              “subnet": {
                “id": “@{body('仮想ネットワークIDを読み取る’)?['id’]}/subnets/AzureBastionSubnet"
              },
              “publicIPAddress": {
                “id": “@{body('パブリックIPのリソースIDを読み取る’)?['id’]}"
              }
            }
          }
        ]
      }
    },
    “authentication": {
      “type": “ManagedServiceIdentity"
    }
  },
  “runAfter": {
    “パブリックIPのリソースIDを読み取る": [
      “Succeeded"
    ]
  },
  “runtimeConfiguration": {
    “contentTransfer": {
      “transferMode": “Chunked"
    }
  }
}

作成したワークフローを保存します。

 

完成したAzure Bastionのリソースを作成するワークフロー(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)
完成したAzure Bastionのリソースを作成するワークフロー(Azure Bastionのリソースを作成するLogic Appsワークフローを作成)

Logic AppsのワークフローでサブスクリプションIDを取得する方法についてはこちらで紹介しています。

Azure Logic Appsのワークフローを平日のみ実行する方法についてはこちらで紹介しています。

ワークフローを実行してAzure Bastionのリソースを作成状況を確認

ワークフローを実行して結果を確認します。
Azure Bastionのリソースが作成されている事が確認できます。

※今回は手動でワークフローを実行しています。

ワークフローの実行結果
Logic Appsで実行の履歴を確認します。
成功している事が確認できます。

Azure Bastionのリソースを作成するワークフローの実行履歴例
Azure Bastionのリソースでアクティビティログや構成を確認します。
イベント開始者がLogic Appsのリソース名となっており、ワークフローによりリソースが作成された事が確認できます。
変数に指定した通りAzure Bastionのリソースが作成されている事が構成の設定から確認できます。
Logic AppsのワークフローでAzure Bastionのリソースを作成した場合のアクティビティログ
Azure Bastionの構成画面で、作成したリソースの設定内容を確認

ワークフローのコピー

Logic Appsの従量課金(マルチテナント)では複製を使ってワークフローをコピーする事ができます。
起動と停止を個別にワークフロー作成する場合などに使うと便利かと思います。

Logic AppsのワークフローからREST APIを実行してAzure Bastionを削除

Azure Bastionのリソースを削除するワークフロー例です。
スケジュール設定、変数設定、HTTPのアクションでREST API実行という流れになります。

※パブリックIPアドレスのリソースも削除しています。

Azure Bastionホストを削除
ワークフロー例です。
Azure Bastionのリソース削除後に、パブリックIPアドレスも削除しています。
Azure Bastionのリソースを削除するLogic Appsのワークフロー例

REST APIを利用してAzure Bastionのリソースを削除します。
HTTPのアクションから、REST APIを利用します。
こちらを参照して、URIやパラメーターを指定します。

Bastion Hosts – Delete

MethodはDELETEになります。
ヘッダーや本文の設定は必要ありません。

Azure Bastionのリソースを削除するHTTP(REST API)のアクション設定例

【コードビューの表示結果(Bastionのリソース削除部分)】

{
  “type": “Http",
  “inputs": {
    “uri": “https://management.azure.com/subscriptions/@{body('サブスクリプションを読み取る’)?['subscriptionId’]}/resourceGroups/@{variables('basvariables’)['rg’]['rgname’]  }/providers/Microsoft.Network/bastionHosts/@{variables('basvariables’)['bas’]['basname’]  }?api-version=2023-11-01",
    “method": “DELETE",
    “authentication": {
      “type": “ManagedServiceIdentity"
    }
  },
  “runAfter": {
    “Bastionの設定値": [
      “Succeeded"
    ]
  },
  “runtimeConfiguration": {
    “contentTransfer": {
      “transferMode": “Chunked"
    }
  }
}

ワークフローを実行してAzure Bastionのリソースを削除状況を確認

ワークフローを実行して結果を確認します。
Azure Bastionのリソースが削除されている事が確認できます。

※今回は手動でワークフローを実行しています。

ワークフローの実行結果
Logic Appsで実行の履歴を確認します。
成功している事が確認できます。
アクティビティログから、パブリックIPアドレスとAzure Bastionのリソースが削除された事が確認できます。

Azure Bastionのリソースを削除するワークフローの実行履歴例
Logic AppsのワークフローでAzure Bastionのリソースを削除した場合のアクティビティログ

—広告—

最後に

今回はAzure PowerShellやLogic AppsのワークフローからREST APIを実行してAzure Bastionホストの作成、削除する手順を確認しました。
Logic Appsのワークフローを使う事で、Azure Bastionのリソース作成削除をスケジュール実行できました。
仮想マシンの自動起動停止と組み合わせて使う事でコスト削減も可能かと思いました。

引き続き色々試してみたいと思います。

Logic Appsを使った仮想マシン(Azure VM)の起動停止についてはこちらで紹介しています。
Azure Resource Managerを利用した方法についても紹介しています。

Logic Appsを使ったAzure API Managementの起動停止(論理削除、回復)のスケジュール化についてはこちらで紹介しています。

スポンサーリンク