我正在尝试使用浏览器中的Web套接字连接到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
如果我使用具有有效IoT策略的IAM用户,我可以成功连接,但如果我使用用户凭据,则会收到“101 Switching Protocols”响应,但随后会关闭。
与经过身份验证的用户关联的IAM角色是正确的,我可以签署请求并执行其他私有操作,如调用APIG端点。此外,套接字连接不响应403.因此,它可能不是权限问题。
还有什么呢?
答案 0 :(得分:16)
对于未经身份验证的Cognito身份,“Identity pool anauthenticated”角色足以允许连接到IoT MQTT代理。然而,对于经过身份验证的认知身份,需要做两件事:
“身份池已通过身份验证”角色必须允许访问您需要的IoT操作(例如,连接,发布等)。
第2步是我今天早些时候被困住的地方,因为在任何地方都不是特别清楚这是必需的。
AFAIK无法将任何AWS网站上的IoT政策附加到Cognito用户。但是,如果您在计算机上安装了AWS命令行界面,则可以从那里进行设置。该命令如下所示:
aws iot attach-principal-policy --policy-name <iot-policy-name> --principal <cognito-identity-id>
可以使用Federated Identities > Your Pool > Identity browser
找到认知身份ID,也可以在对CognitoIdentityCredentials.get
来电的回复中找到它。它看起来像us-east-1:ba7cef62-f3eb-5be2-87e5-fffbdeed2824
对于生产系统,您显然希望自动附加此策略,可能在用户注册时使用lambda函数。
可以在this page上找到有关需要附加IoT政策的文档部分:
对于经过身份验证的Amazon Cognito标识,要在AWS账户中的topic1上通过HTTP发布MQTT消息,您必须指定两个策略,如此处所述。必须将第一个策略附加到Amazon Cognito标识池角色,并允许该池中的标识进行发布调用。第二个策略使用AWS IoT AttachPrincipalPolicy API附加到Amazon Cognito用户,并允许指定的Amazon Cognito用户访问topic1主题。
答案 1 :(得分:8)
为了在前端实现Caleb的答案,我不得不做几件事:
AWSIoTDataAccess
策略内容复制并粘贴到其中{"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
});
});
答案 2 :(得分:4)
我参考了Caleb和senornestor的答案,以下实施对我有用:
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);
}
});
答案 3 :(得分:2)
以下是从Lambda(NodeJS)函数将IoT策略附加到Cognito用户ID的代码示例。
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();
}
});
});
}
答案 4 :(得分:1)
事实证明,即使在 2021 年,也有必要创建一个专门的 Lambda 函数来执行 AttachPolicy
(不是 ,因为它已经过时了)。如the official Docs中所述:AttachPrincipalPolicy
要将 AWS IoT Core 策略附加到 Amazon Cognito 身份,您必须定义一个调用 AttachPolicy 的 Lambda 函数。
其他答案展示了如何实现该 Lambda。
答案 5 :(得分:0)
以下示例应用程序应该有助于演示如何使用Cognito验证IoT:
https://github.com/awslabs/aws-iot-chat-example
有关明确说明,请参阅:
https://github.com/awslabs/aws-iot-chat-example/blob/master/docs/authentication.md