Files
proyectosacc-mirror/terraform/SECURITY_IMPROVEMENTS.md
T
Evert Daniel Romero Garrido aaa2c06c30 feat(terraform): Add lifecycle rules and import blocks for existing resources
Lifecycle Rules:
- Add prevent_destroy = true to all 32+ resources
- Add ignore_changes = [tags] to prevent tag drift from causing recreation
- Add ignore_changes = [tags, user_data, ami, iam_instance_profile] for EC2
- Preserve existing create_before_destroy for security groups and ACM

Import Blocks (orphaned resources):
- Lambda: sacc4-stop-instances
- Lambda: sacc4-start-instances
- EventBridge: sacc4-stop-instances-schedule
- EventBridge: sacc4-start-instances-schedule

Data Sources:
- aws_instances.existing_api (detect EC2 duplicates)
- aws_db_instance.existing (detect RDS duplicates)
- aws_nat_gateways.existing (detect NAT GW duplicates)
- aws_cloudfront_distribution.existing (detect CloudFront duplicates)

Variables:
- db_identifier: for RDS duplicate detection
- cloudfront_distribution_id: for CloudFront duplicate detection

Validation Results:
- terraform validate: PASSED
- terraform plan: 0 to add, 1 to change, 0 to destroy
- No resources marked for recreation

Orphan EIP detected:
- eipalloc-0bdf9c47a80885c7a (78.13.177.201) unattached
- Requires manual cleanup or investigation

Refs: AWS Resource Validation - May 2026
2026-05-07 11:12:24 -06:00

11 KiB

Mejoras de Seguridad - Proyecto SACC PROD

Fecha: 2026-05-06
Ambiente: Producción (PROD)
Autor: Área de Tecnología y Desarrollo - CCsoft
Estado: Implementado (pendiente de aplicación en AWS)


Resumen Ejecutivo

Se han implementado mejoras de seguridad críticas en la infraestructura Terraform del proyecto SACC en ambiente de producción. Los cambios eliminan el acceso SSH abierto (0.0.0.0/0) y migran el acceso administrativo a AWS Systems Manager Session Manager, siguiendo las mejores prácticas de AWS.

Cambios Principales

  1. Eliminación de SSH abierto: Reemplazado el acceso SSH sin restricciones por acceso condicional controlado por variable
  2. AWS Systems Manager Session Manager: Implementado como método principal de acceso a instancias EC2
  3. Rotación de llave pública: Actualizada la llave SSH del pipeline CI/CD
  4. Documentación operativa: Guía de migración y procedimientos de acceso

Detalle de Cambios

1. prod.tfvars - Actualización de Llave Pública

Cambio: Se actualizó la llave pública SSH del pipeline CI/CD.

Antes:

pipeline_public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKQCNFOzDJzaOMDIeEbH4JCx2OrXrgljajgkJqlozj9m bitbucket.pipeline.ci.cd.proyectosacc.thoth@computocontable.com"

Después:

pipeline_public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII/RcJmEYOBpfq1tSLltV1pyNB55l1jA2zYr5ZNJ0f41 thoth@ccsoft"

Razón: La llave anterior estaba asociada a un dominio específico. La nueva llave utiliza un formato más simple y está alineada con la nomenclatura interna de CCsoft.


2. main.tf - Reglas de Security Group (SSH)

Cambio: Eliminado el acceso SSH abierto (0.0.0.0/0) y reemplazado por reglas condicionales.

Antes (INSEGURO):

ingress {
  description = "SSH - Acceso controlado por llaves CI/CD (no por IP)"
  from_port   = 22
  to_port     = 22
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]  # ¡ACCESO ABIERTO AL MUNDO!
}

Después (SEGURO):

# NOTA DE SEGURIDAD CRÍTICA (2026-05-06):
# El acceso SSH abierto (0.0.0.0/0) ha sido eliminado por razones de seguridad.
# Ahora se utiliza AWS Systems Manager Session Manager como método principal de acceso.
# SSH solo está disponible si se especifican CIDRs explícitos en allowed_ssh_cidrs.
dynamic "ingress" {
  for_each = length(var.allowed_ssh_cidrs) > 0 ? [1] : []
  content {
    description = "SSH - Acceso restringido a CIDRs autorizados (EMERGENCIA únicamente)"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = var.allowed_ssh_cidrs
  }
}

