皆さん、こんにちは! 動物好きの湯下です。
第 3 回となる今回は、Pester による Azure リソースのテストについてご紹介します。
まず、「Pester」というツールを初めて聞く方に向けて、Pester について簡単に触れておきます。
Pester とは、オープン ソース ソフトウェアとして開発されている PowerShell 向けのテスティング フレームワークです。
Quick Start | Pester
通常、PowerShell スクリプトの自動テストを行う際に使用されますが、ARM Template の中身や ARM Template の実行結果を PowerShell オブジェクトとして扱うことで、Azure リソースに対する自動テストが可能となります。
具体的には、以下のようなテストを自動化できます。
特に、最後のケースはセキュリティ設定の包括的なチェックにも活用できます。 例えば、NSG (仮想ネットワーク用のファイアウォール機能) の割り当て設定や送受信ルールが意図した通りに設定されているかをチェックする際にとても便利です。
前回の記事では、Azure Repos 上に Push した ARM Template を基に Azure リソースのプロビジョニングを行いましたので、今回はそれらの Azure リソースの設定が意図したものであるかをテストしてみましょう。
具体的には、仮想ネットワークのサブネットに NSG が適切に割り当てられているかをテストするデモになります。
今回は、Azure Pipelines で標準で利用できる PowerShell Script タスクを使用し、リリース パイプラインに組み込んでみます。
以下は、今回デモ用に作成したテスト ファイル本体となります。 なお、Azure に接続し、設定状態を取得する部分 (az login, az resource show 等) は、Azure CLI コマンドを使用していますが、Azure PowerShell を使っても同様のことが行えます。
左右にスクロールしてご覧ください。
param(
[Parameter(Mandatory)]
[string]$clientSecret_s
)
# アプリケーション ID の URL を設定
$applicationIdUrl = $env:APPLICATIONIDURL
# シークレットを設定
$clientSecret = $clientSecret_s
# Azure AD テナント ID を設定
$tenantId = $env:TENANTID
# サブスクリプション ID を設定
$subscriptionId = $env:SUBSCRIPTIONID
# テスト対象が含まれるリソース グループを指定
$resourceGroupName = "pester-jpe-test-rg01" # 環境に合わせて変更
Describe "Network Security Group (NSG) 設定値確認" {
BeforeAll {
# サブスクリプション認証 & 選択
az login --service-principal -u $applicationIdUrl -p $clientSecret --tenant $tenantId
az account set --subscription $subscriptionId
}
AfterAll {
$DebugPreference = "SilentlyContinue"
}
Context "NSG 割り当て状態をテストする" {
It "NSG [nsg01] は、VNet [vnet01] のサブネット [subnet01] に割り当てられているべき" {
# テスト対象 (プレフィックス : _t)
$resourceProviderName_t = "Microsoft.Network/networkSecurityGroups"
$resourceName_t = "nsg01" # 環境に合わせて変更
$resourceId_t = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/$resourceProviderName_t/$resourceName_t"
# 期待するテスト結果 (プレフィックス : _e)
$vnetName_e = "vnet01" # 環境に合わせて変更
$subnetName_e = "subnet01" # 環境に合わせて変更
$value_e = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.Network/virtualNetworks/$vnetName_e/subnets/$subnetName_e"
# Azure CLI を使用して現在の設定を取得する
$rawResponse = az resource show --ids $resourceId_t | ConvertFrom-Json
$currentStatus = $rawResponse.properties
# テストを実行する
$currentStatus.subnets.id | Should -Be $value_e
}
}
}
※ # 環境に合わせて変更 の部分は、ご自身の Azure 環境に合わせて変更してください。
また、以下はパイプラインで使用する PowerShell Script タスクで実行するラッパー ファイルになります。 つまり、このファイルを通じて、上記の Pester テスト ファイルを実行します。
左右にスクロールしてご覧ください。
param(
[Parameter(Mandatory)]
[string]$clientSecret
)
# Pester のインストール
Install-Module -Name Pester -Force -SkipPublisherCheck
# Pester の実行
Invoke-Pester -Script @{ Path = "$env:System_DefaultWorkingDirectory\$env:RELEASE_PRIMARYARTIFACTSOURCEALIAS\<テスト ファイルのディレクトリ パス>\Test-NsgSettings.tests.ps1"; Parameters = @{clientSecret_s = $clientSecret} } -EnableExit
※ テスト ファイルをリポジトリのルート ディレクトリに配置した場合は <テスト ファイルのディレクトリ パス>\ の部分は不要です。サブ ディレクトリ (例 : pester\src\) にテスト ファイルを配置した場合は、<テスト ファイルのディレクトリ パス>\ の部分は pester\src\ となります。
ちなみに、このラッパー ファイルは、サービス プリンシパルのシークレットを secure タイプのパイプライン変数 (後述) から読み出して Pester テスト ファイル内で利用するために作成しました。 パイプライン設定を工夫したり他のタスクを利用することで、もっとシンプルに記述できるかもしれません (^_-)☆
前述の Pester テスト ファイルでは Azure CLI で Azure に接続し、現在の NSG 設定を取得する実装になっています。 そのため、Azure に認証するためにサービス プリンシパルを作成し、それを Azure DevOps の「サービス コネクション」として登録する必要があります。 サービス プリンシパルの作成方法については、以下のようなドキュメントを参考にして頂ければと思います。
方法: リソースにアクセスできる Azure AD アプリケーションとサービス プリンシパルをポータルで作成する
サービス プリンシパルの作成後、画面左下部の [Project settings] から [Service connections] - [New service connection] の順にクリックします。
[Azure Resource Manager] を選択し、[Next] をクリックします。
[Service principal (manual)] を選択し、[Next] をクリックします。
必要な情報を入力し、[Verify and save] をクリックします。
[Pipelines] の [Releases] で、[+ New] - [New release pipeline] の順にクリックします。
[Empty job] をクリックします。
なお、リリース パイプライン名については、[New release pipeline] 付近をマウス オーバーすると鉛筆マークが表示されるので、これをクリックすると変更できます。
[Artifacts] の [+ Add an artifact] をクリックします。
[Source type] で [Azure Repos Git] を選択し、プロジェクトとリポジトリを指定して [Add] をクリックします。
先程のステージ内の [1 job, 0 task] をクリックして、タスクを設定していきます。
パイプライン処理時にバックエンドで実行されるマシンの種類やバージョンは [Agent Job] 設定の [Agent Specification] から選択できます。
今回は最新の Windows Server である [windows-2019] を設定してみます。
[Agent Job] の [+] をクリックします。
[Add tasks] 内の検索フォームで [PowerShell] と検索し、表示されたタスク [PowerShell] で [Add] をクリックします。
[Script Path] に、事前に Push しておいたラッパー ファイルを選択します。(右の [...] ボタンから選択すると簡単です)
また、[Arguments] には -clientSecret "$(CLIENTSECRET)" と指定します。
[Variables] タブの [Pipeline variables] で [+ Add] をクリックし、Azure CLI での Azure サブスクリプション認証に必要な情報 (アプリケーション ID の URL、シークレット、テナント ID、サブスクリプション ID) を変数として登録します。
※ 変数 CLIENTSECRET にはサービス プリンシパルのシークレットを格納することから、Value を登録する際に表示される鍵アイコンをクリックして secure な値として登録します。
CLIENTSECRET を secure な値として登録したため、以下のように「********」と表示されています。
画面右上部の [Save] をクリックし、[OK] をクリックします。
これでパイプライン設定は完了です!
それでは、パイプラインを実行してみましょう。
画面右上部の [Create release] をクリックします。
[Create a new release] 画面で [Create] をクリックします。
リリース パイプラインが実行されたので、[Release Release-1 has been created] のリンクをクリックし、実行状況を見てみます。(メニュー バーの Releases をクリックして、リリース パイプラインの一覧から確認することもできます)
現在、実行中のようです。 [In progress] をクリックすると、詳細を表示できます。
全てのタスクが成功しました!
[PowerShell Script] タスクをクリックし、Pester の実行ログを見てみると、意図した通りに動作していることが分かります。
今度は、サブネットに適用されている NSG の割り当てを解除して、テストが失敗するかを確認してみます。(なお、このデモではセキュリティの観点から、事前に仮想マシンを停止して実施しています)
※ NSG がサブネットに割り当てられている状態
※ NSG がサブネットに割り当てられていない状態
[Deploy] ボタンから、もう一度リリース パイプラインを実行します。
PowerShell Script タスクが失敗しましたので、詳細を確認してみます。
想定通り、Pester によるテストが失敗したため、本タスクが失敗していることを確認できますね!
※ ここまでの手順を試されている方は、セキュリティの観点から NSG の割り当て設定を元に戻しておきましょう (^_-)☆
今回は、NSG の割り当て状態を確認するシンプルなテストをご紹介しましたが、より複雑なテストも同様の方法で実施できますので、ご参考になれば幸いです。
第 4 回では、Ansible を用いた OS・MW のコンフィグレーションを行う方法をご紹介しますので、どうぞお楽しみに!
関連ページ
Azure Pipelines で実現する IaC - 第 1 回 Introduction |