Permission boundary: delegare senza escalation

Una permission boundary è una managed policy che definisce il massimo dei permessi che le identity-based policy possono concedere a una IAM entity (user o role). Non concede nulla da sola: i permessi effettivi sono l’intersezione tra la boundary e le policy allegate. Il caso d’esame classico è la delega: vuoi che un team crei ruoli in autonomia senza poter fabbricare un ruolo admin e assumerlo. La soluzione è dare al delegato i permessi iam:CreateRole/iam:PutRolePolicy ma vincolarli con una condition su iam:PermissionsBoundary, obbligando ogni ruolo creato ad avere una boundary predefinita. Aggiungi un deny esplicito sulla rimozione o modifica della boundary stessa, altrimenti il delegato la elimina e l’intero controllo salta.

Condition key e ABAC per scalare

Le condition key trasformano policy statiche in controlli contestuali. aws:PrincipalOrgID limita l’accesso ai soli principal della tua Organization senza elencare gli account ID uno per uno — ideale nelle resource policy di S3 o KMS. aws:SourceArn e aws:SourceAccount risolvono il confused deputy problem: quando un servizio AWS (es. S3 event, SNS, CloudWatch) chiama una risorsa per conto tuo, questi vincoli garantiscono che la richiesta provenga davvero dalla risorsa attesa. aws:SourceIp limita per IP pubblico, ma attenzione: dietro un VPC endpoint non funziona (il traffico non ha IP pubblico) e serve invece aws:VpcSourceIp o aws:SourceVpce.

L’ABAC (attribute-based access control) usa i tag: confronti aws:PrincipalTag/project con aws:ResourceTag/project così che un principal acceda solo alle risorse con lo stesso tag. Il vantaggio è la scala — non riscrivi le policy a ogni nuova risorsa o utente, basta il tag corretto. Va protetto con controlli sul tagging, altrimenti la sicurezza è aggirabile ri-taggando.

Access Analyzer, IAM policy e resource policy

IAM Access Analyzer usa reasoning matematico (provable security) per individuare le risorse condivise con entità esterne alla tua zone of trust (account o Organization): bucket S3, ruoli IAM, chiavi KMS e code SQS con accessi cross-account non voluti. Genera inoltre policy least-privilege partendo dai log CloudTrail dell’attività reale di un ruolo, e (unused access) segnala ruoli e permessi mai usati da rimuovere.

Ricorda l’interazione tra le policy. Nello stesso account, identity-based e resource-based policy si sommano: basta che una conceda. In cross-account servono entrambe — la identity policy nel source e la resource policy nel target. La KMS key policy è l’autorità radice della chiave: una IAM policy non concede accesso se la key policy non delega a IAM (statement con Principal root dell’account) o al principal. Il deny esplicito, ovunque appaia (policy, boundary, SCP), prevale sempre.

iam:PassRole e prevenzione dell’escalation

iam:PassRole è la permission più abusata per l’escalation. Chi può passare un ruolo potente a un servizio che controlla — avviare una EC2 o una Lambda con un ruolo admin — eredita quei privilegi. Non concedere mai iam:PassRole su Resource "*": vincola le ARN dei ruoli passabili e usa la condition iam:PassedToService per limitare i servizi destinatari. In combinazione con le permission boundary, questo chiude il cerchio della delega sicura.

Trappole tipiche d’esame

  • SCP che deve “concedere” un permesso → non esiste: una service control policy è un guardrail che limita il massimo consentito, non concede nulla; l’accesso va comunque dato da una identity o resource policy.
  • Accesso KMS negato pur avendo la IAM policy corretta → key policy: senza uno statement nella key policy che deleghi a IAM (Principal root) o al principal, la chiave resta inaccessibile.
  • Restringere per IP dietro un VPC endpoint con aws:SourceIp → non filtra: usa aws:VpcSourceIp o aws:SourceVpce; aws:SourceIp vede solo IP pubblici.
  • Delegare la creazione di ruoli senza escalation → permission boundary obbligatoria: condition su iam:PermissionsBoundary in creazione più deny sulla rimozione della boundary.
  • Confused deputy tra servizi cross-account → aws:SourceArn/aws:SourceAccount: aws:PrincipalOrgID limita all’Organization ma non identifica la singola risorsa chiamante.
  • Bloccare l’escalation via avvio istanze/funzioni → restringere iam:PassRole: limita le ARN dei ruoli e usa iam:PassedToService, mai Resource "*".