Partilhar via


Modelos para segurança

Serviços de DevOps do Azure | Azure DevOps Server 2022 | Azure DevOps Server 2020

Os modelos do Azure Pipelines permitem definir conteúdo, lógica e parâmetros reutilizáveis em pipelines YAML. Este artigo descreve como os modelos podem ajudar a melhorar a segurança do pipeline:

  • Definir a estrutura externa de um pipeline para ajudar a prevenir a infiltração de código malicioso.
  • Incluindo automaticamente etapas para executar tarefas como verificação de credenciais.
  • Ajudar a impor verificações em recursos protegidos, que formam a estrutura de segurança fundamental para o Azure Pipelines e se aplicam a todas as estruturas e componentes de pipeline.

Este artigo faz parte de uma série que ajuda você a implementar medidas de segurança para o Azure Pipelines. Para obter mais informações, consulte Secure Azure Pipelines.

Pré-requisitos

Categoria Requerimentos
Azure DevOps - Implemente recomendações em Tornar seu Azure DevOps seguro e Secure Azure Pipelines.
- Conhecimentos básicos de YAML e Azure Pipelines. Para obter mais informações, consulte Criar seu primeiro pipeline.
Permissões - Para modificar as permissões das pipelines: Membro do grupo Administradores de Projeto.
- Para modificar as permissões da organização: Membro do grupo Administradores da Coleção de Projetos.

Inclui e estende modelos

O Azure Pipelines fornece modelos de includes e extends.

  • Um includes template inclui o código do template diretamente no ficheiro externo que faz referência ao template, semelhante ao #include em C++. O pipeline de exemplo a seguir insere o modelo include-npm-steps.yml na steps seção .

      steps:
      - template: templates/include-npm-steps.yml 
    
  • Um extends modelo define a estrutura externa do pipeline e oferece pontos específicos para personalizações direcionadas. No contexto do C++, extends os modelos se assemelham à herança.

Ao utilizar extends templates, também pode utilizar includes para realizar configurações comuns tanto no template quanto no pipeline final. Para obter mais informações, consulte Usar modelos YAML em pipelines para processos reutilizáveis e seguros.

Estende modelos

Para os pipelines mais seguros, comece usando extends templates. Esses modelos definem a estrutura externa do pipeline e ajudam a prevenir a infiltração de códigos maliciosos.

O exemplo a seguir mostra um arquivo de modelo chamado template.yml.

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

O exemplo de pipeline a seguir estende o modelo 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

Gorjeta

Ao configurar extends modelos, considere ancorá-los a uma ramificação ou tag específica do Git para que quaisquer alterações significativas não afetem os pipelines existentes. O exemplo anterior usa esse recurso.

Recursos de segurança do pipeline

A sintaxe do pipeline YAML inclui várias proteções integradas. Extends Os modelos podem impor o seu uso para melhorar a segurança do pipeline. Você pode implementar qualquer uma das restrições a seguir.

Metas graduais

Você pode restringir as etapas especificadas para execução em um contêiner em vez de no host. As etapas em contêineres não podem acessar o host do agente, portanto, não podem modificar a configuração do agente ou deixar código mal-intencionado para execução posterior.

Por exemplo, você pode executar as etapas do usuário em um contêiner para impedi-lo de acessar a rede, para que ele não possa recuperar pacotes de fontes não autorizadas ou carregar código e segredos para locais externos.

O pipeline de exemplo a seguir executa uma etapa no host do agente que pode potencialmente alterar a rede do host, seguida por uma etapa dentro de um contêiner que limita o acesso à rede.

resources:
  containers:
  - container: builder
    image: mysecurebuildcontainer:latest
steps:
- script: echo This step runs on the agent host
- script: echo This step runs inside the builder container
  target: builder

Parâmetros seguros para tipos

Antes de um pipeline ser executado, os templates e os seus parâmetros transformam-se em constantes. Parâmetros de template podem aumentar a segurança de tipo para parâmetros de entrada.

No modelo de exemplo a seguir, os parâmetros restringem as opções de pool de pipeline disponíveis enumerando opções específicas em vez de permitir qualquer cadeia de caracteres.

# template.yml
parameters:
- name: userpool
  type: string
  default: Azure Pipelines
  values:
  - Azure Pipelines
  - private-pool-1
  - private-pool-2

