Обеспечение безопасности с помощью шаблонов

Azure DevOps Services | Azure DevOps Server 2022 г. | Azure DevOps Server 2020 г.

Проверки защищенных ресурсов — это базовый стандартный блок безопасности для Azure Pipelines. Проверки работают независимо от структуры конвейера (этапов и заданий). Если несколько конвейеров в вашей команде или организации имеют одинаковую структуру, вы можете дополнительно упростить безопасность с помощью шаблонов.

Azure Pipelines предлагает два типа шаблонов: включает и расширяет. Включенные шаблоны ведут себя так же, как #include в C++: код шаблона вставляется прямо во внешний файл, который ссылается на него. Например, здесь вставляется шаблон включения (include-npm-steps.yml) в steps.

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

Чтобы продолжить метафору C++, шаблоны больше похожи на наследование: шаблон предоставляет внешнюю структуру конвейера и набор мест, extends где потребитель шаблона может вносить целевые изменения.

Использование расширений шаблонов

Для наиболее безопасных конвейеров рекомендуется начать с extends шаблонов. Предоставляя внешнюю структуру, шаблон может предотвратить попадание вредоносного кода в конвейер. Вы по-прежнему можете использовать includesкак в шаблоне, так и в конечном конвейере, чтобы учитывать общие элементы конфигурации. Чтобы использовать шаблон расширения, конвейер может выглядеть так, как показано в приведенном ниже примере.

# 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

При настройке extends шаблонов рекомендуется привязать их к определенной ветви или тегу Git. Таким образом, если потребуется вносить критические изменения, существующие конвейеры не будут затронуты. В приведенных выше примерах используется эта функция.

Функции безопасности, применяемые с помощью YAML

В синтаксис YAML встроено несколько средств защиты, и в шаблоне расширения могут принудительно применяться любые из них.

Целевые объекты шагов

Ограничьте выполнение некоторых шагов в контейнере, а не на узле. Без доступа к узлу агента пользователь не сможет изменить конфигурацию агента или оставить вредоносный код для последующего выполнения. Сначала выполните код на узле, чтобы сделать контейнер более безопасным. Например, рекомендуется ограничить доступ к сети. Без открытого доступа к сети действия пользователя не смогут получить доступ к пакетам из несанкционированных источников или отправить код и секреты в сетевое расположение.

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

Ограничения команд ведения журнала агента

Ограничьте службы, предоставляемые агентом Azure Pipelines, для действий пользователя. Шаги запрашивают службы с помощью команд ведения журнала (специально отформатированные строки, напечатанные в stdout). В режиме ограниченного доступа большинство служб агента, таких как отправка артефактов и присоединение результатов теста, недоступны.

# 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

Одной из команд, по-прежнему разрешенных в ограниченном режиме setvariable , является команда . Поскольку переменные конвейера экспортируются в качестве переменных среды для последующих задач, задачи, которые выводят данные, предоставленные пользователем (например, содержимое открытых проблем, полученных из REST API), могут быть уязвимы для атак путем внедрения. Такое пользовательское содержимое может задавать переменные среды, которые, в свою очередь, можно использовать для использования узла агента. Чтобы запретить это, авторы конвейера могут явно объявить переменные, которые можно задать, с помощью setvariable команды ведения журнала. Указание пустого списка запрещает настройку всех переменных.

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

Условная вставка этапов или заданий

Ограничьте этапы и задания для выполнения в определенных условиях. Условия могут помочь, например, убедиться, что вы создаете только определенные ветви.

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

Требовать определенный синтаксис с расширениями шаблонов

Шаблоны могут выполнять итерацию, а также изменять или запрещать любой синтаксис YAML. Итерация может принудительно использовать определенный синтаксис YAML, включая указанные выше функции.

Шаблон может переписать действия пользователя и разрешить выполнение только определенных утвержденных задач. Например, можно запретить выполнение встроенных скриптов.

Предупреждение

В приведенном ниже примере запрещено выполнение шагов типа "bash", "powershell", "pwsh" и "script". Для полной блокировки нерегламентированных скриптов необходимо также заблокировать "BatchScript" и "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

Типобезопасные параметры

Шаблоны и их параметры превратятся в константы перед запуском конвейера. Параметры шаблона обеспечивают безопасность типов входных параметров. Например, он может ограничить, какие пулы можно использовать в конвейере, предлагая перечисление возможных параметров, а не строку свободной формы.

# 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

Настройка обязательных шаблонов

Чтобы требовать использования определенного шаблона, можно задать необходимые проверка шаблона для ресурса или среды. Требуемый шаблон проверка можно использовать при расширении из шаблона.

При просмотре задания конвейера можно проверка состояние проверка. Если конвейер не расширяется из шаблона require, проверка завершится сбоем и выполнение остановится. Вы увидите, что проверка завершилась сбоем.

сбой проверка утверждения

При использовании необходимого шаблона вы увидите, что проверка пройдена.

утверждения проверка проходит

Здесь требуется шаблон params.yml с утверждением ресурса. Чтобы запустить сбой конвейера, закомментируйте ссылку на 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'

Дополнительные действия

Шаблон может добавлять шаги, не добавляя их автору конвейера. Эти действия можно использовать для выполнения проверки учетных данных или статических проверок кода.

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

Принудительное применение шаблона

Шаблон является механизмом безопасности только в том случае, если его можно применить. Контрольная точка для принудительного использования шаблонов является защищенным ресурсом. Вы можете настроить утверждения и проверки для пула агентов или других защищенных ресурсов, таких как репозитории. Пример см. в разделе Добавление ресурса репозитория проверка.

Дальнейшие действия

Далее вы узнаете о безопасном приеме входных данных с помощью переменных и параметров.