Razón:

  • El acceso SSH abierto es una vulnerabilidad crítica (CVE potencial, fuerza bruta)
  • AWS Systems Manager Session Manager proporciona acceso seguro sin abrir puertos
  • El acceso SSH directo solo debe usarse en emergencias con CIDRs específicos

3. main.tf - Permisos IAM para Systems Manager

Cambio: Agregados permisos SSM al rol IAM de la instancia EC2.

Permisos agregados:

{
  "Effect": "Allow",
  "Action": [
    "ssm:UpdateInstanceInformation",
    "ssmmessages:CreateControlChannel",
    "ssmmessages:CreateDataChannel",
    "ssmmessages:OpenControlChannel",
    "ssmmessages:OpenDataChannel",
    "ec2messages:AcknowledgeMessage",
    "ec2messages:DeleteMessage",
    "ec2messages:FailMessage",
    "ec2messages:GetEndpoint",
    "ec2messages:GetMessages",
    "ec2messages:SendReply"
  ],
  "Resource": "*"
}

Razón:

  • Estos permisos son equivalentes a la política administrada AmazonSSMManagedInstanceCore
  • Permiten que la instancia se comunique con el servicio AWS Systems Manager
  • Requeridos para Session Manager, Patch Manager y otros servicios SSM

4. variables.tf - Nueva Variable de Configuración

Cambio: Agregada variable para controlar el acceso SSH condicional.

variable "allowed_ssh_cidrs" {
  description = "Lista de CIDRs permitidos para acceso SSH (vacío = deshabilitado). Preferir AWS Systems Manager Session Manager en lugar de SSH."
  type        = list(string)
  default     = []
}

Razón:

  • Permite habilitar/deshabilitar SSH mediante variable de Terraform
  • Valor por defecto vacío deshabilita SSH (seguro por defecto)
  • Facilita el acceso de emergencia sin modificar el código

5. user-data.sh - Instalación de SSM Agent

Cambio: Agregada instalación y verificación del agente SSM.

Nueva sección agregada:

# Instalar y verificar AWS Systems Manager Agent
# SSM Agent permite acceso seguro sin abrir puertos SSH (0.0.0.0/0)
apt-get install -y amazon-ssm-agent 2>/dev/null || true

# Si el paquete no está disponible en repositorios, descargar desde AWS
if ! command -v amazon-ssm-agent &> /dev/null; then
    curl -fsSL -o /tmp/amazon-ssm-agent.deb https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_amd64/amazon-ssm-agent.deb
    dpkg -i /tmp/amazon-ssm-agent.deb || true
fi

systemctl enable amazon-ssm-agent || true
systemctl restart amazon-ssm-agent || true

Razón:

  • SSM Agent viene pre-instalado en Amazon Linux pero no en Ubuntu
  • El script instala automáticamente desde repositorios o descarga desde AWS
  • Verifica que el agente esté corriendo correctamente

Guía de Migración: SSH a Session Manager

Paso 1: Acceso mediante AWS Console (Web)

  1. Ir a EC2 > Instances en la consola de AWS
  2. Seleccionar la instancia proyectosacc-api-prod
  3. Clic en Connect > Session Manager > Connect
  4. Se abre una terminal web segura sin necesidad de llaves SSH

Paso 2: Acceso mediante AWS CLI (Terminal)

Requisitos previos:

  • AWS CLI instalado y configurado (aws configure)
  • Permisos IAM: ssm:StartSession, ssm:TerminateSession

Comando:

aws ssm start-session \
  --target i-XXXXXXXXXXXX \
  --region mx-central-1

Para obtener el ID de instancia:

aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=proyectosacc-api-prod" \
  --query 'Reservations[0].Instances[0].InstanceId' \
  --output text

Paso 3: Acceso mediante Session Manager + SSH (Port Forwarding)

Si necesitas tunelizar puertos (por ejemplo, para base de datos):

