Подключиться к AWS IoT с помощью веб-сокета с аутентифицированными пользователями Cognito
Я пытаюсь подключиться к AWS IoT с помощью веб-сокета из браузера.
Я попробовал этот пример: https://github.com/awslabs/aws-iot-examples/tree/master/mqttSample
И еще один, немного измененный, чтобы его можно было использовать с зарегистрированными пользователями Cognito Identity Pool. https://github.com/dwyl/learn-aws-iot/blob/master/src/js/utils/request.js#L27
Я могу успешно подключиться, если я использую пользователя IAM с действующей политикой IoT, но если я использую учетные данные пользователя, я получаю ответ "101 Switching Protocols", но затем он закрывается.
Роль IAM, связанная с аутентифицированным пользователем, является правильной, и я могу подписывать запросы и выполнять другие частные операции, такие как вызов конечных точек APIG. Кроме того, соединение с сокетом не отвечает с 403. Таким образом, это, вероятно, не проблема с разрешениями.
Что еще это может быть?
6 ответов
Для неаутентифицированных идентификаторов Cognito достаточно роли "Аутентифицированный пул идентификаторов", чтобы разрешить подключение к брокеру IoT MQTT. Однако для аутентифицированных идентификаторов Cognito требуются две вещи:
Роль "Идентифицированный пул удостоверений" должна разрешать доступ к нужным вам действиям IoT (например, подключение, публикация и т. Д.).
Вы должны присоединить политику IoT (точно так же, как те, которые подключены к вашим устройствам) к идентификатору Cognito, используя 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.
Чтобы реализовать ответ Калеба на внешнем интерфейсе, мне пришлось сделать пару вещей:
- Создайте политику IoT (с именем "по умолчанию"), перейдя в Консоль IoT> Безопасность> Политики, скопировав и вставив
AWSIoTDataAccess
содержание политики в нем - Добавьте следующую встроенную политику к проверенной роли моего Cognito Identity Pool:
{"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
});
});
Вот пример кода для присоединения политики 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();
}
});
});
}
Я сослался на ответы Калеба и сенорнестора, и у меня сработала следующая реализация:
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);
}
});
Вот пример приложения, которое должно помочь продемонстрировать, как аутентифицировать IoT с помощью Cognito:
https://github.com/awslabs/aws-iot-chat-example
Для подробных инструкций вы можете прочитать:
https://github.com/awslabs/aws-iot-chat-example/blob/master/docs/authentication.md
Оказывается, даже в 2021 году необходимо создать специальную лямбда-функцию, которая
AttachPolicy
. Как указано в официальных документах :
Чтобы привязать политику AWS IoT Core к Amazon Cognito Identity, необходимо определить функцию Lambda, которая вызывает AttachPolicy.
Другие ответы показали, как реализовать эту Lambda.