演習 - テスト ジョブをワークフローに追加する

完了

あなたは、勤務先の玩具会社のセキュリティ チームから、あなたの Web サイトが HTTPS を使用した場合にのみアクセスできることを確認するように依頼されました。 この演習では、セキュリティ チームの要求を確認するスモーク テストを実行するようにワークフローを構成します。

プロセスの間に、次のタスクを実行します。

  • テスト スクリプトをリポジトリに追加します。
  • ワークフロー定義を更新して、テスト ジョブを追加します。
  • ワークフローを実行し、テストが失敗することを確認します。
  • Bicep ファイルを修正し、ワークフローが正常に実行されることを確認します。

テスト スクリプトを追加する

ここでは、HTTPS を使用したときには Web サイトにアクセスできること、そして安全ではない HTTP プロトコルを使用したときにはアクセスできないことを確認するテスト スクリプトを追加します。

  1. Visual Studio Code の deploy フォルダー内に Website.Tests.ps1 という名前の新しいファイルを作成します。

    Visual Studio Code エクスプローラーのスクリーンショット。deploy フォルダーとテスト ファイルが表示されています。

  2. 次のテスト コードをファイルにコピーして貼り付けます。

    param(
      [Parameter(Mandatory)]
      [ValidateNotNullOrEmpty()]
      [string] $HostName
    )
    
    Describe 'Toy Website' {
    
        It 'Serves pages over HTTPS' {
          $request = [System.Net.WebRequest]::Create("https://$HostName/")
          $request.AllowAutoRedirect = $false
          $request.GetResponse().StatusCode |
            Should -Be 200 -Because "the website requires HTTPS"
        }
    
        It 'Does not serves pages over HTTP' {
          $request = [System.Net.WebRequest]::Create("http://$HostName/")
          $request.AllowAutoRedirect = $false
          $request.GetResponse().StatusCode | 
            Should -BeGreaterOrEqual 300 -Because "HTTP is not secure"
        }
    
    }
    

    結果は Pester のテスト ファイルです。 これには、$HostName というパラメーターが必要です。 ホスト名に対して 2 つのテストを実行します。

    • HTTPS 経由で Web サイトへの接続を試します。 サーバーから 200 から 299 の HTTP 応答状態コードが返される場合、接続の成功を示すので、テストは合格です。
    • HTTP 経由で Web サイトへの接続を試します。 サーバーから 300 以上の HTTP 応答状態コードが返される場合、テストは合格です。

    この演習では、テスト ファイルの詳細とそのしくみを理解することは重要ではありません。 関心をお持ちの場合は詳細を確認できるように、「概要」でリンクを紹介しています。

Bicep ファイルの出力をジョブ出力として発行する

前のステップで作成したテスト スクリプトには、テストするホスト名が必要です。 Bicep ファイルには既に出力が含まれていますが、スモーク テストで使用する前に、ステージ出力として発行する必要があります。

  1. Visual Studio Code で、.github/workflows フォルダーにある workflow.yml ファイルを開きます。

  2. デプロイ ジョブで、idDeploy website ステップに追加し、このステップで参照できるようにします。 また、デプロイ ステップの appServiceAppHostName 出力をコピーするジョブ出力を追加します。

    deploy:
      runs-on: ubuntu-latest
      environment: Website
      needs: preview
      outputs:
        appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }}
      steps:
      - uses: actions/checkout@v3
      - uses: azure/login@v1
        name: Sign in to Azure
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      - uses: azure/arm-deploy@v1
        id: deploy
        name: Deploy website
        with:
          failOnStdErr: false
          deploymentName: ${{ github.run_number }}
          resourceGroupName: ${{ env.AZURE_RESOURCEGROUP_NAME }}
          template: ./deploy/main.bicep
          parameters: environmentType=${{ env.ENVIRONMENT_TYPE }}
    
  3. ファイルを保存します。

スモーク テスト ジョブをワークフローに追加する

