Skip to main content

Les fondamentaux de la sécurité d’Azure Bicep

Écrit par
Headshot of Mark Johnson

Mark Johnson

feature bicep security

13 décembre 2022

0 minutes de lecture

Cet article a été rédigé par l’ambassadeur Snyk Mark Johnson (@tazmainiandevil). Découvrez Snyk de l’intérieur en devenant ambassadeur Snyk.

Azure Bicep gagne chaque jour en popularité et devient rapidement le remplaçant des modèles Azure Resource Manager (ARM). Dans cet article, je vais passer en revue quelques fondamentaux de sécurité liés à l’utilisation de Bicep. Si vous ne connaissez pas Bicep, je vous recommande de consulter la documentation Microsoft Learn pour en savoir plus.

Ne stockez pas de secrets dans le code source

Nous savons tous qu’il faut éviter de stocker des secrets dans le code source, mais il est très facile d’en laisser accidentellement dans des fichiers, surtout lorsque vous testez vos configurations Bicep en local.

Voici quelques moyens d’éviter de valider des secrets dans le code source :

  • Transmettez les paramètres en ligne de commande.

  • Utilisez un fichier JSON de paramètres ignoré par le système de contrôle de version. Par exemple, ajoutez-le à votre fichier .gitignore si vous utilisez Git.

Sécurisez les entrées

Transmettre des paramètres de l’extérieur, c’est une chose, mais comment s’assurer que les secrets sont protégés et ne s’affichent pas dans les sorties ? Bicep fournit un décorateur @secure pour les paramètres de type String et Object. Par exemple :

@secure()
param adminPassword string

@secure()
param adminCredentials object

Attention aux sorties

Ajouter des sorties à vos modules Bicep est très utile, mais il y a quelques points à prendre en compte. Si vous définissez une sortie qui ressemble à un secret, Bicep vous avertit que vous exposez potentiellement des secrets. La sortie suivante, qui contient une chaîne de connexion à un compte de stockage, déclencherait cet avertissement :

output connection string = 'DefaultEndpointsProtocol=https;AccountName=${storageaccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageaccount.id, storageaccount.apiVersion).keys[0].value}'

Cependant, si la valeur était d’abord affectée à une variable avant d’être attribuée à la sortie, aucun avertissement ne s’afficherait et il serait facile de ne pas le remarquer.

var connectionString = 'DefaultEndpointsProtocol=https;AccountName=${storageaccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageaccount.id, storageaccount.apiVersion).keys[0].value}'

output connection string = connectionString

Voyons maintenant ce qui se passe lorsqu’une ressource de compte de stockage est déployée sur Azure avec la configuration suivante :

deploy.bicep
param location string = resourceGroup().location
param tags object = {}
param storageName string = 'stsecureteststore'
param sku string = 'Standard_LRS'

module storageModule 'modules/storage.bicep' = {
  name: 'StorageDeploy'
  params: {
    location: location
    storageName: storageName
    tags: tags
    sku: sku
  }
}

modules/storage.bicep

@description('The storage account name')
@minLength(3)
@maxLength(24)
param storageName string
@description('The storage account location')
param location string
@description('The tags for the storage account')
param tags object
@description('The storage account sku') 
@allowed([ 'Standard_LRS', 'Standard_GRS', 'Standard_GZRS', 'Standard_RAGRS', 'Standard_RAGZRS', 'Standard_ZRS', 'Premium_LRS', 'Premium_ZRS' ])
param sku string = 'Standard_LRS'
@description('The access tier for the blob services') 
@allowed([ 'Hot', 'Cool' ]) 
param accessTier string = 'Hot' 
@description('Allow public access to blobs') 
param allowBlobPublicAccess bool = false 

resource storageaccount 'Microsoft.Storage/storageAccounts@2022-05-01' = {
  name: storageName
  location: location
  kind: 'StorageV2'
  tags: tags
  sku: {
    name: sku
  }
  properties: {
    supportsHttpsTrafficOnly: true
    minimumTlsVersion: 'TLS1_2'
    accessTier: accessTier
    allowBlobPublicAccess: allowBlobPublicAccess
  }
}

var connectionString = 'DefaultEndpointsProtocol=https;AccountName=${storageaccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageaccount.id, storageaccount.apiVersion).keys[0].value}'
output connection string = connectionString

Toutes les sorties définies dans Bicep sont visibles sous Déploiements pour le groupe de ressources dans lequel les ressources ont été déployées :

Page Déploiements du portail Azure pour le groupe de ressources rg-security-example, affichant les déploiements StorageDeploy et main avec le statut Réussi

En examinant les sorties de StorageDeploy, nous constatons que la chaîne de connexion affiche la clé du compte en texte brut :

Page « Sorties » de StorageDeploy dans le portail Azure, affichant une sortie de chaîne de connexion de compte de stockage.

Cela signifie que toute personne autorisée à consulter les ressources dans le portail Azure peut voir ces sorties. Pour maintenir une bonne posture de sécurité, il est recommandé de ne pas renvoyer de secrets dans les sorties Bicep.

Espérons que Bicep prendra en charge à l’avenir le décorateur @secure pour les sorties, afin de permettre de renvoyer des secrets en toute sécurité.

Secrets provenant de ressources

