クラウドエンジニアブログ

Azure Pipelines で実現する IaC - 第 3 回 Azure リソース テスト

湯下 達郎

1. はじめに

皆さん、こんにちは! 動物好きの湯下です。
第 3 回となる今回は、Pester による Azure リソースのテストについてご紹介します。

まず、「Pester」というツールを初めて聞く方に向けて、Pester について簡単に触れておきます。


2. Pester とは

Pester とは、オープン ソース ソフトウェアとして開発されている PowerShell 向けのテスティング フレームワークです。

Quick Start | Pester

通常、PowerShell スクリプトの自動テストを行う際に使用されますが、ARM Template の中身や ARM Template の実行結果を PowerShell オブジェクトとして扱うことで、Azure リソースに対する自動テストが可能となります。

具体的には、以下のようなテストを自動化できます。

[ プロビジョニング前 ]
  • パラメーター ファイルで指定した値が間違っていないかをチェックする
  • ARM Template の dry run により、構文の誤りや Azure リソースの競合などが無いかをチェックする

[ プロビジョニング後 ]
  • ARM Template のプロビジョニングが正常に完了したかをチェックする
  • Azure リソースの設定値があるべき値であるかどうかをチェックする

特に、最後のケースはセキュリティ設定の包括的なチェックにも活用できます。 例えば、NSG (仮想ネットワーク用のファイアウォール機能) の割り当て設定や送受信ルールが意図した通りに設定されているかをチェックする際にとても便利です。


3. 今回のシナリオ

前回の記事では、Azure Repos 上に Push した ARM Template を基に Azure リソースのプロビジョニングを行いましたので、今回はそれらの Azure リソースの設定が意図したものであるかをテストしてみましょう。

具体的には、仮想ネットワークのサブネットに NSG が適切に割り当てられているかをテストするデモになります。


4. Azure Pipelines で Pester を使うには

今回は、Azure Pipelines で標準で利用できる PowerShell Script タスクを使用し、リリース パイプラインに組み込んでみます。

■ 設定手順


4-1. Pester テスト ファイルを作成し、Azure Repos に Push する

以下は、今回デモ用に作成したテスト ファイル本体となります。 なお、Azure に接続し、設定状態を取得する部分 (az login, az resource show 等) は、Azure CLI コマンドを使用していますが、Azure PowerShell を使っても同様のことが行えます。

Test-NsgSettings.tests.ps1

左右にスクロールしてご覧ください。


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 テスト ファイルを実行します。


Run-Pester.ps1

左右にスクロールしてご覧ください。


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 テスト ファイル内で利用するために作成しました。 パイプライン設定を工夫したり他のタスクを利用することで、もっとシンプルに記述できるかもしれません (^_-)☆



4-2. サービス コネクションを構成する

前述の Pester テスト ファイルでは Azure CLI で Azure に接続し、現在の NSG 設定を取得する実装になっています。 そのため、Azure に認証するためにサービス プリンシパルを作成し、それを Azure DevOps の「サービス コネクション」として登録する必要があります。 サービス プリンシパルの作成方法については、以下のようなドキュメントを参考にして頂ければと思います。

方法: リソースにアクセスできる Azure AD アプリケーションとサービス プリンシパルをポータルで作成する

サービス プリンシパルの作成後、画面左下部の [Project settings] から [Service connections] - [New service connection] の順にクリックします。

サービス コネクションを構成する1



[Azure Resource Manager] を選択し、[Next] をクリックします。

サービス コネクションを構成する2



[Service principal (manual)] を選択し、[Next] をクリックします。

サービス コネクションを構成する3



必要な情報を入力し、[Verify and save] をクリックします。

サービス コネクションを構成する4




4-3. リリース パイプラインを作成する

[Pipelines] の [Releases] で、[+ New] - [New release pipeline] の順にクリックします。

リリース パイプラインを作成する1



[Empty job] をクリックします。

リリース パイプラインを作成する2



リリース パイプラインを作成する3



リリース パイプラインを作成する4



なお、リリース パイプライン名については、[New release pipeline] 付近をマウス オーバーすると鉛筆マークが表示されるので、これをクリックすると変更できます。

リリース パイプラインを作成する5


リリース パイプラインを作成する6



