, , ,

Backup automático de VMs no Azure por TAG com Azure Policy

Passo a passo para automatizar Azure Backup em VMs via Azure Policy usando a definição built-in “Configure backup on virtual machines with a given tag”, com Managed Identity e parâmetros de TAG.

Fala, pessoal! Nas últimas semanas venho revisando o desenho de proteção de dados de VMs em ambientes Azure com escala razoável (dezenas a algumas centenas de máquinas) e a mesma dor apareceu em mais de um cliente: backup ainda depende de alguém lembrar de “clicar” na VM depois que ela nasce. Este artigo que escrevi mostra como resolver isso de forma nativa, usando Azure Policy e a definição built-in Configure backup on virtual machines with a given tag to an existing recovery services vault in the same location.

Por que automatizar backup por TAG

Ambientes cloud crescem por delegação: times de aplicação sobem VMs, esteiras de IaC provisionam recursos por Pull Request, workloads sobem em janelas de 3h da manhã. Delegar a decisão “essa VM entra no backup?” para um humano depois da criação é a receita clássica de VM em produção sem restore point — e a descoberta costuma ser feita no pior dia possível.

A abordagem baseada em Azure Policy resolve isso invertendo a lógica: em vez de proteger a VM depois, o ambiente já garante que qualquer VM que nasça com a TAG certa (por exemplo, Ambiente=Prod) seja automaticamente associada a um cofre e a uma política de backup pré-definidos. É governança contínua, não campanha de conformidade.

Comparação de abordagens

AbordagemEscalaAuditávelRisco de gapQuando usar
Portal — associação manualBaixaNãoAltoAmbiente pequeno, poucas VMs
Runbook / script pós-criaçãoMédiaParcialMédioJá existe automação central madura
Azure Policy + TAG (este artigo)AltaSim (Compliance)BaixoPadrão para ambientes governados
IaC (Terraform/Bicep) — módulo padrãoAltaSim (código)BaixoAmbientes 100% IaC, sem criação de VM via portal

Na prática, Azure Policy + IaC não competem — se complementam. A Policy é a rede de segurança para tudo que escapa do módulo IaC (VMs criadas via portal, ARM, ou por times sem acesso ao repositório).

Pré-requisitos

ItemDetalhe
Permissões na SubscriptionResource Policy Contributor (para criar a Policy Assignment) e User Access Administrator ou Owner (para atribuir roles à Managed Identity).
Permissões no Recovery Services VaultBackup Contributor — será concedida à Managed Identity da Policy Assignment.
Recovery Services Vault (RSV)Já existente, na mesma região das VMs que serão protegidas. O parâmetro vaultLocation da política é rígido nisso.
Backup Policy no cofreStandard ou Enhanced — o subtipo precisa ser compatível com o cenário (ver seção sobre subtipo).
Padronização de TAGA TAG que vai disparar a proteção (ex.: Ambiente) precisa ter governança — idealmente com uma policy de Deny ou Append garantindo que VMs nasçam com o valor correto.
FerramentasAzure CLI 2.60+ ou PowerShell 7 com módulos Az e Az.RecoveryServices. Portal também funciona.

Um detalhe que muita gente pula: Standard vs. Enhanced

Quando você cria a Backup Policy no cofre, precisa escolher o subtipo:

  • Standard: backup diário, retenção até 9999 dias, cenário clássico para VMs de produção com RPO de 24h.
  • Enhanced: permite backup múltiplas vezes ao dia (frequência Hourly), suporta Trusted Launch VMs, Ultra Disks, discos compartilhados. Habilita também o Vault-Standard Tier archive.

Uma vez criada a policy como Standard ou Enhanced, não dá para converter. Se você vai precisar de RPO menor que 24h ou usa Trusted Launch, comece com Enhanced.

Passo a passo

Passo 1 — Preparar o Recovery Services Vault e a Backup Policy

No portal, navegue até Recovery Services vaults › Create e provisione o cofre na região das VMs alvo (ex.: brazilsouth). Nomeie de forma que já indique o cenário: rsv-vms-prod. Depois, dentro do cofre, vá em Manage › Backup policies › Add e crie a policy que a Azure Policy vai referenciar. Você pode criar um RSV para vms para homologação/dev e sua politica em separado para melhor governança.

