Övning – Lägga till ett teststeg i pipelinen

Slutförd

Leksaksföretagets säkerhetsteam har bett dig att kontrollera att din webbplats endast är tillgänglig via HTTPS. I den här övningen konfigurerar du pipelinen så att den kör ett röktest som kontrollerar säkerhetsteamets krav.

Under processen gör du följande:

  • Lägg till ett testskript på lagringsplatsen.
  • Uppdatera pipelinedefinitionen för att lägga till ett teststeg.
  • Kör pipelinen och observera att testet misslyckas.
  • Åtgärda Bicep-filen och observera att pipelinekörningen har körts.

Lägga till ett testskript

Här ska du lägga till ett testskript för att kontrollera att webbplatsen är tillgänglig när HTTPS används och inte är tillgänglig när http-protokollet som inte är säkert används.

  1. I Visual Studio Code skapar du en ny fil i distributionsmappen med namnet Website.Tests.ps1.

    Skärmbild av Visual Studio Code Explorer med mappen deploy och testfilen som visas.

  2. Klistra in följande testkod 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"
        }
    
    }
    

    Den här koden är en Pester-testfil. Den kräver en parameter med namnet $HostName. Den kör två tester mot värdnamnet:

    • Försök att ansluta till webbplatsen via HTTPS. Testet godkänns om servern svarar med en HTTP-svarsstatuskod mellan 200 och 299, vilket indikerar en lyckad anslutning.
    • Försök att ansluta till webbplatsen via HTTP. Testet godkänns om servern svarar med en HTTP-svarsstatuskod på 300 eller högre.

    I den här övningen är det inte viktigt att du förstår informationen i testfilen och hur den fungerar. Vi tillhandahåller länkar i sammanfattningen så att du kan lära dig mer om du är intresserad.

Publicera Bicep-filens utdata som en fasutdatavariabel

Testskriptet som du skapade i föregående steg kräver ett värdnamn för att testa. Din Bicep-fil innehåller redan utdata, men innan du kan använda den i dina röktester måste du publicera den som en stegutdatavariabel.

  1. I Visual Studio Code öppnar du filen azure-pipelines.yml i distributionsmappen.

  2. I distributionssteget uppdaterar du distributionssteget för att publicera utdata till 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 använder distributionsprocessen fortfarande samma uppgift som tidigare, men utdata från distributionerna lagras i en pipelinevariabel med namnet deploymentOutputs. Utdatavariabeln formateras som JSON.

  3. Om du vill konvertera JSON-formaterade utdata till pipelinevariabler lägger du till följande skriptsteg under distributionssteget:

    - 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)
    

    Om distributionen har slutförts kommer skriptet åt värdet för varje utdata från Bicep-distributionen. Skriptet jq använder verktyget för att komma åt den relevanta delen av JSON-utdata. Sedan publiceras värdet till en fasutdatavariabel med samma namn som Bicep-distributionsutdata.

    Kommentar

    Pester och jq är båda förinstallerade på Microsoft-värdbaserade agenter för Azure Pipelines. Du behöver inte göra något speciellt för att använda dem i ett skriptsteg.

  4. Spara filen.

Lägga till ett rökteststeg i pipelinen

Nu kan du lägga till ett rökteststeg som kör dina tester.

  1. Lägg till följande definition för SmokeTest-fasen längst ned i filen:

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

    Den här koden definierar fasen och ett jobb. Den skapar också en variabel i jobbet med namnet appServiceAppHostName. Den här variabeln tar värdet från utdatavariabeln som du skapade i föregående avsnitt.

  2. Lägg till följande stegdefinition i SmokeTest-fasen längst ned i filen:

    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
    

    Det här steget kör ett PowerShell-skript för att köra testskriptet som du skrev tidigare med hjälp av Pester-testverktyget.

  3. Lägg till följande stegdefinition i SmokeTest-fasen längst ned i filen:

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

    Det här steget tar testresultatfilen som Pester skapar och publicerar den som pipelinetestresultat. Du ser hur resultatet visas inom kort.

    Observera att stegdefinitionen innehåller condition: always(). Det här villkoret anger för Azure Pipelines att det alltid ska publicera testresultaten, även om föregående steg misslyckas. Det här villkoret är viktigt eftersom ett misslyckat test gör att teststeget misslyckas och normalt slutar pipelinen att köras efter ett misslyckat steg.

  4. Spara filen.

