Подключение AWS IOT с использованием учетных данных Cognito - PullRequest
1 голос
/ 25 апреля 2019

У меня проблемы с подключением к AWS IOT из скрипта Python с использованием учетных данных Cognito. Я использую AWS IOT SDK в Python, а также пакет boto3. Вот что я делаю:

Сначала я настроил Cognito User Pool с парой пользователей, у которых есть имя пользователя и пароль для входа. Я также настроил Cognito Identity Pool с моим Cognito User Pool в качестве единственного поставщика аутентификации. Я не предоставляю доступ к неаутентифицированным личностям. У пула удостоверений есть роль авторизации. Я просто назову ее «MyAuthRole», и когда я перехожу к IAM, к этой роли прикрепляются две политики: одна - это политика по умолчанию:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "mobileanalytics:PutEvents",
                "cognito-sync:*",
                "cognito-identity:*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

и вторая политика для доступа к IOT:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "iot:*",
            "Resource": "*"
        }
    ]
}

Далее у меня есть код Python, чтобы использовать учетные данные своей учетной записи AWS IAM (ключ доступа и секретный ключ), чтобы получить временный токен аутентификации, подобный следующему:

auth_data = { 'USERNAME':username , 'PASSWORD':password }
provider_client=boto3.client('cognito-idp', region_name=region)
resp = provider_client.admin_initiate_auth(UserPoolId=user_pool_id, AuthFlow='ADMIN_NO_SRP_AUTH', AuthParameters=auth_data, ClientId=client_id)
id_token=resp['AuthenticationResult']['IdToken']

Наконец, я пытаюсь использовать этот токен для подключения к AWS IOT, используя эту функцию:

def _get_aws_cognito_temp_credentials(aws_access_key_id=None,aws_secret_access_key=None,
                region_name='us-west-2',account_id=None,user_pool_id=None,
                identity_pool_id=None,id_token=None):
    boto3.setup_default_session(aws_access_key_id=aws_access_key_id,
                aws_secret_access_key=aws_secret_access_key,
                region_name = region_name)
    identity_client = boto3.client('cognito-identity', region_name=region_name)
    loginkey = "cognito-idp.%s.amazonaws.com/%s" % (region_name,user_pool_id)
    print("loginkey is %s" % loginkey)
    loginsdict={
        loginkey: id_token
    }
    identity_response = identity_client.get_id(AccountId=account_id,
                IdentityPoolId=identity_pool_id,
                Logins=loginsdict)
    identity_id = identity_response['IdentityId']
    #
    # Get the identity's credentials
    #
    credentials_response = identity_client.get_credentials_for_identity(
                IdentityId=identity_id,
                Logins=loginsdict)
    credentials = credentials_response['Credentials']
    access_key_id = credentials['AccessKeyId']
    secret_key = credentials['SecretKey']
    service = 'execute-api'
    session_token = credentials['SessionToken']
    expiration = credentials['Expiration']
    return access_key_id,secret_key,session_token,expiration

Наконец, я создаю клиент AWS IOT и пытаюсь подключиться так:

myAWSIoTMQTTClient = AWSIoTMQTTClient(clientId, useWebsocket=True)
myAWSIoTMQTTClient.configureEndpoint(host, port)
myAWSIoTMQTTClient.configureIAMCredentials(temp_access_key_id,
                        temp_secret_key,
                        temp_session_token)
myAWSIoTMQTTClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTClient.configureOfflinePublishQueueing(-1)
myAWSIoTMQTTClient.configureDrainingFrequency(2)
myAWSIoTMQTTClient.configureConnectDisconnectTimeout(10)
myAWSIoTMQTTClient.configureMQTTOperationTimeout(5)
log.info("create_aws_iot_client", pre_connect=True)
myAWSIoTMQTTClient.connect()
log.info("create_aws_iot_client", post_connect=True, myAWSIoTMQTTClient=myAWSIoTMQTTClient)

Проблема в том, что он доходит до pre_connect, а затем просто зависает и, в конце концов, отключается. Я получаю сообщение об ошибке:

AWSIoTPythonSDK.exception.AWSIoTExceptions.connectTimeoutException

Я также где-то читал, что могут быть другие политики, которые так или иначе должны быть прикреплены:

"В соответствии с документацией« Политики для HTTP »и« WebSocketClients », для аутентификации удостоверения Amazon Cognito для публикации сообщений MQTT по HTTP необходимо указать две политики. Первая политика должна быть присоединена к роли пула удостоверений Amazon Cognito. является управляемой политикой AWSIoTDataAccess, которая была определена ранее в IdentityPoolAuthRole.

Вторая политика должна быть присоединена к пользователю Amazon Cognito с помощью API AWS IoT AttachPrincipalPolicy. "

Однако я понятия не имею, как добиться этого в python или с помощью консоли AWS.

Как мне исправить эту проблему?

1 Ответ

0 голосов
/ 26 апреля 2019

Вы правы, что пропущенный шаг использует API AttachPrincipalPolicy (который теперь устарел и был заменен на Iot :: AttachPolicy .)

Для этого:

  • Создание политики IoT (IoT Core> Защита> Политики> Создать)
  • Дайте политике разрешения, которые вы хотите, чтобы любой пользователь, присоединенный к этой политике, из вашего кода как общего ресурса означал бы просто копирование второй политики IAM. Хотя вы захотите заблокировать это на производстве!
  • Используя AWS CLI , вы можете прикрепить эту политику к своему cognito пользователю, используя:

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

Существует гораздо более сложный пример AWS на aws-samples / aws-iot-chat-example , однако он есть в JavaScript. Я не смог найти эквивалент в Python, однако шаги по настройке Cognito / IAM / IoT и требуемые вызовы API останутся неизменными независимо от языка.

...