Skip to main content

Fundamentos de segurança do Azure Bicep

Escrito por
Headshot of Mark Johnson

Mark Johnson

feature bicep security

13 de dezembro de 2022

0 minutos de leitura

Este post foi escrito pelo embaixador da Snyk Mark Johnson (@tazmainiandevil). Tenha acesso antecipado à Snyk inscrevendo-se para se tornar um embaixador da Snyk.

O Azure Bicep está se tornando cada vez mais popular e rapidamente substituindo os modelos do Azure Resource Manager (ARM). Neste post, vou apresentar alguns fundamentos de segurança para usar o Bicep. Se você ainda não conhece o Bicep, recomendo consultar a documentação do Microsoft Learn para saber mais.

Mantenha os segredos fora do controle de versão

Todos sabemos que precisamos manter os segredos fora do controle de versão, mas é muito fácil deixá-los acidentalmente em arquivos, especialmente ao testar configurações do Bicep localmente.

Veja algumas maneiras de evitar o commit de segredos:

  • Passe parâmetros pela linha de comando.

  • Use um arquivo JSON de parâmetros ignorado pelo controle de versão. Por exemplo, se você usa Git, adicione-o ao arquivo .gitignore.

Proteja as entradas

Passar parâmetros externamente é uma coisa, mas como garantir que os segredos estejam protegidos e não apareçam nas saídas? O Bicep oferece o decorador @secure para parâmetros dos tipos String e Object. Por exemplo:

@secure()
param adminPassword string

@secure()
param adminCredentials object

Tenha cuidado com as saídas

Adicionar saídas aos módulos do Bicep é muito útil, mas há alguns pontos importantes. Se você definir uma saída que pareça conter um segredo, o Bicep emitirá um aviso de que possíveis segredos estão sendo expostos. A saída a seguir, com uma cadeia de conexão de uma conta de armazenamento, geraria esse aviso:

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

No entanto, se o valor fosse atribuído a uma variável antes de ser incluído na saída, nenhum aviso seria exibido, e isso poderia passar despercebido.

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

output connection string = connectionString

Agora, veja o que acontece quando um recurso de conta de armazenamento é implantado no Azure com a seguinte configuração:

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

Todas as saídas definidas no Bicep podem ser visualizadas em Implantações, no grupo de recursos em que os recursos foram implantados:

Página Implantações do portal do Azure para o grupo de recursos rg-security-example, mostrando as implantações StorageDeploy e main com status Concluído

Ao analisar as saídas de StorageDeploy, vemos que a conexão é exibida com a chave da conta em texto simples:

Página de saídas StorageDeploy do portal do Azure exibindo a saída de uma string de conexão de uma conta de armazenamento.

Isso significa que qualquer pessoa com acesso para visualizar os recursos no portal do Azure pode ver essas saídas. Para manter uma boa postura de segurança, recomendamos não retornar segredos como saídas no Bicep.

Esperamos que, no futuro, o Bicep ofereça suporte ao decorador @secure nas saídas para permitir o retorno seguro de segredos.

Segredos de recursos

Se retornar segredos do Bicep é um problema, como passar segredos de um módulo para outro? Uma opção é acessar um recurso existente usando a palavra-chave existing. Por exemplo:

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

Essa cadeia de conexão poderia então ser usada como entrada para outro recurso.

Segredos do Key Vault

Acessar recursos existentes é uma maneira de obter segredos, mas também há suporte para recuperá-los usando o Key Vault.

Observação: verifique se a configuração de acesso do Key Vault permite o acesso por meio de "Azure Resource Manager para implantação de modelos"

Configurações de acesso a recursos com o Azure Resource Manager selecionado para implantação de modelos, enquanto máquinas virtuais e criptografia de disco permanecem desmarcadas.

Os Key Vaults são acessados da mesma forma descrita na seção anterior, usando a palavra-chave existing. No entanto, há uma ressalva: o método getSecret só pode ser usado ao atribuir um parâmetro de módulo com o decorador @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
  }
}

Análise de segurança do Bicep

A análise de infraestrutura como código (IaC) está se tornando bastante popular, e é bom ver o interesse em identificar problemas de segurança o quanto antes. A Snyk oferece uma CLI gratuita que pode ser usada para analisar IaC localmente com base em padrões de segurança e conformidade. Embora não ofereça suporte direto ao formato Bicep, ela analisa modelos ARM, para os quais o Bicep é compilado.

Para compilar Bicep em ARM, você precisa ter a CLI do Bicep instalada. Para começar a usar a CLI da Snyk, crie uma conta gratuita e depois instale a CLI da Snyk usando npm. Se você tiver o Node.js instalado localmente, poderá instalá-la executando:

npm install snyk@latest -g

Depois de instalar e configurar, execute o comando:

az bicep build -f {file_name}.bicep

Isso vai gerar um arquivo JSON com o mesmo nome do arquivo Bicep. Em seguida, você poderá executar a análise da Snyk com o comando:

snyk iac test {file_name}.json

Considerações finais

Todos precisamos pensar em segurança. Embora ela seja um alvo em constante mudança, quanto mais aprendemos, mais podemos fazer para proteger nossos recursos. Espero que este post tenha sido informativo e ajudado você a proteger suas configurações do Bicep.

Segurança de IaC pensada para quem desenvolve

A Snyk protege sua infraestrutura como código do ciclo de vida do desenvolvimento de software até a execução na nuvem, com um mecanismo unificado de políticas como código para que todas as equipes possam desenvolver, implantar e operar com segurança.

Leia mais

feature insights context
Blog

Os ataques autônomos já chegaram. A defesa precisa acompanhar o ritmo.

Os atacantes autônomos estão reduzindo o tempo disponível para a defesa. Saiba como a descoberta, a correção, a validação e a prevenção contínuas ajudam as equipes de segurança a acompanhar esse ritmo.

Blog

Evo ADS Govern Agent Behavior já está disponível: controle o uso de MCP

Evo ADS Govern Agent Behavior já está disponível, começando por MCP Governance. Descubra, aprove, monitore, registre e bloqueie o uso de servidores MCP nos principais agentes de programação com IA.

illustration hero ai
Blog

O que é Agentic AppSec?

Saiba como Agentic AppSec usa agentes de IA fundamentados, com limites definidos e verificados de forma independente para executar o ciclo de segurança de aplicações.