Øvelse – Føj en testfase til din pipeline

Fuldført

Dit legetøjsfirmas sikkerhedsteam har bedt dig om at bekræfte, at dit websted kun er tilgængeligt via HTTPS. I denne øvelse skal du konfigurere din pipeline til at køre en røgtest, der kontrollerer sikkerhedsteamets krav.

Under processen skal du:

  • Føj et testscript til dit lager.
  • Opdater din pipelinedefinition for at tilføje en testfase.
  • Kør pipelinen, og se, om testen mislykkes.
  • Ret Bicep-filen, og hold øje med, at pipelinen kører.

Tilføj et testscript

Her skal du tilføje et testscript for at bekræfte, at webstedet er tilgængeligt, når HTTPS bruges og ikke er tilgængeligt, når den ikke-sikre HTTP-protokol bruges.

  1. I Visual Studio Code skal du oprette en ny fil i installere mappe med navnet Website.Tests.ps1.

    Skærmbillede af Visual Studio Code Explorer, hvor installationsmappen og testfilen vises.

  2. Indsæt følgende testkode i filen:

    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"
        }
    
    }
    

    Denne kode er en Pester-testfil. Det kræver en parameter med navnet $HostName. Den kører to test i forhold til værtsnavnet:

    • Prøv at oprette forbindelse til webstedet via HTTPS. Testen består, hvis serveren svarer med en HTTP-svarstatuskode mellem 200 og 299, hvilket angiver en vellykket forbindelse.
    • Prøv at oprette forbindelse til webstedet via HTTP. Testen består, hvis serveren svarer med en HTTP-svarstatuskode på 300 eller nyere.

    I forbindelse med denne øvelse er det ikke vigtigt, at du forstår detaljerne i testfilen, og hvordan den fungerer. Vi indeholder links i oversigten, så du kan få mere at vide, hvis du er interesseret.

Publicer outputtet for din Bicep-fil som en faseoutputvariabel

Det testscript, du oprettede i de foregående trin, kræver et værtsnavn for at teste. Din Bicep-fil indeholder allerede et output, men før du kan bruge den i dine røgtest, skal du publicere den som en faseoutputvariabel.

  1. I Visual Studio Code skal du åbne filen azure-pipelines.yml i mappen installere.

  2. I fasen Installér skal du opdatere installationstrinnet for at publicere outputtet til en variabel:

    - task: AzureResourceManagerTemplateDeployment@3
      name: DeployBicepFile
      displayName: Deploy Bicep file
      inputs:
        connectedServiceName: $(ServiceConnectionName)
        deploymentName: $(Build.BuildNumber)
        location: $(deploymentDefaultLocation)
        resourceGroupName: $(ResourceGroupName)
        csmFile: deploy/main.bicep
        overrideParameters: >
          -environmentType $(EnvironmentType)
        deploymentOutputs: deploymentOutputs
    

    Nu bruger installationsprocessen stadig den samme opgave som tidligere, men outputtet fra udrulningerne gemmes i en pipelinevariabel med navnet deploymentOutputs. Outputvariablen er formateret som JSON.

  3. Hvis du vil konvertere JSON-formaterede output til pipelinevariabler, skal du tilføje følgende scripttrin under installationstrinnet:

    - bash: |
        echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')"
      name: SaveDeploymentOutputs
      displayName: Save deployment outputs into variables
      env:
        DEPLOYMENT_OUTPUTS: $(deploymentOutputs)
    

    Hvis installationen fuldføres, får scriptet adgang til værdien af hvert output fra Bicep-installationen. Scriptet bruger værktøjet jq til at få adgang til den relevante del af JSON-outputtet. Derefter publiceres værdien til en faseoutputvariabel med samme navn som Bicep-udrulningsoutputtet.

    Seddel

    Pester og jq er begge forudinstalleret på Microsoft-hostede agenter til Azure Pipelines. Du behøver ikke at gøre noget særligt for at bruge dem i et scripttrin.

  4. Gem filen.

Føj en røgtestfase til din pipeline

