Dela via


Använda mallar för säkerhet

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

Den här artikeln beskriver hur mallar kan effektivisera säkerheten för Azure Pipelines. Mallar kan definiera den yttre strukturen för din pipeline och hjälpa till att förhindra skadlig kodinfiltration. Mallar kan också automatiskt innehålla steg för att utföra uppgifter, till exempel genomsökning av autentiseringsuppgifter. Om flera pipelines i ditt team eller din organisation delar samma struktur bör du överväga att använda mallar.

Kontroller av skyddade resurser utgör det grundläggande säkerhetsramverket för Azure Pipelines. Dessa kontroller gäller oavsett pipelinestruktur, steg och jobb. Du kan använda mallar för att framtvinga dessa kontroller.

Innehåller och utökar mallar

Azure Pipelines innehåller och utökar mallar.

  • Innehåller mallar som innehåller mallens kod direkt i den yttre filen som refererar till #include den, ungefär som i C++. Följande exempelpipeline infogar mallen include-npm-steps.yml i steps avsnittet.

      steps:
      - template: templates/include-npm-steps.yml 
    
  • Utökar mallar definierar pipelinens yttre struktur och erbjuder specifika punkter för riktade anpassningar. I C++- extends kontexten liknar mallar arv.

När du använder extends mallar kan du också använda includes i både mallen och den slutliga pipelinen för att utföra vanliga konfigurationsdelar. En fullständig referens finns i mallanvändningsreferensen.

Utökar mallar

För de säkraste pipelines börjar du med att använda utökar mallar. Dessa mallar definierar pipelinens yttre struktur och förhindrar att skadlig kod infiltrerar pipelinen.

Följande mallfil heter till exempel template.yml.

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

Följande pipeline utökar mallen 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

Dricks

När du konfigurerar extends mallar bör du överväga att förankra dem i en viss Git-gren eller tagg, så om det sker icke-bakåtkompatibla ändringar påverkas inte befintliga pipelines. I föregående exempel används den här funktionen.

Säkerhetsfunktioner för YAML-pipeline

YAML-pipelinesyntaxen innehåller flera inbyggda skydd. Utökar mallen kan framtvinga deras användning. För att förbättra pipelinesäkerheten kan du implementera någon av följande begränsningar.

Stegmål

Du kan begränsa vissa steg så att de körs i en container i stället för på värden. Steg i containrar har inte åtkomst till agentens värd, vilket förhindrar att dessa steg ändrar agentkonfigurationen eller lämnar skadlig kod för senare körning.

Överväg till exempel att begränsa nätverksåtkomsten. Utan öppen nätverksåtkomst kan användarsteg inte hämta paket från obehöriga källor eller ladda upp kod och hemligheter till externa nätverksplatser.

Följande exempelpipeline kör steg på agentvärden innan du kör steg i en container.

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

Du kan begränsa de tjänster som Azure Pipelines-agenten tillhandahåller till användarsteg. Användarsteg begär tjänster med hjälp av loggningskommandon, som är särskilt formaterade strängar som skrivs ut till standardutdata. I begränsat läge är de flesta av agentens tjänster, till exempel att ladda upp artefakter och koppla testresultat, inte tillgängliga.

Följande exempelaktivitet misslyckas eftersom dess target egenskap instruerar agenten att inte tillåta publicering av artefakter.

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

I restricted läge förblir setvariable kommandot tillåtet, så försiktighet är nödvändigt eftersom pipelinevariabler exporteras som miljövariabler till efterföljande uppgifter. Om uppgifter matar ut användarspecifika data, till exempel öppna problem som hämtats via ett REST-API, kan de vara sårbara för inmatningsattacker. Skadligt användarinnehåll kan ange miljövariabler som kan utnyttjas för att kompromettera agentvärden.

För att minska den här risken kan pipelineförfattare uttryckligen deklarera vilka variabler som kan anges med hjälp setvariable av loggningskommandot. När du anger en tom lista tillåts inte alla variabelinställningar.

Följande exempelaktivitet misslyckas eftersom aktiviteten endast tillåts ange variabeln expectedVar eller en variabel med prefixet ok.

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

Villkorsstyrd fas eller jobbkörning

Du kan begränsa faser och jobb så att de endast körs under specifika förhållanden. I följande exempel säkerställer villkoret att begränsad kod endast skapas för huvudgrenen.

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

Syntaxändring

Azure Pipelines-mallar har flexibiliteten att iterera över och ändra YAML-syntax. Genom att använda iteration kan du framtvinga specifika YAML-säkerhetsfunktioner.

En mall kan också skriva om användarsteg, så att endast godkända uppgifter kan köras. Du kan till exempel förhindra körning av infogade skript.

Följande exempelmall förhindrar att stegtyperna bash, powershell, pwshoch script körs. För fullständig låsning av ad hoc-skript kan du även 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 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 }}'

I följande pipeline som utökar den här mallen tas skriptstegen bort och körs inte.

# 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

Innan en pipeline körs omvandlas mallar och deras parametrar till konstanter. Mallparametrar kan förbättra typsäkerheten för indataparametrar.

I följande exempelmall begränsar parametrarna de tillgängliga alternativen för pipelinepooler genom att ange en uppräkning av specifika alternativ i stället för att tillåta frihandssträngar.

# 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

När pipelinen utökar mallen måste den ange ett av de tillgängliga poolalternativen.

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

Mallsteg

En mall kan automatiskt inkludera steg i en pipeline. De här stegen kan utföra uppgifter som genomsökning av autentiseringsuppgifter eller statiska kodkontroller. Följande mall infogar steg före och efter användarstegen i varje jobb.

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

Tillämpning av mallar

Mallar är en värdefull säkerhetsmekanism, men deras effektivitet är beroende av tillämpning. De viktigaste kontrollpunkterna för att framtvinga mallanvändning är skyddade resurser. Du kan konfigurera godkännanden och kontroller för din agentpool eller andra skyddade resurser, till exempel lagringsplatser. Ett exempel finns i Lägg till en resurskontroll för lagringsplats.

Nödvändiga mallar

Om du vill framtvinga användningen av en specifik mall konfigurerar du den nödvändiga mallkontrollen för en resurs. Den här kontrollen gäller endast när pipelinen sträcker sig från en mall.

När du visar pipelinejobbet kan du övervaka kontrollens status. Om pipelinen inte sträcker sig från den mall som krävs misslyckas kontrollen. Körningen stoppar och meddelar dig om den misslyckade kontrollen.

Skärmbild som visar en misslyckad godkännandekontroll.

När du använder den mall som krävs godkänns kontrollen.

Skärmbild som visar en godkänd godkännandekontroll.

Följande params.yml mall måste refereras till i alla pipelines som utökar den.

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

Följande exempelpipeline utökar mallen params.yml och kräver den för godkännande. Om du vill visa ett pipelinefel kommenterar du ut referensen till 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'