pool: ${{ parameters.userpool }}
steps:
- script: echo Hello world

Para estender o modelo, o pipeline deve especificar uma das opções de pool disponíveis.

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

Restrições de comando de log do agente

As etapas do usuário solicitam serviços usando comandos de log, que são cadeias de caracteres especialmente formatadas impressas na saída padrão. Você pode restringir os serviços que os comandos de log fornecem para as etapas do usuário. No modo restricted, a maioria dos serviços do agente, como carregar artefatos e anexar resultados de teste, não estão disponíveis para o registo de comandos.

No exemplo a seguir, a target propriedade instrui o agente a restringir a publicação de artefatos, fazendo com que a tarefa de publicação de artefatos falhe.

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

Variáveis em comandos de log

O setvariable comando permanece permitido no restricted modo, portanto, tarefas que produzem dados fornecidos pelo usuário, como problemas abertos recuperados por meio de uma API REST, podem ser vulneráveis a ataques de injeção. O conteúdo de usuário mal-intencionado pode definir variáveis que exportam para tarefas subsequentes como variáveis de ambiente e pode comprometer o host do agente.

Para reduzir esse risco, você pode declarar explicitamente as variáveis que são configuráveis usando o setvariable comando log. Se você especificar uma lista vazia no settableVariables, todas as configurações de variáveis não serão permitidas.

O exemplo a seguir restringe settableVariables a expectedVar e qualquer variável prefixada com ok. A tarefa falha porque tenta definir uma variável diferente chamada BadVar.

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

Estágio condicional ou execução do trabalho

Você pode restringir estágios e trabalhos para serem executados somente sob condições específicas. O exemplo a seguir garante que o código restrito seja compilado somente para a main ramificação.

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ção da sintaxe

Os modelos do Azure Pipelines têm a flexibilidade de iterar e modificar a sintaxe YAML. Usando a iteração, você pode impor recursos de segurança YAML específicos.

Um modelo também pode reescrever as etapas do usuário, permitindo que apenas tarefas aprovadas sejam executadas. Por exemplo, o modelo pode impedir a execução de script embutido.

O modelo de exemplo a seguir impede que os tipos de etapa de script bash, powershell, pwsh e script sejam executados. Para o bloqueio completo de scripts, você também pode 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 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 }}'

No pipeline de exemplo a seguir que estende o modelo anterior, as etapas de script são removidas e não executadas.

# azure-pipelines.yml
extends:
  template: template.yml
  parameters:
    usersteps:
    - task: MyTask@1
    - script: echo This step is stripped out and not run
    - bash: echo This step is stripped out and not run
    - powershell: echo "This step is stripped out and not run"
    - pwsh: echo "This step is stripped out and not run"
    - script: echo This step is stripped out and not run
    - task: CmdLine@2
      displayName: Test - stripped out
      inputs:
        script: echo This step is stripped out and not run
    - task: MyOtherTask@2

Etapas do modelo

Um modelo pode incluir automaticamente etapas em um pipeline, por exemplo, para fazer verificação de credenciais ou verificações de código estático. O modelo a seguir insere etapas antes e depois das etapas do usuário em cada trabalho.

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

Aplicação do modelo

A eficácia dos modelos como mecanismo de segurança depende da aplicação. Os principais pontos de controle para impor o uso do modelo são recursos protegidos.

Você pode configurar aprovações e verificações para seu pool de agentes ou outros recursos protegidos, como repositórios. Para obter um exemplo, consulte Adicionar uma verificação de recursos do repositório.

Modelos necessários

Para impor o uso de um modelo específico, configure a verificação de modelo obrigatório na conexão de serviço para um recurso. Essa verificação se aplica somente quando o pipeline se estende a partir de um modelo.

Ao visualizar o trabalho de pipeline, você pode monitorar o status da verificação. Se o pipeline não se estender a partir do modelo necessário, a verificação falhará.

Captura de ecrã a mostrar uma verificação de aprovação falhada.

Quando você usa o modelo necessário, a verificação é aprovada.

Captura de tela mostrando uma verificação de aprovação aprovada.

Por exemplo, o modelo de ficheiro params.yml que se segue deve ser referenciado em qualquer pipeline que o estenda.

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

O pipeline de exemplo a seguir expande o modelo params.yml e exige a sua utilização para obter aprovação. Para demonstrar uma falha de pipeline, comente a extends referência 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'