Zabezpečení prostřednictvím šablon

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

Kontroly chráněných prostředků jsou základním stavebním blokem zabezpečení služby Azure Pipelines. Kontroluje fungování bez ohledu na strukturu – fáze a úlohy – vašeho kanálu. Pokud má několik kanálů ve vašem týmu nebo organizaci stejnou strukturu, můžete zabezpečení ještě zjednodušit pomocí šablon.

Azure Pipelines nabízí dva druhy šablon: zahrnuje a rozšiřuje. Zahrnuté šablony se chovají jako #include v jazyce C++: je to, jako byste kód šablony vložili přímo do vnějšího souboru, který na něj odkazuje. Tady je například vložena šablona obsahující (include-npm-steps.yml) do steps.

  steps:
  - template: templates/include-npm-steps.yml 

Chcete-li pokračovat v metaforě jazyka C++, extends šablony se více podobají dědičnosti: šablona poskytuje vnější strukturu kanálu a sadu míst, kde může příjemce šablony provádět cílené změny.

Použití rozšiřujících šablon

Pro nejbezpečnější kanály doporučujeme začít se šablonami extends . Poskytnutím vnější struktury může šablona zabránit škodlivému kódu v přístupu do vašeho kanálu. Stále můžete použít includes, a to jak v šabloně, tak v konečném kanálu, abyste mohli zohlednit běžné části konfigurace. Pokud chcete použít šablonu rozšíření, váš kanál může vypadat jako v následujícím příkladu.

# 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

Při nastavování extends šablon zvažte jejich ukotvení ke konkrétní větvi nebo značce Gitu. Pokud je tak potřeba provést změny způsobující chybu, nebudou ovlivněny stávající kanály. Výše uvedené příklady používají tuto funkci.

Funkce zabezpečení vynucované prostřednictvím YAML

V syntaxi YAML je zabudováno několik ochran a šablona extends může vynutit použití některé z nich nebo všech.

Cíle kroků

Omezte spouštění některých kroků v kontejneru místo na hostiteli. Bez přístupu k hostiteli agenta nemůžou kroky uživatele změnit konfiguraci agenta ani ponechat škodlivý kód pro pozdější spuštění. Nejprve spusťte kód na hostiteli, aby byl kontejner bezpečnější. Doporučujeme například omezit přístup k síti. Bez otevřeného přístupu k síti nebudou kroky uživatele moci získat přístup k balíčkům z neautorizovaných zdrojů nebo nahrát kód a tajné kódy do síťového umístění.

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

Omezte, jaké služby bude agent Azure Pipelines poskytovat uživatelům. Kroky požadují služby pomocí "příkazů protokolování" (speciálně formátovaných řetězců vytištěných do stdout). V omezeném režimu není k dispozici většina služeb agenta, jako je nahrávání artefaktů a připojení výsledků testů.

# 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

Jeden z příkazů, které jsou stále povolené v omezeném režimu, je příkaz setvariable . Vzhledem k tomu, že se proměnné kanálu exportují jako proměnné prostředí do následných úloh, můžou být úkoly, které vykládají data poskytnutá uživatelem (například obsah otevřených problémů načtených z rozhraní REST API), zranitelné vůči útokům injektáže. Takový uživatelský obsah může nastavit proměnné prostředí, které lze následně použít ke zneužití hostitele agenta. Pokud chcete tuto možnost zakázat, můžou autoři kanálu explicitně deklarovat, které proměnné jsou nastavené pomocí setvariable příkazu protokolování. Zadání prázdného seznamu zakáže nastavení všech proměnných.

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

Podmíněné vkládání fází nebo úloh

Omezte spouštění fází a úloh za určitých podmínek. Podmínky můžou například pomoct zajistit, že vytváříte jenom určité větve.

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

Vyžadovat určitou syntaxi s rozšiřujícími šablonami

Šablony můžou iterovat a měnit nebo zakázat jakoukoli syntaxi YAML. Iterace může vynutit použití konkrétní syntaxe YAML, včetně výše uvedených funkcí.

Šablona může přepsat kroky uživatele a povolit spuštění pouze některých schválených úloh. Můžete například zabránit spuštění vloženého skriptu.

Upozornění

V následujícím příkladu není možné provádět kroky typu "bash", "powershell", "pwsh" a "script". Pro úplné uzamčení ad hoc skriptů byste také museli 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 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 bezpečné pro typ

Šablony a jejich parametry se před spuštěním kanálu převádějí na konstanty. Parametry šablony poskytují zabezpečení typů vstupním parametrům. Může například omezit, které fondy se dají v kanálu použít, tím, že místo řetězce volného formátu nabídne výčet možných možností.

# 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

Nastavení požadovaných šablon

Pokud chcete vyžadovat použití konkrétní šablony, můžete nastavit požadovanou kontrolu šablony pro prostředek nebo prostředí. Požadovanou kontrolu šablony je možné použít při rozšiřování ze šablony.

Stav kontroly můžete zkontrolovat při zobrazení úlohy kanálu. Pokud se kanál nezasahuje ze šablony vyžadovat, kontrola selže a spuštění se zastaví. Uvidíte, že kontrola selhala.

Kontrola schválení se nezdařila

Při použití požadované šablony uvidíte, že kontrola prošla.

schválení schválení propustky

V této části se šablona params.yml vyžaduje se schválením prostředku. Pokud chcete aktivovat selhání kanálu, zakomentujte odkaz na 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'

Další kroky

Šablona může přidat kroky, aniž by je autor kanálu musel zahrnout. Pomocí těchto kroků můžete spustit kontrolu přihlašovacích údajů nebo kontroly statického kódu.

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

Vynucení šablony

Šablona je pouze bezpečnostní mechanismus, pokud ji můžete vynutit. Řídicí bod pro vynucení použití šablon je chráněný prostředek. U fondu agentů nebo jiných chráněných prostředků, jako jsou úložiště, můžete nakonfigurovat schválení a kontroly. Příklad najdete v tématu Přidání kontroly prostředků úložiště.

Další kroky

Dále se dozvíte, jak bezpečně přijímat vstupy prostřednictvím proměnných a parametrů.