Criar VM Windows com Bicep
📋 Visão Geral
Neste workshop você aprenderá a provisionar uma máquina virtual Windows Server usando Bicep — a linguagem nativa de Infrastructure as Code da Microsoft para Azure.
Bicep é uma linguagem declarativa que simplifica a criação de templates ARM, oferecendo:
- Sintaxe concisa e legível (vs. JSON ARM templates)
- Suporte nativo no Azure CLI e Azure PowerShell
- IntelliSense completo no VS Code
- Deploy com Trusted Launch e segurança avançada
✅ Pré-requisitos
Antes de começar, certifique-se de ter:
- Uma subscrição Azure ativa
- Azure CLI instalado (versão 2.20.0+) com Bicep CLI incluído
- VS Code com extensão Bicep instalada (recomendado)
🚀 Configuração do Ambiente
Prepare o ambiente para o deploy com Bicep:
1. Autenticar e criar Resource Group
# Login no Azure az login # Criar Resource Group az group create --name myResourceGroupBicep --location eastus
2. Verificar instalação do Bicep
# Verificar versão do Bicep az bicep version # Instalar/atualizar se necessário az bicep install az bicep upgrade
⚙️ Implementação
Crie o arquivo main.bicep com toda a infraestrutura necessária:
Passo 1: Definir parâmetros
O arquivo Bicep começa com parâmetros configuráveis:
@description('Username for the Virtual Machine.')
param adminUsername string
@description('Password for the Virtual Machine.')
@minLength(12)
@secure()
param adminPassword string
@description('Unique DNS Name for the Public IP.')
param dnsLabelPrefix string = toLower('${vmName}-${uniqueString(resourceGroup().id, vmName)}')
@description('Name of the virtual machine.')
param vmName string = 'simple-vm'
@description('Location for all resources.')
param location string = resourceGroup().location
@description('Size of the virtual machine.')
param vmSize string = 'Standard_D2s_v5'
@description('Windows Server version.')
@allowed([
'2016-datacenter-gensecond'
'2016-datacenter-server-core-g2'
'2019-datacenter-gensecond'
'2019-datacenter-core-g2'
'2022-datacenter-azure-edition'
'2022-datacenter-azure-edition-core'
'2022-datacenter-core-g2'
'2022-datacenter-g2'
])
param OSVersion string = '2022-datacenter-azure-edition'
@description('Security Type of the Virtual Machine.')
@allowed([
'Standard'
'TrustedLaunch'
])
param securityType string = 'TrustedLaunch'
Passo 2: Definir variáveis e recursos de rede
var storageAccountName = 'bootdiags${uniqueString(resourceGroup().id)}'
var nicName = 'myVMNic'
var addressPrefix = '10.0.0.0/16'
var subnetName = 'Subnet'
var subnetPrefix = '10.0.0.0/24'
var virtualNetworkName = 'MyVNET'
var networkSecurityGroupName = 'default-NSG'
var securityProfileJson = {
uefiSettings: {
secureBootEnabled: true
vTpmEnabled: true
}
securityType: securityType
}
var extensionName = 'GuestAttestation'
var extensionPublisher = 'Microsoft.Azure.Security.WindowsAttestation'
var extensionVersion = '1.0'
var maaTenantName = 'GuestAttestation'
// Storage Account
resource storageAccount 'Microsoft.Storage/storageAccounts@2022-05-01' = {
name: storageAccountName
location: location
sku: { name: 'Standard_LRS' }
kind: 'Storage'
}
// Public IP Address
resource publicIp 'Microsoft.Network/publicIPAddresses@2022-05-01' = {
name: '${vmName}-PublicIP'
location: location
sku: { name: 'Basic' }
properties: {
publicIPAllocationMethod: 'Dynamic'
dnsSettings: { domainNameLabel: dnsLabelPrefix }
}
}
// Network Security Group
resource nsg 'Microsoft.Network/networkSecurityGroups@2022-05-01' = {
name: networkSecurityGroupName
location: location
properties: {
securityRules: [
{
name: 'default-allow-3389'
properties: {
priority: 1000
access: 'Allow'
direction: 'Inbound'
protocol: 'Tcp'
sourcePortRange: '*'
sourceAddressPrefix: '*'
destinationAddressPrefix: '*'
destinationPortRange: '3389'
}
}
{
name: 'default-allow-80'
properties: {
priority: 1001
access: 'Allow'
direction: 'Inbound'
protocol: 'Tcp'
sourcePortRange: '*'
sourceAddressPrefix: '*'
destinationAddressPrefix: '*'
destinationPortRange: '80'
}
}
]
}
}
// Virtual Network
resource vnet 'Microsoft.Network/virtualNetworks@2022-05-01' = {
name: virtualNetworkName
location: location
properties: {
addressSpace: { addressPrefixes: [ addressPrefix ] }
subnets: [
{
name: subnetName
properties: {
addressPrefix: subnetPrefix
networkSecurityGroup: { id: nsg.id }
}
}
]
}
}
// Network Interface
resource nic 'Microsoft.Network/networkInterfaces@2022-05-01' = {
name: nicName
location: location
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
privateIPAllocationMethod: 'Dynamic'
publicIPAddress: { id: publicIp.id }
subnet: { id: resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, subnetName) }
}
}
]
}
}
Passo 3: Definir a Virtual Machine com Trusted Launch
// Windows Virtual Machine
resource vm 'Microsoft.Compute/virtualMachines@2022-03-01' = {
name: vmName
location: location
properties: {
hardwareProfile: { vmSize: vmSize }
osProfile: {
computerName: vmName
adminUsername: adminUsername
adminPassword: adminPassword
}
storageProfile: {
imageReference: {
publisher: 'MicrosoftWindowsServer'
offer: 'WindowsServer'
sku: OSVersion
version: 'latest'
}
osDisk: {
createOption: 'FromImage'
managedDisk: { storageAccountType: 'StandardSSD_LRS' }
}
dataDisks: [
{
diskSizeGB: 1023
lun: 0
createOption: 'Empty'
}
]
}
networkProfile: {
networkInterfaces: [
{ id: nic.id }
]
}
diagnosticsProfile: {
bootDiagnostics: {
enabled: true
storageUri: storageAccount.properties.primaryEndpoints.blob
}
}
securityProfile: ((securityType == 'TrustedLaunch') ? securityProfileJson : null)
}
}
// Guest Attestation Extension (Trusted Launch)
resource vmExtension 'Microsoft.Compute/virtualMachines/extensions@2022-03-01' = if ((securityType == 'TrustedLaunch') && ((securityProfileJson.uefiSettings.secureBootEnabled == true) && (securityProfileJson.uefiSettings.vTpmEnabled == true))) {
parent: vm
name: extensionName
location: location
properties: {
publisher: extensionPublisher
type: extensionName
typeHandlerVersion: extensionVersion
autoUpgradeMinorVersion: true
enableAutomaticUpgrade: true
settings: {
AttestationConfig: {
MaaSettings: { maaEndpoint: '', maaTenantName: maaTenantName }
}
}
}
}
// Install IIS Extension
resource iisExtension 'Microsoft.Compute/virtualMachines/extensions@2022-03-01' = {
parent: vm
name: 'installIIS'
location: location
properties: {
publisher: 'Microsoft.Compute'
type: 'CustomScriptExtension'
typeHandlerVersion: '1.10'
autoUpgradeMinorVersion: true
settings: {
commandToExecute: 'powershell -ExecutionPolicy Unrestricted Install-WindowsFeature -name Web-Server -IncludeManagementTools;'
}
}
}
// Outputs
output hostname string = publicIp.properties.dnsSettings.fqdn
output publicIPAddress string = publicIp.properties.ipAddress
Passo 4: Fazer o deploy com Azure CLI
# Deploy com Bicep az deployment group create \ --resource-group myResourceGroupBicep \ --template-file main.bicep \ --parameters adminUsername=azureuser
Você será solicitado a fornecer a senha (adminPassword) durante o deploy. Use uma senha com pelo menos 12 caracteres, incluindo maiúsculas, minúsculas, números e caracteres especiais.
✅ Validação
Verifique se o deploy foi concluído com sucesso:
1. Verificar outputs do deploy
# Ver resultados do deploy az deployment group show \ --resource-group myResourceGroupBicep \ --name main \ --query properties.outputs
2. Obter IP público da VM
# Obter IP público az vm show \ --resource-group myResourceGroupBicep \ --name simple-vm \ --show-details \ --query publicIps \ --output tsv
3. Testar o IIS no navegador
Acesse o IP público retornado ou o hostname DNS:
http://<PUBLIC_IP_ADDRESS>
🧹 Limpeza
Remova todos os recursos criados para evitar cobranças:
# Deletar o resource group e todos os recursos az group delete \ --name myResourceGroupBicep \ --yes --no-wait