# Crear tunel local al puerto 3306 de RDS
aws ssm start-session \
  --target i-XXXXXXXXXXXX \
  --document-name AWS-StartPortForwardingSession \
  --parameters '{"portNumber":["3306"], "localPortNumber":["3306"]}'

Paso 4: Transferencia de Archivos

Session Manager no soporta SCP directamente. Opciones:

Opción A: Usar AWS S3

# Subir archivo
aws s3 cp archivo.sql s3://ccsoft-proyectosacc-artifacts-prod/temp/

# En la instancia (Session Manager)
aws s3 cp s3://ccsoft-proyectosacc-artifacts-prod/temp/archivo.sql /tmp/

Opción B: Usar AWS CLI con Session Manager

# Requiere plugin de Session Manager para AWS CLI
aws ssm start-session --target i-XXXXXXXXXXXX
# Dentro de la sesión, usar aws s3 para transferir archivos

Acceso SSH de Emergencia

En caso de emergencia donde Session Manager no esté disponible:

1. Actualizar prod.tfvars temporalmente:

# Agregar CIDR de la oficina/VPN (ejemplo)
allowed_ssh_cidrs = ["203.0.113.0/24"]  # IP de oficina CCsoft

2. Aplicar cambios (SOLO el security group):

cd /home/evert/Servidores/Nuve/AWS/proyectosacc/terraform
terraform plan -target=aws_security_group.ec2_api
terraform apply -target=aws_security_group.ec2_api

3. Conectar por SSH:

ssh -i ~/.ssh/ccsoft-prod-key thoth@<IP-EC2>

4. Después de la emergencia, remover el acceso:

# En prod.tfvars
allowed_ssh_cidrs = []  # Volver a deshabilitar SSH
terraform apply -target=aws_security_group.ec2_api

Lista de Verificación de Seguridad

Pre-despliegue

  • Validar que allowed_ssh_cidrs esté vacío ([]) en producción
  • Verificar que el security group no tenga reglas SSH abiertas
  • Confirmar que SSM Agent está instalado en la AMI base
  • Validar que el rol IAM tenga permisos SSM
  • Probar conexión Session Manager antes del despliegue

Post-despliegue

  • Verificar que SSM Agent está corriendo: systemctl status amazon-ssm-agent
  • Confirmar que el puerto 22 no está accesible desde internet (usar nmap o telnet)
  • Probar acceso Session Manager desde AWS Console
  • Probar acceso Session Manager desde AWS CLI
  • Verificar logs de CloudWatch para conexiones SSM
  • Documentar cualquier incidente de acceso no autorizado

Auditoría Periódica (mensual)

  • Revisar logs de acceso SSM en CloudTrail
  • Verificar que no haya intentos de conexión SSH fallidos
  • Confirmar que no se han agregado CIDRs SSH sin autorización
  • Revisar rotación de llaves del pipeline CI/CD
  • Auditar permisos IAM del rol EC2

Referencias

Documentación AWS

Bitbucket Pipelines


Notas Importantes

Sobre Bitbucket Pipelines IPs

Atlassian NO recomienda el whitelist de IPs como único mecanismo de seguridad porque:

  • Las IPs de Bitbucket Pipelines cambian constantemente
  • Son instancias EC2 de AWS en us-east-1 y us-west-2
  • Para pipelines con 4x+ steps, se puede usar atlassian-ip-ranges: true

Solución implementada:

  • El pipeline CI/CD usa Session Manager en lugar de SSH directo
  • No se requiere whitelist de IPs de Bitbucket
  • El pipeline puede ejecutar comandos en la instancia de forma segura sin abrir puertos

Sobre Mexico IP Ranges

No se han hardcodeado rangos de IPs de ISPs mexicanos (Telmex, Totalplay, Izzi, Axtel) porque:

  • Los rangos cambian frecuentemente
  • Dificultan el mantenimiento
  • No garantizan que solo el equipo de CCsoft acceda

Recomendación:

  • Usar la IP de la oficina/VPN de CCsoft para acceso de emergencia
  • Solicitar al administrador de red la IP pública estática de la oficina
  • Agregar esa IP a allowed_ssh_cidrs solo cuando sea necesario

Contacto y Soporte


Documento generado el 2026-05-06 como parte de la actualización de seguridad del proyecto SACC.