Ćwiczenie — dodawanie etapu testu do potoku
Zespół ds. zabezpieczeń twojej firmy z prośbą o sprawdzenie, czy witryna internetowa jest dostępna tylko za pośrednictwem protokołu HTTPS. W tym ćwiczeniu skonfigurujesz potok, aby uruchomić test weryfikacyjny kompilacji sprawdzający wymagania zespołu ds. zabezpieczeń.
Podczas tego procesu wykonasz następujące czynności:
- Dodaj skrypt testowy do repozytorium.
- Zaktualizuj definicję potoku, aby dodać etap testu.
- Uruchom potok i obserwuj niepowodzenie testu.
- Napraw plik Bicep i sprawdź przebieg potoku pomyślnie.
Dodawanie skryptu testowego
W tym miejscu dodasz skrypt testowy, aby sprawdzić, czy witryna internetowa jest dostępna, gdy jest używany protokół HTTPS i nie jest dostępny, gdy jest używany niezabezpieczony protokół HTTP.
W programie Visual Studio Code utwórz nowy plik w folderze wdrażania o nazwie Website.Tests.ps1.
Wklej następujący kod testowy do pliku:
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" } }
Ten kod jest plikiem testowym Pester. Wymaga parametru o nazwie
$HostName
. Uruchamia dwa testy względem nazwy hosta:- Spróbuj nawiązać połączenie z witryną internetową za pośrednictwem protokołu HTTPS. Test zakończy się pomyślnie, jeśli serwer odpowie kodem stanu odpowiedzi HTTP z zakresu od 200 do 299, co oznacza pomyślne połączenie.
- Spróbuj nawiązać połączenie z witryną internetową za pośrednictwem protokołu HTTP. Test zakończy się pomyślnie, jeśli serwer odpowie kodem stanu odpowiedzi HTTP 300 lub wyższym.
Na potrzeby tego ćwiczenia nie jest ważne, aby zrozumieć szczegóły pliku testowego i sposób jego działania. W podsumowaniu udostępnimy linki, aby dowiedzieć się więcej, jeśli cię interesują.
Publikowanie danych wyjściowych pliku Bicep jako zmiennej wyjściowej etapu
Skrypt testowy utworzony w poprzednich krokach wymaga przetestowania nazwy hosta. Plik Bicep zawiera już dane wyjściowe, ale zanim będzie można go użyć w testach weryfikacyjnych kompilacji, musisz opublikować go jako zmienną wyjściową etapu.
W programie Visual Studio Code otwórz plik azure-pipelines.yml w folderze deploy .
Na etapie Wdrażania zaktualizuj krok wdrażania, aby opublikować dane wyjściowe w zmiennej:
- 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
Teraz proces wdrażania nadal używa tego samego zadania, co wcześniej, ale dane wyjściowe z wdrożeń są przechowywane w zmiennej potoku o nazwie
deploymentOutputs
. Zmienna wyjściowa jest formatowana jako JSON.Aby przekonwertować dane wyjściowe sformatowane w formacie JSON na zmienne potoku, dodaj następujący krok skryptu poniżej kroku wdrażania:
- 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)
Jeśli wdrożenie zakończy się pomyślnie, skrypt uzyskuje dostęp do wartości poszczególnych danych wyjściowych z wdrożenia Bicep. Skrypt używa
jq
narzędzia do uzyskiwania dostępu do odpowiedniej części danych wyjściowych JSON. Następnie wartość jest publikowana w zmiennej wyjściowej etapu o takiej samej nazwie jak dane wyjściowe wdrożenia Bicep.Uwaga
Oprogramowanie Pester i jq są wstępnie zainstalowane na agentach hostowanych przez firmę Microsoft dla usługi Azure Pipelines. Nie musisz wykonywać żadnych specjalnych czynności, aby używać ich w kroku skryptu.
Zapisz plik.
Dodawanie etapu testu weryfikacyjnego kompilacji do potoku
Teraz możesz dodać etap testu weryfikacyjnego kompilacji, który uruchamia testy.
W dolnej części pliku dodaj następującą definicję etapu SmokeTest :
- stage: SmokeTest jobs: - job: SmokeTest displayName: Smoke test variables: appServiceAppHostName: $[ stageDependencies.Deploy.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ]
Ten kod definiuje etap i zadanie. Tworzy również zmienną w zadaniu o nazwie
appServiceAppHostName
. Ta zmienna pobiera jego wartość ze zmiennej wyjściowej utworzonej w poprzedniej sekcji.W dolnej części pliku dodaj następującą definicję kroku do etapu 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
Ten krok uruchamia skrypt programu PowerShell, aby uruchomić napisany wcześniej skrypt testowy przy użyciu narzędzia do testowania Pester.
W dolnej części pliku dodaj następującą definicję kroku do etapu SmokeTest :
- task: PublishTestResults@2 name: PublishTestResults displayName: Publish test results condition: always() inputs: testResultsFormat: NUnit testResultsFiles: 'testResults.xml'
Ten krok wykonuje plik wyników testu, który Pester tworzy i publikuje jako wyniki testu potoku. Wkrótce zobaczysz, jak są wyświetlane wyniki.
Zwróć uwagę, że definicja kroku zawiera
condition: always()
element . Ten warunek wskazuje usłudze Azure Pipelines, że powinien zawsze publikować wyniki testu, nawet jeśli poprzedni krok zakończy się niepowodzeniem. Ten warunek jest ważny, ponieważ każdy test kończący się niepowodzeniem spowoduje niepowodzenie kroku testu, a zwykle potok przestaje działać po kroku niepowodzenia.Zapisz plik.
Weryfikowanie i zatwierdzanie definicji potoku
Sprawdź, czy plik azure-pipelines.yml wygląda następująco:
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'
Jeśli tak nie jest, zaktualizuj go tak, aby był zgodny z tym przykładem, a następnie zapisz go.
Zatwierdź i wypchnij zmiany do repozytorium Git, uruchamiając następujące polecenia w terminalu programu Visual Studio Code:
git add . git commit -m "Add test stage" git push
Uruchamianie potoku i przeglądanie wyniku testu
W przeglądarce przejdź do potoku.
Wybierz najnowszy przebieg potoku.
Poczekaj, aż potok zakończy etapy Lint, Validate i Preview . Chociaż usługa Azure Pipelines automatycznie aktualizuje stronę o najnowszym stanie, warto odświeżyć stronę od czasu do czasu.
Wybierz przycisk Przejrzyj, a następnie wybierz pozycję Zatwierdź.
Poczekaj na zakończenie przebiegu potoku.
Zwróć uwagę, że etap Deploy (Wdrażanie) kończy się pomyślnie. Etap SmokeTest kończy się błędem.
Wybierz kartę Testy .
Zwróć uwagę, że podsumowanie testu pokazuje, że uruchomiono dwa testy. Jeden przeszedł, a jeden nie powiódł się. Test, który zakończył się niepowodzeniem, jest wyświetlany jako witryna internetowa toy.Nie obsługuje stron za pośrednictwem protokołu HTTP.
Ten tekst wskazuje, że witryna internetowa nie została poprawnie skonfigurowana w celu spełnienia wymagań zespołu ds. zabezpieczeń.
Aktualizowanie pliku Bicep
Po zidentyfikowaniu, że definicja Bicep nie spełnia wymagań zespołu ds. zabezpieczeń, naprawisz ją.
W programie Visual Studio Code otwórz plik main.bicep w folderze deploy .
Znajdź definicję aplikacji usługi aplikacja systemu Azure Service i zaktualizuj ją, aby uwzględnić
httpsOnly
właściwość w swoimproperties
obszarze: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 } ] } } }
Zapisz plik.
Zatwierdź i wypchnij zmiany do repozytorium Git, uruchamiając następujące polecenia w terminalu programu Visual Studio Code:
git add . git commit -m "Configure HTTPS on website" git push
Ponownie uruchom potok
W przeglądarce przejdź do potoku.
Wybierz najnowszy przebieg.
Poczekaj, aż potok zakończy etapy Lint, Validate i Preview . Chociaż usługa Azure Pipelines automatycznie aktualizuje stronę o najnowszym stanie, warto odświeżyć stronę od czasu do czasu.
Wybierz etap Podgląd i ponownie przejrzyj wyniki analizy co-jeżeli.
Zwróć uwagę, że polecenie analizy co-jeżeli wykryło zmianę wartości
httpsOnly
właściwości: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.
Wróć do uruchomienia potoku.
Wybierz przycisk Przejrzyj, a następnie wybierz pozycję Zatwierdź.
Poczekaj na zakończenie przebiegu potoku.
Zwróć uwagę, że cały potok zostanie pomyślnie zakończony, w tym etap SmokeTest . Ten sukces wskazuje, że oba testy zakończyły się pomyślnie.
Oczyszczanie zasobów
Po ukończeniu ćwiczenia możesz usunąć zasoby, aby nie były naliczane opłaty.
W terminalu programu Visual Studio Code uruchom następujące polecenie:
az group delete --resource-group ToyWebsiteTest --yes --no-wait
Grupa zasobów jest usuwana w tle.
Remove-AzResourceGroup -Name ToyWebsiteTest -Force