Sdílet prostřednictvím


Použití šablon pro zabezpečení

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020

Tento článek popisuje, jak šablony můžou zjednodušit zabezpečení pro Azure Pipelines. Šablony můžou definovat vnější strukturu kanálu a pomáhají zabránit infiltraci škodlivého kódu. Šablony můžou také automaticky zahrnovat kroky pro úlohy, jako je kontrola přihlašovacích údajů. Pokud několik kanálů v rámci vašeho týmu nebo organizace sdílí stejnou strukturu, zvažte použití šablon.

Kontroly chráněných prostředků tvoří základní architekturu zabezpečení pro Azure Pipelines. Tyto kontroly platí bez ohledu na strukturu kanálu, fáze a úlohy. Tyto kontroly můžete vynutit pomocí šablon.

Zahrnuje a rozšiřuje šablony.

Azure Pipelines poskytuje zahrnutí a rozšíření šablon.

  • Obsahuje šablony, které obsahují kód šablony přímo do vnějšího souboru, který na ni odkazuje, podobně jako #include v jazyce C++. Následující příklad kanálu vloží šablonu include-npm-steps.yml do oddílu steps .

      steps:
      - template: templates/include-npm-steps.yml 
    
  • Rozšiřuje šablony definují vnější strukturu kanálu a nabízejí specifické body pro cílené přizpůsobení. V kontextu jazyka C++ extends se šablony podobají dědičnosti.

Když používáte extends šablony, můžete také použít includes šablonu i konečný kanál k provedení běžných částí konfigurace. Úplný odkaz najdete v referenčních informacích k použití šablony.

Rozšiřuje šablony

Pro nejbezpečnější kanály začněte použitím rozšiřujících šablon. Tyto šablony definují vnější strukturu kanálu a brání škodlivému kódu v infiltrování kanálu.

Například následující soubor šablony má název template.yml.

parameters:
- name: usersteps
  type: stepList
  default: []
steps:
- ${{ each step in parameters.usersteps }}:
  - ${{ step }}

Následující kanál rozšiřuje šablonu 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

Tip

Když nastavíte extends šablony, zvažte jejich ukotvení na konkrétní větev Gitu nebo značku, takže pokud dojde k zásadním změnám, stávající kanály to neovlivní. Předchozí příklad používá tuto funkci.

Funkce zabezpečení kanálů YAML

Syntaxe kanálu YAML zahrnuje několik předdefinovaných ochrany. Rozšíření šablony může vynutit jejich použití. Pokud chcete zvýšit zabezpečení kanálu, můžete implementovat některá z následujících omezení.

Cíle kroku

Určité kroky můžete omezit tak, aby se spouštěly v kontejneru, nikoli v hostiteli. Kroky v kontejnerech nemají přístup k hostiteli agenta, což brání těmto krokům v úpravě konfigurace agenta nebo ponechání škodlivého kódu pro pozdější spuštění.

Zvažte například omezení síťového přístupu. Bez otevřeného síťového přístupu nemůžou kroky uživatelů načítat balíčky z neautorizovaných zdrojů ani nahrávat kód a tajné kódy do externích síťových umístění.

Následující příklad kanálu spustí kroky na hostiteli agenta před spuštěním kroků uvnitř kontejneru.

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

Omezení příkazů protokolování agenta

Služby, které agent Azure Pipelines poskytuje, můžete omezit na kroky uživatelů. Uživatelské kroky požadují služby pomocí příkazů protokolování, které jsou speciálně formátované řetězce vytištěné do standardního výstupu. V omezeném režimu není většina služeb agenta, jako je nahrání artefaktů a připojení výsledků testu, nedostupná.

Následující příklad úlohy selže, protože jeho target vlastnost dává agent pokyn, aby nepovolil publikování artefaktů.

- task: PublishBuildArtifacts@1
  inputs:
    artifactName: myartifacts
  target:
    commands: restricted