これで、テストを実行するスモーク テスト ジョブを追加できます。

  1. ファイルの末尾に、smoke-test ジョブの次の定義を追加します。

    smoke-test:
      runs-on: ubuntu-latest
      needs: deploy
      steps:
      - uses: actions/checkout@v3
      - run: |
          $container = New-PesterContainer `
            -Path 'deploy/Website.Tests.ps1' `
            -Data @{ HostName = '${{needs.deploy.outputs.appServiceAppHostName}}' }
          Invoke-Pester `
            -Container $container `
            -CI
        name: Run smoke tests
        shell: pwsh
    

    このコードがジョブを定義します。 ジョブには、コードをチェックアウトするステップと、Pester 使用してテストを実行するステップが含まれています。

    ジョブ定義では needs プロパティを使用して、デプロイ ジョブにおける依存関係を定義します。 この依存関係により、必要な順序でジョブが実行されるようになります。 また、スモーク テストの実行時にデプロイ ジョブの出力を使用できます。

    Note

    PowerShell と Pester の両方が GitHub ホステッド ランナーにプレインストールされています。 スクリプト ステップでそれらを使用するために特別な操作を行う必要はありません。

  2. ファイルを保存します。

ワークフロー定義を検証してコミットする

  1. deploy.yml ファイルが次のようなコードになっていることを検証します。

    name: deploy-toy-website-test
    concurrency: toy-company
    
    on:
      push:
        branches:
          - main
    
    permissions:
      id-token: write
      contents: read
    
    env:
      AZURE_RESOURCEGROUP_NAME: ToyWebsiteTest
      ENVIRONMENT_TYPE: Test
    
    jobs:
      lint:
        runs-on: ubuntu-latest
        steps:
        - uses: actions/checkout@v3
        - name: Run Bicep linter
          run: az bicep build --file deploy/main.bicep
    
      validate:
        runs-on: ubuntu-latest
        steps:
        - uses: actions/checkout@v3
        - uses: azure/login@v1
          name: Sign in to Azure
          with:
            client-id: ${{ secrets.AZURE_CLIENT_ID }}
            tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
        - uses: azure/arm-deploy@v1
          name: Run preflight validation
          with:
            deploymentName: ${{ github.run_number }}
            resourceGroupName: ${{ env.AZURE_RESOURCEGROUP_NAME }}
            template: ./deploy/main.bicep
            parameters: environmentType=${{ env.ENVIRONMENT_TYPE }}
            deploymentMode: Validate
    
      preview:
        runs-on: ubuntu-latest
        needs: [lint, validate]
        steps:
        - uses: actions/checkout@v3
        - uses: azure/login@v1
          name: Sign in to Azure
          with:
            client-id: ${{ secrets.AZURE_CLIENT_ID }}
            tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
        - uses: azure/arm-deploy@v1
          name: Run what-if
          with:
            failOnStdErr: false
            resourceGroupName: ${{ env.AZURE_RESOURCEGROUP_NAME }}
            template: deploy/main.bicep
            parameters: >
              environmentType=${{ env.ENVIRONMENT_TYPE }}
            additionalArguments: --what-if
    
      deploy:
        runs-on: ubuntu-latest
        environment: Website
        needs: preview
        outputs:
          appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }}
        steps:
        - uses: actions/checkout@v3
        - uses: azure/login@v1
          name: Sign in to Azure
          with:
            client-id: ${{ secrets.AZURE_CLIENT_ID }}
            tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
        - uses: azure/arm-deploy@v1
          id: deploy
          name: Deploy website
          with:
            failOnStdErr: false
            deploymentName: ${{ github.run_number }}
            resourceGroupName: ${{ env.AZURE_RESOURCEGROUP_NAME }}
            template: ./deploy/main.bicep
            parameters: environmentType=${{ env.ENVIRONMENT_TYPE }}
    
      smoke-test:
        runs-on: ubuntu-latest
        needs: deploy
        steps:
        - uses: actions/checkout@v3
        - run: |
            $container = New-PesterContainer `
              -Path 'deploy/Website.Tests.ps1' `
              -Data @{ HostName = '${{needs.deploy.outputs.appServiceAppHostName}}' }
            Invoke-Pester `
              -Container $container `
              -CI
          name: Run smoke tests
          shell: pwsh
    

    ファイルの外観が異なる場合は、この例に一致するようにファイルを更新し、保存します。

  2. Visual Studio Code ターミナルで次のコマンドを実行し、変更をコミットして Git リポジトリにプッシュします。

    git add .
    git commit -m "Add test job"
    git push
    

