Säkerhet via mallar

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

Kontroller av skyddade resurser är det grundläggande byggblocket för säkerhet för Azure Pipelines. Kontrollerar arbetet oavsett strukturen – faserna och jobben – för din pipeline. Om flera pipelines i ditt team eller din organisation har samma struktur kan du ytterligare förenkla säkerheten med hjälp av mallar.

Azure Pipelines erbjuder två typer av mallar: inkluderar och utökar. Inkluderade mallar fungerar som #include i C++: det är som om du klistrar in mallens kod direkt i den yttre filen, som refererar till den. Här infogas till exempel en mall (include-npm-steps.yml) i steps.

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

För att fortsätta C++-metaforen extends är mallar mer som arv: mallen ger pipelinens yttre struktur och en uppsättning platser där mallkonsumenten kan göra riktade ändringar.

Använda utökar mallar

För de säkraste pipelines rekommenderar vi att du börjar med extends mallar. Genom att tillhandahålla den yttre strukturen kan en mall förhindra att skadlig kod kommer in i din pipeline. Du kan fortfarande använda includes, både i mallen och i den slutliga pipelinen, för att ta hänsyn till vanliga konfigurationsdelar. Om du vill använda en utökad mall kan din pipeline se ut som i exemplet nedan.

# 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

När du konfigurerar extends mallar bör du överväga att fästa dem på en viss Git-gren eller -tagg. På så sätt påverkas inte befintliga pipelines om icke-bakåtkompatibla ändringar behöver göras. Exemplen ovan använder den här funktionen.

Säkerhetsfunktioner som tillämpas via YAML

Det finns flera inbyggda skydd i YAML-syntaxen, och en utökad mall kan framtvinga användningen av något av dem eller alla.

Stegmål

Begränsa vissa steg för att köra i en container i stället för värden. Utan åtkomst till agentens värd kan användarstegen inte ändra agentkonfigurationen eller lämna skadlig kod för senare körning. Kör koden på värden först för att göra containern säkrare. Vi rekommenderar till exempel att du begränsar åtkomsten till nätverket. Utan öppen åtkomst till nätverket kommer användarsteg inte att kunna komma åt paket från obehöriga källor eller ladda upp kod och hemligheter till en nätverksplats.

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

Kommandobegränsningar för agentloggning

Begränsa vilka tjänster som Azure Pipelines-agenten ska tillhandahålla till användarsteg. Steg begär tjänster med hjälp av "loggningskommandon" (särskilt formaterade strängar som skrivs ut till stdout). I begränsat läge är de flesta av agentens tjänster som att ladda upp artefakter och koppla testresultat inte tillgängliga.

# 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

Ett av kommandona som fortfarande tillåts i begränsat läge är setvariable kommandot . Eftersom pipelinevariabler exporteras som miljövariabler till efterföljande uppgifter kan uppgifter som matar ut användarspecifika data (till exempel innehållet i öppna problem som hämtats från ett REST-API) vara sårbara för inmatningsattacker. Sådant användarinnehåll kan ange miljövariabler som i sin tur kan användas för att utnyttja agentvärden. För att inte tillåta detta kan pipelineförfattare uttryckligen deklarera vilka variabler som kan anges via loggningskommandot setvariable . Om du anger en tom lista tillåts inte inställningen för alla variabler.

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

Villkorsstyrd infogning av faser eller jobb

Begränsa faser och jobb som ska köras under specifika förhållanden. Villkor kan till exempel hjälpa dig att se till att du bara skapar vissa grenar.

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

Kräv viss syntax med utökar mallar

Mallar kan iterera över och ändra/inte tillåta YAML-syntax. Iteration kan tvinga användningen av viss YAML-syntax, inklusive ovanstående funktioner.

En mall kan skriva om användarsteg och endast tillåta att vissa godkända uppgifter körs. Du kan till exempel förhindra körning av infogade skript.

Varning

I exemplet nedan hindras stegtypen "bash", "powershell", "pwsh" och "script" från att köras. För fullständig låsning av ad hoc-skript måste du också blockera "BatchScript" och "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

Typsäkra parametrar

Mallar och deras parametrar omvandlas till konstanter innan pipelinen körs. Mallparametrar ger typsäkerhet för indataparametrar. Den kan till exempel begränsa vilka pooler som kan användas i en pipeline genom att erbjuda en uppräkning av möjliga alternativ i stället för en frihandssträng.

# 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

Ange nödvändiga mallar

Om du vill kräva att en specifik mall används kan du ange den nödvändiga mallkontrollen för en resurs eller miljö. Den nödvändiga mallkontrollen kan användas när du utökar från en mall.

Du kan kontrollera statusen för en kontroll när du visar ett pipelinejobb. När en pipeline inte sträcker sig från require-mallen misslyckas kontrollen och körningen stoppas. Du ser att kontrollen misslyckades.

godkännandekontrollen misslyckas

När den mall som krävs används ser du att kontrollen har godkänts.

godkännandekontroll godkänns

Här krävs mallen params.yml med ett godkännande för resursen. Om du vill utlösa att pipelinen misslyckas kommenterar du ut referensen till 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'

Ytterligare steg

En mall kan lägga till steg utan att pipelineförfattaren behöver inkludera dem. De här stegen kan användas för att köra genomsökning av autentiseringsuppgifter eller statiska kodkontroller.

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

Tillämpning av mallar

En mall är bara en säkerhetsmekanism om du kan framtvinga den. Kontrollpunkten för att framtvinga användning av mallar är en skyddad resurs. Du kan konfigurera godkännanden och kontroller på din agentpool eller andra skyddade resurser som lagringsplatser. Ett exempel finns i Lägga till en resurskontroll för lagringsplats.

Nästa steg

Lär dig sedan om att ta indata på ett säkert sätt via variabler och parametrar.