今回はAzureの外にあるログ取得~Blob格納までをAutomationで自動化する話です。
概要
今回の対象はAzure内ではなく外部製品のログは監査系のログとなります。
製品の仕様として監査ログを14日間取得されますが、それ以降は破棄されてしまうため、破棄される前にどこかに格納しておく必要がありました。
今回はAzure Blobストレージに格納し長期保管をすることが目的です。
要件
要件を簡単にまとめると以下の通りとなります。
- 1時間おきにログを取得する
- 個別のTOKENを使用する
- Internet経由でログをgetする
- 取得してくるデータはJSON形式
- ログのデータ構造はdata配列内にログが複数存在する形
- Pagination設定がある
- ログはBlobストレージに格納する
Automationの作成イメージ
- 1時間おきにログを取得する
これはAzure AutomationとAutomationのスケジュール機能で実装します。
Runbookの種類はPowershellにしました。
- 個別のTOKENを使用する
Tokenはシークレット情報になりますので、コード内にべた書きや他人の目に触れるようなところには置きたくありません。
なので、TokenはAzure KeyVault(キーコンテナー)に格納し、コード内でKeyVaultから取得するようにします。
- Internet経由でログをgetする
LinuxとかであればcurlですがPowershellなのでInvoke-RestMethodで実装します。
learn.microsoft.com
- 取得してくるデータはJSON形式
PowershellはJSONをいじるのには向いていない気がします…。
- ログのデータ構造はdata配列内にログが複数存在する形
ちょっと苦戦しましたが、今回は何とかなりました。
というのも、将来的にDataExplorerなどでログ検索をすることを考慮した場合、data配列の下にログが入り1行ですべて表されるのはクエリ検索するにはちょっと不向きなので、data配列をなくして1つのログを1行で表せるようにしました。
元のデータは以下の感じでした。
{ "data": [ { "xxx": "aaa", "yyy": "bbb", "zzz": "ccc" }, { "xxx": "aaa", "yyy": "bbb", "zzz": "ccc" } ], "pagination": { "current_page": xx, "next_page": xx } }
- Pagination設定がある
Paginationの情報は今回はJSONのデータの最後にPaginationの配列が入る形でした。
- データはBlobストレージに格納する
Automationと同じサブスクリプション内のBlobに格納しています。
フォルダはAzureの診断ログを取るときと同じような構成となる「autid/y=yyyy/m=MM/d=dd/h=HH/yyyymmdd.json」としました。
Automation
コードは以下の通りです。
try { "Logging in to Azure..." Connect-AzAccount -Identity } catch { Write-Error -Message $_.Exception throw $_.Exception } # Token取得 $secret = Get-AzKeyVaultSecret -VaultName "KeyVault名" -Name "シークレット名" AsPlainText # URI生成 $headerParam = @{"Authorization" = "Bearer " + $secret} $date = (Get-date).ToUniversalTime().AddHours(-1).ToString("yyyy-MM-dd-HH") # 一時使用ファイル作成 New-Item -Path . -Name "data.json" # ログ取得 $UserResponse = 1 while ($UserResponse -ne $null){ # Getするページ設定 $url = "https://example.com/api/audit?since=" + $date + ":00:00+00:00&page%5Bnumber%5D=" + $UserResponse Invoke-RestMethod -Headers $headerParam -Uri $url -Method Get -OutFile "audit.json" # 次ページがあるかどうかチェック $apidata = Get-Content -Path audit.json -Raw | ConvertFrom-Json $UserResponse = $apidata.pagination.next_page # Jsonデータ加工 $apidata.data | ForEach-Object{ $auditlog = $_ $auditlog | ConvertTo-Json -Compress | Add-Content -Path "data.json" -Force } } # Blob格納 $StorageHT = @{ ResourceGroupName = "リソースグループ名" Name = "Storageアカウント名" } $StorageAccount = Get-AzStorageAccount @StorageHT $Context = $StorageAccount.Context $date2 = (Get-date).ToUniversalTime().AddHours(-1).ToString("yyyy") $date3 = (Get-date).ToUniversalTime().AddHours(-1).ToString("MM") $date4 = (Get-date).ToUniversalTime().AddHours(-1).ToString("dd") $date5 = (Get-date).ToUniversalTime().AddHours(-1).ToString("yyyyMMddhh") $ContainerName = "Blobのコンテナ名" $Blob = "audit/y=$date2/m=$date3/d=$date4/h=$date1/$date5.json" $Blob1HT = @{ File = 'data.json' Container = $ContainerName Blob = $Blob Context = $Context StandardBlobTier = 'Hot' } Set-AzStorageBlobContent @Blob1HT # テンポラリーファイル削除 Remove-item ./audit.json Remove-item ./data.json
取得したログをそのまま出力するのであれば「Jsonデータ加工」のロジックは不要です。
スケジュール設定
スケジュールはAutomationのスケジュール設定で実施しました。
繰り返しは定期的、間隔は1時間にしています。
おわり
定期的に実行することは手動ではなくなるべく簡単に自動化したいところ。
今回はAzureメインでよそのシステムのログを定期的に取得しデータを少し加工してBlobコンテナーに格納することをAzure Automationで実現しました。
こんな感じでどんどん自動化していけると仕事の手間が減っていいですね。
VM建てたりKubernetesのcronjobも考えましたが、思ってたよりPowershellでいろいろと出来て、Automationで実現出来たのでよかったです。
もう少しうまくPowershellで書けるといいのですが…。いけてないところは直してくれると嬉しいです。