Exemplo de configuração para bkp-vms-prod (Enhanced, RPO de 4h):

  • Policy sub type: Enhanced
  • Backup frequency: Hourly
  • Schedule: Start 10:00 Pm, Every 4 Hours, Duration 12 Hours, Timezone (UTC-03:00) Brasília
  • Instant restore snapshot retention: 1 dia
  • Retention of daily backup point: 7 dias
  • Retention of weekly backup point: 4 semanas (ajustar por RTO/RPO)
  • Retention of monthly backup point: 12 meses

Demais segue como padrão, dependendo das configurações de compliance da sua organização.

Figura 1 — Criação da Backup Policy Enhanced no cofre, com frequência Hourly a cada 4 horas.

Passo a criação da política:

01

02 –

Alternativa via CLI (útil para IaC e para documentar em runbook):

# Criar o Recovery Services Vault
az backup vault create \
--resource-group rg-backup \
--name rsv-vms-prod \
--location brazilsouth
# Listar policies existentes no cofre (as built-in DefaultPolicy e EnhancedPolicy já vêm)
az backup policy list \
--resource-group rg-backup \
--vault-name rsv-vms-prod \
--output table
# Recuperar o ID de uma policy específica (será usado no parâmetro backupPolicyId da Azure Policy)
az backup policy show \
--resource-group rg-backup \
--vault-name rsv-vms-prod \
--name bkp-vms-prod \
--query id -o tsv

Guarde o id completo da Backup Policy — ele é obrigatório no parâmetro backupPolicyId da Azure Policy. Copiar só o nome não funciona.

Passo 2 — Criar a Azure Policy Assignment

No portal: Policy › Definitions e busque por “Configure backup on virtual machines with a given tag to an existing recovery services vault“. A definição built-in tem o ID 345fa903-145c-4fe1-8bcd-93ec2adccde8.

Clique em Assign e preencha:

  • Scope: Subscription ou Resource Group. Nunca Management Group — a política built-in não suporta esse escopo (voltamos a isso na seção de armadilhas).
  • Assignment name: algo descritivo, ex.: backup-vms-prod-por-tag.
  • Policy enforcement: Enabled se você quer que o DeployIfNotExists atue; Disabled (DoNotEnforce) para rodar em modo auditoria inicial.

Figura 2 — Aba Basics do Assignment: escopo em Subscription e enforcement habilitado.

Na aba Parameters, preencha:

ParâmetroValor de exemploObservação
effectDeployIfNotExistsPadrão. É o que cria a proteção automaticamente.
vaultLocationbrazilsouthPrecisa ser igual à região das VMs. A Policy só age em VMs da mesma região.
backupPolicyId/subscriptions/<sub>/resourceGroups/rg-backup/providers/Microsoft.RecoveryServices/vaults/rsv-vms-prod/backupPolicies/bp-vms-prodID completo. Cole o output do az backup policy show --query id.
tagName (Inclusion Tag Name)AmbienteNunca deixe vazio. Ver armadilha #3.
tagValues (Inclusion Tag Value)["Prod"]Array. Aceita múltiplos valores, ex.: ["Prod","Producao"].

Figura — Parâmetros preenchidos: tagName=Ambiente, tagValues=[“Prod”].

Na aba Remediation:

  • Marque Create a Managed Identity (System-assigned, na mesma região do cofre).
  • Marque Create a remediation task se você já tem VMs pré-existentes que devem ser protegidas nesta rodada. Para VMs futuras (novas), essa opção é irrelevante — o DeployIfNotExists age automaticamente na criação.

Figura 4 — Aba Remediation com Managed Identity System-assigned selecionada.

⚠️ Ponto crítico: RBAC da Managed Identity

Ao finalizar o Assignment, o portal promete conceder as roles automaticamente. Na prática, em vários casos que já vi, essa concessão demora ou falha silenciosamente. Não confie — valide manualmente:

  1. No cofre, vá em Access control (IAM) › Role assignments e confirme que a Managed Identity da Policy tem a role Backup Contributor.
  2. Na Subscription ou RG do escopo, confirme que a mesma identidade tem Virtual Machine Contributor (precisa dessa role para ler as VMs e disparar o registro no cofre).

Se faltar qualquer uma, atribua manualmente:

# Recuperar o principalId da Managed Identity do Assignment
PRINCIPAL_ID=$(az policy assignment show \
--name backup-vms-prod-por-tag \
--scope "/subscriptions/<sub>" \
--query identity.principalId -o tsv)
# Backup Contributor no cofre
az role assignment create \
--assignee-object-id $PRINCIPAL_ID \
--assignee-principal-type ServicePrincipal \
--role "Backup Contributor" \
--scope "/subscriptions/<sub>/resourceGroups/rg-backup/providers/Microsoft.RecoveryServices/vaults/rsv-vms-prod"
# Virtual Machine Contributor no escopo da Policy
az role assignment create \
--assignee-object-id $PRINCIPAL_ID \
--assignee-principal-type ServicePrincipal \
--role "Virtual Machine Contributor" \
--scope "/subscriptions/<sub>"