Si renvoyer des secrets depuis Bicep pose problème, comment récupérer des secrets d’un module à l’autre ? Une option consiste à accéder à une ressource existante à l’aide du mot-clé existing. Par exemple :

param storageName string

resource storageaccount 'Microsoft.Storage/storageAccounts@2022-05-01' existing = {
  name: storageName  
}

var connectionString = 'DefaultEndpointsProtocol=https;AccountName=${storageName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageaccount.id, storageaccount.apiVersion).keys[0].value}'

Cette chaîne de connexion pourrait ensuite être utilisée comme entrée pour une autre ressource.

Secrets provenant de Key Vault

Récupérer des ressources existantes est une façon d’obtenir des secrets, mais il est également possible d’utiliser Key Vault pour les récupérer.

Remarque : assurez-vous que la configuration d’accès à Key Vault autorise l’accès via « Azure Resource Manager pour le déploiement de modèles ».

Paramètres d’accès aux ressources avec Azure Resource Manager sélectionné pour le déploiement du modèle, tandis que les machines virtuelles et le chiffrement des disques ne sont pas cochés.

Les coffres Key Vault sont accessibles comme dans la section précédente, à l’aide du mot-clé existing. Notez toutefois que la méthode getSecret ne peut être utilisée que pour affecter une valeur à un paramètre de module doté du décorateur @secure :

deploy.bicep
param location string = resourceGroup().location
param tags object
param sqlServerName string
param keyVaultName string
param keyVaultResourceGroupName string
param subscriptionId string = subscription().subscriptionId

resource vaultResource 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
  name: keyVaultName 
  scope: resourceGroup(subscriptionId, keyVaultResourceGroupName  )
}

module sqlModule 'modules/sql.bicep' = {
  name: 'SqlDeploy'
  params: {
    location: location
    tags: tags
    sqlServerName: sqlServerName
    administratorLogin: vaultResource.getSecret('sqlUser')
    administratorLoginPassword: vaultResource.getSecret('sqlPassword')
  }  
}

modules/sql.bicep
@description('The resource location')
param location string
@description('The tags for the resources')
param tags object
@description('The name for the SQL Server')
param sqlServerName string
@secure()
@description('The SQL Administrator Login')
param administratorLogin string
@secure()
@description('The SQL Administrator password')
param administratorLoginPassword string

resource sqlServerResource 'Microsoft.Sql/servers@2022-05-01-preview' = {
  name: sqlServerName
  location: location
  tags:tags
  properties: {
    administratorLogin: administratorLogin
    administratorLoginPassword: administratorLoginPassword
  }
}

Analyser la sécurité de Bicep

L’analyse de l’infrastructure as code (IaC) gagne en popularité, et il est réjouissant de constater que l’on cherche à détecter les problèmes de sécurité le plus tôt possible. Snyk propose une CLI gratuite qui permet d’effectuer des analyses IaC en local, selon des normes de sécurité et de conformité. Elle ne prend pas directement en charge le format Bicep, mais permet d’analyser les modèles ARM vers lesquels Bicep est compilé.

Pour compiler Bicep en ARM, vous devez avoir installé la CLI Bicep. Pour commencer à utiliser la CLI Snyk, créez un compte gratuit, puis installez la CLI Snyk avec npm. Si Node.js est installé en local, vous pouvez l’installer en exécutant la commande suivante :

npm install snyk@latest -g

Une fois l’installation et la configuration terminées, vous pouvez exécuter la commande suivante :

az bicep build -f {file_name}.bicep

Cette commande génère un fichier JSON portant le même nom que le fichier Bicep. Vous pouvez ensuite lancer l’analyse Snyk avec la commande suivante :

snyk iac test {file_name}.json

Pour conclure

La sécurité est un enjeu auquel nous devons tous penser. Même si la cible évolue constamment, plus nous apprenons, plus nous pouvons contribuer à protéger nos ressources. J’espère que cet article vous a été utile et vous a apporté des pistes pour sécuriser vos configurations Bicep.

Une sécurité IaC pensée pour les développeurs

Snyk sécurise votre infrastructure en tant que code, du cycle de développement logiciel à l’exécution dans le cloud, grâce à un moteur unifié de politiques sous forme de code. Chaque équipe peut ainsi développer, déployer et exploiter ses applications en toute sécurité.

Lire la suite

feature insights context
Blog

Les attaques autonomes sont déjà là. La défense doit suivre leur rythme.

Les attaquants autonomes réduisent la fenêtre de défense. Découvrez comment la découverte, la correction, la validation et la prévention continues peuvent aider les équipes de sécurité à suivre le rythme.

Blog

Evo ADS : la gouvernance des comportements des agents est disponible : maîtrisez l’utilisation de MCP

La gouvernance des comportements des agents Evo ADS est désormais disponible, avec MCP Governance en première étape. Découvrez, approuvez, surveillez, consignez et bloquez l’utilisation des serveurs MCP par les principaux agents de programmation IA.

illustration hero ai
Blog

Qu’est-ce que l’AppSec agentique ?

Découvrez comment l’AppSec agentique s’appuie sur des agents IA ancrés dans la réalité, aux missions délimitées et vérifiés de manière indépendante pour gérer le cycle de sécurité des applications.