[Artifacts] の [+ Add an artifact] をクリックします。

リリース パイプラインを作成する7



[Source type] で [Azure Repos Git] を選択し、プロジェクトとリポジトリを指定して [Add] をクリックします。

リリース パイプラインを作成する8



先程のステージ内の [1 job, 0 task] をクリックして、タスクを設定していきます。

リリース パイプラインを作成する9



パイプライン処理時にバックエンドで実行されるマシンの種類やバージョンは [Agent Job] 設定の [Agent Specification] から選択できます。

リリース パイプラインを作成する10



今回は最新の Windows Server である [windows-2019] を設定してみます。

リリース パイプラインを作成する11



[Agent Job] の [+] をクリックします。

リリース パイプラインを作成する12



[Add tasks] 内の検索フォームで [PowerShell] と検索し、表示されたタスク [PowerShell] で [Add] をクリックします。

リリース パイプラインを作成する13



[Script Path] に、事前に Push しておいたラッパー ファイルを選択します。(右の [...] ボタンから選択すると簡単です)

また、[Arguments] には -clientSecret "$(CLIENTSECRET)" と指定します。

リリース パイプラインを作成する14


リリース パイプラインを作成する15



[Variables] タブの [Pipeline variables] で [+ Add] をクリックし、Azure CLI での Azure サブスクリプション認証に必要な情報 (アプリケーション ID の URL、シークレット、テナント ID、サブスクリプション ID) を変数として登録します。

※ 変数 CLIENTSECRET にはサービス プリンシパルのシークレットを格納することから、Value を登録する際に表示される鍵アイコンをクリックして secure な値として登録します。

リリース パイプラインを作成する16



CLIENTSECRET を secure な値として登録したため、以下のように「********」と表示されています。

リリース パイプラインを作成する17



画面右上部の [Save] をクリックし、[OK] をクリックします。

リリース パイプラインを作成する18



これでパイプライン設定は完了です!


■ 実行手順

それでは、パイプラインを実行してみましょう。

画面右上部の [Create release] をクリックします。

実行手順1



[Create a new release] 画面で [Create] をクリックします。

実行手順2



リリース パイプラインが実行されたので、[Release Release-1 has been created] のリンクをクリックし、実行状況を見てみます。(メニュー バーの Releases をクリックして、リリース パイプラインの一覧から確認することもできます)

実行手順3



現在、実行中のようです。 [In progress] をクリックすると、詳細を表示できます。

実行手順4


実行手順5



全てのタスクが成功しました!

[PowerShell Script] タスクをクリックし、Pester の実行ログを見てみると、意図した通りに動作していることが分かります。

実行手順6


実行手順7



今度は、サブネットに適用されている NSG の割り当てを解除して、テストが失敗するかを確認してみます。(なお、このデモではセキュリティの観点から、事前に仮想マシンを停止して実施しています)


実行手順8

※ NSG がサブネットに割り当てられている状態

実行手順9

※ NSG がサブネットに割り当てられていない状態


実行手順10


[Deploy] ボタンから、もう一度リリース パイプラインを実行します。

PowerShell Script タスクが失敗しましたので、詳細を確認してみます。

実行手順11



想定通り、Pester によるテストが失敗したため、本タスクが失敗していることを確認できますね!

実行手順12



※ ここまでの手順を試されている方は、セキュリティの観点から NSG の割り当て設定を元に戻しておきましょう (^_-)☆


5. まとめ

今回は、NSG の割り当て状態を確認するシンプルなテストをご紹介しましたが、より複雑なテストも同様の方法で実施できますので、ご参考になれば幸いです。

第 4 回では、Ansible を用いた OS・MW のコンフィグレーションを行う方法をご紹介しますので、どうぞお楽しみに!



関連ページ

Azure Pipelines で実現する IaC - 第 1 回 Introduction
Azure Pipelines で実現する IaC - 第 2 回 Azure リソース プロビジョニング
Azure Pipelines で実現する IaC - 第 4 回 OS・MW コンフィグレーション

お問い合わせ

製品・サービスに関するお問い合わせはお気軽にご相談ください。

ピックアップ

セミナー情報
クラウドエンジニアブログ
clouXion
メールマガジン登録