TL;DR
- Usa la API ValidatePolicy de AWS IAM Access Analyzer en CI/CD para detectar políticas excesivamente permisivas antes del deployment—es gratis y detecta errores gramaticales más violaciones de mejores prácticas
- Combina análisis estático (Checkov) con simulación de políticas (IAM Policy Simulator) para cobertura completa—estático detecta patrones, simulación detecta comportamiento en runtime
- El testing IAM cross-cloud requiere herramientas diferentes: AWS Access Analyzer, Azure Policy Insights, GCP Policy Analyzer cada uno tiene capacidades únicas
Ideal para: Equipos gestionando políticas IAM en IaC que necesitan prevenir escalación de privilegios y asegurar mínimo privilegio No recomendado si: Usas servicios de identidad gestionados donde las políticas están abstraídas (ej., AWS SSO con permission sets predefinidos) Tiempo de lectura: 14 minutos
Las políticas IAM excesivamente permisivas siguen siendo una de las principales causas de brechas cloud. Un solo "Resource": "*" o condición faltante puede exponer toda tu cuenta AWS. Estudios muestran que 82% de las misconfiguraciones cloud provienen de error humano—haciendo el testing automatizado de políticas IAM esencial, no opcional.
Para contexto más amplio sobre testing de infraestructura, consulta Testing de Policy as Code y Testing de Compliance para IaC.
Enfoques Asistidos por IA
Las herramientas de IA destacan analizando políticas IAM complejas y generando suites de tests comprehensivas.
Analizando políticas IAM por permisos excesivos:
Analiza esta política IAM de AWS por problemas de seguridad:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:*"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["iam:PassRole"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["ec2:*"],
"Resource": "*",
"Condition": {
"StringEquals": {"ec2:Region": "us-east-1"}
}
}
]
}
Identifica: Riesgos de escalación de privilegios, permisos excesivamente amplios,
condiciones faltantes, y proporciona una alternativa de mínimo privilegio para
un rol de pipeline CI/CD.
Generando casos de test de políticas IAM:
Genera casos de test pytest para validar políticas IAM de AWS usando boto3:
1. Verificar que ninguna política permite iam:* o iam:PassRole a Resource "*"
2. Verificar que políticas S3 requieren condiciones de encriptación
3. Asegurar que ninguna política permite assume-role a cuentas externas sin condiciones
4. Validar que políticas admin solo están adjuntas a roles break-glass
Incluye setup apropiado de sesión AWS, parsing de documentos de política y
assertions claras.
Creando checks personalizados de Checkov:
Escribe un check personalizado de Checkov en Python que valide:
1. Las políticas IAM no deben permitir acciones terminando en "*" (ej., s3:*, ec2:*)
2. Todas las declaraciones iam:PassRole deben tener ARNs de Resource explícitos
3. Políticas con acciones administrativas deben tener condiciones MFA
4. Políticas de trust cross-account deben especificar IDs de cuenta explícitos
Incluye la clase del check, lógica de evaluación y tipos de recursos soportados.
Cuándo Usar Diferentes Enfoques de Testing
Framework de Decisión de Estrategia de Testing
| Tipo de Test | Herramienta | Cuándo Ejecutar | Qué Detecta |
|---|---|---|---|
| Validación gramatical | IAM Access Analyzer | Pre-commit, CI | Errores de sintaxis, elementos deprecados |
| Mejores prácticas | Access Analyzer ValidatePolicy | Pipeline CI | Acciones excesivamente permisivas, condiciones faltantes |
| Análisis estático | Checkov, cfn-nag | Pre-commit, CI | Patrones malos conocidos (Resource: “*”) |
| Simulación de políticas | IAM Policy Simulator | Pre-deploy | Comportamiento real de permisos |
| Análisis de acceso | Hallazgos Access Analyzer | Continuo | Acceso externo, permisos no usados |
| Reglas personalizadas | OPA/Rego | Pipeline CI | Requisitos específicos de organización |
Checks Críticos de Políticas IAM
| Check ID | Descripción | Nivel de Riesgo |
|---|---|---|
| CKV_AWS_1 | Políticas IAM no deben permitir privilegios administrativos completos “*” | Crítico |
| CKV_AWS_49 | Políticas IAM no deben permitir PassRole a “*” | Crítico |
| CKV_AWS_40 | Políticas IAM no deben permitir escalación de privilegios | Crítico |
| CKV_AWS_62 | Políticas IAM no deben tener SID vacío | Bajo |
| CKV_AWS_109 | Políticas IAM no deben permitir exposición de credenciales | Alto |
| CKV_AWS_110 | Políticas IAM no deben permitir gestión de permisos sin restricciones | Alto |
Testing de Políticas IAM en AWS
Validación de Políticas con IAM Access Analyzer
# Instalar el validador de políticas IAM para Terraform
pip install tf-policy-validator
# Validar template Terraform
tf-policy-validator validate \
--template-path ./terraform \
--region us-east-1
# Ejecutar checks específicos
tf-policy-validator validate \
--template-path ./terraform \
--region us-east-1 \
--check-type VALIDATE_POLICY \
--check-type CHECK_NO_NEW_ACCESS
Integración con GitHub Actions
name: Validación de Políticas IAM
on:
pull_request:
paths:
- 'terraform/**/*.tf'
- 'cloudformation/**/*.yaml'
jobs:
validate-iam-policies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configurar credenciales AWS
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Validar Políticas IAM Terraform
uses: aws-actions/terraform-aws-iam-policy-validator@v1
with:
template-path: terraform/
region: us-east-1
check-no-new-access: true
check-access-not-granted: true
check-no-public-access: true
- name: Ejecutar Checkov
uses: bridgecrewio/checkov-action@v12
with:
directory: terraform/
check: CKV_AWS_1,CKV_AWS_40,CKV_AWS_49,CKV_AWS_109,CKV_AWS_110
framework: terraform
Checkov para Políticas IAM
# Instalar Checkov
pip install checkov
# Escanear por problemas específicos de IAM
checkov -d ./terraform --check CKV_AWS_1,CKV_AWS_40,CKV_AWS_49
# Output como JUnit para CI
checkov -d ./terraform --framework terraform \
--check CKV_AWS_1,CKV_AWS_40,CKV_AWS_49,CKV_AWS_109,CKV_AWS_110 \
--output junitxml > iam-checkov-results.xml
Check Personalizado de Checkov
# custom_checks/iam_no_passrole_star.py
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.common.models.enums import CheckResult, CheckCategories
import json
class IAMNoPassRoleStar(BaseResourceCheck):
def __init__(self):
name = "Asegurar que políticas IAM no permiten PassRole a todos los recursos"
id = "CKV_CUSTOM_IAM_1"
supported_resources = ['aws_iam_policy', 'aws_iam_role_policy']
categories = [CheckCategories.IAM]
super().__init__(name=name, id=id, categories=categories,
supported_resources=supported_resources)
def scan_resource_conf(self, conf):
policy = conf.get('policy', [None])[0]
if not policy:
return CheckResult.UNKNOWN
# Manejar formatos string y dict
if isinstance(policy, str):
try:
policy = json.loads(policy)
except json.JSONDecodeError:
return CheckResult.UNKNOWN
statements = policy.get('Statement', [])
for statement in statements:
if statement.get('Effect') != 'Allow':
continue
actions = statement.get('Action', [])
if isinstance(actions, str):
actions = [actions]
resources = statement.get('Resource', [])
if isinstance(resources, str):
resources = [resources]
# Verificar PassRole con recurso *
has_passrole = any('PassRole' in action for action in actions)
has_star_resource = '*' in resources
if has_passrole and has_star_resource:
return CheckResult.FAILED
return CheckResult.PASSED
check = IAMNoPassRoleStar()
Testing de Políticas con boto3 en Python
import boto3
import json
import pytest
class TestIAMPolicies:
@pytest.fixture
def iam_client(self):
return boto3.client('iam')
@pytest.fixture
def access_analyzer_client(self):
return boto3.client('accessanalyzer')
def test_no_admin_star_policies(self, iam_client):
"""Verificar que ninguna política otorga acceso admin completo."""
paginator = iam_client.get_paginator('list_policies')
for page in paginator.paginate(Scope='Local'):
for policy in page['Policies']:
version = iam_client.get_policy_version(
PolicyArn=policy['Arn'],
VersionId=policy['DefaultVersionId']
)
document = version['PolicyVersion']['Document']
statements = document.get('Statement', [])
for stmt in statements:
if stmt.get('Effect') != 'Allow':
continue
actions = stmt.get('Action', [])
if isinstance(actions, str):
actions = [actions]
resources = stmt.get('Resource', [])
if isinstance(resources, str):
resources = [resources]
# Fallar si Action: "*" y Resource: "*"
assert not (
'*' in actions and '*' in resources
), f"Política {policy['PolicyName']} tiene privilegios admin"
def test_validate_policy_with_access_analyzer(self, access_analyzer_client):
"""Usar Access Analyzer para validar política."""
policy_document = {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::my-bucket/*"
}]
}
response = access_analyzer_client.validate_policy(
policyDocument=json.dumps(policy_document),
policyType='IDENTITY_POLICY'
)
# Verificar errores y advertencias de seguridad
findings = response.get('findings', [])
errors = [f for f in findings if f['findingType'] == 'ERROR']
security_warnings = [f for f in findings
if f['findingType'] == 'SECURITY_WARNING']
assert len(errors) == 0, f"Errores de validación: {errors}"
assert len(security_warnings) == 0, f"Advertencias de seguridad: {security_warnings}"
Testing con IAM Policy Simulator
def test_policy_denies_unauthorized_actions(iam_client):
"""Simular política para verificar acciones denegadas."""
# Probar que rol de desarrollador no puede acceder a producción
response = iam_client.simulate_principal_policy(
PolicySourceArn='arn:aws:iam::123456789012:role/DeveloperRole',
ActionNames=[
'ec2:TerminateInstances',
's3:DeleteBucket',
'iam:CreateUser'
],
ResourceArns=[
'arn:aws:ec2:us-east-1:123456789012:instance/*',
'arn:aws:s3:::production-*',
'arn:aws:iam::123456789012:user/*'
]
)
for result in response['EvaluationResults']:
assert result['EvalDecision'] == 'implicitDeny', \
f"Rol desarrollador no debería tener permiso {result['EvalActionName']}"
def test_policy_allows_required_actions(iam_client):
"""Verificar que rol tiene permisos requeridos."""
response = iam_client.simulate_principal_policy(
PolicySourceArn='arn:aws:iam::123456789012:role/CICDRole',
ActionNames=[
's3:PutObject',
'ecr:PushImage',
'ecs:UpdateService'
],
ResourceArns=[
'arn:aws:s3:::deployment-artifacts/*',
'arn:aws:ecr:us-east-1:123456789012:repository/my-app',
'arn:aws:ecs:us-east-1:123456789012:service/my-cluster/my-service'
]
)
for result in response['EvaluationResults']:
assert result['EvalDecision'] == 'allowed', \
f"Rol CICD sin permiso requerido: {result['EvalActionName']}"
Testing IAM en Azure
Azure Policy para Validación de RBAC
# Listar definiciones de roles personalizados
az role definition list --custom-role-only true --output table
# Verificar asignaciones de roles
az role assignment list --scope /subscriptions/<sub-id> --output table
# Validar con Azure Policy
az policy assignment list --query "[?policyDefinitionId contains 'rbac']"
InSpec para Azure RBAC
control 'azure-no-owner-custom-roles' do
impact 1.0
title 'Roles personalizados no deben tener permisos equivalentes a Owner'
azure_role_definitions.where(role_type: 'CustomRole').ids.each do |role_id|
describe azure_role_definition(name: role_id) do
its('permissions.first.actions') { should_not include '*' }
its('permissions.first.not_actions') { should_not be_empty }
end
end
end
control 'azure-no-subscription-owner-assignments' do
impact 1.0
title 'Rol Owner no debe asignarse a nivel de suscripción'
describe azure_role_assignments.where(
scope: "/subscriptions/#{input('subscription_id')}",
role_name: 'Owner'
) do
its('count') { should be <= 2 } # Solo permitir cuentas break-glass
end
end
Testing IAM en GCP
GCP Policy Analyzer
# Analizar política IAM de un proyecto
gcloud policy-intelligence analyze-iam-policy \
--project=my-project \
--full-resource-name="//cloudresourcemanager.googleapis.com/projects/my-project"
# Verificar bindings excesivamente permisivos
gcloud projects get-iam-policy my-project --format=json | \
jq '.bindings[] | select(.members[] | contains("allUsers") or contains("allAuthenticatedUsers"))'
Validación Terraform para GCP IAM
# variables.tf - Definir roles permitidos
variable "allowed_project_roles" {
type = list(string)
default = [
"roles/viewer",
"roles/editor",
# Listar explícitamente roles permitidos
]
}
# Validación en recurso
resource "google_project_iam_binding" "binding" {
project = var.project_id
role = var.role
members = var.members
lifecycle {
precondition {
condition = contains(var.allowed_project_roles, var.role)
error_message = "Rol ${var.role} no está en la lista de roles permitidos."
}
precondition {
condition = !contains(var.members, "allUsers") && !contains(var.members, "allAuthenticatedUsers")
error_message = "Bindings IAM públicos (allUsers/allAuthenticatedUsers) no están permitidos."
}
}
}
Integración en Pipeline CI/CD
Workflow Completo de GitHub Actions
name: Seguridad de Políticas IAM
on:
pull_request:
paths:
- 'terraform/iam/**'
- 'policies/**'
jobs:
static-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Ejecutar checks IAM de Checkov
uses: bridgecrewio/checkov-action@v12
with:
directory: terraform/iam/
check: CKV_AWS_1,CKV_AWS_40,CKV_AWS_49,CKV_AWS_109,CKV_AWS_110
output_format: sarif
output_file_path: checkov-iam.sarif
- name: Subir SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: checkov-iam.sarif
access-analyzer:
runs-on: ubuntu-latest
needs: static-analysis
steps:
- uses: actions/checkout@v4
- name: Configurar credenciales AWS
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
working-directory: terraform/iam/
- name: Validar con Access Analyzer
uses: aws-actions/terraform-aws-iam-policy-validator@v1
with:
template-path: terraform/iam/
region: us-east-1
check-no-new-access: true
policy-simulation:
runs-on: ubuntu-latest
needs: access-analyzer
if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v4
- name: Configurar credenciales AWS
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Instalar dependencias
run: pip install boto3 pytest
- name: Ejecutar tests de simulación de políticas
run: pytest tests/iam/ -v --tb=short
Midiendo el Éxito
| Métrica | Antes del Testing | Después del Testing | Cómo Rastrear |
|---|---|---|---|
| Políticas excesivamente permisivas | Encontradas en auditorías | 0 en producción | Reportes Checkov |
| Paths de escalación de privilegios | Desconocidos | 0 detectados | Hallazgos Access Analyzer |
| Tiempo de validación de políticas | Revisión manual (horas) | Automatizado (minutos) | Métricas CI/CD |
| Permisos no usados | Acumulados con el tiempo | Limpieza trimestral | Access Analyzer |
Señales de que tu testing IAM no funciona:
- Checkov pasa pero hallazgos de Access Analyzer en producción
- Cambios de política de “emergencia” evadiendo CI/CD
- Roles acumulando permisos con el tiempo
- Cuentas de servicio con privilegios admin
Conclusión
El testing efectivo de políticas IAM requiere múltiples capas de validación:
- Análisis estático (Checkov) detecta patrones malos conocidos en código
- Validación gramatical (Access Analyzer ValidatePolicy) asegura sintaxis y estructura de políticas
- Simulación de políticas (IAM Policy Simulator) verifica comportamiento real de permisos
- Análisis continuo (hallazgos de Access Analyzer) detecta drift y permisos no usados
La idea clave: las políticas IAM son demasiado críticas para revisión manual solamente. Testing automatizado en pipelines CI/CD detecta problemas antes de llegar a producción, mientras el monitoreo continuo detecta drift de políticas con el tiempo.
Ver También
- Testing de Policy as Code - OPA y Sentinel para reglas IAM personalizadas
- Testing de Security Groups - Testing de control de acceso a nivel de red
- Testing de Compliance para IaC - Cumpliendo requisitos IAM regulatorios
- Estrategias de Testing de Terraform - Pirámide completa de testing IaC
- Testing de Infraestructura AWS - Estrategias más amplias de testing AWS
