Lab 43 — Multi-conta: OU, SCP e Control Tower
O problema, e a empresa que o tem
A Cadência, do L03, cresceu: hoje são quatro desenvolvedores, todos com acesso de operação na mesma conta AWS que hospeda o RDS de produção. A separação entre ambiente de desenvolvimento e produção existe só na cabeça de quem escreve o comando — e no nome do recurso, que começa com cadencia-dev- ou cadencia-prod-. A conta é uma só.
Na semana passada, um desenvolvedor rodou um script de limpeza de bancos de teste antigos com a variável de ambiente apontando, por engano, para produção. O comando chegou a executar — a policy IAM da role de operação permitia, porque foi escrita com um wildcard de prefixo pensado para cobrir "qualquer banco da Cadência" e não "qualquer banco de desenvolvimento da Cadência". Só não terminou em incidente porque alguém no canal reconheceu o nome do banco a tempo de interromper.
O problema não é a falta de cuidado de quem escreveu o script. É que numa conta só, nenhuma política de identidade, por mais bem escrita, é uma fronteira — é sempre possível escrever (ou herdar) uma permissão ampla o bastante para alcançar os dois lados. A mesma escada que o L38 percorreu para isolar dado de cliente por linha, esquema e conta se aplica aqui a ambiente em vez de cliente: linha e esquema não seguram um erro de identidade: só conta segura.
O que este laboratório NÃO é
Não é uma landing zone completa de produção, com dezenas de contas, RCP e Account Factory for Terraform. O entregável aqui é o mínimo que já resolve o risco declarado: duas OUs e uma SCP. A escala maior é o assunto dos laboratórios seguintes desta fronteira, e forçar essa escala agora, para duas pessoas de plataforma, seria construir governança antes de ter o que governar.
O que você vai conseguir fazer
Objetivos verificáveis: cada um se prova com um comando na seção de implantação, não com a sensação de ter entendido a distinção teórica.
- Explicar por que uma política IAM, sozinha, nunca é uma fronteira de ambiente.
- Diferenciar o que uma SCP concede (nada) do que ela restringe (o teto disponível).
- Provar, com o mesmo comando em duas contas diferentes, que o resultado diverge.
- Provisionar duas OUs e anexar uma SCP que nega ações destrutivas só em uma delas.
- Justificar por que a conta de gestão nunca é restringida por SCP, e o que isso implica sobre onde ela pode ser usada.
- Configurar um caminho de quebra-vidro que sobrevive à própria trava que ele contorna.
- Conceder acesso humano por Identity Center, sem criar usuário IAM de longa duração.
- Diagnosticar por que uma SCP "não está funcionando" a partir de três causas distintas.
- Decidir quando duas OUs bastam, e quando a estrutura organizacional precisa crescer.
O que a certificação cobra disto
| Conceito | Certificação | Como aparece aqui | O que dominar |
|---|---|---|---|
| Unidade organizacional (OU) | SAA-C03, SAP-C02 | duas OUs: Não-Produção e Produção | que SCP se herda pela árvore de OUs, de pai para filho |
| Service Control Policy (SCP) | SAA-C03, SAP-C02, SCS-C02 | Deny explícito anexado só na OU Produção | que SCP só RESTRINGE, nunca concede; o resultado final é interseção com o IAM |
| Conta de gestão (management account) | SAP-C02, SCS-C02 | a conta que provisiona a organização inteira | que SCP nunca se aplica a ela, mesmo anexada na raiz |
| Landing zone / Control Tower | SAP-C02, DOP-C02 | Security OU com contas de Log Archive e Audit | a diferença entre provisionar manualmente e usar o Account Factory |
| IAM Identity Center (permission sets) | SAA-C03, SAP-C02, SCS-C02 | o mesmo permission set atribuído nas duas contas | que Identity Center concede, como o IAM; não restringe, como a SCP |
| Interseção de políticas | SCS-C02, DOP-C02 | provado com iam:SimulatePrincipalPolicy | que um Allow final exige Allow em TODAS as camadas aplicáveis, sem exceção |
| Explicit Deny sempre vence | todas as trilhas com componente de segurança | SCP nega mesmo com AdministratorAccess concedido | a ordem de avaliação: Deny explícito supera Allow, em qualquer camada |
| Guardrails preventivos vs. detectivos | SAP-C02, DOP-C02 | SCP é preventivo; CloudTrail e Config no Log Archive são detectivos | a diferença entre impedir a ação e perceber que ela foi tentada |
Onde isto costuma ser cobrado errado
A pergunta clássica dá um usuário com `AdministratorAccess` numa conta cuja OU tem uma SCP negando uma ação específica, e pede o resultado. Quem responde "permitido, porque AdministratorAccess vence" está aplicando um modelo de prioridade entre políticas que não existe: SCP e IAM não competem, o resultado é sempre a interseção, e Deny explícito em qualquer uma delas já basta para negar.
Requisitos, e como cada um muda o desenho
Requisito que não muda uma linha do desenho é intenção, não requisito. A coluna da direita é onde cada um deixou marca concreta.
| Requisito | Valor declarado | O que ele decide no desenho |
|---|---|---|
| Erro de ambiente-alvo não pode alcançar produção | obrigatório | força fronteira de CONTA, não de policy: SCP na OU Produção, independente do que o IAM concede |
| Nenhuma trava pode ficar sem saída em incidente real | obrigatório | exige role de quebra-vidro com exceção explícita na condition da SCP |
| Auditoria centralizada, que a conta auditada não controla | obrigatório | conta Log Archive separada, provisionada pelo Control Tower, fora do alcance de quem opera |
| Acesso humano sem usuário IAM de longa duração | obrigatório | Identity Center com permission sets por conta, não access key nem usuário IAM local |
| Orçamento de duas pessoas de plataforma, sem equipe dedicada de governança | restrição | apenas duas OUs — o mínimo viável, não uma OU por serviço ou por desenvolvedor |
| Provisionamento de conta não pode ser processo manual esquecível | obrigatório | Account Factory do Control Tower, nunca `aws_organizations_account` criado solto |
| Produção não pode ficar bloqueada de toda ação administrativa em emergência | obrigatório | a SCP nega uma lista curta e específica de ações, nunca um `Deny` genérico com `Action: "*"` |
Arquitetura mínima: uma conta, e o nome como única fronteira
Este é o desenho que a Cadência tem hoje, e ele é legítimo como ponto de partida: uma conta é menos para administrar, menos para pagar, menos login para lembrar. O laboratório começa por tornar o defeito discutível com um comando, em vez de deixá-lo como "quase aconteceu".
- → assume a única role de operação existente
- → rds:DeleteDBInstance permitido, Resource casa por prefixo
- → o MESMO allow, porque cadencia-* também casa com cadencia-prod
- Fora da AWS
- Segurança e identidade
- Banco de dados
Este desenho é o que a Cadência tem hoje, e ele funciona até alguém errar o ambiente-alvo de um comando. Repare que não existe nenhuma linha entre "desenvolvimento" e "produção" neste diagrama além do texto dentro da caixa — e texto dentro da caixa não é aplicado por nada.
- Uma política, pensada só para o ambiente de dev. A política foi escrita com `Resource: arn:aws:rds:*:*:db:cadencia-*`, na intenção de restringir a ação a bancos de desenvolvimento. Quem a escreveu pensou em "cadencia" como o nome do projeto, não como um prefixo que os dois ambientes compartilham.
- cadencia-dev: o alvo que a política pretendia autorizar. Aqui o wildcard funciona exatamente como planejado: o comando atinge o banco de desenvolvimento, e um erro ali é barato — é para isso que ele existe.
- cadencia-prod: o alvo que ela também autoriza, sem ninguém pedir. O mesmo `cadencia-*` casa com `cadencia-prod` porque os dois nomes compartilham o prefixo do projeto. Não é um bug de digitação na policy: é o comportamento correto e documentado de um wildcard de prefixo, aplicado a um par de nomes que não foi desenhado para ser discriminado por prefixo.
- Nenhuma fronteira de conta contém o erro. Se o comando usar a variável de ambiente errada — `$DB_ID` apontando para "prod" em vez de "dev" — a chamada chega até a AWS com uma identidade que TEM permissão de executá-la. Não há um segundo portão perguntando "isto é mesmo produção?": a policy já respondeu sim antes de a pergunta existir.
- Por que a Cadência monta assim. Uma conta é uma linha no cartão de crédito e um e-mail de cadastro; duas seriam duas de cada, mais um segundo login para lembrar. Com duas pessoas de plataforma e um prazo, "uma role com wildcard de prefixo" é a menor quantidade de configuração que parece resolver o problema — até resolver o problema errado.
O comando abaixo não apaga nada: ele pergunta à própria AWS se a ação seria permitida, contra o recurso de produção, usando a role de operação real. É a prova mais barata que existe para um risco que ninguém quer provar apagando o banco de verdade.
# Nao apaga nada. So pergunta: "esta role poderia apagar cadencia-prod?"
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::111122223333:role/OperacaoCadencia \
--action-names rds:DeleteDBInstance \
--resource-arns arn:aws:rds:us-east-1:111122223333:db:cadencia-prod \
--query "EvaluationResults[0].EvalDecision" --output text
# Na conta unica de hoje: "allowed". A policy que foi escrita para cobrir
# "qualquer banco de dev" cobre tambem "qualquer banco que comece com cadencia-".O wildcard de prefixo não sabe o que é produção
`Resource: arn:aws:rds:*:*:db:cadencia-*` foi escrito para restringir a ação a bancos de desenvolvimento, e restringe exatamente o que o texto diz: qualquer recurso cujo nome comece com `cadencia-`. `cadencia-prod` cumpre essa condição tão bem quanto `cadencia-dev`. Isso não é um erro de digitação corrigível — é o comportamento correto de um wildcard aplicado a dois nomes que compartilham prefixo. Nenhuma revisão de policy elimina esse risco em uma conta só; só a fronteira de conta elimina.
Arquitetura para produção: duas contas, duas OUs
Cada peça nova abaixo rastreia a uma linha da tabela de requisitos. O permission set de operação não muda — de propósito: a prova que este laboratório entrega é que a fronteira funciona mesmo com o IAM idêntico nas duas contas.
- → provisiona conta via Account Factory e registra nos guardrails
- → publica a SCP só na OU Produção
- → toda conta-membro replica CloudTrail para cá, por padrão do Control Tower
- → login federado, permission set Operador
- → o MESMO login federado, o mesmo permission set
- → rds:DeleteDBInstance concedido, sem teto de SCP acima
- → rds:DeleteDBInstance concedido pelo IAM...
- → ...e negado antes de chegar, pela SCP da OU
- Fora da AWS
- Segurança e identidade
- Gestão e governança
- Banco de dados
Cada peça nova aqui rastreia a um requisito da seção anterior. A diferença estrutural em relação ao desenho anterior não é uma caixa a mais: é que "Não-Produção" e "Produção" deixam de ser um texto dentro do nome do recurso e passam a ser uma fronteira que a própria AWS aplica, na camada abaixo do IAM.
- Control Tower provisiona; Organizations é a árvore que ele usa. O Account Factory do Control Tower cria a conta-membro e, no mesmo processo, a registra nos guardrails da landing zone. Uma conta criada fora dele existe na árvore de Organizations, mas não tem os guardrails detectivos nem os baselines que o Control Tower normalmente garante.
- A SCP mora na OU, não numa conta isolada. Anexar a policy na OU Produção, e não em cada conta individualmente, significa que toda conta futura que entrar ali herda a trava automaticamente — sem exigir um passo manual extra que alguém pode esquecer no dia em que a organização crescer.
- O mesmo permission set, nas duas contas. Este é o ponto que a maioria erra: o Identity Center concede a MESMA coisa nas duas contas de propósito. O laboratório não prova que "produção tem uma policy mais restrita" — prova que a fronteira funciona mesmo quando a policy é idêntica, porque a proteção não está na policy.
- Em Não-Produção, o IAM decide sozinho. Sem SCP nesta OU, o resultado da chamada é exatamente o que a policy do permission set concede. É o comportamento padrão de qualquer conta AWS sem Organizations — e é legítimo aqui, porque um erro em dev é barato.
- Em Produção, o IAM concederia a mesma coisa.... O permission set não mudou. Se você olhasse só a política de identidade, concluiria — corretamente — que a ação é permitida. É exatamente por isso que a proteção não pode depender só desta camada.
- ...mas a SCP nega antes de a pergunta chegar ao IAM. A avaliação de SCP acontece antes da avaliação de IAM, e um Deny explícito nela decide o resultado sozinho, sem precisar "vencer" a policy de identidade. O IAM nunca chega a ser consultado sobre esta chamada especificamente.
- A trilha de auditoria não mora na conta que ela audita. Mesmo a tentativa NEGADA fica registrada — na conta Log Archive, que a conta de Produção não controla. Um operador comprometido na conta de Produção não consegue apagar essa evidência, porque ela nunca esteve lá.
A diferença estrutural em relação ao desenho anterior não é uma conta a mais: é que "Produção" deixa de ser um prefixo de nome dentro de uma conta compartilhada e passa a ser uma fronteira que a própria AWS aplica, numa camada abaixo — e anterior — ao IAM.
O que NÃO precisou mudar, e por que isso importa
O permission set `Operador` continua concedendo `rds:DeleteDBInstance` nas duas contas. Isso não é descuido: é a demonstração de que a proteção não depende de lembrar de escrever uma policy IAM diferente para produção — ela vem de uma camada que existe independentemente de quão bem ou mal a policy de identidade foi escrita.
Como uma chamada é avaliada, ponta a ponta
A ordem de avaliação não é jargão de prova de certificação: é o que explica por que duas contas com o mesmo permission set produzem resultados diferentes para o mesmo comando. SCP é avaliada antes do IAM, e um Deny nela nunca precisa "disputar prioridade" com um Allow do IAM — a chamada nem chega lá.
A consequência que mais surpreende quem vem de uma conta só
Um Deny explícito de SCP não é "mais forte" que um Allow do IAM no sentido de vencer uma disputa — os dois nunca disputam. O resultado é sempre a interseção: só é permitido o que SOBRA depois de aplicar as duas camadas. Isso significa que uma SCP não pode conceder nada que o IAM já não conceda; ela só pode tirar. Um erro comum é anexar uma SCP e esperar que ela "libere" alguma ação — SCP não tem Allow que signifique concessão real; o Allow dela só amplia o teto disponível, quem concede a ação de fato continua sendo o IAM.
O que aparece no CloudTrail da conta de Producao quando a SCP nega a chamada. A tentativa fica registrada mesmo tendo sido bloqueada -- e fica na conta Log Archive, fora do alcance de quem operou a chamada.
{
"eventSource": "rds.amazonaws.com",
"eventName": "DeleteDBInstance",
"awsRegion": "us-east-1",
"errorCode": "AccessDenied",
"errorMessage": "User: arn:aws:sts::333333333333:assumed-role/Operador/sessao is not authorized to perform: rds:DeleteDBInstance with an explicit deny in a service control policy",
"requestParameters": {
"dBInstanceIdentifier": "cadencia-prod"
},
"recipientAccountId": "333333333333"
}As decisões, e o que se perde em cada uma
📋 A Cadência cresceu para quatro desenvolvedores, todos com acesso de operação na mesma conta que hospeda o RDS de produção do L03. Um comando com a variável de ambiente errada já quase apagou o banco errado — só não apagou porque alguém percebeu a tempo de cancelar.
O erro que quase aconteceu não foi de digitação corrigível com mais atenção: foi estrutural, porque uma única conta não tem como conter um comando que a policy IAM já autorizou. SCP resolve isso sem exigir reescrever nenhuma policy existente — o permission set do Identity Center continua o mesmo nas duas contas, e a proteção vem de uma camada que nenhuma equipe de duas pessoas de plataforma precisa reinventar por conta própria. Não é preciso uma conta por serviço: duas OUs bastam para a fronteira que importa, que é entre onde se experimenta e onde o cliente real está.
Alt: Policy IAM ainda mais restrita, na mesma conta — Reduz a área do erro, não a elimina: qualquer wildcard de prefixo que sirva para nomear "cadencia-dev-1", "cadencia-dev-2" etc. corre o mesmo risco de casar com um nome de produção que compartilhe o prefixo. Apertar a mira ajuda; não é uma fronteira.
Alt: Uma conta por serviço ou por desenvolvedor — Multiplica custo fixo — NAT Gateway, endpoint de VPC, log group — por conta nova, sem reduzir o risco que motivou a mudança. É otimização de organização grande, prematura para duas pessoas de plataforma.
Alt: Tags de recurso mais IAM condition (aws:ResourceTag) — Depende de todo recurso estar corretamente tagueado para sempre; um único recurso criado sem a tag reabre exatamente o buraco que a condição tentava fechar, e ninguém percebe até o incidente.
Alt: Só reforçar backup e snapshot automático — Encurta o tempo de recuperação depois do erro; não impede o erro de acontecer. Uma restauração de RDS ainda é minutos de indisponibilidade e um incidente registrado — comparado a uma ação que simplesmente não executa.
| Decisão | Escolha | Alternativas | Motivo | O que se perde |
|---|---|---|---|---|
| Número de contas | duas: Não-Produção e Produção | uma conta por serviço; uma por desenvolvedor; três com uma de homologação | resolve o risco declarado com o menor número de contas a administrar | ambiente de homologação convive com dev por enquanto, dentro da mesma OU |
| Onde a SCP é anexada | na OU Produção, não em cada conta | anexar em cada conta individualmente | toda conta futura naquela OU herda a trava sem passo manual extra | depurar exige olhar toda a árvore de OUs no caminho, não só a conta |
| Como provisionar a conta nova | Account Factory do Control Tower | `aws_organizations_account` direto no Terraform | a conta nasce já registrada nos guardrails detectivos da landing zone | menos controle imediato via código; o provisionamento passa por um produto do Service Catalog |
| Acesso humano | Identity Center, permission set único nas duas contas | usuário IAM local por conta; access key de longa duração | prova que a fronteira não depende de policy diferente por ambiente | exige que o Identity Center esteja habilitado e configurado corretamente na organização |
| Escopo da SCP | lista curta de ações destrutivas específicas | `Deny` amplo com `Action: "rds:*"` ou `Action: "*"` | não bloqueia leitura, backup nem ação administrativa legítima em emergência | exige revisar a lista quando uma ação destrutiva nova for identificada |
| Caminho de exceção | role de quebra-vidro nomeada, na condition da SCP | nenhuma exceção; ou desanexar a SCP manualmente quando preciso | incidente real tem saída sem remover a proteção inteira | a role de quebra-vidro vira, ela mesma, um alvo que precisa de proteção extra |
A dívida que este módulo não paga
A conta de gestão da organização concentra poder de administrar toda a árvore de OUs e, por definição, não é restringida por nenhuma SCP. Este laboratório não resolve quem pode acessá-la nem como — trata isso na seção de segurança, mas a resposta completa (MFA de hardware obrigatório, número mínimo de pessoas, acesso de emergência auditado) é assunto mais amplo de governança organizacional.
Construir: a organização e as duas OUs
A organização precisa existir antes de qualquer SCP, e o modo de recursos precisa ser `ALL` — no modo de faturamento consolidado, a API de política nem aceita a chamada de anexar SCP.
# organizacao.tf — a arvore que uma SCP precisa para existir
resource "aws_organizations_organization" "cadencia" {
# SCP so existe no modo "ALL" (todos os recursos habilitados). No modo de
# faturamento consolidado (CONSOLIDATED_BILLING, o padrao de quem so queria
# juntar a fatura de duas contas) a API de policy nem aceita anexar SCP —
# e a mudanca de modo, uma vez feita, nao tem caminho de volta.
feature_set = "ALL"
enabled_policy_types = [
"SERVICE_CONTROL_POLICY",
]
# Habilita a integracao de servico com Control Tower, Identity Center e
# CloudTrail organizacional. Sem isto, cada um desses servicos so enxerga
# a propria conta, nao a arvore inteira.
aws_service_access_principals = [
"controltower.amazonaws.com",
"sso.amazonaws.com",
"cloudtrail.amazonaws.com",
]
}
resource "aws_organizations_organizational_unit" "nao_producao" {
name = "Não-Produção"
parent_id = aws_organizations_organization.cadencia.roots[0].id
}
resource "aws_organizations_organizational_unit" "producao" {
name = "Produção"
parent_id = aws_organizations_organization.cadencia.roots[0].id
}
# NAO crie a conta-membro com `aws_organizations_account` direto quando o
# Control Tower administra a landing zone: a conta nasceria fora do radar do
# Account Factory, sem os guardrails detectivos nem os baselines que o
# Control Tower normalmente aplica no provisionamento. O caminho certo e o
# Account Factory (console ou o produto do Service Catalog que ele publica) —
# ou, em escala maior, o Account Factory for Terraform (AFT), fora do escopo
# deste laboratorio de duas contas.
output "ou_producao_id" {
value = aws_organizations_organizational_unit.producao.id
description = "id da OU onde a SCP deste modulo e anexada"
}
A mudança de modo não tem volta simples
Migrar uma organização já existente de faturamento consolidado para "todos os recursos" é uma ação com processo próprio da AWS, incluindo aceite formal de cada conta-membro. Se você está criando a organização do zero para este laboratório, isso não se aplica; se está adaptando uma organização de faturamento já existente, planeje esse passo separadamente antes de continuar.
Construir: a SCP que veta mesmo com o IAM permitindo
Esta é a peça central do módulo. Ela não substitui a política do Identity Center — convive com ela, e é a interseção das duas que decide o resultado final.
# scp-producao.tf — o teto. Ele nao concede nada; so recorta o que o IAM concede.
data "aws_iam_policy_document" "nega_destrutivo_prod" {
# A policy padrao FullAWSAccess continua anexada: uma SCP e uma politica
# ADICIONAL de Deny, ela nao substitui a permissiva que a AWS anexa por
# padrao a toda OU nova.
statement {
sid = "NegaExclusaoDeBancoEmProducao"
effect = "Deny"
actions = [
"rds:DeleteDBInstance",
"rds:DeleteDBCluster",
"rds:DeleteDBSnapshot",
"rds:DeleteDBClusterSnapshot",
]
# Resource "*" aqui e decisao, nao preguica: o objetivo e negar a ACAO em
# qualquer banco desta OU, sem depender de alguem lembrar de incluir o
# ARN de cada instancia nova na lista. Restringir por Resource exigiria
# atualizar a SCP a cada banco criado — o oposto de um teto confiavel.
resources = ["*"]
# A saida de emergencia: uma role de nome fixo, so para o incidente raro
# que exige apagar mesmo. Sem isto, o proprio time de plataforma fica
# preso pela propria trava — e a resposta previsivel sob pressao e
# desanexar a SCP inteira, o que remove a protecao de tudo que ela cobria.
condition {
test = "StringNotLike"
variable = "aws:PrincipalArn"
values = ["arn:aws:iam::*:role/QuebraVidroProducao"]
}
}
statement {
sid = "NegaSairDaOrganizacao"
effect = "Deny"
actions = ["organizations:LeaveOrganization"]
resources = ["*"]
# Sem isto, uma conta-membro pode se autorremover da organizacao — e
# levar consigo a unica fronteira que este laboratorio constroi.
}
}
resource "aws_organizations_policy" "nega_destrutivo_prod" {
name = "nega-acoes-destrutivas-producao"
description = "Teto para a OU Producao: nega exclusao de banco e saida da organizacao, mesmo com IAM AdministratorAccess"
type = "SERVICE_CONTROL_POLICY"
content = data.aws_iam_policy_document.nega_destrutivo_prod.json
}
resource "aws_organizations_policy_attachment" "producao" {
policy_id = aws_organizations_policy.nega_destrutivo_prod.id
target_id = aws_organizations_organizational_unit.producao.id
# Anexada na OU, nao na conta: toda conta que entrar aqui no futuro herda
# a trava sem exigir um passo manual extra que alguem pode esquecer.
}
O `Resource: "*"` desta SCP, e por que ele se justifica
A regra de menor privilégio pede Resource específico sempre que possível — mas aqui o objetivo é negar a AÇÃO em qualquer banco desta OU, presente ou futuro, sem depender de alguém lembrar de adicionar o ARN de cada instância nova numa lista. Restringir por Resource particular exigiria reeditar a SCP a cada banco criado, e um teto que precisa de manutenção manual a cada recurso novo deixa de ser um teto confiável.
Construir: acesso humano por Identity Center, não por usuário IAM
O mesmo permission set nas duas contas não é simplificação: é o que prova que a proteção não depende de reescrever a política de identidade por ambiente.
# identity-center.tf — o que o IAM concede, e por que ele pode continuar igual
data "aws_ssoadmin_instances" "this" {}
resource "aws_ssoadmin_permission_set" "operador" {
name = "Operador"
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
session_duration = "PT4H"
# O MESMO permission set e atribuido nas duas contas. E o ponto do
# laboratorio: a diferenca de comportamento entre elas vem da SCP anexada
# na OU, nao de uma policy IAM diferente por ambiente.
}
resource "aws_ssoadmin_managed_policy_attachment" "operador_rds" {
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
managed_policy_arn = "arn:aws:iam::aws:policy/AmazonRDSFullAccess"
permission_set_arn = aws_ssoadmin_permission_set.operador.arn
# Sim, FullAccess — de proposito. O laboratorio prova que a SCP contem o
# dano mesmo quando o IAM e generoso, que e o cenario realista: ninguem
# reaudita todo permission set toda semana.
}
resource "aws_ssoadmin_account_assignment" "operador_nao_producao" {
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
permission_set_arn = aws_ssoadmin_permission_set.operador.arn
principal_id = var.grupo_engenharia_id
principal_type = "GROUP"
target_id = var.conta_nao_producao_id
target_type = "AWS_ACCOUNT"
}
resource "aws_ssoadmin_account_assignment" "operador_producao" {
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
permission_set_arn = aws_ssoadmin_permission_set.operador.arn
principal_id = var.grupo_engenharia_id
principal_type = "GROUP"
target_id = var.conta_producao_id
target_type = "AWS_ACCOUNT"
}
Variáveis que este trecho pressupõe
`var.grupo_engenharia_id`, `var.conta_nao_producao_id` e `var.conta_producao_id` vêm de fora deste arquivo — o id do grupo do Identity Center e os ids de conta gerados pelo Account Factory na seção anterior. Não codifique esses valores fixos no módulo: eles mudam a cada ambiente que reusar este Terraform.
Construir: a ferramenta que prova a fronteira, em C#
Um utilitário de linha de comando que roda `iam:SimulatePrincipalPolicy` nas duas contas e imprime o resultado lado a lado — sem executar nenhuma chamada destrutiva de verdade.
// VerificadorFronteira/Program.cs — prova a fronteira sem tocar em dado real
//
// Chama iam:SimulatePrincipalPolicy nas duas contas, para a MESMA acao, e
// imprime lado a lado. Segundo a documentacao da AWS, o simulador avalia SCP
// com logica "consciente do servico" — por isso o resultado diverge entre as
// contas sem nenhuma chamada destrutiva de verdade ter sido executada.
using Amazon.IdentityManagement;
using Amazon.IdentityManagement.Model;
using Amazon.SecurityToken;
using Amazon.SecurityToken.Model;
var acoes = new List<string> { "rds:DeleteDBInstance", "rds:DeleteDBCluster" };
var contas = new[]
{
new { Nome = "Não-Produção", RoleArn = Ambiente("ROLE_NAO_PRODUCAO") },
new { Nome = "Produção", RoleArn = Ambiente("ROLE_PRODUCAO") },
};
foreach (var conta in contas)
{
// Assume a role NA CONTA ALVO — o simulador roda com as credenciais
// dessa conta, entao ele enxerga a SCP que se aplica especificamente a
// ela, e nao a de outra conta da organizacao.
using var sts = new AmazonSecurityTokenServiceClient();
var assumida = await sts.AssumeRoleAsync(new AssumeRoleRequest
{
RoleArn = conta.RoleArn,
RoleSessionName = "verificador-fronteira",
});
using var iam = new AmazonIdentityManagementServiceClient(
assumida.Credentials.AccessKeyId,
assumida.Credentials.SecretAccessKey,
assumida.Credentials.SessionToken);
var resposta = await iam.SimulatePrincipalPolicyAsync(new SimulatePrincipalPolicyRequest
{
PolicySourceArn = conta.RoleArn,
ActionNames = acoes,
// Recurso curinga: o alvo da prova e o TETO da conta, nao um banco
// especifico. Para provar contra um recurso real, troque por um ARN.
ResourceArns = new List<string> { "*" },
});
Console.WriteLine($"— {conta.Nome} —");
foreach (var resultado in resposta.EvaluationResults)
{
// EvalDecision vem como "allowed", "explicitDeny" ou "implicitDeny".
// Na conta de Producao, espera-se explicitDeny — a SCP se
// manifestando, mesmo que a role tenha AmazonRDSFullAccess.
Console.WriteLine($" {resultado.EvalActionName}: {resultado.EvalDecision}");
}
}
static string Ambiente(string nome) =>
Environment.GetEnvironmentVariable(nome)
?? throw new InvalidOperationException($"defina a variável {nome} com o ARN da role a testar");
O que o simulador enxerga, e o que ele esconde
O simulador de políticas do IAM avalia identidade, limite de permissão e as SCPs aplicáveis à conta da role simulada, com lógica consciente do serviço — é por isso que o resultado diverge entre as contas sem uma chamada real. A ressalva documentada: por segurança, ele não expõe qual statement específico de uma SCP causou a negação, só o resultado final. Para achar QUAL policy negou, o caminho é ler o conteúdo de cada SCP anexada manualmente.
Implantar, e provar com o mesmo comando nos dois ambientes
Cinco provas. Nenhuma aceita "parece que funcionou" como resultado — cada uma tem um estado esperado, e a quinta é a que mais gente pula por parecer óbvia demais para testar.
| Prova | Comando | Resultado que aprova | O que reprova, e o que significa |
|---|---|---|---|
| 1 · A ferramenta diverge entre contas | rodar `VerificadorFronteira` com as duas roles | `allowed` em Não-Produção, `explicitDeny` em Produção, para as mesmas ações | se as duas derem `allowed`, a SCP não está anexada onde deveria — confira a OU alvo |
| 2 · O comando real funciona em Não-Produção | excluir um RDS descartável criado só para o teste | a instância entra em `deleting` | se falhar, o permission set não tem `rds:DeleteDBInstance` — confira o `AmazonRDSFullAccess` anexado |
| 3 · O MESMO comando falha em Produção | excluir o RDS descartável equivalente, na conta de Produção | erro `AccessDenied` citando SCP explicitamente | se excluir de verdade, a SCP não está ativa nesta conta — é o incidente que este módulo existe para evitar |
| 4 · A tentativa negada fica auditável | consultar CloudTrail na conta Log Archive | o evento `DeleteDBInstance` aparece, com `errorCode: AccessDenied` | se não aparecer, a integração de CloudTrail organizacional para o Log Archive não está ativa |
| 5 · A conta de gestão está mesmo fora do alcance da SCP | rodar a mesma simulação com uma role da conta de gestão | `allowed`, mesmo com a SCP anexada na OU Produção | este resultado é o ESPERADO — prova a exceção da conta de gestão, não uma falha de configuração |
# Provas 2 e 3: crie DUAS instancias RDS descartaveis, uma por conta, so para o
# teste -- t3.micro, sem Multi-AZ, sem snapshot final. NAO aponte para um banco
# que tenha dado de verdade.
# ── Prova 2: sucede em Nao-Producao ──────────────────────────────────────────
aws rds delete-db-instance --db-instance-identifier teste-fronteira \
--skip-final-snapshot --profile nao-producao
# Esperado: "DBInstanceStatus": "deleting"
# ── Prova 3: falha em Producao, com o MESMO comando ──────────────────────────
aws rds delete-db-instance --db-instance-identifier teste-fronteira \
--skip-final-snapshot --profile producao
# Esperado: erro AccessDenied mencionando "service control policy"
# ── Prova 4: a tentativa negada e auditavel na conta que nao operou a chamada ─
aws cloudtrail lookup-events --profile log-archive \
--lookup-attributes AttributeKey=EventName,AttributeValue=DeleteDBInstance \
--query "Events[?contains(CloudTrailEvent, 'AccessDenied')]"
# ── Prova 5: a conta de gestao esta fora do alcance, de proposito ────────────
aws iam simulate-principal-policy --profile gestao \
--policy-source-arn arn:aws:iam::111100002222:role/AdministradorGestao \
--action-names rds:DeleteDBInstance \
--resource-arns "*" --query "EvaluationResults[0].EvalDecision" --output textAs instâncias das provas 2 e 3 são descartáveis, e isso não é opcional
Rode as provas 2 e 3 contra um banco criado só para este teste, nunca contra um recurso com dado real — a prova 2 EXCLUI de verdade. `--skip-final-snapshot` acelera o teste e também significa que não há como recuperar essa instância depois. Confirme o `--profile` antes de apertar Enter: é exatamente o erro de ambiente-alvo que este laboratório existe para conter, e a prova que o comprova não pode, ela mesma, ser esse erro.
Quebrar de propósito: três falhas e o diagnóstico
As três se parecem no sintoma superficial — "a SCP deveria ter feito algo e não fez", ou o oposto. O que as separa é onde se olha primeiro.
| Falha | Como provocar | Sintoma | Onde olhar | Correção |
|---|---|---|---|---|
| SCP sem efeito nenhum | anexe a SCP na OU Não-Produção por engano, deixando a de Produção sem nenhuma | a prova 3 sucede quando deveria falhar: o comando real apaga o banco de produção | `list-policies-for-target` no id da conta ou OU de Produção retorna vazio | reanexar a policy no `target_id` da OU Produção, não da Não-Produção |
| `terraform apply` falha ao criar a SCP | tente aplicar numa organização ainda em modo `CONSOLIDATED_BILLING` | erro da API recusando o tipo de política | `aws organizations describe-organization` → campo `FeatureSet` | migrar a organização para `ALL` antes de tentar anexar qualquer SCP |
| Time de plataforma fica preso, sem conseguir nem corrigir a própria SCP | escreva a `condition` da exceção com o ARN errado, ou sem a role de quebra-vidro criada | toda tentativa de correção, inclusive pela própria role de quebra-vidro, é negada | teste a role de quebra-vidro FORA de incidente, comparando o ARN da condition com o ARN real da role | corrigir o ARN na `condition`, ou criar a role de quebra-vidro que ainda não existia |
A falha que não aparece em nenhum teste automatizado
Uma SCP com `Deny` amplo demais — por exemplo `Action: "rds:*"` em vez da lista curta de ações destrutivas — bloqueia também leitura, tag e backup legítimos em produção. Isso não quebra o `terraform apply`, não aparece em nenhuma das cinco provas deste módulo, porque elas testam exatamente as ações que deveriam ser negadas. Só aparece quando alguém tenta uma ação legítima, no meio de um incidente, e descobre que a SCP levou junto o que não devia.
Uma role em uma conta-membro tem a política gerenciada AdministratorAccess anexada. A OU dessa conta tem uma SCP com `Effect: Deny` para `rds:DeleteDBInstance`, sem exceção. O que acontece quando essa role tenta apagar um banco RDS?
Segurança: o que protege a fronteira que acabamos de construir
A fronteira entre contas é mais forte que qualquer policy — e por isso quem consegue contorná-la (a conta de gestão, ou a role de quebra-vidro) passa a concentrar o risco que antes estava espalhado por toda a policy IAM.
| Risco | Probabilidade | Impacto | Controle preventivo | Detecção | Resposta |
|---|---|---|---|---|---|
| Conta de gestão usada para carga de trabalho do dia a dia | média | alto | nunca hospedar recurso de aplicação nela; acesso restrito a quem administra a organização | CloudTrail na própria conta de gestão, alarme para qualquer ação de escrita fora de Organizations/billing | revisar quem tem acesso e por quê; mover qualquer carga de trabalho encontrada |
| SCP mal escrita bloqueia ação legítima do próprio time de plataforma | média | médio | testar toda SCP nova numa OU isolada antes de aplicar em Produção; usar o simulador antes do `apply` | aumento de tickets "AccessDenied inesperado" logo após uma mudança de SCP | usar a role de quebra-vidro da conta de gestão para corrigir ou desanexar |
| Role de quebra-vidro comprometida | baixa | alto | MFA obrigatório na role, rotação periódica, aprovação humana para uso | alarme dedicado em CloudTrail para todo `AssumeRole` desta role específica | revogar a sessão, investigar o uso, rotacionar a role |
| Conta criada fora do Account Factory, sem guardrails registrados | média | médio | provisionar só via Account Factory ou AFT; proibir `aws_organizations_account` direto | comparar `list-managed-accounts` (Control Tower) com `organizations list-accounts` | registrar (enroll) a conta retroativamente nos guardrails |
| Permission set com permissão ampla demais, sem SCP correspondente em OU nova | média | alto | nova OU herda de um baseline com SCP mínima aplicada por padrão de organização | auditoria periódica de `list-policies-for-target` em toda OU | aplicar a SCP baseline retroativamente antes de mover qualquer conta para dentro |
| Conta Log Archive comprometida ou com trilha alterada | baixa | alto | bucket com versionamento e SCP negando exclusão, inclusive para administradores locais dessa conta | alarme de integridade sobre o bucket de CloudTrail | restaurar de versão anterior do objeto; investigar a causa do acesso |
Observabilidade: as perguntas que a governança precisa responder
Um painel de fronteira multi-conta tem função estreita: dizer se a árvore de OUs continua sendo o que o Terraform declara que ela é. Deriva sozinho, sem alarme, é o defeito mais comum desta camada.
| Pergunta | Métrica ou consulta | O que significa mudar | Limiar inicial |
|---|---|---|---|
| Alguém tentou uma ação que a SCP negou? | CloudTrail, `errorCode = AccessDenied` com menção a SCP | tentativa legítima sendo barrada, ou tentativa de contornar o teto | qualquer ocorrência, sempre revisada |
| Toda conta está dentro de uma OU coberta por SCP? | `list-accounts-for-parent` comparado à lista total de contas | conta órfã, fora de qualquer OU com teto | zero contas fora de uma OU coberta |
| A conta de gestão está sendo usada para carga de trabalho? | CloudTrail na conta de gestão, ações fora de Organizations/billing | uso indevido da única conta sem SCP | qualquer ação de escrita fora do esperado |
| O quebra-vidro foi usado? | CloudTrail, `AssumeRole` da role `QuebraVidroProducao` | incidente real, ou teste programado | qualquer uso, sempre revisado manualmente |
| As SCPs continuam anexadas onde o Terraform declara? | `list-policies-for-target` periódico contra o estado do Terraform | drift de governança — alguém alterou fora do código | qualquer divergência |
| Toda conta da Organization está registrada no Control Tower? | comparar `list-managed-accounts` com `organizations list-accounts` | conta que escapou do Account Factory | diferença maior que zero |
A métrica que não existe, e por que sua ausência é o ponto
Não existe um "alarme de tentativa de exclusão negada com sucesso": o próprio silêncio na conta de produção — nenhum evento `DeleteDBInstance` bem-sucedido no CloudTrail dela — é o sinal positivo. O painel certo aqui mede AUSÊNCIA de um tipo de evento, não presença, e é fácil esquecer de alarmar sobre algo que nunca deveria acontecer.
Escala: 2 contas, 10, 50 e a falha de uma conta inteira
| Situação | O que acontece com a governança | O que passa a doer | O que fazer |
|---|---|---|---|
| 2 contas, 2 OUs | gestão manual de SCP e OU é razoável | nada; é o cenário deste laboratório | nada |
| 5 equipes, 10 contas | cada equipe cruza ambiente × produto | uma SCP por ambiente pode não bastar quando uma equipe precisa de exceção que outra não precisa | sub-OUs por equipe dentro de cada ambiente, com SCP herdada mais exceções específicas |
| 50 contas | criação e SCP geridas manualmente não escalam mais | drift entre o que o Terraform declara e o que existe de fato na organização | Account Factory for Terraform (AFT): todo provisionamento sai de um repositório único, com revisão |
| Centenas de contas, múltiplas unidades de negócio | a árvore de OUs cresce em profundidade, não só em largura | SCP restringe identidade; um recurso ainda pode ser alcançado por credencial externa à organização | complementar com Resource Control Policies (RCP), que restringem o RECURSO, não a identidade |
| Falha ou comprometimento de uma conta inteira | a conta é a unidade de blast radius, não a AZ | uma conta comprometida não deve vazar para outra — é o teste real da fronteira | confirmar que a conta comprometida não tem via de acesso direta às demais além do que a SCP e o IAM explicitamente permitem |
| Quebra-vidro precisa ser usado em incidente com múltiplas contas ao mesmo tempo | o caminho manual de exceção não escala sob pressão | decisão de exceção feita às pressas, sem trilha clara | automatizar a concessão temporária de quebra-vidro, com aprovação e expiração automática |
O gargalo que só aparece com muitas contas
Cada conta nova, se replicar a topologia de rede do L01/L02 sem revisão, duplica NAT Gateway e endpoint de VPC — infraestrutura fixa que cobra por hora, ligada, independente de tráfego. Governança de conta resolve o risco de identidade; não resolve, sozinha, o custo de rede repetido — isso é rede compartilhada entre contas, assunto de outro laboratório desta série.
Custo: o que multi-conta acrescenta à fatura
Organizations, OUs e SCP não têm custo direto — a AWS não cobra por política nem por unidade organizacional. O que cobra é o que cada conta nova replica.
| Cenário | Volume | O que acrescenta | Tendência | Otimização |
|---|---|---|---|---|
| Protótipo | 2 contas, sem carga real ainda | CloudTrail e Config organizacionais em duas contas pequenas | desprezível | nenhuma; otimizar aqui é gastar atenção onde não há fatura relevante |
| Produção pequena | 2 a 5 contas, cada uma com sua própria VPC do L01 | NAT Gateway, Elastic IP e endpoints de VPC multiplicados por conta | cresce linearmente com o número de contas | avaliar rede compartilhada via Transit Gateway entre contas que não precisam de isolamento total de rede |
| Alta escala | dezenas de contas | Config rules e GuardDuty organizacional cobrando por conta monitorada, mais o armazenamento crescente do Log Archive | custo fixo por conta passa a dominar a linha de governança | ciclo de vida de log no Log Archive; revisar contas realmente ativas periodicamente |
| Dimensão | Cobra por | Cuidado |
|---|---|---|
| AWS Organizations, OUs, SCP | nada — sem custo direto | não é o lugar de otimizar |
| Control Tower | nada pelo serviço em si | os recursos que ele provisiona por conta (Config, CloudTrail, S3) cobram separadamente |
| CloudTrail organizacional | eventos de gestão, geralmente incluídos no nível gratuito por conta | trilhas de dados (S3 object-level, por exemplo) cobram por evento e crescem rápido em conta com muito tráfego |
| Armazenamento no Log Archive | GB-mês de log retido de TODAS as contas | sem política de ciclo de vida, cresce sem teto — é o mesmo erro do L03, agora multiplicado por conta |
| Infraestrutura de rede duplicada por conta | hora ligada de NAT Gateway, Elastic IP ocioso | é o custo oculto real desta arquitetura: cada conta nova que replica a VPC do L01 sem revisão soma uma linha fixa |
O ganho de custo que não aparece na fatura da AWS
O incidente que quase aconteceu na abertura deste módulo — apagar o banco errado — teria custado horas de restauração, indisponibilidade de clientes reais e o tempo de reconstruir confiança. Nenhuma dessas horas aparece como linha de fatura da AWS, mas são exatamente o que a fronteira de conta compra.
Well-Architected nos seis pilares
| Pilar | Situação ao fim deste laboratório | Risco que fica | Melhoria | Prioridade |
|---|---|---|---|---|
| Excelência operacional | duas OUs provisionadas e testadas por medição, não por afirmação | criar conta nova ainda pode escapar do Account Factory se alguém usar o console diretamente | Account Factory for Terraform (AFT) como único caminho de provisionamento | alta |
| Segurança | SCP nega ação destrutiva independente do IAM; Identity Center substitui usuário IAM de longa duração | conta de gestão sem MFA de hardware obrigatório para todo humano com acesso | exigir MFA de hardware na conta de gestão e restringir o número de pessoas com acesso | alta |
| Confiabilidade | erro de ambiente-alvo não alcança mais produção | quebra-vidro mal testado deixa incidente real sem saída | exercício periódico (game day) do caminho de exceção, fora de incidente real | alta |
| Eficiência de performance | nenhuma mudança de performance de aplicação neste laboratório | nenhum risco novo introduzido nesta dimensão | não se aplica a este módulo | baixa |
| Otimização de custos | Organizations e SCP são gratuitos; nenhum recurso pago novo por si só | cada conta nova duplica infraestrutura fixa se replicar a topologia do L01 sem revisão | rede compartilhada entre contas que não precisam de isolamento total | média |
| Sustentabilidade | nenhum recurso computacional novo relevante introduzido | contas órfãs esquecidas continuam consumindo recursos residuais indefinidamente | revisão periódica de contas ativas versus contas realmente necessárias | baixa |
Evolução em níveis: de uma conta a uma plataforma multi-conta
A terceira arquitetura não é um desenho: é a resposta a QUANDO a estrutura de duas OUs deixa de bastar. Cada nível resolve um risco e compra outro — e é a segunda coluna que raramente se escreve.
Uma conta só, dev e produção separados por convenção de nome. É onde a Cadência estava, e continua legítimo para um projeto pessoal ou uma prova de conceito de fim de semana.Duas contas, duas OUs, uma SCP negando ação destrutiva na OU de Produção, landing zone provisionada por Control Tower.OUs por equipe dentro de cada ambiente (Produção/Equipe-A, Produção/Equipe-B), com SCPs que herdam da OU-mãe e adicionam exceções específicas por equipe.Account Factory for Terraform (AFT) substitui a criação manual de conta; todo provisionamento — conta, SCP, permission set — sai de um repositório versionado, com revisão obrigatória.Resource Control Policies (RCP) complementam a SCP: onde a SCP restringe o que uma IDENTIDADE pode fazer, a RCP restringe o acesso a um RECURSO, mesmo vindo de fora da organização.Uma OU dedicada a dados e IA, com SCP restringindo em quais regiões um modelo do Bedrock pode ser invocado e proibindo que dado de treinamento saia da conta de dados para qualquer outra.A ordem não é negociável, e o motivo é concreto
RCP no nível 5 pressupõe uma organização que já sabe operar SCP com disciplina — adicionar uma segunda camada de política antes de dominar a primeira multiplica a superfície de depuração sem multiplicar a proteção proporcionalmente. É a mesma lição do L03 sobre canário antes de ter identidade de imagem: a peça avançada depende da peça anterior estar sólida, não só presente.
Onde IA entra nesta arquitetura, e onde não entra
Neste módulo, IA não resolve o problema central, e forçá-la seria o antipadrão que a própria série critica. "Uma ação deve ou não ser permitida nesta conta" é uma pergunta com resposta determinística — SCP e IAM avaliam isso por regra explícita, não por inferência. Um modelo não melhora a interseção de duas políticas: ela já é exata.
Há um lugar onde IA acrescentaria valor real, e ele é modesto: ajudar a ESCREVER a lista certa de ações a negar. Hoje a lista de ações destrutivas da SCP deste módulo foi derivada manualmente, olhando o catálogo de ações do RDS. Um classificador treinado sobre o histórico de ações do serviço — quais são irreversíveis, quais têm `DryRun`, quais aparecem em runbooks de incidente como "a ação que causou o estrago" — poderia sugerir candidatas a entrar numa SCP nova, para revisão humana.
| Pergunta | Resposta honesta para este módulo |
|---|---|
| Qual problema a IA resolveria? | sugerir candidatas a ação destrutiva ao escrever uma SCP nova, para revisão humana |
| Por que uma regra não bastaria? | uma lista curada manualmente, como a deste módulo, já cobre o caso comum; IA ajudaria a não esquecer uma ação obscura, não a decidir sozinha |
| De onde viriam os dados? | o catálogo de ações de cada serviço AWS, cruzado com CloudTrail de incidentes passados — nenhum dos dois é dado sensível |
| Qual o risco? | sugerir uma ação de menos, dando falsa sensação de cobertura completa; ou uma ação de mais, negando algo legítimo — as duas exigem revisão humana antes de qualquer SCP nova ir para Produção |
| Por que não agora? | a Cadência tem uma SCP e um histórico de incidente; treinar ou avaliar um classificador sobre uma amostra dessas exige volume que ainda não existe |
O uso de IA que parece atraente e é armadilha aqui
Pedir a um modelo para "decidir, em tempo real, se esta chamada específica deveria ser permitida" substitui uma regra determinística e auditável por um julgamento probabilístico, exatamente na camada em que a certificação e a auditoria de segurança exigem previsibilidade total. SCP existe justamente para que a resposta seja sempre a mesma, para a mesma entrada — é a propriedade que qualquer sistema de IA teria que reconstruir do zero, e provavelmente pior.
Anti-padrões deste laboratório
| Anti-padrão | Por que alguém faz | Por que é problema | Sintoma em produção | Forma correta | Quando é aceitável |
|---|---|---|---|---|---|
| Usar a conta de gestão para hospedar carga de trabalho | ela já existe, e criar mais uma conta parece burocracia | SCP nunca alcança essa conta — nada nela tem o teto que este módulo constrói | "por que este recurso não tem a mesma proteção dos outros?" sem resposta boa | conta de gestão só administra a organização; carga de trabalho vai em conta-membro | nunca, em nenhuma escala |
| Copiar a mesma policy IAM em toda conta, achando que basta | funcionou na conta única, e Identity Center parece complexidade extra | sem SCP, é a mesma ausência de teto de antes, só que espalhada por mais contas | erro de ambiente-alvo continua possível, agora em qualquer uma das contas | IAM concede o que faz sentido por papel; SCP recorta o teto por OU | nunca — IAM sozinho nunca foi a fronteira, com uma conta ou com dez |
| Criar conta via `aws_organizations_account` direto, sob Control Tower | é um resource do provider Terraform, parece o caminho natural de infraestrutura como código | a conta nasce fora do radar do Account Factory, sem os guardrails detectivos esperados | `list-managed-accounts` do Control Tower não lista uma conta que existe na Organization | provisionar via Account Factory (console ou Service Catalog) ou AFT | organizações sem Control Tower, onde não há Account Factory para contornar |
| SCP com `Deny` total, sem exceção de quebra-vidro | parece mais seguro: "nega tudo que é destrutivo, sem brecha" | quando o incidente real exige a ação, a saída sob pressão é desanexar a SCP inteira | proteção cai por completo justamente no momento em que mais precisa dela | condition nomeando uma role de quebra-vidro específica, com MFA e alarme dedicado | nunca — mesmo SCP crítica precisa de saída auditável |
| Achar que SCP substitui a política IAM | "coloquei a SCP, então não preciso mais escrever policy fina" | SCP não CONCEDE nada; sem IAM allow, ninguém faz nada de útil, mesmo com a SCP mais permissiva | permission set vazio ou insuficiente, e tudo continua negado apesar da SCP liberar o teto | as duas continuam necessárias: IAM concede, SCP recorta o teto | nunca — são camadas complementares, não substitutas |
| Uma OU só para "tudo que não é dev" | parece suficiente separar em duas categorias amplas | mistura homologação com produção real; a SCP acaba generosa o bastante para caber os dois | ambiente de teste com acesso amplo herda o mesmo teto frouxo que produção precisaria ter estreito | OU própria para cada ambiente que precisa de um teto de SCP diferente | organização pequena o bastante para não ter ambiente de homologação separado ainda |
Quando algo não funciona
| Sintoma | Causa provável | Como investigar | Onde olhar | Correção |
|---|---|---|---|---|
| SCP não bloqueia nada, em nenhuma conta | policy anexada na OU errada, ou não anexada em lugar nenhum | confira o `target_id` real da policy attachment | `aws organizations list-policies-for-target --target-id <ou-producao>` | reanexar a policy no id correto da OU Produção |
| `terraform apply` falha ao criar a policy de Organizations | `feature_set` da organização não é `ALL` | consulte o modo atual da organização | `aws organizations describe-organization` → campo `FeatureSet` | migrar para `ALL` antes de tentar anexar qualquer SCP |
| Time de plataforma preso, sem conseguir nem corrigir a própria SCP | quebra-vidro mal configurado, ou role errada na condition | testar a role de quebra-vidro FORA de incidente | comparar o ARN da `condition` com o ARN real da role criada | corrigir o ARN, ou criar a role de quebra-vidro que ainda não existia |
| Conta nova não aparece nos guardrails do Control Tower | conta criada fora do Account Factory | comparar as duas listas de contas | `list-managed-accounts` (Control Tower) vs. `organizations list-accounts` | registrar (enroll) a conta retroativamente pelo console do Control Tower |
| Usuário legítimo não consegue nem LER o recurso em produção | SCP com `Deny` amplo demais, sem escopo de ação específico | revisar a lista de `Action` da statement de Deny | conteúdo da SCP anexada à OU Produção | restringir a statement à lista exata de ações destrutivas, nunca `rds:*` inteiro |
| `iam simulate-principal-policy` diz `allowed`, mas a chamada real falha | condição dinâmica (IP de origem, hora do dia) que só resolve em tempo de execução real | conferir se a SCP ou o IAM usam alguma `Condition` de contexto de requisição | statement completa da SCP e da policy IAM, não só a lista de ações | testar com a chamada real em ambiente de teste, não só com o simulador |
A pergunta que resolve metade destes casos
Antes de mexer em qualquer policy, pergunte: isto é IAM negando, ou SCP negando? O texto do erro geralmente cita "service control policy" quando é a SCP — se não citar, o problema provavelmente está na política de identidade, não na fronteira de conta.
Limpeza: o que desfazer a estrutura não leva
Diferente de um laboratório de aplicação, aqui "destruir" envolve processos da própria AWS com etapas e prazos próprios — fechar uma conta não é como apagar um bucket.
# 1. Remova as atribuicoes do Identity Center ANTES de mexer em conta ou OU --
# senao ficam referencias soltas para um alvo que deixou de existir.
aws sso-admin delete-account-assignment \
--instance-arn "$INSTANCE_ARN" \
--permission-set-arn "$PERMISSION_SET_ARN" \
--principal-id "$GRUPO_ID" --principal-type GROUP \
--target-id "$CONTA_PRODUCAO_ID" --target-type AWS_ACCOUNT
# 2. Apague as instancias RDS descartaveis das provas 2 e 3, se ainda existirem.
aws rds describe-db-instances --profile nao-producao \
--query "DBInstances[?DBInstanceIdentifier=='teste-fronteira']" --output table
# 3. Desanexe e apague a SCP.
terraform destroy -target=aws_organizations_policy_attachment.producao
terraform destroy -target=aws_organizations_policy.nega_destrutivo_prod
# 4. As OUs so sao removidas se estiverem VAZIAS -- sem conta e sem OU filha.
# Mova ou fece as contas primeiro.
terraform destroy -target=aws_organizations_organizational_unit.nao_producao
terraform destroy -target=aws_organizations_organizational_unit.producao
# 5. O fechamento de conta-membro tem processo e prazo proprios da AWS -- nao e
# instantaneo, e a reversao e limitada. So feche uma conta que voce tem certeza
# de que nao vai precisar mais.
aws organizations close-account --account-id "$CONTA_NAO_PRODUCAO_ID"
# 6. Prova final: nenhuma SCP customizada sobrando em nenhuma OU.
aws organizations list-policies --filter SERVICE_CONTROL_POLICY \
--query "Policies[?AwsManaged=='false'].Name" --output table| Recurso | Sai no destroy? | Cobra parado? | Por que fica |
|---|---|---|---|
| SCP desanexada | não, se só desanexar sem apagar | não | continua existindo na lista de policies da organização, sem custo, mas poluindo |
| Conta-membro fechada | entra em processo de fechamento próprio da AWS | não | o fechamento tem prazo e reversão limitada — não é instantâneo nem sempre reversível |
| Bucket de Log Archive (CloudTrail) | não é removido por este laboratório | sim, GB-mês | guarda o histórico de auditoria mesmo depois de a estrutura ser desfeita — remover é decisão à parte |
| Instância RDS descartável das provas | não, exige exclusão explícita | sim, por hora | foi criada fora do Terraform principal, só para o teste — fácil de esquecer |
| Atribuição de permission set no Identity Center | não some sozinha ao apagar a OU | não | fica como referência a um alvo que não existe mais até ser removida explicitamente |
Fechar a conta errada não tem o mesmo botão de desfazer de um `terraform destroy`
Fechamento de conta-membro na AWS Organizations segue processo e prazo próprios da AWS, com janela de reversão limitada — bem diferente de apagar um recurso comum. Confirme o `account-id` duas vezes antes de rodar o passo 5, e nunca automatize esse comando específico num script que roda sem confirmação humana.
Resumo: problema, peça e motivo
| Problema | Peça | Por que ela, e não outra |
|---|---|---|
| Wildcard de prefixo casa dev e prod na mesma conta | duas contas, duas OUs | fronteira de conta contém o erro que nenhuma policy, por mais cuidadosa, contém sozinha |
| IAM generoso permitiria ação destrutiva em produção | SCP com Deny explícito na OU Produção | SCP é avaliada antes do IAM e nunca precisa "vencer" um Allow — a interseção decide |
| SCP legítima pode travar o próprio time em emergência | role de quebra-vidro na condition | dá saída auditável sem exigir desanexar a proteção inteira |
| Conta operada pode apagar a própria trilha de auditoria | conta Log Archive separada | auditoria centralizada, fora do alcance de quem opera a conta auditada |
| Usuário IAM de longa duração por conta, difícil de auditar | Identity Center com permission set único | mesmo acesso concedido nas duas contas — prova que a proteção não depende de policy diferente |
| Conta criada fora do radar dos guardrails | Account Factory do Control Tower | toda conta nova nasce já registrada, sem depender de alguém lembrar de registrar depois |
| Falha | O que a protege | O que ela NÃO protege |
|---|---|---|
| Erro de ambiente-alvo em comando destrutivo | SCP na OU Produção | ação legítima acidentalmente incluída na lista de Deny — exige revisão da lista |
| Incidente real bloqueado pela própria SCP | role de quebra-vidro | quebra-vidro nunca testado, que ninguém sabe se funciona quando precisa |
| Conta operada apaga a própria auditoria | conta Log Archive separada | a conta de gestão em si, que continua sem teto de SCP nenhum |
| Usuário IAM de longa duração vazado | Identity Center, sessão temporária | sessão do Identity Center comprometida enquanto ainda válida — é sessão, não credencial eterna, mas ainda é sessão |
| Conta criada fora dos guardrails | Account Factory | alguém com permissão de administrar Organizations decidindo ignorar o processo |
- A Cadência provisiona a organização com `feature_set = ALL`, habilitando SCP.
- Duas OUs são criadas: Não-Produção e Produção.
- O Account Factory do Control Tower provisiona uma conta em cada OU, já registrada nos guardrails.
- A SCP com Deny em ações destrutivas é anexada só na OU Produção.
- O Identity Center atribui o MESMO permission set Operador nas duas contas.
- Em Não-Produção, o comando de exclusão sucede: só o IAM decide.
- Em Produção, o mesmo comando falha: a SCP nega antes de o IAM ser consultado.
- A tentativa negada fica registrada na conta Log Archive, fora do alcance de quem operou.
- Uma role de quebra-vidro, protegida por MFA, permanece como única exceção auditável.
- A conta de gestão, de propósito, continua fora do alcance de qualquer SCP anexada.
Desafio — sem roteiro
O requisito
Adicione uma Service Control Policy que bloqueia uma ação de risco específica — por exemplo, desabilitar o GuardDuty — em toda a unidade organizacional, mesmo para quem tem permissão de administrador na conta.
Critério de aceite — executável, não "verifique se funciona"
Um usuário com policy IAM de `AdministratorAccess` DENTRO de uma conta da OU tenta desabilitar o GuardDuty e recebe erro de permissão negada pela organização — a SCP vence mesmo sobre o admin local.
- Dica 1: SCP não CONCEDE permissão, só define o teto do que é permitido — um `AdministratorAccess` continua precisando que a SCP não bloqueie a ação, senão o próprio conceito de "teto" não faz sentido.
- Dica 2: A ação a negar (`guardduty:DeleteDetector`, por exemplo) precisa do nome EXATO da API — negar a ação errada dá a falsa sensação de proteção sem bloquear nada de verdade.
- Dica 3: Teste a partir de uma conta MEMBRO da OU, nunca da conta de management — SCPs não se aplicam à conta de management por padrão, e testar lá dá um falso negativo.
Lembrete de limpeza
Todo recurso que este desafio criar entra no mesmo `terraform destroy` do laboratório — nada fica para trás cobrando sozinho.
Perguntas frequentes
❓ SCP substitui a política IAM, ou as duas continuam necessárias?
❓ Por que a conta de gestão da AWS Organizations não é afetada por SCP?
❓ Uma SCP com Deny bloqueia até quem tem AdministratorAccess?
❓ Preciso do Control Tower para usar Organizations e SCP, ou dá para configurar na mão?
❓ Quantas contas AWS eu preciso ter para separar dev de produção de verdade?
❓ O que acontece se eu esquecer de anexar a SCP na OU certa?
❓ Preciso de MFA ou de uma role especial para casos de emergência em produção?
❓ iam simulate-principal-policy considera as SCPs da organização, ou só a política IAM?
Fixando
A equipe de plataforma da Cadência precisa investigar por que uma tentativa de `rds:DeleteDBInstance` foi negada na conta de Produção. O `iam simulate-principal-policy` já confirmou `explicitDeny`. Qual é o próximo passo mais direto para descobrir QUAL policy causou a negação?
Uma SCP na OU de Produção nega `rds:DeleteDBInstance` sem nenhuma condição de exceção. Durante um incidente real, a equipe de plantão precisa apagar uma réplica corrompida com urgência e não consegue, mesmo com a role certa. Qual é o risco mais provável dessa situação, além do atraso no incidente?
Conhecimentos, próximo módulo e documentação
| Item | Conteúdo |
|---|---|
| Conhecimentos anteriores necessários | L38 (isolamento multi-tenant por linha, esquema e conta) e L41 (política de menor privilégio em IAM); Terraform e AWS CLI básicos |
| Conhecimentos adquiridos | a distinção entre CONCEDER (IAM) e RESTRINGIR (SCP); a interseção como modelo de avaliação; a exceção estrutural da conta de gestão; o caminho de quebra-vidro; Account Factory versus criação manual de conta |
| Limitação que fica | apenas duas OUs — suficiente para o risco declarado, mas sem Resource Control Policies nem Account Factory for Terraform, que entram quando o número de contas crescer |
| Próximo exemplo recomendado | L56 e L98, que aprofundam esta mesma fronteira em escala e automação maiores, reutilizando a organização e as OUs provisionadas aqui |
| Também habilitado por este módulo | qualquer laboratório futuro que precise de um ambiente de produção genuinamente isolado do de desenvolvimento passa a poder assumir essa fronteira como dada |
| Data da última validação técnica | 7 de agosto de 2026 |
Documentação oficial consultada: How SCPs work e SCP evaluation — a mecânica de interseção entre SCP e IAM, a exceção da conta de gestão e a isenção de service-linked roles; Service control policies (SCPs) — a policy padrão `FullAWSAccess`; How AWS Control Tower works — a Security OU com as contas de Log Archive e Audit criadas por padrão; e IAM policy testing with the IAM policy simulator — a confirmação de que o simulador avalia SCP com lógica consciente do serviço, mas não expõe o statement responsável pela negação. Os valores de preço não aparecem neste módulo por decisão: Organizations e SCP não têm custo direto, e o restante varia por conta e por região — use o AWS Pricing Calculator.
O que não foi verificado, e você deve conferir na sua conta
O texto exato da mensagem de erro citada no exemplo de CloudTrail ("...with an explicit deny in a service control policy") é o padrão observado em material de troubleshooting da própria AWS, mas não foi conferido caractere a caractere contra a documentação de referência atual — trate como formato típico, não como contrato garantido, e confirme a mensagem real que aparece na sua conta. Da mesma forma, os ids de conta, ARNs e nomes de OU usados nos exemplos são fictícios; substitua pelos da sua organização antes de rodar qualquer comando.
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…