Faça isso imediatamente após criar o Assignment. A razão está na próxima seção — se a role só aparecer 20 minutos depois, você perdeu a janela automática e vai depender de remediation manual para qualquer VM criada nesse intervalo.

Após a criação da policy, localize a mesma e vamos editá-la:

Agora salve a policy

Passo 3 — Testar com uma VM nova

Crie uma VM de teste na região configurada, com a TAG Ambiente – Prod que dispara a proteção:

az vm create \
--resource-group rg-servidores \
--name vm-teste-backup \
--image Ubuntu2204 \
--location brazilsouth \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--tags Ambiente=Prod

Tags aplicadas

Aguarde de 10 a 20 minutos. Depois:

  1. Em Policy › Compliance, filtre pelo Assignment. A VM deve estar como Compliant.

Figura 5 — VM aparecendo em Protected items automaticamente após a janela de avaliação.

E se a janela passou e a VM ficou como Non-compliant?

Isso normalmente significa que a Managed Identity não tinha as roles no exato momento da avaliação. Depois de corrigir o RBAC, dispare uma Remediation Task:

Via portal: Policy › Remediation › Remediate policy › selecione o Assignment › Remediate.

Via CLI:

az policy remediation create \
--name remediate-backup-vms-prod-$(date +%Y%m%d) \
--policy-assignment "/subscriptions/<sub>/providers/Microsoft.Authorization/policyAssignments/backup-vms-prod-por-tag" \
--resource-group rg-lab

Acompanhe em Policy › Remediation › Remediation tasks até o status ficar Succeeded.

Deep-dive técnico

ElementoO que faz
effect: DeployIfNotExistsAvalia se a VM já está protegida no cofre alvo. Se não, dispara um deployment ARM que faz o enable-protection. Só age quando o recurso é criado ou atualizado — não é um scan contínuo.
Janela de avaliaçãoApós um PUT no Resource Provider da VM, a Policy dispara em ~10 minutos. Se a Managed Identity não tem role naquele instante, o deployment falha silenciosamente e a VM cai em Non-compliant nas avaliações periódicas subsequentes — sem retry automático.
Managed Identity (System-assigned)É o “usuário” que a Policy usa para executar o deployment. Precisa de Backup Contributor no cofre e Virtual Machine Contributor no escopo. Sem isso, DeployIfNotExists vira DoNotDeploy.
tagName + tagValuesFiltro de inclusão. Só VMs com tags[tagName] IN tagValues são elegíveis. Case-sensitive nos valores.
vaultLocationFiltro geográfico. Se a VM está em outra região do cofre, é ignorada.
Remediation TaskAplica o efeito retroativamente em recursos que já existem no escopo. Útil para: (a) VMs criadas antes da Policy; (b) VMs que perderam a janela por falha de RBAC.

Armadilhas de campo (as que doeram)

Armadilha #1 — Management Group não é escopo suportado

A definição built-in with a given tag só aceita Subscription ou Resource Group como escopo. Se você tentar criar o Assignment em um Management Group, o portal aceita a criação, o Compliance mostra tudo como Compliant, e nenhuma VM recebe backup. É uma falha silenciosa.

Isso está na documentação oficial da definição, mas passa batido em toda revisão de desenho que fiz. Se você governa um Landing Zone com dezenas de subscriptions, precisa criar um Assignment por Subscription — o que é ruim de manter à mão, mas gerenciável via IaC ou script.

Solução prática: mantenha a definição de Backup Policy centralizada em um cofre de hub ou padronizada por IaC, e escreva um script que faça foreach subscription criando o Assignment com os mesmos parâmetros.

Armadilha #2 — Condição de corrida entre RBAC e avaliação

Cronologia típica que causa o problema:

  1. Você cria o Assignment às 14:00 e o portal “promete” atribuir as roles à Managed Identity.
  2. Uma esteira de IaC cria uma VM às 14:03.
  3. Às 14:13, a Policy tenta o DeployIfNotExists — mas as roles só apareceram às 14:20.
  4. A VM fica Non-compliant. Como não há retry automático em DeployIfNotExists após a criação, apenas remediation manual protege essa VM específica.

