Amazon S3 e ISO27001: cómo convertir buckets en controles de seguridad reales
Hablar de ISO 27001 no va de cumplir por cumplir. Va de demostrar control.
Y pocos servicios ponen tan a prueba ese control como Amazon S3.
Porque S3 no falla, pero expone cualquier debilidad organizativa:
- 🔓 Accesos mal definidos
- ⏳ Retenciones inexistentes
- 📋 Auditorías improvisadas
- 👥 Responsabilidades poco claras
Cuando estuve preparando las pruebas de certificación, teníamos inicialmente unos buckets que podría llamarlos caóticos, y causaron más de 15 no conformidades. Cuando se preparó correctamente, se aceleró muchos estas pruebas.
Este artículo conecta Amazon S3 con ISO 27001 desde un enfoque práctico: cómo usar buckets para cumplir, evidenciar y sostener un SGSI en el tiempo, sin burocracia inútil.
El error más común: “ISO es solo documentación”
En Amazon Web Services, S3 suele convertirse en:
Usos típicos de S3:
- Repositorio de backups
- Almacén de logs de aplicaciones
- Contenedor de evidencias de auditoría
- Archivos de compliance
- Datos históricos regulatorios
Y ahí aparece el error: pensar que ISO 27001 se resuelve con PDFs y políticas.
La realidad es más cruda:
Si tu S3 no está bien diseñado, tu SGSI tampoco lo está.
ISO 27001 exige controles técnicos reales, no solo textos bonitos. Un auditor competente revisará:
- ✅ Configuración técnica real de buckets
- ✅ Logs de acceso verificables
- ✅ Políticas de retención implementadas
- ✅ Evidencias de revisiones periódicas
- ✅ Controles de cifrado activos
No basta con escribir “tenemos controles de acceso”. Hay que demostrarlo con evidencias técnicas.
ISO 27001 y S3: el marco conceptual
ISO 27001 define un Sistema de Gestión de Seguridad de la Información (SGSI) basado en:
Ciclo PDCA aplicado a S3:
Plan (Planificar):
- Identificar buckets como activos
- Clasificar información almacenada
- Definir controles técnicos necesarios
- Asignar responsables (owners)
Do (Hacer):
- Implementar configuraciones técnicas
- Activar cifrado, logging, lifecycle
- Documentar decisiones de diseño
- Capacitar a equipos
Check (Verificar):
- Auditar configuraciones periódicamente
- Revisar logs de acceso
- Validar cumplimiento de controles
- Medir efectividad
Act (Actuar):
- Corregir desviaciones detectadas
- Mejorar configuraciones
- Actualizar documentación
- Implementar lecciones aprendidas
S3 encaja perfectamente en este ciclo… si lo diseñas conscientemente.
S3 como activo del SGSI
El primer paso correcto es tratar cada bucket como un activo de información.
Registro de activos (Anexo A.8.1):
Ficha de activo - Bucket S3:
Nombre: s3://company-financial-reports-prod
Clasificación: CONFIDENCIAL
Propietario: CFO / Finance Department
Custodio Técnico: Cloud Platform Team
Tipo de información:
- Reportes financieros trimestrales
- Estados contables
- Auditorías financieras
Requisitos legales:
- Retención: 10 años (Ley Tributaria)
- Disponibilidad: 99.9%
- Cifrado: Obligatorio
Controles aplicados:
- A.9.1.2: Control de acceso
- A.10.1.1: Cifrado
- A.12.3.1: Backup
- A.12.4.1: Logging
- A.18.1.3: Retención
Riesgos identificados:
- Acceso no autorizado (Probabilidad: Media, Impacto: Alto)
- Pérdida de datos (Probabilidad: Baja, Impacto: Crítico)
- Borrado accidental (Probabilidad: Media, Impacto: Alto)
Revisión: Trimestral
Última revisión: 15/12/2025
Próxima revisión: 15/03/2026
Un bucket sin dueño es un riesgo latente. Y en una auditoría, eso se detecta rápido.
Implementación práctica con tags:
# Terraform: tagging para ISO 27001
resource "aws_s3_bucket" "financial_reports" {
bucket = "company-financial-reports-prod"
tags = {
# Gestión de activos
AssetID = "ASSET-S3-001"
Owner = "finance-team"
TechnicalOwner = "platform-team"
# Clasificación
DataClassification = "CONFIDENTIAL"
Criticality = "HIGH"
# Compliance
ISO27001Control = "A.8.1.1,A.9.1.2,A.10.1.1"
RetentionPeriod = "10-years"
LegalRequirement = "Tax-Law-2023"
# Operacional
Environment = "production"
BackupRequired = "true"
DRPlan = "enabled"
# Auditoría
LastReview = "2025-12-15"
NextReview = "2026-03-15"
AuditScope = "ISO27001"
}
}
Los tags no son metadata bonita. Son evidencia auditable.
Controles ISO 27001 que impactan directamente en S3
Aunque ISO 27001 no habla específicamente de S3, muchos controles del Anexo A caen directamente sobre él:
Mapeado completo de controles:
ISO 27001 Anexo A → Amazon S3:
A.8 - Gestión de activos:
A.8.1.1 - Inventario de activos:
✅ Registro de todos los buckets
✅ Tags de clasificación y ownership
✅ Documentación de propósito
A.8.2.3 - Manipulación de activos:
✅ Lifecycle policies
✅ Versionado para cambios
✅ Procedimientos de borrado seguro
A.9 - Control de acceso:
A.9.1.1 - Política de control de acceso:
✅ Bucket policies restrictivas
✅ IAM roles con mínimo privilegio
✅ Block Public Access habilitado
A.9.1.2 - Acceso a redes y servicios:
✅ Acceso solo desde VPC autorizada
✅ Endpoint policies
✅ Restricción por IP si aplica
A.9.2.1 - Registro de usuarios:
✅ IAM users/roles documentados
✅ Matriz RACI de accesos
A.9.4.1 - Restricción de acceso a la información:
✅ Policies basadas en tags
✅ Session policies
✅ Conditions en bucket policies
A.10 - Criptografía:
A.10.1.1 - Política de uso de controles criptográficos:
✅ Cifrado en reposo (SSE-S3/KMS)
✅ Cifrado en tránsito (TLS enforced)
✅ Gestión de claves documentada
A.10.1.2 - Gestión de claves:
✅ AWS KMS para claves maestras
✅ Rotación automática
✅ Auditoría de uso de claves
A.12 - Seguridad de las operaciones:
A.12.3.1 - Copias de seguridad:
✅ Versionado habilitado
✅ Replicación cross-region
✅ Lifecycle para retención
A.12.4.1 - Registro de eventos:
✅ CloudTrail activo
✅ S3 Access Logs
✅ Almacenamiento de logs protegido
A.12.4.2 - Protección de logs:
✅ Logs en bucket separado
✅ Solo append, no modificación
✅ Lifecycle para retención legal
A.13 - Seguridad de las comunicaciones:
A.13.2.1 - Políticas y procedimientos de transferencia:
✅ TLS obligatorio (aws:SecureTransport)
✅ Presigned URLs con expiración
✅ VPC Endpoints para tráfico interno
A.18 - Cumplimiento:
A.18.1.3 - Protección de registros:
✅ Versionado inmutable
✅ Object Lock para WORM
✅ Retención según requisitos legales
A.18.1.5 - Regulación de controles criptográficos:
✅ Cifrado conforme a estándares
✅ Documentación de algoritmos
✅ Revisión periódica
S3 puede cubrirlos todos… o fallarlos todos, según cómo lo configures.
A.9 - Control de accesos: mínimo privilegio o no hay ISO
Desde ISO 27001, no vale “todo el equipo tiene acceso”. El control A.9.1.2 exige restricción efectiva.
Implementación conforme:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnforceMinimumPrivilege",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sensitive-data-prod",
"arn:aws:s3:::sensitive-data-prod/*"
],
"Condition": {
"StringNotEquals": {
"aws:PrincipalAccount": "123456789012"
}
}
},
{
"Sid": "AllowOnlyFromCorporateVPC",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sensitive-data-prod",
"arn:aws:s3:::sensitive-data-prod/*"
],
"Condition": {
"StringNotEquals": {
"aws:SourceVpc": "vpc-corporate-12345"
}
}
},
{
"Sid": "EnforceTLSOnly",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sensitive-data-prod",
"arn:aws:s3:::sensitive-data-prod/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
},
{
"Sid": "AllowReadOnlyForAuditors",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/ISO27001-Auditor"
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::sensitive-data-prod",
"arn:aws:s3:::sensitive-data-prod/*"
]
}
]
}
Matriz de accesos documentada:
Matriz RACI - Bucket: sensitive-data-prod
Roles IAM:
data-engineers-role:
Permissions: Read, Write
Justification: "Procesamiento diario de datos"
Approved by: CISO
Review date: Q1-2026
Responsible: Data Team Lead
auditors-role:
Permissions: Read-only
Justification: "Auditorías de compliance"
Approved by: CISO
Review date: Anual
Accountable: Compliance Officer
backup-service-role:
Permissions: Read, Write, Delete
Justification: "Gestión automatizada de backups"
Approved by: CTO
Review date: Q2-2026
Consulted: Platform Team
platform-admins-role:
Permissions: Full (con MFA Delete)
Justification: "Gestión de infraestructura"
Approved by: CTO + CISO
Review date: Mensual
Informed: Security Team
Revisión periódica: Trimestral
Última revisión: 15/12/2025
Hallazgos: 0 accesos innecesarios detectados
Esto no solo cumple ISO: reduce incidentes reales.
A.10 - Cifrado y protección del dato
ISO 27001 control A.10.1.1 exige proteger la información almacenada. En S3 eso se traduce en:
Decisión documentada de cifrado:
Política de cifrado S3 - ISO27001:
Clasificación PÚBLICA:
Cifrado: SSE-S3 (AES-256)
Justificación: "Sin requisitos especiales"
Coste: $0
Clasificación INTERNA:
Cifrado: SSE-S3 (AES-256)
Justificación: "Protección básica suficiente"
Coste: $0
Clasificación CONFIDENCIAL:
Cifrado: SSE-KMS
Key: aws/s3 (AWS managed)
Justificación: "Auditoría de uso de claves necesaria"
Coste: ~$1/mes + requests
Clasificación CRÍTICA/PII:
Cifrado: SSE-KMS
Key: Customer Managed Key (CMK)
Rotación: Automática anual
Justificación: "Control total sobre claves, GDPR/HIPAA"
Coste: ~$1/mes/key + requests
Policies: Restricción por rol y uso
Implementación con enforcement:
# KMS Key para datos críticos
resource "aws_kms_key" "s3_critical_data" {
description = "KMS key for critical S3 data - ISO27001 A.10.1.1"
deletion_window_in_days = 30
enable_key_rotation = true
tags = {
ISO27001Control = "A.10.1.1"
Purpose = "S3-Encryption-Critical-Data"
Compliance = "GDPR,ISO27001"
}
}
resource "aws_kms_alias" "s3_critical_data" {
name = "alias/s3-critical-data"
target_key_id = aws_kms_key.s3_critical_data.key_id
}
# Bucket con cifrado obligatorio
resource "aws_s3_bucket" "critical_data" {
bucket = "company-critical-data-prod"
tags = {
DataClassification = "CRITICAL"
ISO27001Control = "A.10.1.1"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "critical_data" {
bucket = aws_s3_bucket.critical_data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.s3_critical_data.arn
}
bucket_key_enabled = true
}
}
# Forzar cifrado vía policy
resource "aws_s3_bucket_policy" "critical_data_encryption" {
bucket = aws_s3_bucket.critical_data.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "DenyUnencryptedObjectUploads"
Effect = "Deny"
Principal = "*"
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.critical_data.arn}/*"
Condition = {
StringNotEquals = {
"s3:x-amz-server-side-encryption" = "aws:kms"
}
}
},
{
Sid = "DenyIncorrectKMSKey"
Effect = "Deny"
Principal = "*"
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.critical_data.arn}/*"
Condition = {
StringNotEquals = {
"s3:x-amz-server-side-encryption-aws-kms-key-id" = aws_kms_key.s3_critical_data.arn
}
}
}
]
})
}
No es necesario sobredimensionar, pero sí justificar la decisión. ISO no castiga la sencillez, castiga la improvisación.
A.12.4 - Auditoría y trazabilidad: la prueba de fuego
Un auditor ISO 27001 no quiere promesas, quiere evidencias verificables.
Control A.12.4.1 - Registro de eventos:
Con S3 debes poder demostrar:
Evidencias auditables:
¿Quién accede?
Fuente: CloudTrail
Dato: userIdentity.principalId
¿Cuándo?
Fuente: CloudTrail
Dato: eventTime (ISO 8601)
¿Desde dónde?
Fuente: CloudTrail + Access Logs
Dato: sourceIPAddress, vpcEndpointId
¿Qué acciones realiza?
Fuente: CloudTrail
Dato: eventName (GetObject, PutObject, DeleteObject)
¿Con qué resultado?
Fuente: CloudTrail
Dato: errorCode, errorMessage
¿Qué objetos?
Fuente: CloudTrail
Dato: requestParameters.bucketName, requestParameters.key
Implementación completa de logging:
# Bucket dedicado para logs (A.12.4.2)
resource "aws_s3_bucket" "audit_logs" {
bucket = "company-audit-logs-iso27001"
tags = {
Purpose = "ISO27001-Audit-Logs"
ISO27001Control = "A.12.4.1,A.12.4.2"
Retention = "7-years"
}
}
# Bloquear acceso público a logs
resource "aws_s3_bucket_public_access_block" "audit_logs" {
bucket = aws_s3_bucket.audit_logs.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Cifrado de logs
resource "aws_s3_bucket_server_side_encryption_configuration" "audit_logs" {
bucket = aws_s3_bucket.audit_logs.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# Versionado para inmutabilidad
resource "aws_s3_bucket_versioning" "audit_logs" {
bucket = aws_s3_bucket.audit_logs.id
versioning_configuration {
status = "Enabled"
}
}
# Object Lock para WORM (Write Once Read Many)
resource "aws_s3_bucket_object_lock_configuration" "audit_logs" {
bucket = aws_s3_bucket.audit_logs.id
rule {
default_retention {
mode = "GOVERNANCE" # o "COMPLIANCE" para requisitos más estrictos
years = 7
}
}
}
# Lifecycle para retención legal
resource "aws_s3_bucket_lifecycle_configuration" "audit_logs" {
bucket = aws_s3_bucket.audit_logs.id
rule {
id = "ISO27001-Log-Retention"
status = "Enabled"
transition {
days = 90
storage_class = "STANDARD_IA"
}
transition {
days = 365
storage_class = "GLACIER_IR"
}
transition {
days = 1825 # 5 años
storage_class = "DEEP_ARCHIVE"
}
expiration {
days = 2555 # 7 años (requisito legal)
}
}
}
# Activar S3 Access Logging en bucket de producción
resource "aws_s3_bucket_logging" "production_bucket" {
bucket = aws_s3_bucket.critical_data.id
target_bucket = aws_s3_bucket.audit_logs.id
target_prefix = "s3-access-logs/critical-data/"
}
# CloudTrail para eventos de gestión
resource "aws_cloudtrail" "iso27001" {
name = "iso27001-audit-trail"
s3_bucket_name = aws_s3_bucket.audit_logs.id
s3_key_prefix = "cloudtrail/"
include_global_service_events = true
is_multi_region_trail = true
enable_log_file_validation = true # Integridad de logs
event_selector {
read_write_type = "All"
include_management_events = true
data_resource {
type = "AWS::S3::Object"
values = ["${aws_s3_bucket.critical_data.arn}/*"]
}
}
tags = {
ISO27001Control = "A.12.4.1"
Purpose = "Audit-Trail"
}
}
Consultas de auditoría con Athena:
-- Query: Accesos fuera de horario laboral (indicador de riesgo)
SELECT
eventTime,
userIdentity.principalId as user,
eventName,
requestParameters.bucketName as bucket,
requestParameters.key as object_key,
sourceIPAddress,
errorCode
FROM cloudtrail_logs
WHERE
eventSource = 's3.amazonaws.com'
AND eventName IN ('GetObject', 'PutObject', 'DeleteObject')
AND (
CAST(date_format(from_iso8601_timestamp(eventTime), '%H') AS INTEGER) < 8
OR CAST(date_format(from_iso8601_timestamp(eventTime), '%H') AS INTEGER) > 18
)
AND errorCode IS NULL
ORDER BY eventTime DESC
LIMIT 100;
-- Query: Cambios en bucket policies (control crítico)
SELECT
eventTime,
userIdentity.principalId,
eventName,
requestParameters.bucketName,
responseElements
FROM cloudtrail_logs
WHERE
eventName IN (
'PutBucketPolicy',
'DeleteBucketPolicy',
'PutBucketPublicAccessBlock',
'DeleteBucketPublicAccessBlock'
)
ORDER BY eventTime DESC;
-- Query: Accesos desde IPs no corporativas
SELECT
eventTime,
userIdentity.principalId,
eventName,
sourceIPAddress,
requestParameters.bucketName
FROM cloudtrail_logs
WHERE
eventSource = 's3.amazonaws.com'
AND sourceIPAddress NOT LIKE '10.%' -- Red corporativa
AND sourceIPAddress NOT LIKE '172.16.%'
AND userIdentity.type != 'AWSService'
ORDER BY eventTime DESC;
CloudTrail y los access logs de S3 son controles técnicos, no extras opcionales. Si no están activos en buckets críticos, el SGSI es débil.
A.18.1.3 - Retención y borrado: lifecycle como control ISO
ISO 27001 exige que los datos:
- ✅ No vivan más de lo necesario (minimización)
- ✅ Se eliminen de forma controlada (borrado seguro)
- ✅ Se conserven según requisitos legales (retención)
Política de retención documentada:
Política de retención - ISO27001 A.18.1.3:
Logs de aplicación:
Retención: 90 días
Justificación: "Debugging operacional"
Base legal: "Política interna"
Destrucción: Automática (lifecycle)
Logs de acceso (S3/CloudTrail):
Retención: 7 años
Justificación: "Auditoría y cumplimiento"
Base legal: "ISO 27001, normativa local"
Destrucción: Automática post-retención
Backups de bases de datos:
Retención: 30 días (diarios), 12 meses (mensuales)
Justificación: "Recuperación ante desastres"
Base legal: "Plan de continuidad"
Destrucción: Automática con verificación
Documentos financieros:
Retención: 10 años
Justificación: "Requisitos fiscales"
Base legal: "Código Tributario Art. 123"
Destrucción: Proceso aprobado por CFO
Datos personales (GDPR):
Retención: Mientras exista relación contractual + 5 años
Justificación: "Base legal: ejecución de contrato"
Base legal: "GDPR Art. 6.1.b"
Destrucción: Automática salvo oposición legal
Implementación con Lifecycle Policies:
{
"Rules": [
{
"Id": "ISO27001-ApplicationLogs-90days",
"Status": "Enabled",
"Filter": {
"Prefix": "logs/application/"
},
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
}
],
"Expiration": {
"Days": 90
}
},
{
"Id": "ISO27001-AuditLogs-7years",
"Status": "Enabled",
"Filter": {
"Prefix": "logs/audit/"
},
"Transitions": [
{
"Days": 90,
"StorageClass": "STANDARD_IA"
},
{
"Days": 365,
"StorageClass": "GLACIER_IR"
},
{
"Days": 1825,
"StorageClass": "DEEP_ARCHIVE"
}
],
"Expiration": {
"Days": 2555
}
},
{
"Id": "ISO27001-FinancialDocs-10years",
"Status": "Enabled",
"Filter": {
"And": {
"Prefix": "documents/financial/",
"Tags": [
{
"Key": "DataClassification",
"Value": "CONFIDENTIAL"
},
{
"Key": "RetentionPeriod",
"Value": "10-years"
}
]
}
},
"Transitions": [
{
"Days": 365,
"StorageClass": "GLACIER_IR"
},
{
"Days": 1095,
"StorageClass": "DEEP_ARCHIVE"
}
],
"Expiration": {
"Days": 3650
}
},
{
"Id": "CleanupIncompleteMultipartUploads",
"Status": "Enabled",
"AbortIncompleteMultipartUpload": {
"DaysAfterInitiation": 7
}
},
{
"Id": "ExpireOldVersions",
"Status": "Enabled",
"NoncurrentVersionExpiration": {
"NoncurrentDays": 90,
"NewerNoncurrentVersions": 3
}
}
]
}
Un bucket sin lifecycle es una bomba de tiempo… y un punto débil en auditoría.
A.12.3.1 - Copias de seguridad: versionado y replicación
ISO 27001 exige backups verificables y recuperables.
Estrategia de backup conforme:
Plan de backup S3 - ISO27001 A.12.3.1:
Nivel 1 - Versionado:
Mecanismo: S3 Versioning
RPO: 0 (inmediato)
RTO: < 5 minutos
Alcance: Todos los buckets críticos
Pruebas: Mensuales
Nivel 2 - Replicación Cross-Region:
Mecanismo: S3 Replication
Destino: eu-west-1 (región secundaria)
RPO: < 15 minutos
RTO: < 1 hora
Alcance: Buckets clasificados como CRÍTICOS
Pruebas: Trimestrales con failover real
Nivel 3 - Exportación a Glacier:
Mecanismo: Lifecycle + S3 Batch Operations
Frecuencia: Semanal (snapshots)
Retención: 7 años
Alcance: Documentos regulatorios
Pruebas: Anuales con restauración completa
Implementación de replicación:
# Bucket de destino (región secundaria)
resource "aws_s3_bucket" "replication_dest" {
provider = aws.secondary_region
bucket = "company-critical-data-replica-eu"
tags = {
Purpose = "Disaster-Recovery"
ISO27001Control = "A.12.3.1"
}
}
# Versionado en ambos buckets (requisito para replicación)
resource "aws_s3_bucket_versioning" "replication_dest" {
provider = aws.secondary_region
bucket = aws_s3_bucket.replication_dest.id
versioning_configuration {
status = "Enabled"
}
}
# IAM Role para replicación
resource "aws_iam_role" "replication" {
name = "s3-replication-role-iso27001"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "s3.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy" "replication" {
role = aws_iam_role.replication.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"s3:GetReplicationConfiguration",
"s3:ListBucket"
]
Effect = "Allow"
Resource = aws_s3_bucket.critical_data.arn
},
{
Action = [
"s3:GetObjectVersionForReplication",
"s3:GetObjectVersionAcl"
]
Effect = "Allow"
Resource = "${aws_s3_bucket.critical_data.arn}/*"
},
{
Action = [
"s3:ReplicateObject",
"s3:ReplicateDelete"
]
Effect = "Allow"
Resource = "${aws_s3_bucket.replication_dest.arn}/*"
}
]
})
}
# Configuración de replicación
resource "aws_s3_bucket_replication_configuration" "critical_data" {
bucket = aws_s3_bucket.critical_data.id
role = aws_iam_role.replication.arn
rule {
id = "ISO27001-DR-Replication"
status = "Enabled"
filter {
and {
prefix = ""
tags = {
Replicate = "true"
}
}
}
destination {
bucket = aws_s3_bucket.replication_dest.arn
storage_class = "STANDARD_IA"
replication_time {
status = "Enabled"
time {
minutes = 15
}
}
metrics {
status = "Enabled"
event_threshold {
minutes = 15
}
}
}
delete_marker_replication {
status = "Enabled"
}
}
}
Pruebas de recuperación documentadas:
Registro de pruebas de backup - ISO27001:
Prueba Q4-2025:
Fecha: 15/12/2025
Tipo: Recuperación desde versionado
Escenario: Borrado accidental de objeto crítico
Procedimiento:
1. Simular borrado: aws s3 rm s3://bucket/critical-file.pdf
2. Listar versiones: aws s3api list-object-versions
3. Restaurar: aws s3api delete-object (delete marker)
Resultado: ✅ EXITOSO
Tiempo recuperación: 3 minutos
Responsable: John Doe (Platform Team)
Prueba Q3-2025:
Fecha: 20/09/2025
Tipo: Failover cross-region
Escenario: Caída de región us-east-1
Procedimiento:
1. Actualizar DNS a región EU
2. Verificar integridad de réplica
3. Validar accesos de aplicación
4. Rollback tras confirmación
Resultado: ✅ EXITOSO
RTO real: 45 minutos (objetivo: < 1 hora)
Responsable: Jane Smith (SRE Lead)
Hallazgos: Documentación de runbook actualizada
Próxima prueba: Q1-2026 (marzo)
Evidencias para auditoría: S3 como aliado
Cuando S3 está bien diseñado, se convierte en un aliado brutal para auditorías:
Evidencias que puedes presentar:
Paquete de evidencias ISO27001 - Bucket S3:
1. Configuración técnica:
✅ Export de Terraform state
✅ Screenshot de bucket policies
✅ Configuración de cifrado (KMS keys)
✅ Lifecycle policies activas
✅ Versionado habilitado
✅ Replicación configurada
2. Controles de acceso:
✅ Lista de IAM roles con permisos
✅ Matriz RACI de responsables
✅ Logs de revisión trimestral de permisos
✅ Block Public Access enabled (screenshot)
3. Registros de auditoría:
✅ CloudTrail logs últimos 12 meses
✅ S3 Access Logs almacenados
✅ Query de Athena: accesos fuera de horario
✅ Query de Athena: cambios en policies
✅ Alertas configuradas en CloudWatch
4. Gestión de incidentes:
✅ Registro de simulacros de recuperación
✅ Tiempos de respuesta documentados
✅ Runbooks de procedimientos
✅ Post-mortems de incidentes
5. Cumplimiento de retención:
✅ Política de retención aprobada
✅ Lifecycle rules implementadas
✅ Reportes de objetos próximos a expirar
✅ Logs de eliminaciones automáticas
6. Cifrado y protección:
✅ Política de cifrado documentada
✅ KMS keys con rotación activa
✅ Enforcement via bucket policies
✅ Auditoría de uso de claves (CloudTrail)
Dashboard de cumplimiento:
# Script para generar reporte de cumplimiento ISO27001
import boto3
import json
from datetime import datetime
def generate_iso27001_compliance_report(bucket_name):
s3 = boto3.client('s3')
report = {
"bucket": bucket_name,
"audit_date": datetime.now().isoformat(),
"controls": {}
}
# A.8.1.1 - Inventario
try:
tags = s3.get_bucket_tagging(Bucket=bucket_name)
report["controls"]["A.8.1.1"] = {
"status": "COMPLIANT" if tags else "NON_COMPLIANT",
"evidence": tags.get('TagSet', [])
}
except:
report["controls"]["A.8.1.1"] = {"status": "NON_COMPLIANT"}
# A.9.1.2 - Control de acceso
try:
public_access = s3.get_public_access_block(Bucket=bucket_name)
all_blocked = all([
public_access['PublicAccessBlockConfiguration']['BlockPublicAcls'],
public_access['PublicAccessBlockConfiguration']['BlockPublicPolicy'],
public_access['PublicAccessBlockConfiguration']['IgnorePublicAcls'],
public_access['PublicAccessBlockConfiguration']['RestrictPublicBuckets']
])
report["controls"]["A.9.1.2"] = {
"status": "COMPLIANT" if all_blocked else "NON_COMPLIANT",
"evidence": public_access
}
except:
report["controls"]["A.9.1.2"] = {"status": "NON_COMPLIANT"}
# A.10.1.1 - Cifrado
try:
encryption = s3.get_bucket_encryption(Bucket=bucket_name)
report["controls"]["A.10.1.1"] = {
"status": "COMPLIANT",
"evidence": encryption['ServerSideEncryptionConfiguration']
}
except:
report["controls"]["A.10.1.1"] = {"status": "NON_COMPLIANT"}
# A.12.3.1 - Backups
try:
versioning = s3.get_bucket_versioning(Bucket=bucket_name)
is_enabled = versioning.get('Status') == 'Enabled'
report["controls"]["A.12.3.1"] = {
"status": "COMPLIANT" if is_enabled else "NON_COMPLIANT",
"evidence": versioning
}
except:
report["controls"]["A.12.3.1"] = {"status": "NON_COMPLIANT"}
# A.12.4.1 - Logging
try:
logging = s3.get_bucket_logging(Bucket=bucket_name)
is_enabled = 'LoggingEnabled' in logging
report["controls"]["A.12.4.1"] = {
"status": "COMPLIANT" if is_enabled else "PARTIAL",
"evidence": logging
}
except:
report["controls"]["A.12.4.1"] = {"status": "NON_COMPLIANT"}
# A.18.1.3 - Retención
try:
lifecycle = s3.get_bucket_lifecycle_configuration(Bucket=bucket_name)
report["controls"]["A.18.1.3"] = {
"status": "COMPLIANT",
"evidence": lifecycle['Rules']
}
except:
report["controls"]["A.18.1.3"] = {"status": "PARTIAL"}
# Resumen
total = len(report["controls"])
compliant = sum(1 for c in report["controls"].values() if c["status"] == "COMPLIANT")
report["summary"] = {
"compliance_rate": f"{(compliant/total)*100:.1f}%",
"compliant": compliant,
"total": total
}
return report
# Generar reporte
buckets_criticos = ["company-financial-reports-prod", "company-customer-data-prod"]
for bucket in buckets_criticos:
report = generate_iso27001_compliance_report(bucket)
print(json.dumps(report, indent=2))
Esto reduce fricción con el auditor y transmite algo clave: el sistema está pensado para ser controlado, no solo para funcionar.
El fallo que delata un SGSI inmaduro
El patrón se repite en auditorías:
Bucket creado "para ISO":
❌ Sin owner claro (tag vacío o "TBD")
❌ Sin lifecycle (datos crecen indefinidamente)
❌ Sin revisión periódica (última review: "nunca")
❌ Sin integración real en operaciones
❌ Sin procedimientos documentados
❌ Sin pruebas de recuperación
❌ "Lo hicimos para la auditoría del año pasado"
Resultado:
- No conformidad mayor
- Plan de acción correctiva
- Revisión en 3 meses
- Pérdida de confianza del auditor
Eso no es cumplimiento. Es teatro de seguridad.
Signos de madurez ISO27001 con S3:
Organización madura:
✅ Buckets documentados en registro de activos
✅ Owners identificados y responsables
✅ Tags estandarizados y verificados
✅ IaC (Terraform/CloudFormation) para todo
✅ Lifecycle aplicado por diseño
✅ Alertas configuradas proactivamente
✅ Revisiones trimestrales ejecutadas
✅ Pruebas de DR documentadas y exitosas
✅ Procedimientos operativos actualizados
✅ Métricas de cumplimiento monitoreadas
✅ Mejora continua documentada
Resultado:
✅ Auditoría fluida
✅ 0 no conformidades en S3
✅ Auditor satisfecho con evidencias
✅ Certificación sin observaciones
Checklist completo: S3 conforme a ISO27001
Usa esto antes de cada auditoría:
Checklist ISO27001 para buckets S3:
□ Gestión de activos (A.8):
□ Bucket registrado en inventario de activos
□ Owner y custodio técnico asignados
□ Clasificación de información documentada
□ Riesgos identificados y evaluados
□ Tags completos y actualizados
□ Revisión periódica programada (trimestral/anual)
□ Control de acceso (A.9):
□ Block Public Access habilitado
□ Bucket policy restrictiva implementada
□ IAM roles con mínimo privilegio
□ Acceso solo desde VPC/IPs autorizadas
□ Matriz RACI documentada
□ Revisión de permisos ejecutada
□ MFA Delete en buckets críticos
□ Criptografía (A.10):
□ Cifrado en reposo activo (SSE-S3/KMS)
□ Cifrado en tránsito forzado (TLS)
□ Decisión de cifrado documentada y justificada
□ KMS keys con rotación (si aplica)
□ Auditoría de uso de claves configurada
□ Operaciones seguras (A.12):
□ Versionado habilitado (backups)
□ Replicación cross-region (DR, si aplica)
□ CloudTrail activo y monitoreado
□ S3 Access Logs configurados
□ Logs protegidos (bucket separado, inmutable)
□ Lifecycle policies implementadas
□ Retención según requisitos legales
□ Pruebas de recuperación documentadas
□ Cumplimiento (A.18):
□ Política de retención definida
□ Lifecycle conforme a retención
□ Object Lock para datos inmutables (si aplica)
□ Procedimientos de borrado seguro
□ Evidencias de auditoría disponibles
□ Conformidad con GDPR/HIPAA (si aplica)
□ Documentación:
□ Procedimientos operativos actualizados
□ Runbooks de incidentes disponibles
□ Registros de cambios (change log)
□ Evidencias de revisiones periódicas
□ Plan de continuidad documentado
□ Matriz de cumplimiento actualizada
□ Monitoreo y alertas:
□ CloudWatch Alarms configuradas
□ EventBridge rules para cambios críticos
□ Dashboard de compliance operativo
□ Notificaciones a equipos responsables
□ Reportes automáticos generados
Automatización del cumplimiento con AWS Config
Para organizaciones maduras, la verificación continua es clave:
# AWS Config Rules para ISO27001
resource "aws_config_config_rule" "s3_bucket_public_read_prohibited" {
name = "s3-bucket-public-read-prohibited-iso27001"
source {
owner = "AWS"
source_identifier = "S3_BUCKET_PUBLIC_READ_PROHIBITED"
}
depends_on = [aws_config_configuration_recorder.main]
}
resource "aws_config_config_rule" "s3_bucket_public_write_prohibited" {
name = "s3-bucket-public-write-prohibited-iso27001"
source {
owner = "AWS"
source_identifier = "S3_BUCKET_PUBLIC_WRITE_PROHIBITED"
}
}
resource "aws_config_config_rule" "s3_bucket_server_side_encryption_enabled" {
name = "s3-bucket-server-side-encryption-enabled-iso27001"
source {
owner = "AWS"
source_identifier = "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
}
}
resource "aws_config_config_rule" "s3_bucket_versioning_enabled" {
name = "s3-bucket-versioning-enabled-iso27001"
source {
owner = "AWS"
source_identifier = "S3_BUCKET_VERSIONING_ENABLED"
}
}
resource "aws_config_config_rule" "s3_bucket_logging_enabled" {
name = "s3-bucket-logging-enabled-iso27001"
source {
owner = "AWS"
source_identifier = "S3_BUCKET_LOGGING_ENABLED"
}
}
# Remediation automática
resource "aws_config_remediation_configuration" "s3_enable_versioning" {
config_rule_name = aws_config_config_rule.s3_bucket_versioning_enabled.name
target_type = "SSM_DOCUMENT"
target_identifier = "AWS-ConfigureS3BucketVersioning"
target_version = "1"
parameter {
name = "BucketName"
resource_value = "RESOURCE_ID"
}
parameter {
name = "VersioningState"
static_value = "Enabled"
}
automatic = true
maximum_automatic_attempts = 5
retry_attempt_seconds = 60
}
Cierre: ISO 27001 no se cumple, se opera
S3 puede ser uno de los pilares más sólidos de tu SGSI… o una fuente constante de no conformidades.
La diferencia no está en AWS, está en cómo piensas el servicio:
Mentalidad usuario:
- "Es un disco en la nube"
- "Para guardar cosas"
- "Funciona solo"
Mentalidad Cloud Engineer ISO27001:
- "Es un activo crítico de información"
- "Bajo control técnico verificable"
- "Con evidencias auditables"
- "Integrado en el SGSI"
- "Mejora continua"
Cuando usas S3 alineado con ISO 27001, no solo pasas auditorías. Construyes sistemas:
- ✅ Más seguros (controles técnicos reales)
- ✅ Más auditables (evidencias verificables)
- ✅ Más profesionales (diseño consciente)
- ✅ Más resilientes (DR probado)
- ✅ Más eficientes (automatización)
Y eso, al final, es exactamente lo que busca cualquier organización que se toma la seguridad en serio.