Verifiera och checka in din pipelinedefinition

  1. Kontrollera att filen azure-pipelines.yml ser ut som följande kod:

    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'
    

    Om den inte gör det uppdaterar du den så att den matchar det här exemplet och sparar det sedan.

  2. Checka in och skicka ändringarna till Git-lagringsplatsen genom att köra följande kommandon i Visual Studio Code-terminalen:

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

Kör pipelinen och granska testresultatet

  1. Gå till din pipeline i webbläsaren.

  2. Välj den senaste körningen av din pipeline.

    Vänta tills pipelinen har slutfört faserna Lint, Validate och Preview . Även om Azure Pipelines automatiskt uppdaterar sidan med den senaste statusen är det en bra idé att uppdatera sidan ibland.

  3. Välj knappen Granska och välj sedan Godkänn.

    Vänta tills pipelinekörningen har slutförts.

  4. Observera att distributionssteget har slutförts. SmokeTest-fasen avslutas med ett fel.

    Skärmbild av Azure DevOps-gränssnittet som visar pipelinekörningsstegen. SmokeTest-fasen rapporterar fel.

  5. Välj fliken Tester .

    Skärmbild av Azure DevOps-gränssnittet som visar pipelinekörningen med fliken Tester markerad.

  6. Observera att testsammanfattningen visar att två tester har körts. En passerade och en misslyckades. Testet som misslyckades visas som Leksakswebbplats.Hanterar inte sidor via HTTP.

    Skärmbild av Azure DevOps-gränssnittet som visar pipelinekörningens testresultat med det misslyckade testet markerat.

    Den här texten anger att webbplatsen inte har konfigurerats korrekt för att uppfylla säkerhetsteamets krav.

Uppdatera Bicep-filen

Nu när du har upptäckt att din Bicep-definition inte uppfyller säkerhetsteamets krav ska du åtgärda det.

  1. Öppna filen main.bicep i mappen deploy i Visual Studio Code.

  2. Hitta definitionen för Azure App Service-appen och uppdatera den så att den httpsOnly innehåller egenskapen i dess 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. Spara filen.

  4. Checka in och skicka ändringarna till Git-lagringsplatsen genom att köra följande kommandon i Visual Studio Code-terminalen:

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

Kör pipelinen igen

  1. Gå till din pipeline i webbläsaren.

  2. Välj den senaste körningen.

    Vänta tills pipelinen har slutfört faserna Lint, Validate och Preview . Även om Azure Pipelines automatiskt uppdaterar sidan med den senaste statusen är det en bra idé att uppdatera sidan ibland.

  3. Välj förhandsgranskningssteget och granska konsekvensanalysresultatet igen.

    Observera att kommandot what-if har identifierat ändringen i httpsOnly egenskapens värde:

    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å tillbaka till pipelinekörningen.

  5. Välj knappen Granska och välj sedan Godkänn.

    Vänta tills pipelinekörningen har slutförts.

  6. Observera att hela pipelinen har slutförts, inklusive SmokeTest-fasen . Den här framgången indikerar att båda testerna har godkänts.

    Skärmbild av Azure DevOps-gränssnittet som visar en lyckad pipelinekörning.

Rensa resurserna

Nu när du har slutfört övningen kan du ta bort resurserna så att du inte debiteras för dem.

Kör följande kommando i Visual Studio Code-terminalen:

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

Resursgruppen tas bort i bakgrunden.

Remove-AzResourceGroup -Name ToyWebsiteTest -Force