使用Cognito凭证的AWS IOT连接

时间:2019-04-25 18:10:14

标签: python amazon-cognito amazon-iam aws-iot

我在使用Cognito凭证从python脚本连接到AWS IOT时遇到问题。我正在python中使用AWS IOT SDK以及boto3软件包。这是我在做什么:

首先,我建立了一个Cognito用户池,其中有几个具有用户名和密码才能登录的用户。我还建立了一个Cognito身份池,其中Cognito用户池是唯一的身份验证提供程序。我不提供对未经身份验证的身份的访问。身份池具有Auth角色,我将其称为“ MyAuthRole”,当我转到IAM时,该角色具有两个附加策略:一个是默认策略:

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

第二个是用于物联网访问的策略:

{
    "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身份进行身份验证以通过HTTP发布MQTT消息,您必须指定两个策略。第一个策略必须附加到Amazon Cognito身份池角色。是先前在IdentityPoolAuthRole中定义的托管策略AWSIoTDataAccess。

第二个策略必须使用AWS IoT AttachPrincipalPolicy API附加到Amazon Cognito用户。”

但是,我不知道如何使用python或使用AWS控制台实现以上目标。

如何解决此问题?

1 个答案:

答案 0 :(得分:0)

很正确,您错过的步骤是使用AttachPrincipalPolicy API(现已弃用,并已由Iot::AttachPolicy取代。)

为此:

  • 创建物联网策略(IoT Core > Secure > Policies > Create)
  • 从共享的代码中为该策略授予您希望该策略附加的任何用户拥有的权限,这意味着仅复制第二个IAM策略。尽管您希望将其锁定在生产中!
  • 使用AWS CLI,您可以使用以下方法将此策略附加到您的认知用户:

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

aws-samples/aws-iot-chat-example上有一个涉及更多的AWS示例,但是它使用的是JavaScript。我无法在Python中找到等效项,但是无论哪种语言,Cognito / IAM / IoT配置步骤和所需的API调用都将保持不变。