Como evitar: crie o Assignment em janela de manutenção, valide RBAC na hora (Passo 2 acima), e só então libere a criação de VMs no escopo. Em ambiente já rodando, agende uma Remediation Task semanal para varrer o que a janela automática eventualmente perde.

Armadilha #3 — TAG ou valor vazio protege ZERO VMs

Aqui é onde muita gente que migrou da política antiga without a given tag se queima. Comportamento:

PolíticatagName ou tagValues vazioEfeito
without a given tag (exclusão)VazioTodas as VMs viram elegíveis (nada é excluído).
with a given tag (inclusão) — este artigoVazioNenhuma VM vira elegível (nada bate o filtro).

Ou seja: no with a given tag, esquecer de preencher a TAG não gera VMs protegidas em excesso — gera VMs sem proteção alguma. E o Compliance vai mostrar 100% Compliant, porque não há VM elegível para ficar Non-compliant. É a pior categoria de falha silenciosa possível em backup.

Troubleshooting

SintomaDiagnósticoAção
VM criada com a TAG certa não aparece em Backup items após 20minManaged Identity sem Backup Contributor no cofre, ou sem Virtual Machine Contributor no escopo, no momento da criação da VM.Confirmar roles (aba IAM do cofre e da Subscription), rodar Remediation Task manual, validar novamente.
VM aparece como Non-compliant sem detalhesProvável mismatch de região entre VM e cofre (vaultLocation).Confirmar que a VM está na mesma região do cofre. Não há workaround — cofre é regional.
Nenhuma VM elegível, apesar de haver dezenas com a TAGAssignment criado em Management Group (não suportado), ou tagValues com case diferente (prod vs Prod).Recriar Assignment em Subscription/RG. Verificar case exato dos valores.
Remediation Task fica em FailedErro no deployment ARM — geralmente permissão ou lock em RG.Abrir a Remediation Task › Deployments › ver mensagem do provider. Corrigir e rerodar.
Backup Policy exibe erro ao reduzir retençãoCofre marcado como imutável (Immutable Vault).Comportamento esperado — reduções seguem processo específico documentado pela Microsoft.
Last backup status = Failed em VM específicaProblema no agente da VM, lock em disco, ou snapshot travado.Cofre › Backup jobs › abrir o job com erro. Ações comuns: reiniciar agente, liberar snapshot pendente, verificar espaço.

Boas práticas para produção

  • Governança de TAG antes da Policy de backup. Se a TAG Ambiente não é obrigatória, a proteção fica furada. Combine com uma policy de Deny na criação de VM sem a TAG, ou Append aplicando um valor default.
  • Immutable Vault. Habilite imutabilidade nos cofres de produção. Bloqueia reduções acidentais de retenção e é uma barreira concreta contra cenários de ransomware que tentam apagar restore points.
  • Soft Delete. Mantenha habilitado (padrão 14 dias). Complementa a imutabilidade.
  • Cross-Region Restore. Para workloads críticos, habilite CRR no cofre — permite restaurar em região secundária em cenário de desastre regional.
  • Modo auditoria antes de enforcement. Suba o Assignment como DoNotEnforce primeiro, avalie o Compliance por alguns dias, corrija VMs órfãs, só então promova para Default.
  • Remediation Task periódica. Agende (via Automation Runbook ou pipeline) uma remediation semanal para pegar VMs que porventura perderam a janela.
  • Monitoramento. Integre Backup jobs com Log Analytics/Azure Monitor e crie alerta para Failed ou Warning nas últimas 24h. Backup sem monitoramento é ficção de compliance.

Fecho

Automatizar Azure Backup por TAG via Azure Policy é uma das mudanças de maior impacto e menor custo em governança de nuvem: elimina a decisão humana no caminho crítico da proteção, gera evidência auditável via Compliance, e escala junto com a esteira de provisionamento. Mas depende de três coisas darem certo ao mesmo tempo: escopo correto (não é MG), RBAC da Managed Identity no lugar antes da primeira VM, e TAG realmente preenchida — nenhuma delas grita quando falha.

O código-fonte dos exemplos deste artigo (comandos CLI, exemplos de assignment JSON, script de bulk assignment por Subscription) está no GitHub. Se este material te ajudou, deixa uma estrelinha ⭐ no repositório — ajuda a chegar em mais gente do time de Cloud.

👉 github.com/ErickMedeiros

E se você tem uma armadilha diferente das que listei — daquelas que só descobriu tomando na cara — conta nos comentários. Governança de backup é área em que a comunidade aprende junto.

Forte abraço pessoal 👊