【发布时间】:2019-09-15 05:49:00
【问题描述】:
我在使用 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": [
"*"
]
}
]
}
第二个是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 身份以通过 HTTP 发布 MQTT 消息,您必须指定两个策略。第一个策略必须附加到 Amazon Cognito 身份池角色。此是之前在 IdentityPoolAuthRole 中定义的托管策略 AWSIoTDataAccess。
第二个策略必须使用 AWS IoT AttachPrincipalPolicy API 附加到 Amazon Cognito 用户。”
但是,我不知道如何在 python 中或使用 AWS 控制台实现上述目标。
我该如何解决这个问题?
【问题讨论】:
标签: python amazon-cognito amazon-iam aws-iot