Python 使用Cognito凭据的AWS IOT连接

Python 使用Cognito凭据的AWS IOT连接,python,amazon-cognito,amazon-iam,aws-iot,Python,Amazon Cognito,Amazon Iam,Aws Iot,我使用Cognito凭据从python脚本连接到AWS IOT时遇到问题。我正在使用python中的AWS IOT SDK以及boto3包。以下是我正在做的: 首先,我建立了一个Cognito用户池,其中有两个用户有用户名和密码可以登录。我还设置了一个Cognito身份池,其中我的Cognito用户池是唯一的身份验证提供者。我不提供对未经验证身份的访问。标识池有一个身份验证角色,我将其称为“MyAuthRole”,当我转到IAM时,该角色附带了两个策略:一个是默认策略: { "Versi

我使用Cognito凭据从python脚本连接到AWS IOT时遇到问题。我正在使用python中的AWS IOT SDK以及boto3包。以下是我正在做的:

首先,我建立了一个Cognito用户池,其中有两个用户有用户名和密码可以登录。我还设置了一个Cognito身份池,其中我的Cognito用户池是唯一的身份验证提供者。我不提供对未经验证身份的访问。标识池有一个身份验证角色,我将其称为“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']
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)
最后,我尝试使用此令牌连接到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客户端并尝试如下连接:

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']
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和WebSocketClient文档的策略,为了验证Amazon Cognito标识以通过HTTP发布MQTT消息,必须指定两个策略。第一个策略必须附加到Amazon Cognito标识池角色。这是前面在IdentityPoolAuthRole中定义的托管策略AWSIoTDataAccess

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

但是,我不知道如何在python中或使用AWS控制台实现上述功能


如何解决此问题?

您是对的,您错过的步骤是使用AttachPrincipalPolicy API(该API现在已折旧,并已替换为。)

为此:

  • 创建物联网策略

  • 将您希望附加到该策略的任何用户所拥有的权限从共享代码中授予该策略,这意味着只需复制第二个IAM策略。尽管您希望在生产中锁定该权限

  • 使用,您可以使用以下方法将此策略附加到您的cognito用户:

    aws物联网附加策略--策略名称--目标


在中有一个更为复杂的AWS示例,但它是在JavaScript中。我在Python中找不到类似的示例,但是Cognito/IAM/IoT配置步骤和所需的API调用在任何语言中都将保持不变。

谢谢,但不清楚我到底在哪里执行此操作。我在获得temp凭据后是否执行此操作?您的代码很好,这只是一个过程。与您必须创建标识池身份验证角色的方式相同,您还必须使用CLI中的“附加策略”命令将策略附加到标识(似乎没有用于该策略的用户界面).不,不起作用。我在AWS物联网服务中创建了一个新的物联网策略,我们称之为MarcIOTAttachPolicy。然后我尝试了两种方法:(1)运行您给我的AWS cli命令,以及(2)使用boto3 python包:物联网客户端=boto3.client('IOT',region\u name=region\u name),然后是物联网客户端.attach\u策略(policyName=cognito\u user\u policy\u name,target=identity\u id)。仍然挂起并超时。