Używanie szablonów do zabezpieczeń
Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020
W tym artykule opisano, jak szablony mogą usprawnić zabezpieczenia usługi Azure Pipelines. Szablony mogą definiować zewnętrzną strukturę potoku i zapobiegać infiltracji złośliwego kodu. Szablony mogą również automatycznie dołączać kroki do wykonywania zadań, takich jak skanowanie poświadczeń. Jeśli wiele potoków w zespole lub organizacji współużytkuje tę samą strukturę, rozważ użycie szablonów.
Sprawdzanie zasobów chronionych stanowi podstawową strukturę zabezpieczeń dla usługi Azure Pipelines. Te testy mają zastosowanie niezależnie od struktury potoku, etapów i zadań. Za pomocą szablonów można wymusić te kontrole.
Dołącza i rozszerza szablony
Usługa Azure Pipelines udostępnia szablony i rozszerza je .
Zawiera szablony zawierają kod szablonu bezpośrednio w pliku zewnętrznym, który się do niego odwołuje, podobnie jak
#include
w języku C++. Poniższy przykładowy potok wstawia szablon include-npm-steps.yml dosteps
sekcji.steps: - template: templates/include-npm-steps.yml
Rozszerza szablony definiują zewnętrzną strukturę potoku i oferują określone punkty dla dostosowań docelowych. W kontekście języka C++
extends
szablony przypominają dziedziczenie.
Gdy używasz extends
szablonów, możesz również użyć includes
go zarówno w szablonie, jak i w końcowym potoku, aby wykonać typowe elementy konfiguracji. Aby uzyskać pełną dokumentację, zobacz dokumentację użycia szablonu.
Rozszerza szablony
W przypadku najbardziej bezpiecznych potoków zacznij od używania szablonów rozszerzeń. Te szablony definiują zewnętrzną strukturę potoku i uniemożliwiają złośliwemu kodowi infiltrowanie potoku.
Na przykład następujący plik szablonu ma nazwę template.yml.
parameters:
- name: usersteps
type: stepList
default: []
steps:
- ${{ each step in parameters.usersteps }}:
- ${{ step }}
Poniższy potok rozszerza szablon template.yml .
# azure-pipelines.yml
resources:
repositories:
- repository: templates
type: git
name: MyProject/MyTemplates
ref: refs/tags/v1
extends:
template: template.yml@templates
parameters:
usersteps:
- script: echo This is my first step
- script: echo This is my second step
Napiwek
Podczas konfigurowania extends
szablonów należy rozważyć zakotwiczenie ich w określonej gałęzi lub tagu Usługi Git, więc jeśli wystąpią zmiany powodujące niezgodność, istniejące potoki nie będą miały wpływu. W poprzednim przykładzie użyto tej funkcji.
Funkcje zabezpieczeń potoku YAML
Składnia potoku YAML zawiera kilka wbudowanych zabezpieczeń. Rozszerzenie szablonu może wymuszać ich użycie. Aby zwiększyć bezpieczeństwo potoku, można zaimplementować dowolne z poniższych ograniczeń.
Cele kroków
Niektóre kroki można ograniczyć do uruchamiania w kontenerze, a nie na hoście. Kroki w kontenerach nie mają dostępu do hosta agenta, uniemożliwiając tym krokom modyfikowanie konfiguracji agenta lub pozostawienie złośliwego kodu do późniejszego wykonania.
Rozważ na przykład ograniczenie dostępu do sieci. Bez otwartego dostępu do sieci kroki użytkownika nie mogą pobierać pakietów z nieautoryzowanych źródeł ani przekazywać kodu i wpisów tajnych do zewnętrznych lokalizacji sieciowych.
Poniższy przykładowy potok uruchamia kroki na hoście agenta przed uruchomieniem kroków wewnątrz kontenera.
resources:
containers:
- container: builder
image: mysecurebuildcontainer:latest
steps:
- script: echo This step runs on the agent host, and it could use Docker commands to tear down or limit the container's network
- script: echo This step runs inside the builder container
target: builder
Ograniczenia poleceń rejestrowania agenta
Możesz ograniczyć usługi, które agent usługi Azure Pipelines udostępnia użytkownikowi. Kroki użytkownika żądają usług przy użyciu poleceń rejestrowania, które są specjalnie sformatowanymi ciągami drukowanymi w standardowych danych wyjściowych. W trybie ograniczonym większość usług agenta, takich jak przekazywanie artefaktów i dołączanie wyników testu, jest niedostępna.
Następujące przykładowe zadanie kończy się niepowodzeniem, ponieważ jego target
właściwość instruuje agenta, aby nie zezwalał na publikowanie artefaktów.
- task: PublishBuildArtifacts@1
inputs:
artifactName: myartifacts
target:
commands: restricted
W restricted
trybie setvariable
polecenie pozostaje dopuszczalne, dlatego należy zachować ostrożność, ponieważ zmienne potoku są eksportowane jako zmienne środowiskowe do kolejnych zadań. Jeśli zadania wyjściowe danych dostarczanych przez użytkownika, takich jak otwarte problemy pobierane za pośrednictwem interfejsu API REST, mogą być narażone na ataki iniekcyjne. Złośliwa zawartość użytkownika może ustawić zmienne środowiskowe, które mogą zostać wykorzystane w celu naruszenia zabezpieczeń hosta agenta.
Aby ograniczyć to ryzyko, autorzy potoków mogą jawnie zadeklarować, które zmienne można ustawić przy użyciu polecenia rejestrowania setvariable
. Po określeniu pustej listy wszystkie ustawienia zmiennych są niedozwolone.
Następujące przykładowe zadanie kończy się niepowodzeniem, ponieważ zadanie może ustawić expectedVar
zmienną lub zmienną poprzedzoną prefiksem ok
.
- task: PowerShell@2
target:
commands: restricted
settableVariables:
- expectedVar
- ok*
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[task.setvariable variable=BadVar]myValue"
Etap warunkowy lub wykonywanie zadania
Można ograniczyć etapy i zadania do uruchamiania tylko w określonych warunkach. W poniższym przykładzie warunek gwarantuje, że ograniczony kod kompiluje tylko dla gałęzi głównej.
jobs:
- job: buildNormal
steps:
- script: echo Building the normal, unsensitive part
- ${{ if eq(variables['Build.SourceBranchName'], 'refs/heads/main') }}:
- job: buildMainOnly
steps:
- script: echo Building the restricted part that only builds for main branch
Modyfikowanie składni
Szablony usługi Azure Pipelines mają elastyczność iteracji i modyfikowania składni YAML. Za pomocą iteracji można wymusić określone funkcje zabezpieczeń YAML.
Szablon może również przepisać kroki użytkownika, zezwalając na uruchamianie tylko zatwierdzonych zadań. Można na przykład uniemożliwić wykonywanie skryptów wbudowanych.
Poniższy przykładowy szablon uniemożliwia uruchamianie typów kroków bash
, powershell
, pwsh
i script
. Aby uzyskać pełną blokadę skryptów ad hoc, można również zablokować BatchScript
i ShellScript
.
# template.yml
parameters:
- name: usersteps
type: stepList
default: []
steps:
- ${{ each step in parameters.usersteps }}:
- ${{ if not(or(startsWith(step.task, 'Bash'),startsWith(step.task, 'CmdLine'),startsWith(step.task, 'PowerShell'))) }}:
- ${{ step }}
# The following lines replace tasks like Bash@3, CmdLine@2, PowerShell@2
- ${{ else }}:
- ${{ each pair in step }}:
${{ if eq(pair.key, 'inputs') }}:
inputs:
${{ each attribute in pair.value }}:
${{ if eq(attribute.key, 'script') }}:
script: echo "Script removed by template"
${{ else }}:
${{ attribute.key }}: ${{ attribute.value }}
${{ elseif ne(pair.key, 'displayName') }}:
${{ pair.key }}: ${{ pair.value }}
displayName: 'Disabled by template: ${{ step.displayName }}'
W poniższym potoku, który rozszerza ten szablon, kroki skryptu są usuwane i nie są uruchamiane.
# azure-pipelines.yml
extends:
template: template.yml
parameters:
usersteps:
- task: MyTask@1
- script: echo This step will be stripped out and not run!
- bash: echo This step will be stripped out and not run!
- powershell: echo "This step will be stripped out and not run!"
- pwsh: echo "This step will be stripped out and not run!"
- script: echo This step will be stripped out and not run!
- task: CmdLine@2
displayName: Test - Will be stripped out
inputs:
script: echo This step will be stripped out and not run!
- task: MyOtherTask@2
Parametry bezpieczne dla typu
Przed uruchomieniem potoku szablony i ich parametry są przekształcane w stałe. Parametry szablonu mogą zwiększyć bezpieczeństwo typów dla parametrów wejściowych.
W poniższym przykładowym szablonie parametry ograniczają dostępne opcje puli potoków, udostępniając wyliczenie określonych opcji zamiast zezwalania na ciągi wolnych kształtów.
# template.yml
parameters:
- name: userpool
type: string
default: Azure Pipelines
values:
- Azure Pipelines
- private-pool-1
- private-pool-2
pool: ${{ parameters.userpool }}
steps:
- script: # ... removed for clarity
Po rozszerzeniu szablonu potok musi określić jedną z dostępnych opcji puli.
# azure-pipelines.yml
extends:
template: template.yml
parameters:
userpool: private-pool-1
Kroki szablonu
Szablon może automatycznie uwzględniać kroki w potoku. Te kroki mogą wykonywać zadania, takie jak skanowanie poświadczeń lub sprawdzanie kodu statycznego. Poniższy szablon wstawia kroki przed i po wykonaniu kroków użytkownika w każdym zadaniu.
parameters:
jobs: []
jobs:
- ${{ each job in parameters.jobs }}:
- ${{ each pair in job }}:
${{ if ne(pair.key, 'steps') }}:
${{ pair.key }}: ${{ pair.value }}
steps:
- task: CredScan@1
- ${{ job.steps }}
- task: PublishMyTelemetry@1
condition: always()
Wymuszanie szablonu
Szablony są cennym mechanizmem zabezpieczeń, ale ich skuteczność opiera się na wymuszaniu. Kluczowymi punktami kontrolnymi wymuszania użycia szablonu są chronione zasoby. Możesz skonfigurować zatwierdzenia i sprawdzanie puli agentów lub innych chronionych zasobów, takich jak repozytoria. Aby zapoznać się z przykładem, zobacz Dodawanie sprawdzania zasobów repozytorium.
Wymagane szablony
Aby wymusić użycie określonego szablonu, skonfiguruj wymagany szablon sprawdzania zasobu. Ta kontrola ma zastosowanie tylko wtedy, gdy potok rozszerza się z szablonu.
Podczas wyświetlania zadania potoku można monitorować stan sprawdzania. Jeśli potok nie rozszerza się z wymaganego szablonu, sprawdzanie zakończy się niepowodzeniem. Przebieg zatrzymuje się i powiadamia o nieudanym sprawdzeniu.
Jeśli używasz wymaganego szablonu, sprawdzanie jest sprawdzane.
Poniższy szablon params.yml należy odwołać się do dowolnego potoku, który go rozszerza.
# params.yml
parameters:
- name: yesNo
type: boolean
default: false
- name: image
displayName: Pool Image
type: string
default: ubuntu-latest
values:
- windows-latest
- ubuntu-latest
- macOS-latest
steps:
- script: echo ${{ parameters.yesNo }}
- script: echo ${{ parameters.image }}
Poniższy przykładowy potok rozszerza szablon params.yml i wymaga zatwierdzenia. Aby zademonstrować błąd potoku, oznacz jako komentarz odwołanie do params.yml.
# azure-pipeline.yml
resources:
containers:
- container: my-container
endpoint: my-service-connection
image: mycontainerimages
extends:
template: params.yml
parameters:
yesNo: true
image: 'windows-latest'