我在使用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控制台实现以上目标。
如何解决此问题?
答案 0 :(得分:0)
很正确,您错过的步骤是使用AttachPrincipalPolicy API(现已弃用,并已由Iot::AttachPolicy取代。)
为此:
使用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调用都将保持不变。