Problema

En entornos con varios equipos, es habitual encontrarse con recursos de AWS que carecen de tags de propietario o que presentan información desactualizada. La ausencia de metadatos fiables dificulta responder preguntas como: ¿Quién creó esta instancia EC2?, ¿A qué proyecto pertenece este bucket S3? o ¿Quién mantiene este rol IAM? La falta de claridad genera retrasos en auditorías, en la gestión de costos y en la resolución de incidentes. Además, cuando los equipos rotan, la pista de “dueño” se vuelve aún más difusa, lo que obliga a los ingenieros a invertir tiempo en “arqueología” de Slack, documentos internos o correos.

Causa

  1. Política de tagging incompleta – Los equipos a menudo ignoran la obligatoriedad de aplicar tags al crear recursos, o lo hacen de forma manual y propensa a errores.
  2. Migraciones y refactorizaciones – Cuando una infraestructura se traslada de CloudFormation a Terraform, o de scripts ad‑hoc a CDK, los tags pueden perderse si no se migran explícitamente.
  3. Desconexión entre IaC y recursos existentes – Recursos creados directamente desde la consola o mediante herramientas de terceros quedan fuera del estado de Terraform/CloudFormation, por lo que el “owner” no está registrado en el código.
  4. Rotación de equipos – La documentación de quién es responsable a menudo reside en wikis o canales de Slack que desaparecen con la salida de los miembros.
  5. Uso de recursos compartidos – Un bucket S3 o un rol IAM pueden ser consumidos por varios equipos, lo que complica la asignación de un único propietario.

Solución

Una estrategia robusta combina fuentes de verdad (IaC, historial de cambios) con registros de actividad (CloudTrail, AWS Config) y mecanismos de cost allocation. El flujo recomendado es el siguiente:

1. Consulta el estado de IaC

  • Terraform: terraform state list muestra todos los recursos gestionados. Cada recurso tiene un bloque metadata que incluye created_by si se definió.
  • CloudFormation: aws cloudformation describe-stack-resources --stack-name <stack> devuelve el ARN y la fecha de creación.
  • CDK: los artefactos de síntesis (cdk.out) incluyen metadatos de recurso.

Si el recurso aparece en el estado, el propietario suele estar indicado en el commit que introdujo la línea correspondiente. Busca en el repositorio con:

git log -p -S '<resource-id>' -- <path/to/terraform/files>

2. Revisa CloudTrail

CloudTrail registra cada llamada a la API, incluyendo Create*, RunInstances, CreateBucket, etc. Busca eventos que involucren el ARN del recurso:

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=ResourceName,AttributeValue=<resource-id> \
  --max-results 50

Los campos userIdentity y eventSource revelan quién (IAM user/role) ejecutó la acción y desde qué cuenta/organización. Si el evento muestra un role de servicio, sigue el rastro hasta el pipeline de CI que lo utilizó.

3. Usa AWS Config

Config mantiene un historial de configuraciones y relaciones entre recursos. Con una regla personalizada (custom-config-rule) puedes generar un snapshot de relationships y filtrar por resourceId. El comando:

aws configservice get-resource-config-history \
  --resource-type <type> \
  --resource-id <resource-id>

Muestra la configuración más reciente y, a menudo, la etiqueta aws:cloudformation:stack-id si el recurso provino de una pila.

4. Analiza Cost Allocation Tags y Billing Reports

Los cost allocation tags pueden estar habilitados aunque los tags de negocio no lo estén. Ejecuta:

aws ce get-cost-and-usage \
  --time-period Start=$(date -d '-30 days' +%Y-%m-%d),End=$(date +%Y-%m-%d) \
  --granularity DAILY \
  --filter '{"Dimensions":{"Key":"RESOURCE_ID","Values":["<resource-id>"]}}' \
  --metrics "UnblendedCost"

El informe asocia el costo a la cuenta o al role que facturó el recurso, lo que ayuda a identificar al equipo financiero responsable.

