Azure Automation で Bastion を自動作成/削除してみる

Azure Automation で Bastion を自動作成/削除してみる

今回は Azure Automation を使って Azure Bastion の自動作成および削除を行えるようにしてみます。Azure Bastion は Azure AD と連携してセキュアに仮想マシンへのリモート接続 (SSH, RDP) ができるソリューションです。

はじめに

Azure Bastion って何がいいの

従来だと踏み台サーバーとして接続用の VM を用意しておくのがセオリーでしたが、昨今はクラウドにシステムを構築する関係上インターネットからの接続のためにポートを開いておく必要がある状態ではリスクが付きまといます。かといって細かく接続元の IP アドレスを指定するのも管理の負荷が増えてしまいます。

そのため Azure であれば、Azure AD と連携して認証を行い、ブラウザベースでリモート接続できる Azure Bastion を利用するのが望ましいです。他のクラウドサービスでも似たような接続機能が用意されています。

Azure Bastion のアーキテクチャ

具体的には Azure Bastion がプロキシーのような役割をして、仮想ネットワーク内の VM への接続を中継してくれます。接続したい VM にパブリック IP アドレスを付ける必要はありません。

Azure Bastion | Microsoft Docs

でもお高いんでしょう?

そう、Azure Bastion は中々いいお値段をしています。通常の SKU で \21.28/h なので、大体月額だと 15534.4 円になります。Standard は現段階だと \32.48 なので月額 23710.4 円くらいでしょうか。プレビュー価格だった場合は半額になっているのでもしかしたら倍の 47420.8 円くらいかもしれません。

価格 – Azure Bastion | Microsoft Azure

セキュリティには役立ちますが、常時起動させておく必要がない環境では節約のために電源を落とせる VM でいいや〜となってしまうかもしれません。

なので、今回は Azure Automation を使って簡単に Azure Bastion をデプロイできるようにして、使いたい時だけ Azure Bastion を利用できるようにしてみたいと思います。こうすると例えば平日日中9時から18時の間だけ稼働させれば月額3800円くらいになります。(9 hours * 5 days * 4 weeks = 180 hours として試算)

構築手順

事前準備

  • Azure Automation アカウントを作成しておく
  • 仮想ネットワークを作成しておく
  • 仮想ネットワークに Azure Bastion 用のサブネットを作成しておく

Azure Bastion 用のサブネットは名称と必要なアドレス範囲の大きさが決まっているのでご注意ください。

項目設定値
サブネット名AzureBastionSubnet
サブネット範囲の大きさ/27 以上

1. Automation モジュールのインポート

Automation アカウントで PowerShell コマンドを実行できるよう、必要なモジュールをインポートします。Az モジュールを一発インストールしたいところですが、依存関係を細かく解かないといけないため必要最低限で進めます。

Automation アカウントのメニューから [モジュール ギャラリー] をクリックします。検索バーに「Az.Accounts」と入力し、検索結果の一覧に表示された [Az.Accounts] をクリックします。

[Az.Accounts] にて、[インポート] をクリックします。

少し時間がかかるので待機し、モジュールがインポートされたことを確認します。

同様の手順で「Az.Network」モジュールもインポートします。

2. Automation 変数の準備

PowerShell スクリプト内で利用するための変数を準備しておきます。

Automation アカウントのメニューから [変数] をクリックし、上部の [変数の追加] をクリックします。

[新しい変数] にて、次のように変数を作成します。値は実際の環境に合わせて設定してください。

名前説明タイプ
AZBAS_Bastion_NameBastion のリソース名文字列
AZBAS_PIP_NAMEBastion のパブリック IP アドレス名文字列
AZBAS_ResourceGroup_NameBastion を配置する仮想ネットワークのリソースグループ名文字列
AZBAS_Vnet_NameBastion を展開する仮想ネットワーク名文字列

次のように設定できていれば OK です。

3. 作成ランブックの作成

Azure Bastion を作成するランブックを作成していきます。

Automation アカウントのメニューから [Runbook] をクリックし、上部の [Runbook の作成] をクリックします。

[Runbook の作成] にて、次のように入力して [作成] をクリックします。

  • [名前]: Create-AzBastion
  • [Runbook の種類]: [PowerShell]
  • [説明]: Bastion を作成する Runbook

