web-dev-qa-db-fra.com

se connecter à AWS IoT à l'aide d'un socket Web avec des utilisateurs authentifiés par Cognito

J'essaie de me connecter à AWS IoT à l'aide du socket Web du navigateur.

J'ai essayé cet exemple: https://github.com/awslabs/aws-iot-examples/tree/master/mqttSample

Et un autre, légèrement modifié, pouvant être utilisé avec les utilisateurs connectés au pool Cognito Identity. https://github.com/dwyl/learn-aws-iot/blob/master/src/js/ utils/request.js # L27

Je peux réussir la connexion si j'utilise un utilisateur IAM avec une stratégie IoT valide, mais si j'utilise les informations d'identification de l'utilisateur, je reçois une réponse "101 protocoles de commutation", mais elle se ferme.

Le rôle IAM associé à l'utilisateur authentifié est correct et je peux signer des demandes et effectuer d'autres opérations privées, telles que l'appel de points de terminaison APIG. De plus, la connexion de socket ne répond pas avec 403. Il ne s'agit donc probablement pas d'un problème d'autorisations.

Quoi d'autre cela pourrait-il être?

15
nachoab

Pour les identités cognito non authentifiées, le rôle "Identity pool anauthenticated" est suffisant pour permettre la connexion au courtier IoT MQTT. Cependant, pour les identités cognito authentifiées, deux choses sont nécessaires:

  1. Le rôle "Identity pool authentified" doit autoriser l'accès aux actions IoT requises (par exemple, connecter, publier, etc.).

  2. Vous devez associer une stratégie IoT (exactement comme celles attachées à vos appareils) à l'identité cognito à l'aide de l'API AttachPrincipalPolicy

La deuxième étape est celle où j’ai été bloquée plus tôt dans la journée car il n’était pas particulièrement clair que cela était nécessaire.

Autant que je sache, il n’existe aucun moyen de lier la stratégie IoT à un utilisateur de cognito à partir d’un site Web AWS. Cependant, si vous avez la configuration de l'interface de ligne de commande AWS sur votre machine, vous pouvez le faire à partir de là. La commande ressemble à:

aws iot attach-principal-policy --policy-name <iot-policy-name> --principal <cognito-identity-id>

L'identifiant d'identité cognito peut être trouvé à l'aide du Federated Identities > Your Pool > Identity browser ou vous pouvez également le trouver dans les réponses à votre appel CognitoIdentityCredentials.get. Cela ressemble à ceci us-east-1:ba7cef62-f3eb-5be2-87e5-fffbdeed2824

Pour un système de production, vous souhaiterez évidemment automatiser la connexion de cette stratégie, probablement à l'aide d'une fonction lambda lors de l'inscription de l'utilisateur.

La section de la documentation traitant de la nécessité de joindre la stratégie IoT est disponible sur cette page :

Pour qu'une identité Amazon Cognito authentifiée publie des messages MQTT via HTTP sur la rubrique 1 de votre compte AWS, vous devez spécifier deux stratégies, comme indiqué ici. La première stratégie doit être attachée à un rôle de pool d'identités Amazon Cognito et permettre aux identités de ce pool d'effectuer un appel de publication. La deuxième stratégie est liée à un utilisateur Amazon Cognito à l'aide de l'API AWS IoT AttachPrincipalPolicy et permet à l'utilisateur Amazon Cognito spécifié d'accéder à la rubrique topic1.

16
Caleb Vear

Afin de mettre en œuvre la réponse de Caleb sur le front-end, je devais faire quelques choses:

  1. Créez une stratégie IoT (nommée "par défaut") en accédant à la console IoT> Sécurité> Stratégies, puis en y copiant et en collant le contenu de la stratégie AWSIoTDataAccess.
  2. Ajoutez la stratégie en ligne suivante au rôle authentifié de mon compte Cognito Identity Pool: {"Effect": "Allow", "Action": ["iot:AttachPrincipalPolicy"], "Resource": ["*"]

Ensuite, j'ai mis à jour mon code frontal pour ressembler à:

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
  });
});
8
senornestor

Je me suis référé aux réponses de Caleb et senornestor, et la mise en œuvre suivante a fonctionné pour moi:

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
meetpatelvgec

Voici un exemple de code permettant d'associer une stratégie IoT à un ID utilisateur Cognito à partir d'une fonction 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();
            }
        });
    });
}
2

Voici un exemple d'application qui devrait vous aider à montrer comment authentifier IoT avec Cognito:

https://github.com/awslabs/aws-iot-chat-example

Pour des instructions explicites, vous pouvez lire:

https://github.com/awslabs/aws-iot-chat-example/blob/master/docs/authentication.md

0
Nosajool