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ón | Recurso | Cuándo se evalúa |
|---|---|---|
iot:Connect | client/<client-id> | Al conectar |
iot:Publish | topic/<tópico> | En cada mensaje publicado |
iot:Subscribe | topicfilter/<filtro> | Al suscribirse |
iot:Receive | topic/<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:
${iot:Connection.Thing.ThingName}: el nombre del Thing asociado al certificado que se conectó.
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:
- El client ID debe ser el nombre del Thing. Un dispositivo no puede conectarse haciéndose pasar por otro.
IsAttachedexige que el certificado esté asociado a un Thing; si no, la variable no tendría valor y la conexión se rechaza.- Solo los tópicos de su propio Shadow. El dispositivo A no puede leer ni cambiar el Shadow del dispositivo B, aunque use la misma política.
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
- El dispositivo se conecta y se desconecta en bucle. Falta un permiso para algo que hace al conectar: casi siempre un
Subscribeo elclient/...no coincide con el client ID. - Suscribe pero no recibe. Falta
iot:Receivesobretopic/.... - La variable no se reemplaza. El certificado no está asociado al Thing, o el Thing tiene otro nombre.
$awsen la política. En JSON se escribe tal cual; si la generas con una plantilla o con CDK, asegúrate de que nada lo interprete como variable.- Cambios que tardan. Los cambios de una política pueden tardar unos minutos en aplicarse a conexiones existentes; reconecta el dispositivo para probar.
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.