Nu kan du tilføje en røgtestfase, der kører dine test.

  1. Nederst i filen skal du tilføje følgende definition for SmokeTest fase:

    - stage: SmokeTest
      jobs:
      - job: SmokeTest
        displayName: Smoke test
        variables:
          appServiceAppHostName: $[ stageDependencies.Deploy.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ]
    

    Denne kode definerer fasen og et job. Der oprettes også en variabel i jobbet med navnet appServiceAppHostName. Denne variabel henter sin værdi fra den outputvariabel, du oprettede i det foregående afsnit.

  2. Nederst i filen skal du føje følgende trindefinition til fasen SmokeTest:

    steps:
      - task: PowerShell@2
        name: RunSmokeTests
        displayName: Run smoke tests
        inputs:
          targetType: inline
          script: |
            $container = New-PesterContainer `
              -Path 'deploy/Website.Tests.ps1' `
              -Data @{ HostName = '$(appServiceAppHostName)' }
            Invoke-Pester `
              -Container $container `
              -CI
    

    Dette trin kører et PowerShell-script for at køre det testscript, du skrev tidligere, ved hjælp af testværktøjet Pester.

  3. Nederst i filen skal du føje følgende trindefinition til fasen SmokeTest:

    - task: PublishTestResults@2
      name: PublishTestResults
      displayName: Publish test results
      condition: always()
      inputs:
        testResultsFormat: NUnit
        testResultsFiles: 'testResults.xml'
    

    Dette trin tager filen med testresultater, som Pester opretter og udgiver som pipelinetestresultater. Du kan se, hvordan resultaterne vises om lidt.

    Bemærk, at trindefinitionen indeholder condition: always(). Denne betingelse angiver for Azure Pipelines, at den altid skal publicere testresultaterne, selvom det foregående trin mislykkes. Denne betingelse er vigtig, fordi en eventuel mislykket test medfører, at testtrinnet mislykkes, og pipelinen normalt stopper med at køre efter et mislykket trin.

  4. Gem filen.

Bekræft og bekræft din pipelinedefinition

  1. Kontrollér, at din azure-pipelines.yml-fil ligner følgende kode:

    trigger:
      batch: true
      branches:
        include:
        - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      - name: deploymentDefaultLocation
        value: westus3
    
    stages:
    
    - stage: Lint
      jobs:
      - job: LintCode
        displayName: Lint code
        steps:
          - script: |
              az bicep build --file deploy/main.bicep
            name: LintBicepCode
            displayName: Run Bicep linter
    
    - stage: Validate
      jobs:
      - job: ValidateBicepCode
        displayName: Validate Bicep code
        steps:
          - task: AzureResourceManagerTemplateDeployment@3
            name: RunPreflightValidation
            displayName: Run preflight validation
            inputs:
              connectedServiceName: $(ServiceConnectionName)
              location: $(deploymentDefaultLocation)
              deploymentMode: Validation
              resourceGroupName: $(ResourceGroupName)
              csmFile: deploy/main.bicep
              overrideParameters: >
                -environmentType $(EnvironmentType)
    
    - stage: Preview
      jobs:
      - job: PreviewAzureChanges
        displayName: Preview Azure changes
        steps:
          - task: AzureCLI@2
            name: RunWhatIf
            displayName: Run what-if
            inputs:
              azureSubscription: $(ServiceConnectionName)
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                az deployment group what-if \
                  --resource-group $(ResourceGroupName) \
                  --template-file deploy/main.bicep \
                  --parameters environmentType=$(EnvironmentType)
    
    - stage: Deploy
      jobs:
      - deployment: DeployWebsite
        displayName: Deploy website
        environment: Website
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                - task: AzureResourceManagerTemplateDeployment@3
                  name: DeployBicepFile
                  displayName: Deploy Bicep file
                  inputs:
                    connectedServiceName: $(ServiceConnectionName)
                    deploymentName: $(Build.BuildNumber)
                    location: $(deploymentDefaultLocation)
                    resourceGroupName: $(ResourceGroupName)
                    csmFile: deploy/main.bicep
                    overrideParameters: >
                      -environmentType $(EnvironmentType)
                    deploymentOutputs: deploymentOutputs
    
                - bash: |
                    echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')"
                  name: SaveDeploymentOutputs
                  displayName: Save deployment outputs into variables
                  env:
                    DEPLOYMENT_OUTPUTS: $(deploymentOutputs)
    
    - stage: SmokeTest
      jobs:
      - job: SmokeTest
        displayName: Smoke test
        variables:
          appServiceAppHostName: $[ stageDependencies.Deploy.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ]
        steps:
          - task: PowerShell@2
            name: RunSmokeTests
            displayName: Run smoke tests
            inputs:
              targetType: inline
              script: |
                $container = New-PesterContainer `
                  -Path 'deploy/Website.Tests.ps1' `
                  -Data @{ HostName = '$(appServiceAppHostName)' }
                Invoke-Pester `
                  -Container $container `
                  -CI
    
          - task: PublishTestResults@2
            name: PublishTestResults
            displayName: Publish test results
            condition: always()
            inputs:
              testResultsFormat: NUnit
              testResultsFiles: 'testResults.xml'
    

    Hvis den ikke gør det, skal du opdatere den, så den stemmer overens med dette eksempel, og derefter gemme den.

  2. Bekræft og send dine ændringer til Git-lageret ved at køre følgende kommandoer i Visual Studio Code-terminalen:

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