作成したら上部の [編集] をクリックし、エディターに次のコードをペーストします。

## Initiate connection
$conn = Get-AutomationConnection -Name 'AzureRunAsConnection'
Write-Output 'Connecting to Azure...'
Connect-AzAccount `
  -ServicePrincipal `
  -Tenant $conn.TenantID `
  -ApplicationId $conn.ApplicationID `
  -CertificateThumbprint $conn.CertificateThumbprint
Write-Output 'Connect succeeded!'

## Define variables
$rgName = Get-AutomationVariable -Name 'AZBAS_ResourceGroup_Name'
$basName = Get-AutomationVariable -Name 'AZBAS_Bastion_Name'
$vnetName = Get-AutomationVariable -Name 'AZBAS_Vnet_Name'
$pipName = Get-AutomationVariable -Name 'AZBAS_PIP_Name'

## Create Azure Bastion
$existBas = Get-AzBastion -ResourceGroupName $rgName
if($existBas.Length -eq 0){
    Write-Output "Getting specified Azure Virtual Netwok..."
    $vnet = Get-AzVirtualNetwork -ResourceGroupName $rgName -Name $vnetName
    Write-Output "Creating Azure Public IP Address..."
    $pip = New-AzPublicIpAddress -Name $pipName -ResourceGroupName $rgName -AllocationMethod Static -Sku Standard -Location japaneast
    Write-Output "Created Azure Public IP Address."
    Write-Output "Creating Azure Bastion..."
    $bastion = New-AzBastion -ResourceGroupName $rgName -Name $basName -VirtualNetwork $vnet -PublicIPAddress $pip
    Write-Output "Created Azure Bastion."
}else{
    Write-Output "Azure Bastion is already exist."
}

ペーストしたら上部の [公開] をクリックします。

4. 削除ランブックの作成

先程と同様に [Runbook の作成] にて、次のように入力して [作成] をクリックします。

  • [名前]: Delete-AzBastion
  • [Runbook の種類]: [PowerShell]
  • [説明]: Bastion を削除する Runbook

エディターに次の内容をペーストして公開します。

## Initiate connection
$conn = Get-AutomationConnection -Name 'AzureRunAsConnection'
Write-Output 'Connecting to Azure...'
Connect-AzAccount `
  -ServicePrincipal `
  -Tenant $conn.TenantID `
  -ApplicationId $conn.ApplicationID `
  -CertificateThumbprint $conn.CertificateThumbprint
Write-Output 'Connect succeeded!'

## Define variables
$rgName = Get-AutomationVariable -Name 'AZBAS_ResourceGroup_Name'
$basName = Get-AutomationVariable -Name 'AZBAS_Bastion_Name'
$vnetName = Get-AutomationVariable -Name 'AZBAS_Vnet_Name'
$pipName = Get-AutomationVariable -Name 'AZBAS_PIP_Name'

## Create Azure Bastion
$existBas = Get-AzBastion -ResourceGroupName $rgName
if($existBas.Length -ne 0){
    Write-Output "Deleting Azure Bastion..."
    Remove-AzBastion -ResourceGroupName $rgName -Name $basName -Force
    Write-Output "Deleted Azure Bastion."
    Write-Output "Deleting Azure Public IP Address..."
    Remove-AzPublicIpAddress -Name $pipName -ResourceGroupName $rgName -Force
    Write-Output "Deleted Azure Public IP Address."
}else{
    Write-Output "Azure Bastion is not exist."
}

5. 動作確認

Runbook の作成が完了したら、Create-AzBastion → Delete-AzBastion の順で実行して動作に問題がないか確認します。実行は Runbook 画面上部の [開始] をクリックします。これで好きなタイミングで実行できます。細かいエラー処理は省いているので、失敗時は実行画面のエラータブなどから確認してください。

成功時は出力タブに次のような内容が表示されます。

おまけ: スケジューリング

作成した Runbook を定期実行できるようにスケジューリングできます。

Automation アカウントのメニューから [スケジュール] をクリックし、[スケジュールの追加] をクリックします。[間隔][週] を選ぶと実行する曜日などで指定できます。

設定したらスケジュールを作成します。

Runbook を表示し、上部の [スケジュールへのリンク] をクリックし、[スケジュール] で作成済みのスケジュールを選択して [OK] をクリックします。あとは指定した時間に Runbook が実行されます。