Segurança por meio de modelos
Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020
As verificações sobre recursos protegidos são a peça básica da criação de segurança para o Azure Pipelines. As verificações funcionam independentemente da estrutura (estágios e trabalhos) do pipeline. Se vários pipelines em sua equipe ou organização tiverem a mesma estrutura, você poderá simplificar ainda mais a segurança usando modelos.
O Azure Pipelines oferece dois tipos de modelos: inclui e estende.
Os modelos incluídos se comportam como #include
no C++: é como se você colasse o código do modelo diretamente no arquivo externo, que faz referência a ele. Por exemplo, aqui um modelo de inclusão (include-npm-steps.yml
) é inserido em steps
.
steps:
- template: templates/include-npm-steps.yml
Para continuar a metáfora do C++, os modelos extends
são mais como herança: o modelo fornece a estrutura externa do pipeline e um conjunto de locais onde o consumidor do modelo pode fazer alterações direcionadas.
Usar modelos de extensão
Para os pipelines mais seguros, recomendamos começar com modelos extends
.
Ao fornecer a estrutura externa, um modelo pode impedir que código mal-intencionado entre em seu pipeline.
Você ainda pode usar includes
, tanto no modelo quanto no pipeline final, para fatorar partes comuns da configuração.
Para usar um modelo de extensão, seu pipeline pode ser semelhante ao exemplo abaixo.
# 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
Ao configurar modelos extends
, considere ancorá-los em um branch ou marca git específico.
Dessa forma, se forem necessárias alterações significativas, os pipelines existentes não serão afetados.
Os exemplos acima usam esse recurso.
Recursos de segurança impostos por meio do YAML
Existem várias proteções incorporadas à sintaxe do YAML, e um modelo de ampliações pode implementar o uso de algumas ou todas elas.
Destinos de etapa
Restrinja algumas etapas para execução em um contêiner em vez do host. Sem acesso ao host do agente, as etapas do usuário não podem modificar a configuração do agente ou deixar código mal-intencionado para execução posterior. Execute o código no host primeiro para tornar o contêiner mais seguro. Por exemplo, recomendamos limitar o acesso à rede. Sem acesso aberto à rede, as etapas do usuário não poderão acessar pacotes de fontes não autorizadas ou carregar código e segredos em um local de rede.
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
Restrições de comando de registro em log do agente
Restrinja quais serviços o agente do Azure Pipelines fornecerá às etapas do usuário. Etapas solicitam serviços usando "comandos de log" (cadeias de caracteres especialmente formatadas impressas em stdout). No modo restrito, a maioria dos serviços do agente, como carregar artefatos e anexar resultados de teste, não está disponível.
# 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
Um dos comandos ainda permitidos no modo restrito é o comando setvariable
. Como as variáveis de pipeline são exportadas como variáveis de ambiente para tarefas subsequentes, as tarefas que geram dados fornecidos pelo usuário (por exemplo, o conteúdo de problemas em aberto recuperados de uma API REST) podem ser vulneráveis a ataques de injeção. Esse conteúdo do usuário pode definir variáveis de ambiente que, por sua vez, podem ser usadas para explorar o host do agente. Para não permitir isso, os autores de pipeline podem declarar explicitamente quais variáveis são configuráveis por meio do comando de registro em log setvariable
. Especificar uma lista vazia não permite definir todas as variáveis.
# 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"
Inserção condicional de estágios ou trabalhos
Restrinja estágios e trabalhos a serem executados em condições específicas. As condições podem ajudar, por exemplo, a garantir que você esteja criando apenas determinadas ramificações.
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
Exigir certa sintaxe com modelos estendidos
Os modelos podem iterar e alterar/não permitir qualquer sintaxe YAML. A iteração pode forçar o uso de sintaxe YAML específica, incluindo os recursos acima.
Um modelo pode reescrever as etapas do usuário e permitir apenas a execução de determinadas tarefas aprovadas. Você pode, por exemplo, impedir a execução de script embutido.
Aviso
No exemplo a seguir, as etapas digitam "bash", "powershell", "pwsh" e "script" são impedidas de serem executadas. Para o bloqueio total de scripts ad hoc, você também precisaria bloquear "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 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
Parâmetros de segurança de tipo
Os modelos e seus parâmetros são transformados em constantes antes da execução do pipeline. Os parâmetros de modelo fornecem segurança de tipo aos parâmetros de entrada. Por exemplo, ele pode restringir quais pools podem ser usados em um pipeline oferecendo uma enumeração de opções possíveis em vez de uma cadeia de caracteres de forma livre.
# 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
Definir modelos necessários
Para exigir que um modelo específico seja usado, você pode definir a verificação de modelo necessária para um recurso ou ambiente. A verificação de modelo necessária pode ser usada ao estender de um modelo.
Você pode verificar o status de uma verificação ao exibir um trabalho de pipeline. Quando um pipeline não se estende do modelo necessário, a verificação falhará e a execução será interrompida. Você verá que a verificação falhou.
Quando o modelo necessário for usado, você verá que a verificação foi aprovada.
Aqui, o modelo params.yml
é necessário com uma aprovação no recurso. Para disparar o pipeline para falhar, comente a referência a 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'
Etapas adicionais
Um modelo pode adicionar etapas sem que o autor do pipeline precise incluí-las. Essas etapas podem ser usadas para executar verificações de credenciais ou de código estático.
# 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()
Imposição de modelo
Um modelo será apenas um mecanismo de segurança se você puder aplicá-lo. O ponto de controle para impor o uso de modelos é um recurso protegido. Você pode configurar aprovações e verificações no pool de agentes ou em outros recursos protegidos, como repositórios. Para obter um exemplo, confira Adicionar uma verificação de recursos do repositório.
Próximas etapas
Em seguida, saiba mais sobre como fazer entradas com segurança por meio de variáveis e parâmetros.
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de