V restricted režimu setvariable zůstává příkaz povolený, proto je potřeba opatrnost, protože proměnné kanálu se exportují jako proměnné prostředí do následných úloh. Pokud úkoly vypíše data poskytovaná uživatelem, jako jsou otevřené problémy načtené přes rozhraní REST API, můžou být ohrožené útoky prostřednictvím injektáže. Škodlivý uživatelský obsah může nastavit proměnné prostředí, které by mohly být zneužity k ohrožení hostitele agenta.

Aby se toto riziko omezilo, můžou autoři kanálů explicitně deklarovat, které proměnné jsou nastaveny pomocí setvariable příkazu protokolování. Když zadáte prázdný seznam, nastavení všech proměnných se nepovolí.

Následující příklad úkol selže, protože úkol je povolen pouze nastavit expectedVar proměnnou nebo proměnnou s předponou ok.

- task: PowerShell@2
  target:
    commands: restricted
    settableVariables:
    - expectedVar
    - ok*
  inputs:
    targetType: 'inline'
    script: |
      Write-Host "##vso[task.setvariable variable=BadVar]myValue"

Podmíněná fáze nebo spuštění úlohy

Fáze a úlohy můžete omezit tak, aby běžely pouze za určitých podmínek. V následujícím příkladu podmínka zajistí, že se omezený kód sestaví pouze pro hlavní větev.

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

Úprava syntaxe

Šablony Azure Pipelines mají flexibilitu iterovat a upravovat syntaxi YAML. Pomocí iterace můžete vynutit konkrétní funkce zabezpečení YAML.

Šablona může také přepsat kroky uživatele, což umožňuje spouštět jenom schválené úkoly. Můžete například zabránit spuštění vloženého skriptu.

Následující příklad šablony zabraňuje spuštění typů bashkroků , powershellpwsh, a script spuštění. K úplnému uzamčení ad hoc skriptů můžete také blokovat BatchScript a 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 }}'

V následujícím kanálu, který tuto šablonu rozšiřuje, se kroky skriptu odstraní a nespustí.

# 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 bezpečného typu

Před spuštěním kanálu se šablony a jejich parametry transformují na konstanty. Parametry šablony mohou zvýšit bezpečnost typů pro vstupní parametry.

V následující ukázkové šabloně parametry omezují dostupné možnosti fondu kanálů tím, že poskytují výčet konkrétních voleb místo povolení volných řetězců.

# 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

Když kanál rozšíří šablonu, musí zadat jednu z dostupných možností fondu.

# azure-pipelines.yml
extends:
  template: template.yml
  parameters:
    userpool: private-pool-1

Kroky šablony

Šablona může automaticky zahrnovat kroky v kanálu. Tyto kroky můžou provádět úlohy, jako je kontrola přihlašovacích údajů nebo kontrola statického kódu. Následující šablona vloží kroky před a za kroky uživatele v každé úloze.

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

Vynucení šablony

Šablony jsou cenným mechanismem zabezpečení, ale jejich efektivita spoléhá na vynucování. Klíčové kontrolní body pro vynucování použití šablony jsou chráněné prostředky. Můžete nakonfigurovat schválení a kontroly fondu agentů nebo jiných chráněných prostředků, jako jsou úložiště. Příklad najdete v tématu Přidání kontroly prostředku úložiště.

Požadované šablony

Pokud chcete vynutit použití konkrétní šablony, nakonfigurujte požadovanou kontrolu prostředku. Tato kontrola platí pouze v případě, že kanál rozšiřuje šablonu.

Když zobrazíte úlohu kanálu, můžete monitorovat stav kontroly. Pokud kanál nepochází z požadované šablony, kontrola se nezdaří. Spuštění se zastaví a upozorní vás na neúspěšnou kontrolu.

Snímek obrazovky znázorňující neúspěšnou kontrolu schválení

Když použijete požadovanou šablonu, projde kontrola.

Snímek obrazovky znázorňující úspěšnou kontrolu schválení

Na následující šablonu params.yml se musí odkazovat v jakémkoli kanálu, který ji rozšiřuje.

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

Následující ukázkový kanál rozšiřuje šablonu params.yml a vyžaduje ji ke schválení. Pokud chcete předvést selhání kanálu, zakomentujte odkaz na 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'