Oefening: een testfase toevoegen aan uw pijplijn

Voltooid

Het beveiligingsteam van uw speelgoedbedrijf heeft u gevraagd om te controleren of uw website alleen toegankelijk is via HTTPS. In deze oefening configureert u uw pijplijn om een betrouwbaarheidstest uit te voeren waarmee de vereisten van het beveiligingsteam worden gecontroleerd.

Tijdens het proces gaat u het volgende doen:

  • Voeg een testscript toe aan uw opslagplaats.
  • Werk uw pijplijndefinitie bij om een testfase toe te voegen.
  • Voer de pijplijn uit en controleer of de test mislukt.
  • Corrigeer het Bicep-bestand en bekijk de pijplijnuitvoering.

Een testscript toevoegen

Hier voegt u een testscript toe om te controleren of de website toegankelijk is wanneer HTTPS wordt gebruikt en niet toegankelijk is wanneer het niet-beveiligde HTTP-protocol wordt gebruikt.

  1. Maak in Visual Studio Code een nieuw bestand in de map Deploy met de naam Website.Tests.ps1.

    Schermopname van Visual Studio Code Explorer, met de implementatiemap en het testbestand weergegeven.

  2. Plak de volgende testcode in het bestand:

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

    Deze code is een Pester-testbestand. Hiervoor is een parameter met de naam $HostNamevereist. Er worden twee tests uitgevoerd op basis van de hostnaam:

    • Probeer verbinding te maken met de website via HTTPS. De test wordt doorgegeven als de server reageert met een HTTP-antwoordstatuscode tussen 200 en 299, wat aangeeft dat de verbinding is geslaagd.
    • Probeer verbinding te maken met de website via HTTP. De test wordt doorgegeven als de server reageert met een HTTP-antwoordstatuscode van 300 of hoger.

    Voor deze oefening is het niet belangrijk dat u de details van het testbestand begrijpt en hoe het werkt. We geven koppelingen in de samenvatting, zodat u meer informatie kunt krijgen als u geïnteresseerd bent.

De uitvoer van uw Bicep-bestand publiceren als een fase-uitvoervariabele

Voor het testscript dat u in de voorgaande stappen hebt gemaakt, moet een hostnaam worden getest. Uw Bicep-bestand bevat al een uitvoer, maar voordat u het in uw betrouwbaarheidstests kunt gebruiken, moet u het publiceren als een uitvoervariabele voor fases.

  1. Open in Visual Studio Code het azure-pipelines.yml-bestand in de implementatiemap .

  2. Werk in de implementatiefase de implementatiestap bij om de uitvoer naar een variabele te publiceren:

    - 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
    

    Uw implementatieproces maakt nu nog steeds gebruik van dezelfde taak als voorheen, maar de uitvoer van de implementaties wordt opgeslagen in een pijplijnvariabele met de naam deploymentOutputs. De uitvoervariabele is opgemaakt als JSON.

  3. Als u de met JSON opgemaakte uitvoer wilt converteren naar pijplijnvariabelen, voegt u de volgende scriptstap toe onder de implementatiestap:

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

    Als de implementatie is voltooid, heeft het script toegang tot de waarde van elke uitvoer van de Bicep-implementatie. Het script gebruikt het jq hulpprogramma om toegang te krijgen tot het relevante deel van de JSON-uitvoer. Vervolgens wordt de waarde gepubliceerd naar een fase-uitvoervariabele met dezelfde naam als de Bicep-implementatie-uitvoer.

    Notitie

    Pester en jq zijn beide vooraf geïnstalleerd op door Microsoft gehoste agents voor Azure Pipelines. U hoeft niets speciaals te doen om ze in een scriptstap te gebruiken.

  4. Sla het bestand op.

Een betrouwbaarheidstestfase toevoegen aan uw pijplijn

U kunt nu een betrouwbaarheidstestfase toevoegen waarmee uw tests worden uitgevoerd.

  1. Voeg onderaan het bestand de volgende definitie toe voor de fase SmokeTest :

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

    Met deze code worden de fase en een taak gedefinieerd. Er wordt ook een variabele gemaakt in de taak met de naam appServiceAppHostName. Deze variabele gebruikt de waarde van de uitvoervariabele die u in de vorige sectie hebt gemaakt.

  2. Voeg onderaan het bestand de volgende stapdefinitie toe aan de fase 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
    

    Met deze stap wordt een PowerShell-script uitgevoerd om het testscript uit te voeren dat u eerder hebt geschreven met behulp van het testhulpprogramma Pester.

  3. Voeg onderaan het bestand de volgende stapdefinitie toe aan de fase SmokeTest :

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

    Met deze stap wordt het testresultatenbestand gebruikt dat Pester maakt en publiceert als pijplijntestresultaten. U ziet hoe de resultaten binnenkort worden weergegeven.

    Zoals u ziet, bevat condition: always()de stapdefinitie . Deze voorwaarde geeft aan Azure Pipelines aan dat de testresultaten altijd moeten worden gepubliceerd, zelfs als de vorige stap mislukt. Deze voorwaarde is belangrijk omdat een mislukte test ertoe leidt dat de teststap mislukt en normaal gesproken stopt de pijplijn na een mislukte stap.

  4. Sla het bestand op.