5. Busca en repositorios de naming y documentación interna

Muchas organizaciones usan convenciones de nombres (proj-team-env-resource). Un simple grep en los repositorios de código puede revelar la lógica de nombrado y, por ende, el equipo propietario.

grep -R 'proj-.*-.*-<resource-id>' .

6. Centraliza la información en un registro de recursos

Una vez identificado el propietario, registra la asociación en una tabla de AWS Resource Registry (por ejemplo, una hoja de cálculo en S3 o una tabla DynamoDB). Incluye:

  • ARN del recurso
  • Owner (IAM user/role o equipo)
  • Fuente de la evidencia (CloudTrail, Terraform commit, etc.)
  • Fecha de última verificación

Este registro sirve como punto de referencia para futuros incidentes y para auditorías de compliance.

Cuándo aplicar esta solución

  • Síntomas: No hay tags de Owner o Team; el recurso aparece en facturación inesperada; un incidente requiere contactar al responsable y no se conoce.
  • Entornos: Multi‑account, uso intensivo de Terraform/CloudFormation, equipos con alta rotación.
  • Exclusiones: En entornos de prueba donde los recursos son efímeros y no se persigue trazabilidad, la inversión de tiempo puede no justificar el beneficio.

Código

# 1. Listar recursos en Terraform state y buscar el ID
terraform state list | grep <resource-id>

# 2. Obtener eventos de CloudTrail para el recurso
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=ResourceName,AttributeValue=<resource-id> \
  --max-results 20

# 3. Obtener historial de Config para el recurso
aws configservice get-resource-config-history \
  --resource-type AWS::EC2::Instance \
  --resource-id <resource-id>

# 4. Extraer quien incurrió en el costo (Cost Explorer)
aws ce get-cost-and-usage \
  --time-period Start=$(date -d '-30 days' +%Y-%m-%d),End=$(date +%Y-%m-%d) \
  --granularity DAILY \
  --filter '{"Dimensions":{"Key":"RESOURCE_ID","Values":["<resource-id>"]}}' \
  --metrics "UnblendedCost"

Verificación

  1. Ejecuta los comandos anteriores y confirma que el campo userIdentity.arn o roleArn corresponde a un usuario/role activo.
  2. Verifica que el registro en la tabla de recursos muestra la misma información y que el equipo indicado reconoce la responsabilidad.
  3. Realiza una prueba de ownership creando un recurso de prueba sin tags y repitiendo el proceso; el flujo debe devolver tu propio user/role, confirmando que la cadena de fuentes funciona.

Notas adicionales

  • Automatiza la detección: un Lambda programado que recorra todos los recursos sin tag Owner y genere tickets en Jira o Slack acelera la respuesta.
  • Política de tagging: usa Service Control Policies (SCP) para bloquear la creación de recursos sin al menos un tag Owner o CostCenter.
  • Auditoría continua: Config Rules como required-tags pueden disparar alarmas en CloudWatch cuando un recurso pierde su tag.
  • Manejo de recursos compartidos: si varios equipos usan el mismo bucket, registra una lista de owners en la tabla de recursos y establece políticas de bucket que requieran aws:PrincipalTag/Team para operaciones críticas.
  • Cuidado con los roles de servicio: a veces el creador es un role de CI/CD; rastrea el pipeline (CodePipeline, Jenkins) para llegar al equipo que mantiene ese pipeline.

Con este enfoque, la búsqueda del propietario deja de ser una tarea de “excavación” y se convierte en un proceso reproducible que se apoya en los artefactos que ya existen en la cuenta AWS. La clave está en combinar la historia de infraestructura como código con los registros de actividad y, cuando sea necesario, complementar con datos de facturación. Así se reduce el tiempo de investigación de minutos a segundos y se mantiene la claridad de responsabilidades a lo largo del ciclo de vida del recurso.