Подключитесь к AWS IoT с помощью веб-гнезда с аутентифицированными пользователями Cognito
Я пытаюсь подключиться к AWS IoT с помощью веб-сокета из браузера.
Я пробовал этот пример:
https://github.com/awslabs/aws-iot-examples/tree/master/mqttSample
И еще один немного измененный, чтобы его можно было использовать с пользователями журнала Cognito Identity.
https://github.com/dwyl/learn-aws-iot/blob/master/src/js/utils/request.js#L27
Я могу успешно подключиться, если я использую пользователя IAM с допустимой политикой IoT, но если я использую учетные данные пользователя, я получаю ответ "101 Switching Protocols", но затем он закрывается.
Роль IAM, связанная с аутентифицированным пользователем, является правильной, и я могу подписывать запросы и выполнять другие частные операции, такие как вызов APPS конечных точек. Кроме того, соединение сокета не отвечает 403. Поэтому, скорее всего, это не проблема с разрешениями.
Что еще может быть?
Ответы
Ответ 1
Для неаутентифицированных идентификаторов cognito роль "Identity pool anauthenticated" достаточна для подключения к брокеру IoT MQTT. Однако для аутентифицированных идентификаторов cognito требуются две вещи:
-
Роль аутентифицированного пула удостоверений должна обеспечивать доступ к требуемым действиям IoT (например, подключаться, публиковать и т.д.).
-
Вы должны приложить к идентификатору cognito политику IoT (точно так же, как те, которые прикреплены к вашим устройствам), используя API AttachPrincipalPolicy
Шаг 2 - это то место, где я застрял сегодня сегодня, поскольку это было не особенно ясно, когда это требовалось.
AFAIK нет способа привязать политику IoT к пользователю cognito с любого из веб-сайтов AWS. Однако, если у вас есть интерфейс командной строки AWS на вашем компьютере, вы можете сделать это оттуда. Команда выглядит так:
aws iot attach-principal-policy --policy-name <iot-policy-name> --principal <cognito-identity-id>
Идентификатор идентификатора cognito можно найти с помощью Federated Identities > Your Pool > Identity browser
или вы также можете найти его в ответах на ваш вызов CognitoIdentityCredentials.get
. Это выглядит как us-east-1:ba7cef62-f3eb-5be2-87e5-fffbdeed2824
Для производственной системы вы, очевидно, захотите автоматизировать прикрепление этой политики, возможно, используя лямбда-функцию при регистрации пользователя.
Раздел документов, которые говорят о необходимости приложить политику IoT, можно найти на этой странице:
Для аутентифицированной идентичности Amazon Cognito для публикации сообщений MQTT по HTTP на topic1 в вашей учетной записи AWS необходимо указать две политики, как описано здесь. Первая политика должна быть привязана к роли пула идентификаторов Amazon Cognito и разрешать идентификаторы из этого пула для вызова публикации. Вторая политика связана с пользователем Amazon Cognito с использованием API AWS IoT AttachPrincipalPolicy и позволяет указанному пользователю Amazon Cognito перейти к теме topic1.
Ответ 2
Чтобы реализовать ответ Caleb на интерфейсе, мне пришлось сделать пару вещей:
- Создайте политику IoT (по умолчанию), перейдя в IoT Console > Безопасность > Политики и скопировав и вставив в нее содержимое политики
AWSIoTDataAccess
- Добавьте следующую встроенную политику в мою аутентифицированную роль пула Cognito Identity:
{"Effect": "Allow", "Action": ["iot:AttachPrincipalPolicy"], "Resource": ["*"]
Затем я обновил свой внешний код, чтобы выглядеть так:
AWS.config.region = process.env.AWS_REGION;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: process.env.AWS_IDENTITY_POOL,
Logins: {
'graph.facebook.com': FACEBOOK_ACCESS_TOKEN
}
});
AWS.config.credentials.get(() => {
const IoT = new AWS.Iot();
IoT.attachPrincipalPolicy({
policyName: 'default',
principal: AWS.config.credentials.identityId
}, (err, res) => {
if (err) console.error(err);
// Connect to AWS IoT MQTT
});
});
Ответ 3
Я ссылался на ответы Калеба и сенорстора, и для меня работала следующая реализация:
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: AWSConfiguration.poolId,
Logins: {
'accounts.google.com': user.Zi.id_token
}
});
var cognitoIdentity = new AWS.CognitoIdentity();
AWS.config.credentials.get(function(err, data) {
if (!err) {
console.log('retrieved identity: ' + AWS.config.credentials.identityId);
var params = {
IdentityId: AWS.config.credentials.identityId,
Logins: {
"accounts.google.com": user.Zi.id_token
}
};
cognitoIdentity.getCredentialsForIdentity(params, function(err, data) {
if (!err) {
console.log('retrieved credentials');
const IoT = new AWS.Iot();
IoT.attachPrincipalPolicy({
policyName: 'exampleIoTPolicy',
principal: AWS.config.credentials.identityId
}, (err, res) => {
if (err) console.error(err);
}); // Change the "policyName" to match your IoT Policy
} else {
console.log('error retrieving credentials: ' + err);
alert('error retrieving credentials: ' + err);
}
});
} else {
console.log('error retrieving identity:' + err);
alert('error retrieving identity: ' + err);
}
});
Ответ 4
Вот пример кода для присоединения политики IoT к идентификатору пользователя Cognito из функции Lambda (NodeJS).
function attachPrincipalPolicy(device_id, cognito_user_id) {
const iotMgmt = new AWS.Iot();
return new Promise(function(resolve, reject) {
let params = {
policyName: device_id + '_policy',
principal: cognito_user_id
};
console.log("Attaching IoT policy to Cognito principal")
iotMgmt.attachPrincipalPolicy(params, (err, res) => {
if (err) {
console.error(err);
reject(err);
} else {
resolve();
}
});
});
}
Ответ 5
Вот пример приложения, которое должно помочь продемонстрировать, как аутентифицировать IoT с помощью Cognito:
https://github.com/awslabs/aws-iot-chat-example
Для явных инструкций вы можете прочитать:
https://github.com/awslabs/aws-iot-chat-example/blob/master/docs/authentication.md