Uw pijplijndefinitie controleren en doorvoeren

  1. Controleer of uw azure-pipelines.yml bestand eruitziet als de volgende code:

    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'
    

    Als dit niet het probleem is, werkt u deze bij zodat deze overeenkomt met dit voorbeeld en slaat u het op.

  2. Voer uw wijzigingen door en push deze naar uw Git-opslagplaats door de volgende opdrachten uit te voeren in de Visual Studio Code-terminal:

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

Voer de pijplijn uit en controleer het testresultaat

  1. Ga in uw browser naar uw pijplijn.

  2. Selecteer de meest recente uitvoering van uw pijplijn.

    Wacht totdat de lint-, validatie- en preview-fasen zijn voltooid. Hoewel Azure Pipelines de pagina automatisch bijwerkt met de meest recente status, is het een goed idee om uw pagina af en toe te vernieuwen.

  3. Selecteer de knop Controleren en selecteer vervolgens Goedkeuren.

    Wacht tot de pijplijnuitvoering is voltooid.

  4. U ziet dat de implementatiefase is voltooid. De SmokeTest-fase eindigt met een fout.

    Schermopname van de Azure DevOps-interface met de fasen van de pijplijnuitvoering. De SmokeTest-fase rapporteert een fout.

  5. Selecteer het tabblad Tests .

    Schermopname van de Azure DevOps-interface waarin de pijplijnuitvoering wordt weergegeven, met het tabblad Tests gemarkeerd.

  6. U ziet dat in de testsamenvatting wordt aangegeven dat er twee tests zijn uitgevoerd. Eén geslaagd en één is mislukt. De test die is mislukt, wordt vermeld als Speelgoedwebsite.Biedt geen pagina's via HTTP.

    Schermopname van de Azure DevOps-interface met de testresultaten van de pijplijnuitvoering, met de mislukte test gemarkeerd.

    Deze tekst geeft aan dat de website niet juist is geconfigureerd om te voldoen aan de vereisten van uw beveiligingsteam.

Het Bicep-bestand bijwerken

Nu u hebt vastgesteld dat uw Bicep-definitie niet voldoet aan de vereisten van uw beveiligingsteam, lost u deze op.

  1. Open in Visual Studio Code het bestand main.bicep in de implementatiemap .

  2. Zoek de definitie voor de Azure-app Service-app en werk deze bij om de eigenschap op te nemen in het httpsOnlyproperties gebied:

    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. Sla het bestand op.

  4. Voer uw wijzigingen door en push deze naar uw Git-opslagplaats door de volgende opdrachten uit te voeren in de Visual Studio Code-terminal:

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

De pijplijn opnieuw uitvoeren

  1. Ga in uw browser naar uw pijplijn.

  2. Selecteer de meest recente uitvoering.

    Wacht totdat de lint-, validatie- en preview-fasen zijn voltooid. Hoewel Azure Pipelines de pagina automatisch bijwerkt met de meest recente status, is het een goed idee om uw pagina af en toe te vernieuwen.

  3. Selecteer de preview-fase en bekijk de wat-als-resultaten opnieuw.

    U ziet dat de what-if-opdracht de wijziging heeft gedetecteerd in de waarde van de httpsOnly eigenschap:

    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. Ga terug naar de pijplijnuitvoering.

  5. Selecteer de knop Controleren en selecteer Vervolgens Goedkeuren.

    Wacht tot de pijplijnuitvoering is voltooid.

  6. U ziet dat de hele pijplijn is voltooid, inclusief de SmokeTest-fase . Dit succes geeft aan dat beide tests zijn geslaagd.

    Schermopname van de Azure DevOps-interface met een geslaagde pijplijnuitvoering.

De resources opschonen

Nu u de oefening hebt voltooid, kunt u de resources verwijderen zodat u er geen kosten voor in rekening worden gebracht.

Voer in de Visual Studio Code-terminal de volgende opdracht uit:

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

De resourcegroep wordt op de achtergrond verwijderd.

Remove-AzResourceGroup -Name ToyWebsiteTest -Force