Usare i modelli per la sicurezza
Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020
Questo articolo descrive come i modelli possono semplificare la sicurezza per Azure Pipelines. I modelli possono definire la struttura esterna della pipeline e prevenire l'infiltrazione di codice dannoso. I modelli possono anche includere automaticamente i passaggi per eseguire attività come l'analisi delle credenziali. Se più pipeline all'interno del team o dell'organizzazione condividono la stessa struttura, è consigliabile usare i modelli.
I controlli sulle risorse protette costituiscono il framework di sicurezza fondamentale per Azure Pipelines. Questi controlli si applicano indipendentemente dalla struttura della pipeline, dalle fasi e dai processi. È possibile usare i modelli per applicare questi controlli.
Include ed estende i modelli
Azure Pipelines include ed estende i modelli.
I modelli includono il codice del modello direttamente nel file esterno che vi fa riferimento, simile a
#include
in C++. La pipeline di esempio seguente inserisce il modello di include-npm-steps.yml nellasteps
sezione .steps: - template: templates/include-npm-steps.yml
Estende i modelli definiscono la struttura esterna della pipeline e offrono punti specifici per le personalizzazioni mirate. Nel contesto di C++,
extends
i modelli sono simili all'ereditarietà.
Quando si usano extends
modelli, è anche possibile usare includes
sia nel modello che nella pipeline finale per eseguire parti di configurazione comuni. Per informazioni di riferimento complete, vedere informazioni di riferimento sull'utilizzo del modello.
Estende i modelli
Per le pipeline più sicure, iniziare con l'uso di modelli di estensione. Questi modelli definiscono la struttura esterna della pipeline e impediscono l'infiltrazione della pipeline da parte di codice dannoso.
Ad esempio, il file modello seguente è denominato template.yml.
parameters:
- name: usersteps
type: stepList
default: []
steps:
- ${{ each step in parameters.usersteps }}:
- ${{ step }}
La pipeline seguente estende il modello di 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
Suggerimento
Quando si configurano extends
i modelli, è consigliabile ancorarli a un determinato ramo Git o a un tag, quindi se sono presenti modifiche di rilievo, le pipeline esistenti non sono interessate. Nell'esempio precedente viene usata questa funzionalità.
Funzionalità di sicurezza della pipeline YAML
La sintassi della pipeline YAML include diverse protezioni predefinite. Estende il modello può imporre l'uso. Per migliorare la sicurezza della pipeline, è possibile implementare una delle restrizioni seguenti.
Destinazioni passaggio
È possibile limitare determinati passaggi per l'esecuzione in un contenitore anziché nell'host. I passaggi nei contenitori non hanno accesso all'host dell'agente, impedendo a questi passaggi di modificare la configurazione dell'agente o di lasciare codice dannoso per un'esecuzione successiva.
Si consideri ad esempio la limitazione dell'accesso alla rete. Senza accesso alla rete aperta, i passaggi utente non possono recuperare pacchetti da origini non autorizzate o caricare codice e segreti in percorsi di rete esterni.
La pipeline di esempio seguente esegue i passaggi nell'host dell'agente prima di eseguire i passaggi all'interno di un contenitore.
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
Restrizioni dei comandi di registrazione agente
È possibile limitare i servizi forniti dall'agente di Azure Pipelines ai passaggi utente. I passaggi utente richiedono servizi usando i comandi di registrazione, che sono stringhe appositamente formattate stampate nell'output standard. In modalità con restrizioni, la maggior parte dei servizi dell'agente, ad esempio il caricamento di artefatti e l'associazione dei risultati dei test, non sono disponibili.
L'attività di esempio seguente ha esito negativo perché la relativa target
proprietà indica all'agente di non consentire gli artefatti di pubblicazione.
- task: PublishBuildArtifacts@1
inputs:
artifactName: myartifacts
target:
commands: restricted
In restricted
modalità, il setvariable
comando rimane consentito, quindi è necessario prestare attenzione perché le variabili della pipeline vengono esportate come variabili di ambiente nelle attività successive. Se le attività generano dati forniti dall'utente, ad esempio problemi aperti recuperati tramite un'API REST, potrebbero essere vulnerabili agli attacchi injection. Il contenuto utente malintenzionato potrebbe impostare variabili di ambiente che potrebbero essere sfruttate per compromettere l'host dell'agente.
Per attenuare questo rischio, gli autori di pipeline possono dichiarare in modo esplicito quali variabili sono impostabili usando il setvariable
comando di registrazione. Quando si specifica un elenco vuoto, tutte le impostazioni delle variabili non sono consentite.
L'attività di esempio seguente ha esito negativo perché l'attività è consentita solo per impostare la expectedVar
variabile o una variabile preceduta da ok
.
- task: PowerShell@2
target:
commands: restricted
settableVariables:
- expectedVar
- ok*
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[task.setvariable variable=BadVar]myValue"
Fase condizionale o esecuzione del processo
È possibile limitare le fasi e i processi per l'esecuzione solo in condizioni specifiche. Nell'esempio seguente, la condizione garantisce che il codice con restrizioni venga compilato solo per il ramo principale.
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
Modifica della sintassi
I modelli di Azure Pipelines hanno la flessibilità necessaria per scorrere e modificare la sintassi YAML. Usando l'iterazione, è possibile applicare funzionalità di sicurezza YAML specifiche.
Un modello può anche riscrivere i passaggi utente, consentendo l'esecuzione solo delle attività approvate. Ad esempio, è possibile impedire l'esecuzione di script inline.
Il modello di esempio seguente impedisce l'esecuzione dei tipi di bash
passaggio , powershell
, pwsh
e script
. Per il blocco completo degli script ad hoc, è anche possibile bloccare BatchScript
e 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 }}'
Nella pipeline seguente che estende questo modello, i passaggi dello script vengono rimossi e non vengono eseguiti.
# 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
Parametri indipendenti dai tipi
Prima dell'esecuzione di una pipeline, i modelli e i relativi parametri vengono trasformati in costanti. I parametri del modello possono migliorare la sicurezza dei tipi per i parametri di input.
Nel modello di esempio seguente i parametri limitano le opzioni del pool di pipeline disponibili fornendo un'enumerazione di scelte specifiche anziché consentire stringhe a mano libera.
# 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
Quando la pipeline estende il modello, deve specificare una delle opzioni del pool disponibili.
# azure-pipelines.yml
extends:
template: template.yml
parameters:
userpool: private-pool-1
Passaggi del modello
Un modello può includere automaticamente i passaggi in una pipeline. Questi passaggi possono eseguire attività come l'analisi delle credenziali o i controlli del codice statico. Il modello seguente inserisce i passaggi prima e dopo i passaggi dell'utente in ogni processo.
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()
Applicazione del modello
I modelli sono un meccanismo di sicurezza prezioso, ma la loro efficacia si basa sull'imposizione. I punti di controllo chiave per l'applicazione dell'utilizzo del modello sono risorse protette. È possibile configurare le approvazioni e verificare la presenza del pool di agenti o di altre risorse protette, ad esempio i repository. Per un esempio, vedere Aggiungere un controllo delle risorse del repository.
Modelli obbligatori
Per applicare l'uso di un modello specifico, configurare il controllo del modello richiesto per una risorsa. Questo controllo si applica solo quando la pipeline si estende da un modello.
Quando si visualizza il processo della pipeline, è possibile monitorare lo stato del controllo. Se la pipeline non si estende dal modello richiesto, il controllo ha esito negativo. L'esecuzione si arresta e invia una notifica del controllo non riuscito.
Quando si usa il modello richiesto, il controllo viene superato.
È necessario fare riferimento al modello di params.yml seguente in qualsiasi pipeline che la estende.
# 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 }}
La pipeline di esempio seguente estende il modello di params.yml e ne richiede l'approvazione. Per illustrare un errore della pipeline, impostare come commento il riferimento a 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'