Zabezpieczenia za pośrednictwem szablonów
Azure DevOps Services | Azure DevOps Server 2022 r. | Azure DevOps Server 2020 r.
Sprawdzanie chronionych zasobów to podstawowy blok konstrukcyjny zabezpieczeń usługi Azure Pipelines. Sprawdza działanie niezależnie od struktury — etapów i zadań — potoku. Jeśli kilka potoków w zespole lub organizacji ma taką samą strukturę, możesz dodatkowo uprościć zabezpieczenia przy użyciu szablonów.
Usługa Azure Pipelines oferuje dwa rodzaje szablonów: obejmuje i rozszerza.
Dołączone szablony zachowują się tak jak #include
w języku C++: wklejasz kod szablonu bezpośrednio do pliku zewnętrznego, który się do niego odwołuje. Na przykład w tym miejscu wstawiono szablon dołączania (include-npm-steps.yml
) do steps
elementu .
steps:
- template: templates/include-npm-steps.yml
Aby kontynuować metaforę języka C++, extends
szablony są bardziej podobne do dziedziczenia: szablon zapewnia zewnętrzną strukturę potoku i zestaw miejsc, w których odbiorca szablonu może wprowadzać ukierunkowane zmiany.
Korzystanie z szablonów rozszerzeń
W przypadku najbardziej bezpiecznych potoków zalecamy rozpoczęcie od extends
szablonów.
Udostępniając strukturę zewnętrzną, szablon może uniemożliwić złośliwemu kodowi przejście do potoku.
Nadal można użyć metody includes
, zarówno w szablonie, jak i w ostatnim potoku, aby uwzględnić typowe elementy konfiguracji.
Aby użyć szablonu rozszerzenia, potok może wyglądać podobnie do poniższego przykładu.
# template.yml
parameters:
- name: usersteps
type: stepList
default: []
steps:
- ${{ each step in parameters.usersteps }}:
- ${{ step }}
# 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
Podczas konfigurowania extends
szablonów rozważ zakotwiczenie ich w określonej gałęzi lub tagu usługi Git.
W ten sposób, jeśli konieczne będzie wprowadzenie zmian powodujących niezgodność, istniejące potoki nie będą miały wpływu.
W powyższych przykładach użyto tej funkcji.
Funkcje zabezpieczeń wymuszane za pomocą języka YAML
Istnieje szereg zabezpieczeń wbudowanych w składnię języka YAML, a szablon rozszerzeń może wymuszać użycie dowolnych lub wszystkich z nich.
Cele kroków
Ogranicz kilka kroków do uruchomienia w kontenerze zamiast hosta. Bez dostępu do hosta agenta kroki użytkownika nie mogą modyfikować konfiguracji agenta ani pozostawiać złośliwego kodu do późniejszego wykonania. Najpierw uruchom kod na hoście, aby zwiększyć bezpieczeństwo kontenera. Na przykład zalecamy ograniczenie dostępu do sieci. Bez otwartego dostępu do sieci kroki użytkownika nie będą mogły uzyskać dostępu do pakietów z nieautoryzowanych źródeł lub przekazać kod i wpisy tajne do lokalizacji sieciowej.
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 agentów
Ogranicz usługi, które agent usługi Azure Pipelines zapewni użytkownikowi. Kroki żądań usług przy użyciu "poleceń rejestrowania" (specjalnie sformatowane ciągi drukowane do stdout). W trybie ograniczonym większość usług agenta, takich jak przekazywanie artefaktów i dołączanie wyników testów, jest niedostępna.
# this task will fail because its `target` property instructs the agent not to allow publishing artifacts
- task: PublishBuildArtifacts@1
inputs:
artifactName: myartifacts
target:
commands: restricted
Jednym z poleceń nadal dozwolonych w trybie ograniczonym jest setvariable
polecenie . Ponieważ zmienne potoku są eksportowane jako zmienne środowiskowe do kolejnych zadań, zadania, które generują dane dostarczone przez użytkownika (na przykład zawartość otwartych problemów pobranych z interfejsu API REST) może być podatna na ataki iniekcyjne. Taka zawartość użytkownika może ustawiać zmienne środowiskowe, które z kolei mogą służyć do wykorzystania hosta agenta. Aby to uniemożliwić, autorzy potoków mogą jawnie zadeklarować, które zmienne są ustawiane za pomocą polecenia rejestrowania setvariable
. Określanie pustej listy nie zezwala na ustawienie wszystkich zmiennych.
# this task will fail because the task is only allowed to set the 'expectedVar' variable, or a variable prefixed with "ok"
- task: PowerShell@2
target:
commands: restricted
settableVariables:
- expectedVar
- ok*
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[task.setvariable variable=BadVar]myValue"
Warunkowe wstawianie etapów lub zadań
Ogranicz etapy i zadania do uruchamiania w określonych warunkach. Warunki mogą pomóc, na przykład, aby upewnić się, że tworzysz tylko niektóre gałęzie.
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
Wymagaj określonej składni z szablonami rozszerzeń
Szablony mogą iterować i modyfikować/nie zezwalać na dowolną składnię YAML. Iteracja może wymusić użycie określonej składni YAML, w tym powyższych funkcji.
Szablon może ponownie napisać kroki użytkownika i zezwalać tylko na uruchamianie niektórych zatwierdzonych zadań. Można na przykład uniemożliwić wykonywanie skryptu wbudowanego.
Ostrzeżenie
W poniższym przykładzie kroki typu "bash", "powershell", "pwsh" i "script" nie są wykonywane. Aby zapewnić pełną blokadę skryptów ad hoc, należy 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 lines below will 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 }}'
# 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 typów
Szablony i ich parametry są przekształcane w stałe przed uruchomieniem potoku. Parametry szablonu zapewniają bezpieczeństwo typu parametrom wejściowym. Na przykład może ograniczyć, które pule mogą być używane w potoku, oferując wyliczenie możliwych opcji, a nie ciąg wolny.
# 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
# azure-pipelines.yml
extends:
template: template.yml
parameters:
userpool: private-pool-1
Ustawianie wymaganych szablonów
Aby wymagać użycia określonego szablonu, możesz ustawić wymagany szablon sprawdzania zasobu lub środowiska. Wymagane sprawdzenie szablonu można użyć podczas rozszerzania szablonu.
Stan sprawdzania można sprawdzić podczas wyświetlania zadania potoku. Jeśli potok nie wykracza poza szablon wymagania, sprawdzanie zakończy się niepowodzeniem, a uruchomienie zostanie zatrzymane. Zobaczysz, że sprawdzanie nie powiodło się.
Po użyciu wymaganego szablonu zobaczysz, że sprawdzanie zostało przekazane.
W tym miejscu szablon params.yml
jest wymagany z zatwierdzeniem zasobu. Aby wyzwolić potok, aby zakończyć się niepowodzeniem, oznacz odwołanie do params.yml
.
# 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 }}
# azure-pipeline.yml
resources:
containers:
- container: my-container
endpoint: my-service-connection
image: mycontainerimages
extends:
template: params.yml
parameters:
yesNo: true
image: 'windows-latest'
Dodatkowe kroki
Szablon może dodawać kroki bez konieczności uwzględnienia ich przez autora potoku. Te kroki mogą służyć do uruchamiania skanowania poświadczeń lub sprawdzania kodu statycznego.
# template to insert a step before and after user steps in every job
parameters:
jobs: []
jobs:
- ${{ each job in parameters.jobs }}: # Each job
- ${{ each pair in job }}: # Insert all properties other than "steps"
${{ if ne(pair.key, 'steps') }}:
${{ pair.key }}: ${{ pair.value }}
steps: # Wrap the steps
- task: CredScan@1 # Pre steps
- ${{ job.steps }} # Users steps
- task: PublishMyTelemetry@1 # Post steps
condition: always()
Wymuszanie szablonu
Szablon jest tylko mechanizmem zabezpieczeń, jeśli można go wymusić. Punkt kontrolny do wymuszania używania szablonów jest zasobem chronionym. Zatwierdzenia i kontrole puli agentów lub innych chronionych zasobów, takich jak repozytoria. Aby zapoznać się z przykładem, zobacz Dodawanie sprawdzania zasobów repozytorium.
Następne kroki
Następnie dowiesz się, jak bezpiecznie pobierać dane wejściowe za pomocą zmiennych i parametrów.
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla