Azure para engenheiros AWS: como seus instintos AWS se traduzem (e onde falham)
Você já sabe como organizar contas, conceder permissões e inicializar o estado no AWS. Veja como fazer as mesmas coisas no Azure — os conceitos que se alinham perfeitamente e os quatro pontos onde sua memória muscular AWS vai te enganar ativamente.
Se você é fluente em AWS e agora está diante do Azure, a boa notícia é que ~80% dos seus instintos se transferem diretamente: há uma hierarquia para organizar as coisas, uma forma baseada em funções para conceder acesso, um cenário OIDC para CI sem chaves e uma "dança de bootstrap" para "inicializar seu backend de estado". A má notícia são os outros 20% — e eles estão concentrados em alguns pontos de alta frequência onde fazer as coisas "à moda AWS" produz uma negação confusa em vez de um erro óbvio. Este post é a camada de tradução: os mesmos trabalhos que você faz no AWS, feitos no Azure, com as armadilhas destacadas.
A versão curta, se você ler apenas um parágrafo: AWS tem essencialmente um plano de permissões (IAM), Azure tem três que não se comunicam; contas AWS são assinaturas Azure, mas o faturamento reside em outro lugar; e Azure adiciona um contêiner obrigatório (o resource group) para o qual o AWS não tem um equivalente real. Tudo abaixo expande esses pontos.
A maior mudança: um plano de permissões se torna três
No AWS, IAM é efetivamente a história toda. Um único serviço governa quem são suas identidades, o que elas podem fazer com os recursos e — através de Organizations — como as contas são criadas e agrupadas. As permissões se misturam de uma forma que você provavelmente nem percebe até que elas se separem.
O Azure divide deliberadamente esse plano único em três planos separados, com três sistemas de função, três mecanismos de concessão e quase nenhuma interpenetração automática. Ser todo-poderoso em um plano não te concede nada nos outros. Este é o ponto mais importante a internalizar, pois é a origem de quase todo momento de "mas eu sou um admin, por que isso foi negado?".
A regra que te salva: quando o Azure nega algo que "deveria" funcionar, primeiro pergunte "com qual plano estou falando?" — então verifique as funções desse plano. A maioria das negações misteriosas (não consegue ler uma assinatura, não consegue listar management groups, não consegue ver o faturamento) não são uma permissão ausente dentro de um plano — é você falando com o plano errado completamente.
Plano 1 — Funções de diretório Entra ID (identidade)
Este plano governa objetos de diretório: usuários, grupos, service principals / app registrations, Conditional Access, políticas de MFA, licenças. Ele não governa os recursos que você implanta.
- As funções aqui são como Global Administrator, User Administrator, Application Administrator. Elas são atribuídas e avaliadas no Entra ID e expostas através da Microsoft Graph API.
- Global Administrator é um deus de diretório, não um deus de recursos. Isso confunde a todos: um Global Admin pode gerenciar alegremente todos os usuários e aplicativos na organização e ainda assim obter uma falha de autorização ao tentar simplesmente ler uma assinatura. A analogia mais próxima no AWS é "a pessoa que administra o IAM Identity Center e o próprio diretório" — mas é imperfeita, precisamente porque o AWS funde a administração do diretório com a autorização de recursos e o Azure se recusa a fazer isso.
Plano 2 — Azure RBAC (recursos)
Este é o plano em que você vai viver, e o que o provider azurerm do Terraform impulsiona. Ele governa tudo o que você implanta: VMs, virtual networks, storage, AKS, e assim por diante.
- Uma concessão é um triplo: (principal, definição de função, escopo), onde o escopo é um nó na cadeia
root → management group → subscription → resource group → resource, e ele herda para baixo. As funções internas são Owner, Contributor, Reader, além de quaisquer definições de função personalizadas que você escreva. - Aqui está a armadilha para mentes AWS: não há políticas anexadas à identidade. No AWS, você anexa uma política a um usuário ou função e a permissão viaja com a identidade. No Azure, a função-em-um-escopo é o único modelo. A forma mental AWS mais próxima é "uma política IAM anexada a uma OU do Organizations" — a concessão vive no nó da árvore, não no principal.
- A única ponte sancionada entre os planos 1 e 2 é um movimento deliberado de "quebra de vidro": um Global Administrator pode alternar "Access management for Azure resources" (a operação
elevateAccess) para conceder a si mesmo User Access Administrator no escopo root. É ruidoso, reversível e não é um padrão — você o usa uma vez durante o bootstrap para atribuir a si mesmo Owner no tenant root, que então herda para todas as assinaturas.
Plano 3 — Faturamento / comércio (dinheiro)
Este plano governa contas de faturamento, perfis de faturamento, seções de fatura, métodos de pagamento — e, crucialmente, a criação de assinaturas.
- Ele tem seu próprio conjunto de funções (Billing account owner, Billing profile owner, Azure subscription creator, …), concedidas dentro da conta de faturamento e armazenadas no sistema de faturamento. Essas funções não aparecem em
az role assignment listou nas blades de função do Entra. Elas são um mundo completamente separado. - Você pode bater nesta parede de ambas as direções. Direitos máximos de identidade + recursos (Global Admin + User Access Administrator no root + Owner no management group root) ainda resultam em uma lista vazia de
az billing account liste nenhuma capacidade de criar uma assinatura. Por outro lado, um billing owner pode conceder direitos de faturamento com um clique. - A parte mais traiçoeira: o faturamento é servido através de URLs REST que se parecem com ARM (
Microsoft.Billing/...), então parece o plano de recursos — mas a autorização é avaliada contra funções de faturamento. Mesma porta, segurança diferente.
Uma consequência concreta que o AWS nunca te faz pensar: se você pode criar assinaturas programaticamente depende do seu tipo de acordo de faturamento. Contas legadas pay-as-you-go / web-direct só podem criar assinaturas manualmente no portal, pela identidade de inscrição original — essa propriedade nem é concedível. O moderno Customer Agreement suporta uma API de criação de assinatura (com limites de varejo para contas self-serve — um punhado de assinaturas no total e um limite de taxa por dia), e acordos empresariais/parceiros levantam os limites. No AWS, CreateAccount simplesmente funciona a partir da conta de gerenciamento; no Azure, "posso criar esta conta com código?" é uma pergunta do plano de faturamento que você precisa responder primeiro. É por isso que muitas arquiteturas Azure tratam as assinaturas como importadas para o Terraform, nunca criadas por ele.
Como os planos se cruzam na prática
A maioria das tarefas toca exatamente um plano, e algumas abrangem vários — o que é a principal razão pela qual a divisão importa:
- Criar um usuário, grupo ou app registration → Somente Entra.
- Implantar uma VM / VNet / storage account → Somente recursos (Azure RBAC).
- Criar uma assinatura → o faturamento a cria, ela é vinculada a um tenant Entra, e se torna um escopo Azure RBAC. Três planos para uma ação.
- Exportar logs de auditoria de diretório para um Log Analytics workspace → Entra (origem) mais recursos (destino).
- Terraform
azurermvsazuread→ a API de recursos vs a Graph API — diferentes endpoints, diferentes públicos de token.
Esse último ponto tem um impacto operacional real: um único login gera tokens separados por público (um para o resource manager, um para o Graph, um para o Key Vault). Um token gerado para a API de um plano é inútil no outro. Se sua ferramenta pegar apenas um, metade do seu Terraform misteriosamente retornará 401.
"Entra ID", "tenant" e "directory" são (quase) a mesma coisa
Três palavras para um objeto visto de diferentes ângulos, além de uma renomeação para te confundir:
- Entra ID é o produto — o serviço de identidade. Até 2023 era Azure Active Directory (Azure AD / AAD), e o nome antigo está em todo lugar: o provider
azureaddo Terraform, códigos de erroAADSTS…, "AAD auth" na documentação. Mesma coisa. - Um tenant é a instância dedicada da sua organização do Entra ID — o contêiner e o limite de confiança/isolamento, identificado por um GUID e um domínio primário. Usuários, grupos, aplicativos, Conditional Access e licenças vivem por tenant e não cruzam tenants.
- O directory são os conteúdos de um tenant — o banco de dados de objetos de identidade. Um tenant equivale a um directory, então as pessoas usam as palavras de forma intercambiável; o botão "Switch directory" do portal na verdade troca de tenants.
As regras que se seguem são onde a analogia com o AWS se torna mais flexível:
- Uma assinatura pertence a exatamente um tenant. Esse tenant é seu reino de autenticação e fornece seus principais RBAC. (Assinaturas podem ser transferidas entre tenants; o faturamento é uma associação separada.)
- Uma organização pode possuir vários tenants. Um padrão comum é um tenant de produção bloqueado mais um tenant sandbox totalmente isolado — mundos de identidade separados onde nada que você faça em um pode tocar o outro. Não há equivalente no AWS para "um segundo universo de identidade completamente separado sob a mesma empresa".
- Usuários têm um tenant de origem e podem ser convidados (B2B) em outros lugares. Um convidado obtém um ID de objeto local no tenant convidado enquanto mantém sua identidade de origem. O AWS não tem uma noção de primeira classe de "um usuário convidado do diretório de outra organização".
A analogia mais flexível com o AWS: um tenant é grosseiramente "uma AWS Organization fundida com seu diretório Identity Center" — exceto que as assinaturas se anexam a um tenant apenas para identidade, enquanto o pagamento se anexa a uma conta de faturamento, e convidados inter-organização são um conceito nativo.
Resource groups: o contêiner que o AWS não tem
Um resource group (RG) é um contêiner obrigatório dentro de uma assinatura — cada recurso vive em exatamente um. Esta é a peça que não tem equivalente no AWS (os "resource groups" do AWS são apenas consultas de tags salvas; ignore a colisão de nomes).
Um RG são quatro coisas ao mesmo tempo:
- Um escopo RBAC — conceda Reader em um RG e você terá limitado o acesso exatamente a essa workload.
- Um escopo de política — anexe regras de governança no nível do RG.
- Uma unidade de ciclo de vida — exclua o RG e tudo nele será excluído junto.
- Um limite de custo — um item de linha natural para gastos.
O padrão idiomático é um RG por workload (muitas vezes por região), então um RG se torna "a pasta para este aplicativo nesta região". Um RG tem uma localização, mas isso apenas diz onde seus metadados vivem — seus recursos podem estar em outras regiões, então não supervalorize a localização do RG.
IDs de recursos carregam contexto, então os nomes não precisam
Todo recurso Azure tem um Resource ID completo como /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.App/containerApps/<name>. A assinatura e o RG viajam com cada registro de log, evento de auditoria e chamada de API — o mesmo trabalho que a conta e a região de um ARN fazem no AWS.
A consequência da nomenclatura é o oposto do seu hábito no AWS. No AWS, o nome é frequentemente o único contexto que você obtém, então você coloca tudo nele. No Azure, os nomes devem omitir o que o escopo já codifica: um cluster chamado aks-quest dentro de rg-quest dentro da assinatura qa já está totalmente desambiguado, e os mesmos nomes de RG/recursos podem se repetir com segurança em assinaturas dev/qa/prod. Apenas tipos de recursos globalmente únicos (storage accounts, container registries, Key Vaults) forçam org/env/region de volta ao nome — e esses vêm com limites rígidos de comprimento e caracteres, razão pela qual você vê nomes compactados como stcwtfstateplatformcus.
(Esse sufixo cus não é inventado, a propósito — é o próprio geocódigo da Microsoft para Central US, da mesma tabela oficial que o Azure usa para construir zonas DNS de private-endpoint. eus/eus2 são East US e East US 2. Aprender a tabela de geocódigos cedo compensa.)
O mapa rápido AWS → Azure
Mantenha isso perto de você durante o primeiro mês:
- Organization → um tenant Entra mais management groups. Identidade (o tenant) e estrutura (management groups) são coisas separadas no Azure, não uma só.
- Account → assinatura. Vinculada a um tenant para identidade; faturada por uma conta de faturamento separada.
- SCP (guardrail) → Azure Policy em um escopo de management group — com efeitos mais ricos do que apenas negar (auditoria, negação, modificação, deployIfNotExists).
- IAM role/policy → atribuição de função RBAC — (principal, função, escopo). Lembre-se: sem políticas anexadas à identidade.
- Root-account superpowers → dividido em três: Global Admin (identidade) + elevateAccess (recursos) + billing owner (dinheiro). Nenhum principal único começa com os três.
- Organizations
CreateAccount→ a API de aliases de assinatura + um escopo de faturamento — e apenas nos tipos de acordo de faturamento que permitem isso. - IRSA (IAM Roles for Service Accounts) → workload identity federation — a mesma ideia de OIDC.
- Tag-based grouping → o resource group — estrutural e obrigatório, não uma consulta de tag.
- ARN in logs → o Resource ID (
_ResourceIdcolumn) — o contexto do escopo é estruturado, não codificado no nome.
Inicializando o estado do Terraform, traduzido
Aqui é um lugar onde seu runbook AWS quase funciona, então falha no passo zero.
O bootstrap AWS que você conhece: inicialize um backend de estado na conta de gerenciamento (estado local, então migre o backend para si mesmo), mantenha o estado dos backends por OU nesse backend root, e crie contas membro usando seus próprios backends. O invariante que o torna limpo é que você sempre pode fazer o bootstrap a partir da conta root, porque ela sempre existe e pode conter um bucket S3.
O Azure quebra esse invariante na gênese. O objeto que sempre existe é o tenant — mas um tenant não pode conter recursos. Contas de armazenamento vivem em assinaturas, e as assinaturas nascem do plano de faturamento. Então a "conta root" do Azure é qualquer assinatura que você coroar como root, e você precisa coroar uma conscientemente. Na prática, a maioria dos tenants recebe uma assinatura na inscrição, então o paralelo geralmente se mantém: o AWS te entrega uma conta de gerenciamento, o Azure te entrega uma primeira assinatura.
O fluxo traduzido, quando as assinaturas já existem (o caso comum):
- Um cold-start, sempre: implante o backend de estado em sua assinatura root designada com estado local, então
init -migrate-statepara si mesmo. - Backends por assinatura, estado armazenado no backend root: o componente de backend de cada assinatura adicional fixa seu próprio estado ao backend root, então levantá-los é um apply normal — sem mais cold-starts.
- Todo o resto em cada assinatura usa o próprio backend dessa assinatura.
Do zero absoluto (criando assinaturas com código), a ordem é forçada — assinatura root primeiro, backend root segundo — porque um backend é uma storage account e uma storage account precisa de uma assinatura para existir. Observe uma complicação de "ovo e galinha": o próprio provider azurerm exige um contexto de assinatura, então com zero assinaturas você faz essa primeira assinatura com uma chamada imperativa (o CLI ou o provider azapi), então a importa para o Terraform depois.
E aqui é onde o Azure é genuinamente mais simples do que a memória muscular do AWS: backend-no-root mais recursos-no-membro não precisa de nenhuma da maquinaria de confiança hub-and-spoke do AWS — sem role_arn de backend, sem assume_role de provider, sem políticas de confiança de dois lados. Owner no management group root do tenant herda para todas as assinaturas, então um token funciona em todo o tenant; o provider "salta" entre assinaturas simplesmente configurando subscription_id; e o backend é apenas acesso a blob de data-plane autorizado por uma concessão de Storage Blob Data Contributor. Cross-subscription é um parâmetro, não uma negociação de confiança. (Você vai apertar isso mais tarde com funções personalizadas, PIM e identidades CI dedicadas — mas mesmo assim são atribuições de função em escopos, nunca um handshake de política de confiança.) Se você quiser se aprofundar na codificação de qualquer lado, o exame HashiCorp Terraform Authoring & Operations Pro é construído em torno exatamente desses padrões de estado e provider.
Os quatro pontos onde seus instintos AWS vão te enganar ativamente
Se você esquecer todo o resto, lembre-se destes:
- "Admin" não é global. Global Administrator é somente identidade; ele não pode ler uma assinatura até que alguém lhe conceda uma função de recurso. Não há um principal "root" único.
- Permissões se anexam a escopos, não a identidades. Pare de procurar a política no usuário — procure a atribuição de função no management group, assinatura, resource group ou recurso.
- O faturamento é um universo separado dos recursos. "Eu posso implantar qualquer coisa" não te diz nada sobre "Eu posso criar uma assinatura." Plano diferente, funções diferentes, invisível para
az role assignment list. - O resource group é fundamental. Não é uma tag — é um escopo RBAC, um escopo de política e um limite de exclusão. Projete seu layout de RG propositalmente.
Quais certificações aprofundam cada lado
Governança em nuvem — hierarquia, identidade, guardrails e estado — é a espinha dorsal dos exames de arquitetura e administração em ambas as nuvens, então estudá-los também é a maneira mais rápida de fazer com que os conceitos acima se fixem. Se você já possui a credencial AWS, a do Azure na mesma linha é seu próximo passo natural.
No lado AWS (o conhecimento do qual você está traduzindo):
- AWS Certified Cloud Practitioner (CLF-C02) — as fundações de contas, IAM e Organizations.
- AWS Certified Solutions Architect – Associate (SAA-C03) — IAM, estrutura multi-conta e arquitetura central.
- AWS Certified Solutions Architect – Professional (SAP-C02) — Organizations multi-conta, SCPs e acesso entre contas em escala.
- AWS Certified Security – Specialty (SCS-C03) — Profundidade em IAM, SCPs e gerenciamento de chaves.
No lado Azure (o conhecimento para o qual você está traduzindo):
- Microsoft Certified: Azure Fundamentals (AZ-900) — tenants, assinaturas, resource groups e os fundamentos do RBAC.
- Microsoft Certified: Azure Administrator Associate (AZ-104) — o plano do dia a dia: RBAC, resource groups, assinaturas e conceitos básicos do Entra.
- Microsoft Certified: Azure Solutions Architect Expert (AZ-305) — management groups, governança e design de landing zone.
- Microsoft Certified: Azure Security Engineer Associate (AZ-500) — Entra ID, RBAC, Azure Policy, Conditional Access e Key Vault.
Um caminho pragmático se você é certificado AWS hoje: comece no AZ-900 para mapear o vocabulário, então pule para o AZ-104 (que vive no plano de recursos que você mais usará), e adicione AZ-305 ou AZ-500 dependendo se seu trabalho se inclina para arquitetura ou segurança.
Conclusão
O Azure não é mais difícil que o AWS — ele é fatorado de forma diferente. O AWS colapsa a autoridade de identidade, recursos e faturamento em um plano e te entrega uma conta de gerenciamento que pode fazer tudo. O Azure separa essas três preocupações propositalmente, o que parece atrito no primeiro dia e como limites claros no terceiro mês. Traduza os conceitos uma vez — um plano se torna três, contas se tornam assinaturas faturadas em outro lugar, políticas se anexam a escopos em vez de identidades, e o resource group é uma estrutura real — e o resto é vocabulário. Aprofunde-se com as certificações acima, e as partes que pareciam negações arbitrárias começarão a ser lidas como um design coerente e deliberado.