Automaton Account でリソースの起動・停止と Slack への通知をやってみる

# やりたいこと
Azure の Automaton Account (Runbook) を使って、Web App と Postgre SQL Server の起動・停止を自動化したので、その内容をまとめます。

# 構成
大まかには以下のような構成。A の Automaton Account に登録した Runbook で PowerShell のスクリプトを実行して、B 内の2つのリソース (Web App と Postgre SQL Server) の起動と停止を行う。その結果は、C の Slack のチャンネルに投稿する。

```mermaid
flowchart TB
  subgraph ResourceGroup
    direction TB
    subgraph A
       direction LR
       Automation --> |get webhok URL| KeyVault
    end
    subgraph B
        direction LR
        Automation ---> |Start/Stop| WebApp
        Automation ---> |Start/Stop| id[(PostgreSQL)]
    end
  end
  subgraph C
     Automation ---> |send states to channel |Slack
  end
```

# リソース設定
## アクセス設定
Automaton から各リソースの操作を行うにあたり権限まわりの設定をする。今回は、Automaton Account のマネージド ID にロールを割り当てた。割り当てたロールは、Web App には、`Website Contributor` と Postgre SQL Server には、`Contributor`。権限的には余計なものも含んでいるけど、とりあえず‥ (今後、見直します)。

https://learn.microsoft.com/ja-jp/azure/automation/enable-managed-identity-for-automation

## スケジュール設定
Runbook の実行をスケジュールする。以下を参考に行った。今回は、日本時間の午前6時と午後10時に起動・停止するようにスケジュールを作成した。

https://learn.microsoft.com/ja-jp/azure/automation/shared-resources/schedules

## Slack への通知
Slack への通知は Webhook URL で行った。あらかじめ投稿したいチャンネルに Incoming Webhook を設定して Webhook URL を取得し、Key Vault の Secret として登録しておいたものを Automaton の Runbook から参照する。
実際の通知に関しては、PowerShell のモジュール (PSSlack) を利用している。デフォルトでは Automaton にインポートされていないので、事前にインポートが必要。

https://learn.microsoft.com/ja-jp/azure/automation/shared-resources/modules

https://www.powershellgallery.com/packages/PSSlack/1.0.6

# PowerShell スクリプト (起動時のみ)
Runbook として登録するスクリプトは以下のような形。起動用スクリプトになっているので、停止時のスクリプトについては、内容に合わせて変更が必要。Runbook の作成は以下を参照。

https://learn.microsoft.com/ja-jp/azure/automation/learn/automation-tutorial-runbook-textual

```PowerShell
# Parameters
$PrjName = "YOUR_PRJ_NAME"
$Env = "dev"
$RgName = "rg-${PrjName}-${Env}"
$AppName = "app-${PrjName}-${Env}"
$PsqlName = "psql-${PrjName}-${Env}"

# Connect to Azure with Managed ID
Connect-AzAccount -Identity

"---- Check WebApp ----"

$WebAppInfo = Get-AzWebApp -ResourceGroupName $RgName -Name $AppName
$WebAppState = $WebAppInfo.State
$AppHost = $WebAppInfo.DefaultHostName
$AppUrl = "https://${AppHost}"

"WebAppState: ${WebAppState}"

If ($WebAppState -eq "Stopped") {
    "${AppName} will be started..."
    $Result = Start-AzWebApp -ResourceGroupName $RgName -Name $AppName
    $WebAppState = $Result.State
}

"WebApp is ${WebAppState}"

"---- Check Psql ----"

$PsqlInfo = Get-AzPostgreSqlFlexibleServer -Name $PsqlName -ResourceGroupName $RgName
$PsqlState = $PsqlInfo.State
$PsqlDomainName = $PsqlInfo.FullyQualifiedDomainName

"PsqlState: ${PsqlState}"

If ($PsqlState -eq "Stopped") {
    "Psql will be started..."
    Start-AzPostgreSqlFlexibleServer -Name $PsqlName -ResourceGroupName $RgName
}

$PsqlInfo = Get-AzPostgreSqlFlexibleServer -Name $PsqlName -ResourceGroupName $RgName
$PsqlState = $PsqlInfo.State

"Psql is ${PsqlState}"

"---- Post results in a slack chnnel ----"

$KeyVaultName = Get-AutomationVariable -Name "YOUR_VARIABLE_NAME"
$Msg = "WebApp and Psql have been started."
$WebhookUrl = Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name "YOUR_SECRET_NAME" -AsPlainText

New-SlackMessageAttachment -Color "00CC00" `
                           -Title "WebApp Status" `
                           -Text "<${AppUrl}|${AppName}> is ${WebAppState}" `
                           -Fallback "An error occured" |
New-SlackMessageAttachment -Color "00CC00" `
                           -Title "PostgreSQL Status" `
                           -Text "${PsqlDomainName} is ${PsqlState}" `
                           -Fallback "An error occured" |
New-SlackMessage -IconEmoji ":slack:" `
                 -Username "{YOUR_USERNAME}" `
                 -Text $Msg ` |
Send-SlackMessage -Uri $WebhookUrl
```

実行されると以下のよう形式で Slack へ通知される！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1743460/08e8ff87-73fc-8098-c8a0-a0d9caaf725b.png)


以上です。