Kør pipelinen, og gennemse testresultatet

  1. I din browser skal du gå til din pipeline.

  2. Vælg den seneste kørsel af pipelinen.

    Vent, indtil pipelinen fuldfører faserne Lint, Validateog Preview. Selvom Azure Pipelines automatisk opdaterer siden med den seneste status, er det en god idé at opdatere siden lejlighedsvist.

  3. Vælg knappen Gennemse, og vælg derefter Godkend.

    Vent, indtil pipelinen er færdig.

  4. Bemærk, at fasen Deploy afsluttes. Fasen SmokeTest afsluttes med en fejl.

    Skærmbillede af Azure DevOps-grænsefladen, der viser faserne for pipelinekørsel. Fasen SmokeTest rapporterer fejl.

  5. Vælg fanen Test.

    Skærmbillede af Azure DevOps-grænsefladen, der viser pipelinekørslen, hvor fanen Test er fremhævet.

  6. Bemærk, at testoversigten viser, at to test kørte. En gik forbi, og en mislykkedes. Den mislykkede test er angivet som Toy-websted.Serverer ikke sider via HTTP-.

    Skærmbillede af Azure DevOps-grænsefladen, der viser testresultaterne for pipelinekørslen, hvor den mislykkede test er fremhævet.

    Denne tekst angiver, at webstedet ikke er konfigureret korrekt til at opfylde dit sikkerhedsteams krav.

Opdater Bicep-filen

Nu, hvor du har identificeret, at din Bicep-definition ikke opfylder dit sikkerhedsteams krav, kan du løse problemet.

  1. Åbn filen main.bicep i mappen installér i Visual Studio Code.

  2. Find definitionen af Azure App Service-appen, og opdater den, så den indeholder egenskaben httpsOnly i det properties område:

    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. Gem filen.

  4. Bekræft og send dine ændringer til Git-lageret ved at køre følgende kommandoer i Visual Studio Code-terminalen:

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

Kør pipelinen igen

  1. I din browser skal du gå til din pipeline.

  2. Vælg den seneste kørsel.

    Vent, indtil pipelinen fuldfører faserne Lint, Validateog Preview. Selvom Azure Pipelines automatisk opdaterer siden med den seneste status, er det en god idé at opdatere siden lejlighedsvist.

  3. Vælg prøveversion fase, og gennemse what if-resultaterne igen.

    Bemærk, at what if-kommandoen har registreret ændringen i værdien for egenskaben httpsOnly:

    Resource and property changes are indicated with these symbols:
      + Create
      ~ Modify
      = Nochange
    
    The deployment will update the following scope:
    
    Scope: /subscriptions/f0750bbe-ea75-4ae5-b24d-a92ca601da2c/resourceGroups/ToyWebsiteTest
    
      ~ Microsoft.Web/sites/toy-website-nbfnedv766snk [2021-01-15]
        + properties.siteConfig.localMySqlEnabled:   false
        + properties.siteConfig.netFrameworkVersion: "v4.6"
        ~ properties.httpsOnly:                      false => true
    
      = Microsoft.Insights/components/toywebsite [2020-02-02]
      = Microsoft.Storage/storageAccounts/mystoragenbfnedv766snk [2021-04-01]
      = Microsoft.Web/serverfarms/toy-website [2021-01-15]
    
    Resource changes: 1 to modify, 3 no change.
    
  4. Gå tilbage til pipelinekørslen.

  5. Vælg knappen Gennemse, og vælg derefter Godkend.

    Vent, indtil pipelinen er færdig.

  6. Bemærk, at hele pipelinen afsluttes korrekt, herunder fasen SmokeTest. Denne succes angiver, at begge test er bestået.

    Skærmbillede af Azure DevOps-grænsefladen, der viser en vellykket pipelinekørsel.

Ryd op i ressourcerne

Nu, hvor du har fuldført øvelsen, kan du fjerne ressourcerne, så du ikke faktureres for dem.

Kør følgende kommando i Visual Studio Code-terminalen:

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

Ressourcegruppen slettes i baggrunden.

Remove-AzResourceGroup -Name ToyWebsiteTest -Force