ワークフローを実行してテスト結果をレビューする

  1. ブラウザーでワークフローに移動します。

  2. ワークフローの最新の実行を選択します。

    ワークフローでリント検証プレビューの各ジョブが完了するまで待ちます。 GitHub Actions によってページが最新の状態で自動的に更新されますが、ページを随時更新することをお勧めします。

  3. [デプロイのレビュー] ボタンを選択し、[Web サイト] 環境、[承認してデプロイ] の順に選択します。

    ワークフロー実行が完了するまで待ちます。

  4. デプロイ ジョブが正常に注目することに注目します。 smoke-test ジョブはエラーありで終了します。

    ワークフロー実行ジョブが示されている GitHub インターフェイスのスクリーンショット。スモーク テスト ジョブが失敗とレポートされています。

  5. smoke-test ジョブを選択して詳細を表示します。

  6. smoke-test 出力に、2 つのテストが実行されたことが示されます。 1 つは合格、1 つは失敗でした。 失敗したテストは、Toy Website.Does not serve pages over HTTP として一覧表示されています。

    ワークフロー実行のテスト結果が示されている GitHub インターフェイスのスクリーンショット。失敗したテストが強調表示されています。

    このテキストは、セキュリティ チームの要件を満たすために Web サイトが正しく構成されていなかったことを示しています。

Bicep ファイルを更新する

これで、Bicep 定義がセキュリティ チームの要件を満たしていないことがわかったので、それを修正します。

  1. Visual Studio Code で、deploy フォルダーの main.bicep ファイルを開きます。

  2. Azure App Service アプリの定義を見つけ、それを更新して、その properties 領域に httpsOnly プロパティが含まれるようにします。

    resource appServiceApp 'Microsoft.Web/sites@2022-03-01' = {
      name: appServiceAppName
      location: location
      properties: {
        serverFarmId: appServicePlan.id
        httpsOnly: true
        siteConfig: {
          appSettings: [
            {
              name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
              value: applicationInsights.properties.InstrumentationKey
            }
            {
              name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
              value: applicationInsights.properties.ConnectionString
            }
          ]
        }
      }
    }
    
  3. ファイルを保存します。

  4. Visual Studio Code ターミナルで次のコマンドを実行し、変更をコミットして Git リポジトリにプッシュします。

    git add .
    git commit -m "Configure HTTPS on website"
    git push
    

ワークフローを再実行する

  1. ブラウザーでワークフロー実行に移動します。

  2. 最新の実行を選択します。

    ワークフローでリント検証プレビューの各ジョブが完了するまで待ちます。 GitHub によってページが最新の状態で自動的に更新されますが、ページを随時更新することをお勧めします。

  3. プレビュー ジョブを選択し、もう一度 what-if の結果を確認します。

    what-if コマンドによって、httpsOnly プロパティの値の変更が検出されたことに注目してください。

    Resource and property changes are indicated with these symbols:
      - Delete
      + Create
      ~ Modify
      = Nochange
      * Ignore
    
    The deployment will update the following scope:
    
    Scope: /subscriptions/***/resourceGroups/ToyWebsiteTest
    
      ~ Microsoft.OperationalInsights/workspaces/workspace-abcdefghijklm [2022-10-01]
        - properties.retentionInDays: 30
        - properties.sku:
    
            name: "pergb2018"
    
        - properties.workspaceCapping:
    
            dailyQuotaGb: -1.0
    
      ~ Microsoft.Web/sites/toy-website-abcdefghijklm [2022-03-01]
        + properties.siteConfig.localMySqlEnabled:   false
        + properties.siteConfig.netFrameworkVersion: "v4.6"
        ~ properties.httpsOnly:                      false => true
    
      = Microsoft.Insights/components/toywebsite [2020-02-02]
      = Microsoft.Storage/storageAccounts/mystorageabcdefghijklm [2022-09-01]
      = Microsoft.Web/serverfarms/toy-website [2022-03-01]
      * microsoft.alertsmanagement/smartDetectorAlertRules/Failure Anomalies - toywebsite
    
    Resource changes: 2 to modify, 3 no change, 1 to ignore.
    
  4. ワークフロー実行に戻ります。

  5. [デプロイのレビュー] ボタンを選択し、[Web サイト] 環境、[承認してデプロイ] の順に選択します。

    ワークフロー実行が完了するまで待ちます。

  6. smoke-test ジョブを含め、ワークフロー全体が正常に終了していることに注目してください。 これは、両方のテストが合格したことを示します。

    成功したワークフロー実行を示している GitHub インターフェイスのスクリーンショット。

リソースのクリーンアップ

演習が完了したら、課金されないようにリソースを削除することができます。

Visual Studio Code ターミナルで、次のコマンドを実行します。

az group delete --resource-group ToyWebsiteTest --yes --no-wait

バックグラウンドでリソース グループが削除されます。

Remove-AzResourceGroup -Name ToyWebsiteTest -Force