Especialista

KMS: key policies e grants cross-account

Lição 17 · Módulo 5 — Especialista

O cenário

Uma conta central de segurança (111111111111) cria uma CMK para criptografar volumes EBS e a compartilha com as OUs da organização. Na conta de workload (222222222222), um Auto Scaling group com launch template de EBS criptografado com essa chave tenta subir instâncias e todas terminam na hora:

Activity history do ASG
1
2
3
Client.InvalidKMSKey.InvalidState:
One or more of the attached Amazon EBS volumes are encrypted
with an inaccessible AWS KMS key.

A key policy "parece certa". Por que não funciona? Para responder, você precisa de três peças: como o KMS autoriza, quem é o principal de fato e o que muda em cross-account.

Três mecanismos de autorização no KMS

No KMS, a key policy é a fonte de verdade. Diferente de outros serviços, sem a key policy permitir (direta ou indiretamente), ninguém usa a chave, nem o root da conta.

  • Key policy: resource policy obrigatória da chave. Pode citar principais diretamente ou delegar para o IAM da conta via "Principal": "arn:aws:iam::CONTA:root".
  • IAM policies: só têm efeito se a key policy delegar para a conta dona do principal.
  • Grants: autorizações delegadas e temporárias. Um grant dá a um grantee principal um conjunto de operações na chave, sem precisar mexer em key policy nem em IAM policy. É o mecanismo que EBS, RDS e outros serviços usam por baixo.

Same-account vs cross-account no KMS

Lembra da lição 11? Em same-account, a key policy citando o principal pelo ARN basta. Em cross-account, o KMS exige autorização nos dois lados:

  1. A key policy (conta da chave) precisa permitir o principal ou a conta externa.
  2. Uma IAM policy na conta externa precisa permitir as ações naquela chave.

Ou, alternativamente, um grant para o principal externo substitui o item 2.

A key policy do cenário

Uma policy comum em ambientes multi-conta, abreviada:

JSON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"Sid": "OrgUsage",
"Effect": "Allow",
"Principal": { "AWS": "*" },
"Action": ["kms:Encrypt","kms:Decrypt","kms:ReEncrypt*",
"kms:GenerateDataKey*","kms:DescribeKey","kms:CreateGrant"],
"Resource": "*",
"Condition": {
"ForAnyValue:StringLike": {
"aws:PrincipalOrgPaths": "o-exemplo/r-ab12/ou-ab12-workloads/*"
}
}
},
{
"Sid": "AllowAutoScalingSLR",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::222222222222:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"
},
"Action": ["kms:Encrypt","kms:Decrypt","kms:ReEncrypt*",
"kms:GenerateDataKey*","kms:DescribeKey"],
"Resource": "*"
},
{
"Sid": "AllowAutoScalingSLRGrants",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::222222222222:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"
},
"Action": "kms:CreateGrant",
"Resource": "*",
"Condition": { "Bool": { "kms:GrantIsForAWSResource": "true" } }
}

Do lado da chave, está tudo certo. Note que OrgUsage com Principal: "*" não atrapalha a SLR: Allows se somam. Se a condição não casar, essa statement simplesmente não se aplica, e as statements específicas da SLR continuam valendo. Só um Deny explícito bloquearia.

Mesmo assim, falha. O que falta é o lado da conta 222222222222.

A solução: grant criado na conta do ASG

A documentação do EC2 Auto Scaling é explícita: para CMK de outra conta, uma identidade da conta do ASG (com kms:CreateGrant permitido pela key policy e pelo IAM local) cria um grant para a SLR:

bash
1
2
3
4
5
6
aws kms create-grant \
--region sa-east-1 \
--key-id arn:aws:kms:sa-east-1:111111111111:key/EXEMPLO-KEY-ID \
--grantee-principal arn:aws:iam::222222222222:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling \
--operations "Encrypt" "Decrypt" "ReEncryptFrom" "ReEncryptTo" \
"GenerateDataKey" "GenerateDataKeyWithoutPlaintext" "DescribeKey" "CreateGrant"
  • Use o ARN completo da chave, não um alias, porque aliases não resolvem cross-account.
  • Rode com credenciais da conta do ASG.
  • A SLR precisa existir antes, porque o grant é vinculado ao ID interno da role.
  • Prefira IaC (Terraform aws_kms_grant, CloudFormation custom resource) a um passo manual esquecido.

Checklist de diagnóstico

  1. aws kms describe-key: a chave está Enabled e na região certa?
  2. A AMI ou o snapshot usa outra CMK? A SLR precisa de acesso a ela também.
  3. CloudTrail da conta da chave: qual operação falhou (CreateGrant, GenerateDataKeyWithoutPlaintext, DescribeKey) e qual errorMessage?
  4. Existe Deny na key policy alcançando o principal? SCPs e RCPs não afetam a SLR, mas afetam a role que cria o grant.
  5. Cross-account? Então confirme o grant: aws kms list-grants --key-id <arn>.

Teste rápido

A key policy (conta A) cita explicitamente a SLR do Auto Scaling da conta B com todas as ações corretas. O ASG na conta B continua falhando. Qual a causa mais provável?

Mesmo cenário, mas ASG e chave estão na MESMA conta. As duas statements da SLR na key policy bastam?

Resumo

No KMS, a key policy manda. Em cross-account, você precisa dos dois lados, e quando o principal é uma SLR (policy imutável), o grant é o que fecha a conta. Statements Allow com condições de Org não "roubam" a avaliação de outras statements: se algo bloqueia, procure um Deny ou a metade cross-account que faltou.

Referência Well-Architected

Alinhada com Implement secure key management e Share resources securely within your organization.

Referências

Terminou esta lição?

Seu progresso fica salvo apenas neste navegador.