Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022
Les modèles Azure Pipelines vous permettent de définir du contenu, une logique et des paramètres réutilisables dans des pipelines YAML. Cet article décrit comment les modèles peuvent aider à améliorer la sécurité des pipelines en procédant comme suit :
- Définition de la structure externe d’un pipeline pour empêcher l’infiltration de code malveillante.
- Ajout automatique des étapes pour effectuer des tâches telles que l’analyse des informations d’identification.
- Aider à appliquer des vérifications sur les ressources protégées, qui forment l’infrastructure de sécurité fondamentale pour Azure Pipelines et s’appliquent à toutes les structures et composants de pipeline.
Cet article fait partie d’une série qui vous aide à implémenter des mesures de sécurité pour Azure Pipelines. Pour plus d’informations, consultez Sécuriser Azure Pipelines.
Conditions préalables
| Catégorie | Exigences |
|---|---|
| Azure DevOps | - Implémentez des recommandations dans Rendre vos pipelines Azure DevOps sécurisés et sécurisés. - Connaissance de base de YAML et d’Azure Pipelines. Pour plus d’informations, consultez Créer votre premier pipeline. |
| Autorisations | - Pour modifier les autorisations des pipelines : membre du groupe Administrateurs de projet. - Pour modifier les autorisations de l'Organisation : Membre du groupe Project Collection Administrators. |
Inclut et étend les modèles
Azure Pipelines fournit des modèles inclus et étendus .
Un
includesmodèle inclut le code du modèle directement dans le fichier externe qui fait référence au modèle, comme#includedans C++. L’exemple de pipeline suivant insère le modèle include-npm-steps.yml dans lastepssection.steps: - template: templates/include-npm-steps.ymlUn
extendsmodèle définit la structure externe du pipeline et offre des points spécifiques pour les personnalisations ciblées. Dans le contexte de C++,extendsles modèles ressemblent à l’héritage.
Lorsque vous utilisez extends des modèles, vous pouvez également utiliser includes pour effectuer des éléments de configuration courants dans le modèle et le pipeline final. Pour plus d’informations, consultez Utiliser des modèles YAML dans des pipelines pour des processus réutilisables et sécurisés.
Étend les modèles
Pour les pipelines les plus sécurisés, commencez par utiliser extends modèles. Ces modèles définissent la structure externe du pipeline et aident à empêcher l’infiltration de code malveillante.
L’exemple suivant montre un fichier de modèle nommé template.yml.
parameters:
- name: usersteps
type: stepList
default: []
steps:
- ${{ each step in parameters.usersteps }}:
- ${{ step }}
L’exemple de pipeline suivant étend le modèle 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
Conseil
Lorsque vous configurez des modèles de extends, envisagez de les ancrer à une branche ou une balise Git particulière afin que les modifications disruptives n’affectent pas les pipelines existants. L’exemple précédent utilise cette fonctionnalité.
Fonctionnalités de sécurité du pipeline
La syntaxe du pipeline YAML comprend plusieurs protections intégrées.
Extends les modèles peuvent imposer leur utilisation pour renforcer la sécurité du pipeline. Vous pouvez implémenter l’une des restrictions suivantes.
Cibles d’étape
Vous pouvez restreindre les étapes spécifiées à exécuter dans un conteneur plutôt que sur l’hôte. Les étapes des conteneurs ne peuvent pas accéder à l’hôte de l’agent, de sorte qu’elles ne peuvent pas modifier la configuration de l’agent ou laisser du code malveillant pour une exécution ultérieure.
Par exemple, vous pouvez exécuter des étapes utilisateur dans un conteneur pour les empêcher d’accéder au réseau, afin qu’ils ne puissent pas récupérer des packages à partir de sources non autorisées ou charger du code et des secrets vers des emplacements externes.
L’exemple de pipeline suivant exécute une étape sur l’hôte de l’agent susceptible de modifier le réseau hôte, suivie d’une étape à l’intérieur d’un conteneur qui limite l’accès réseau.
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
Paramètres de type sécurisé
Avant l’exécution d’un pipeline, les modèles et leurs paramètres se transforment en constantes. Les paramètres de modèle peuvent améliorer la sécurité des types pour les paramètres d’entrée.
Dans l’exemple de modèle suivant, les paramètres limitent les options de pool de pipelines disponibles en énumérant des choix spécifiques au lieu d’autoriser n’importe quelle chaîne.
# 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
Pour étendre le modèle, le pipeline doit spécifier l’un des choix de pool disponibles.
# azure-pipelines.yml
extends:
template: template.yml
parameters:
userpool: private-pool-1
Restrictions de la commande de journalisation de l’agent
Les étapes utilisateur demandent des services à l’aide de commandes de journalisation, qui sont des chaînes spécialement mises en forme imprimées en sortie standard. Vous pouvez restreindre les services fournis par les commandes de journalisation pour les étapes utilisateur. En restricted mode, la plupart des services d’agent, tels que le chargement d’artefacts et l’attachement des résultats des tests, ne sont pas disponibles pour la journalisation des commandes.
Dans l’exemple suivant, la propriété target instruit l’agent de restreindre la publication des artefacts, de sorte que la tâche de publication d’artefact échoue.
- task: PublishBuildArtifacts@1
inputs:
artifactName: myartifacts
target:
commands: restricted
Variables dans les commandes de journalisation
La setvariable commande reste autorisée en restricted mode, de sorte que les tâches qui génèrent des données fournies par l’utilisateur, telles que les problèmes d’ouverture récupérés via une API REST, peuvent être vulnérables aux attaques par injection. Le contenu utilisateur malveillant peut définir des variables qui exportent vers des tâches ultérieures en tant que variables d’environnement et peuvent compromettre l’hôte de l’agent.
Pour atténuer ce risque, vous pouvez explicitement déclarer les variables modifiables à l’aide de la commande de "logging" setvariable. Si vous spécifiez une liste vide dans settableVariables, tous les paramètres de variable ne sont pas autorisés.
L’exemple suivant restreint settableVariables à expectedVar et à toute variable préfixée de ok. La tâche échoue, car elle tente de définir une variable différente appelée BadVar.
- task: PowerShell@2
target:
commands: restricted
settableVariables:
- expectedVar
- ok*
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[task.setvariable variable=BadVar]myValue"
Étape conditionnelle ou exécution du travail
Vous pouvez restreindre les étapes et les travaux à exécuter uniquement dans des conditions spécifiques. L’exemple suivant garantit que le code restreint est généré uniquement pour la main branche.
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
Modification de la syntaxe
Les modèles Azure Pipelines ont la possibilité d’itérer et de modifier la syntaxe YAML. En utilisant l’itération, vous pouvez appliquer des fonctionnalités de sécurité YAML spécifiques.
Un modèle peut également réécrire les étapes utilisateur, ce qui autorise uniquement les tâches approuvées à s’exécuter. Par exemple, le modèle peut empêcher l’exécution du script inline.
L’exemple de modèle suivant empêche l'exécution des types d’étapes de script bash, powershell, pwsh, et script. Pour un verrouillage complet des scripts, vous pouvez également bloquer BatchScript et 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 }}'
Dans l’exemple de pipeline suivant qui étend le modèle précédent, les étapes de script sont supprimées et ne sont pas exécutées.
# 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
Étapes du modèle
Un modèle peut inclure automatiquement des étapes dans un pipeline, par exemple pour effectuer une analyse des informations d’identification ou des vérifications de code statiques. Le modèle suivant insère des étapes avant et après les étapes de l’utilisateur dans chaque travail.
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()
Application des modèles
L’efficacité des modèles en tant que mécanisme de sécurité repose sur l’application. Les points de contrôle clés pour appliquer l’utilisation du modèle sont des ressources protégées.
Vous pouvez configurer des approbations et des vérifications pour votre pool d’agents ou d’autres ressources protégées telles que des dépôts. Pour obtenir un exemple, consultez Ajouter une vérification de ressource de référentiel.
Modèles obligatoires
Pour appliquer l’utilisation d’un modèle spécifique, configurez la vérification de modèle requise sur la connexion de service pour une ressource. Cette vérification s’applique uniquement lorsque le pipeline s’étend à partir d’un modèle.
Lorsque vous affichez la tâche de pipeline, vous pouvez surveiller l’état de la vérification. Si le pipeline ne s’étend pas à partir du modèle requis, la vérification échoue.
Lorsque vous utilisez le modèle requis, la vérification passe.
Par exemple, le modèle de params.yml suivant doit être référencé dans n’importe quel pipeline qui l’étend.
# 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 }}
L’exemple de pipeline suivant étend le modèle params.yml et nécessite son approbation. Pour illustrer un échec de pipeline, mettez en commentaire la référence au fichier extends.
# azure-pipeline.yml
resources:
containers:
- container: my-container
endpoint: my-service-connection
image: mycontainerimages
extends:
template: params.yml
parameters:
yesNo: true
image: 'windows-latest'