Azureプライベートエンドポイント環境にてAzureAutomatin(Hybrid Runbook Worker)用AzurePowershellを作成する時に気を付けるべきこと

仕事でAzureAutomation(Hybrid Runbook Worker)を使う機会があり、通常のAzurePowerShellを作成する際にエラーの解消に時間を要したのでAzureプライベートエンドポイント環境にてAzureAutomatin(Hybrid Runbook Worker)用Azure Powershellを作成する時に気を付けるべきことについてまとめてみました。

## 1.環境
・Azure環境
・インターネット外部と通信するには社内のプロキシサーバを経由する必要があります。
・DNSサーバはAzureのプライベートDNSを使用します。社内イントラにはADサーバが存在しますが利用しないので社内サーバの名前解決は利用できません。
・AzureFilesはプライベートエンドポイントからしかアクセスが出来ず、パブリック側からのアクセスは不可です。
・AzureAutomationもプライベートエンドポイントからしかアクセスが出来ず、パブリック側からのアクセスは不可です。
・Hybrid Runbook WorkerはAzure仮想マシン(JOBServer：WindowsServer2022)で稼働させます。

## 2.やりたいこと
・AzureAutomationを使用して、Azure内のデータ(csvなど)を取得してプライベートエンドポイントからしかアクセスが出来ないAzureFilesにアップロードしたい。

## 3.なぜ Hybrid Runbook Worker を使用するのか？
通常のAzureAutomainはサンドボックス環境でAzurePowershellを実行します。
サンドボックス環境からはパブリック側からアクセス可能なAzureリソースにしかアクセス出来ないのでプライベートエンドポイントからしかアクセス出来ないAzureFilesにファイルをアップロードしようとすると、プライベートエンドポイントにアクセス可能な場所に配置されているAzure仮想マシンでAzurePowershellを実行する必要があり
Hybrid Runbook Workerを使用することになりました。

## 4.Azureプライベートエンドポイント環境にてAzureAutomatin(Hybrid Runbook Worker)用Azure Powershellを作成する時に気を付けるべきこと
### 4-1.プロキシの設定
OS側の設定で普通にプロキシの設定をすると全ての全てのHTTP/HTTPS通信がプロキシサーバを経由することになります。
「次ではじまるエントリ以外にはプロキシを使います。」を以下のように設定してプライベートエンドポイントへの通信には
プロキシを使わないように設定する必要がありました。

次ではじまるエントリ以外にはプロキシを使います。
```
localhost;*.azure-automation.net;169.254.169.254;*.file.core.windows.net;168.63.129.16;23.102.135.246;*.blob.core.windows.net
```

*.azure-automation.net ：AzureAutomationのプライベートエンドポイント宛ての通信
*.file.core.windows.net ：AzureFilesののプライベートエンドポイント宛ての通信
*.blob.core.windows.net ：BLOBサービスへのプライベートエンドポイント宛ての通信
169.254.169.254 ：Azure Instance Metadata Service（IMDS）AzureVMからシステムマネージドIDを使うために必要な通信先
168.63.129.16 ：Azure プラットフォーム リソースへの通信チャネルの使用を容易にするために使用される仮想パブリック IP アドレス
23.102.135.246 ：management.core.windows.net Connect-AzAccountの通信に使用するのでこちらもプロキシ宛て通信から除外

### 4-2.AzurePowershellに$env:NO_PROXYを記述した際にワイルドカードが適用されなかった

プロキシの環境変数を以下に設定しましたがNO_PROXYではワイルドカードがうまく動作せずホスト名を記載する必要がありました。
```
$env:HTTP_PROXY = "http://xxx.xxx.xxx.xxx:xxxx"
$env:HTTPS_PROXY = "http://xxx.xxx.xxx.xxx:xxxx"
$env:NO_PROXY = "localhost,*.azure-automation.net,169.254.169.254,168.63.129.16,23.102.135.246,10.221.24.29,*.file.core.windows.net,*.blob.core.windows.net"
```

結果、プロキシの環境変数を以下に設定しました。
```
$env:HTTP_PROXY = "http://xxx.xxx.xxx.xxx:xxxx"
$env:HTTPS_PROXY = "http://xxx.xxx.xxx.xxx:xxxx"
$env:NO_PROXY = "localhost,*.azure-automation.net,169.254.169.254,168.63.129.16,23.102.135.246,10.221.24.29,storage01.file.core.windows.net,storage01.blob.core.windows.net"
```

### 4-3.Azure仮想マシン(JOBServer)にてシステム割り当てのマネージドIDを有効にする
Connect-AzAccount でAzureのリソースにアクセスする時に必要です。

169.254.169.254 宛てで認証要求をするようになります。

### 4-4.認証キャッシュのクリアが必要だった
正常動作したAzurePowerShellのバックアップを取得してから改修したAzurePowershellで認証エラーが出た後に正常動作していた元のAzurePoweshellを
実行すると認証エラーで失敗するという事象に遭遇しました。
どうやら、コンテキスト情報がローカルに保存されたままでエラーが出ていたようです。

下記のように事前の認証キャッシュのクリアとScopeをProcessに限定するように
スクリプトに記載することでエラーを回避することが出来ました。
-Scope Process を指定するとスクリプトの実行毎に認証キャッシュは破棄されるようです。

```
# 認証キャッシュのクリア
Clear-AzContext -Force

# Azure にサインインしてサブスクリプションを設定

$subscriptionId = "サブスクリプションID"

Connect-AzAccount -Scope Process -Identity

Set-AzContext -Scope Process -Subscription $subscriptionId
```

### 4-5.ストレージコンテキスト作成コマンド(New-AzStorageContext)でエンドポイント用のオプション指定が必要だった

エンドポイント用のオプション指定をしなければグローバル側に認証を求めに行くので
エンドポイント用のオプション指定が必要でした。

下記のように記述しました。
```
# ストレージアカウント情報
$storageAccountName = "ストレージアカウント名"
$shareName = "共有名"
$destinationFilePath = "フォルダ/ファイル名"

# ストレージキーを取得
$key = "ストレージキー"

# ストレージコンテキストを作成
$context = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $key -BlobEndpoint "https://storage01.blob.core.windows.net/" -FileEndpoint "https://storage01.file.core.windows.net/"

# ファイルをアップロード（UNC パスではなく API 経由）
Set-AzStorageFileContent -Context $context -ShareName $shareName -Source $outputFullPath -Path $destinationFilePath -Force
```

## 5.まとめ
Azureプライベートエンドポイント環境にてAzureAutomatin(Hybrid Runbook Worker)用AzurePowershellを動作させるのは
Azure仮想マシン上やPCからAzurePowershellを動かすよりも手間がかかるようです。
今時点では処理させたい事の全てが出来ているわけではないのですが、
ここまで出来ればあと一歩というところまで来ました。
続きはGW明けに頑張ります。