Cloud, DevOps e IoT en español

Parte 13 de 22 de la serie Domótica con ESP32 y AWS desde cero

Políticas de AWS IoT: mínimo privilegio para cada dispositivo

8 de octubre de 2026 · Steven Carvajal · Seguridad

Código de este artículo en GitHub →

En AWS IoT Core, el certificado dice quién es un dispositivo, y la política dice qué puede hacer. Es la diferencia entre un certificado robado que solo controla una luz y uno que controla todos los dispositivos de tu cuenta.

En la parte 3 escribimos una política con el nombre del dispositivo dentro. Funciona para uno, pero con diez obliga a escribir diez políticas. En esta parte vemos cómo funcionan las políticas de IoT por dentro y cómo escribir una sola política que limite a cada dispositivo a lo suyo.

Cómo se evalúa una política de IoT

Cada vez que un dispositivo intenta conectarse, publicar o suscribirse, AWS IoT revisa las políticas adjuntas a su certificado. Todo lo que no está permitido explícitamente está prohibido. Si una acción se rechaza, AWS cierra la conexión, sin mensaje de error en el dispositivo.

Las cuatro acciones principales:

AcciónRecursoCuándo se evalúa
iot:Connectclient/<client-id>Al conectar
iot:Publishtopic/<tópico>En cada mensaje publicado
iot:Subscribetopicfilter/<filtro>Al suscribirse
iot:Receivetopic/<tópico>En cada mensaje recibido

topic vs topicfilter

Es la confusión más común. Suscribirse se evalúa sobre el filtro que pides (topicfilter/...), y recibir se evalúa sobre el tópico concreto de cada mensaje (topic/...). Por eso una suscripción necesita los dos permisos: iot:Subscribe sobre topicfilter e iot:Receive sobre topic.

Los comodines no son los de MQTT

En la política, * es el comodín de las políticas de AWS: coincide con cualquier texto, incluidas barras. Los comodines de MQTT (+ y #) no son comodines en la política: allí se tratan como caracteres literales. Si tu dispositivo se suscribe a casa/+/estado, la política debe permitir exactamente topicfilter/casa/+/estado, o un * que lo cubra.

Variables de política: una política para toda la flota

AWS IoT reemplaza ciertas variables en cada evaluación con los datos de la conexión. La más útil:

Con ella, la misma política sirve para todos los dispositivos:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:REGION:CUENTA:client/${iot:Connection.Thing.ThingName}",
      "Condition": { "Bool": { "iot:Connection.Thing.IsAttached": "true" } }
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": [
        "arn:aws:iot:REGION:CUENTA:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update",
        "arn:aws:iot:REGION:CUENTA:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": [
        "arn:aws:iot:REGION:CUENTA:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/delta",
        "arn:aws:iot:REGION:CUENTA:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/rejected",
        "arn:aws:iot:REGION:CUENTA:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get/accepted"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:Receive",
      "Resource": "arn:aws:iot:REGION:CUENTA:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/*"
    }
  ]
}

Qué garantiza:

Para que funcione, cada certificado tiene que estar asociado a su Thing (attach-thing-principal), y el dispositivo debe conectarse con el nombre de su Thing como client ID.

Otras variables útiles: ${iot:ClientId} (el client ID de la conexión) y ${iot:Connection.Thing.Attributes[nombre]} (un atributo del Thing, por ejemplo una zona o un grupo).

Tópicos propios con la misma idea

Si además del Shadow usas tópicos propios, ponles el nombre del dispositivo para poder limitarlos igual:

casa-demo/<thing>/telemetria     ← el dispositivo publica
casa-demo/<thing>/comandos       ← el dispositivo recibe
{
  "Effect": "Allow",
  "Action": "iot:Publish",
  "Resource": "arn:aws:iot:REGION:CUENTA:topic/casa-demo/${iot:Connection.Thing.ThingName}/telemetria"
}

Diseñar los tópicos con el identificador del dispositivo dentro es lo que hace posible el mínimo privilegio. Un tópico compartido como casa-demo/telemetria obliga a dar permisos sobre todo el tópico a todos.

Probar una política sin un dispositivo

AWS IoT puede evaluar una política sin conectar nada, con test-authorization:

aws iot test-authorization \
  --principal <certificateArn> \
  --client-id mi-esp32 \
  --auth-infos '[{"actionType":"PUBLISH","resources":["arn:aws:iot:REGION:CUENTA:topic/$aws/things/otro-esp32/shadow/update"]}]'

La respuesta dice si la acción está permitida o denegada y por qué política. Es la forma más rápida de comprobar que un dispositivo no puede tocar los tópicos de otro.

Para vigilar la flota, AWS IoT Device Defender tiene una auditoría que marca políticas demasiado permisivas, como las que usan * en iot:Connect.

Errores comunes

Preguntas frecuentes

¿Puedo adjuntar varias políticas a un certificado?

Sí, y se suman. Es útil para separar permisos comunes (el Shadow) de permisos especiales de algunos dispositivos.

¿Las políticas de IoT son las mismas que las de IAM?

Se parecen en la sintaxis, pero son distintas: las de IoT se adjuntan a certificados (o identidades de Cognito) y se evalúan en el broker. Los roles IAM se usan para las llamadas a la API de AWS, por ejemplo desde una Lambda.

¿Qué pasa si un certificado se roba?

Con una política como la de esta parte, quien lo tenga solo puede hacer lo que haría ese dispositivo. Desactiva o revoca el certificado en AWS IoT y deja de funcionar al instante. Más en certificados X.509 para IoT.

Sigue leyendo