ブラウザからWebソケットを使用してAWSIoTに接続しようとしています。
私はこの例を試しました: https://github.com/awslabs/aws-iot-examples/tree/master/mqttSample
また、もう1つは少し変更されているため、CognitoIdentityプールのログに記録されたユーザーで使用できます。 https://github.com/dwyl/learn-aws-iot/blob/master/src/js/utils/request.js#L27
有効なIoTポリシーを持つIAMユーザーを使用すると正常に接続できますが、ユーザー資格情報を使用すると、「101スイッチングプロトコル」応答を受け取りますが、その後閉じられます。
認証されたユーザーに関連付けられたIAMロールは正しく、リクエストに署名したり、APIGエンドポイントの呼び出しなどの他のプライベート操作を実行したりできます。また、ソケット接続は403で応答しません。したがって、アクセス許可の問題ではない可能性があります。
他に何ができるでしょうか?
認証されていないコグニトIDの場合、IoTMQTTブローカーへの接続を可能にするには「IDプールの認証済み」ロールで十分です。ただし、認証されたコグニトIDには、次の2つが必要です。
「IDプール認証済み」ロールは、必要なIoTアクション(接続、公開など)へのアクセスを許可する必要があります。
AttachPrincipalPolicy API を使用して、IoTポリシー(デバイスにアタッチされているものとまったく同じ)をコグニトIDにアタッチする必要があります。
ステップ2は、これが必要であることがどこにも特に明確ではなかったため、今日の初めに立ち往生した場所です。
AFAIKには、AWSWebサイトのいずれかからcognitoユーザーにIoTポリシーを添付する方法はありません。ただし、マシンにAWSコマンドラインインターフェイスをセットアップしている場合は、そこから実行できます。コマンドは次のようになります。
aws iot attach-principal-policy --policy-name <iot-policy-name> --principal <cognito-identity-id>
コグニトIDIDは、Federated Identities > Your Pool > Identity browser
を使用して見つけることができます。または、CognitoIdentityCredentials.get
呼び出しへの応答で見つけることもできます。このように見えますus-east-1:ba7cef62-f3eb-5be2-87e5-fffbdeed2824
本番システムの場合、おそらくユーザーのサインアップ時にラムダ関数を使用して、このポリシーの添付を自動化する必要があります。
IoTポリシーを添付する必要があることについて説明しているドキュメントのセクションは、 このページ にあります。
認証されたAmazonCognito IDがAWSアカウントのtopic1でHTTPを介してMQTTメッセージを公開するには、ここで概説するように2つのポリシーを指定する必要があります。最初のポリシーは、Amazon Cognito IDプールロールにアタッチされ、そのプールからのIDが発行呼び出しを行えるようにする必要があります。 2番目のポリシーは、AWS IoT AttachPrincipalPolicyAPIを使用してAmazonCognitoユーザーにアタッチされ、指定されたAmazonCognitoユーザーがtopic1トピックにアクセスできるようにします。
カレブの答えをフロントエンドに実装するために、私はいくつかのことをしなければなりませんでした:
AWSIoTDataAccess
ポリシーの内容をコピーして貼り付けることにより、IoTポリシー(「デフォルト」という名前)を作成します{"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
});
});
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);
}
});
Lambda(NodeJS)関数からCognitoユーザーIDにIoTポリシーをアタッチするためのコードサンプルを次に示します。
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();
}
});
});
}
これは、Cognitoを使用してIoTを認証する方法を示すのに役立つアプリケーションの例です。
https://github.com/awslabs/aws-iot-chat-example
明示的な指示については、次のように読むことができます。
https://github.com/awslabs/aws-iot-chat-example/blob/master/docs/authentication.md