如何在 Python 中使用 Cognito 凭据调用 API 网关

How do I call an API Gateway with Cognito credentials in Python

我已经成功设置了一个使用 Cognito 保护的 API 网关。未经身份验证的用户角色有一个访问策略,应该授予它访问网关的权限。我还设法使用 boto3 从池中检索身份 ID 并获取关联的开放 ID 令牌,以及关联的秘密和访问密钥。

我现在如何使用这些凭证调用网关?有没有办法使用 boto3 来处理对 API 上特定方法的请求签名?

这是我们 public 文档中的示例:http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html

Cognito 信用与任何其他临时信用没有区别,签名过程也相同。如果你想回到 Python 上面的例子应该很好,或者我猜想有第三方库可以为你做签名。

以下代码(和 requests-aws4auth 库)完成了这项工作:

import boto3
import datetime
import json
from requests_aws4auth import AWS4Auth
import requests

boto3.setup_default_session(region_name='us-east-1')
identity = boto3.client('cognito-identity', region_name='us-east-1')

account_id='XXXXXXXXXXXXXXX'
identity_pool_id='us-east-1:YYY-YYYY-YYY-YY'
api_prefix='ZZZZZZZZZ'

response = identity.get_id(AccountId=account_id, IdentityPoolId=identity_pool_id)
identity_id = response['IdentityId']
print ("Identity ID: %s"%identity_id)

resp = identity.get_credentials_for_identity(IdentityId=identity_id)
secretKey = resp['Credentials']['SecretKey']
accessKey = resp['Credentials']['AccessKeyId']
sessionToken = resp['Credentials']['SessionToken']
expiration = resp['Credentials']['Expiration']

print ("\nSecret Key: %s"%(secretKey))
print ("\nAccess Key %s"%(accessKey))
print ("\nSession Token: %s"%(sessionToken))
print ("\nExpiration: %s"%(expiration))

method = 'GET'
headers = {}
body = ''
service = 'execute-api'
url = 'https://%s.execute-api.us-east-1.amazonaws.com/dev/helloworld' % api_prefix
region = 'us-east-1'

auth = AWS4Auth(accessKey, secretKey, region, service, session_token=sessionToken)
response = requests.request(method, url, auth=auth, data=body, headers=headers)
print(response.text)

我的代码主要基于提问者自己的回答,但我试图更清楚地说明所有值的来源。

import boto3
import requests
from requests_aws4auth import AWS4Auth
# Use 'pip install boto3 requests requests-aws4auth' to get these

region_name = 'ap-southeast-2' # or 'us-west-1' or whatever

# 12 decimal digits from your AWS login page
account_id = '123456789012'

# I've only found this in the sample code for other languages, e.g. JavaScript
# Services→Cognito→Manage Federated Identities→(your-id-pool)→Sample code
identity_pool_id = 'ap-southeast-2:fedcba98-7654-3210-1234-56789abcdef0'

# Create a new identity
boto3.setup_default_session(region_name = region_name)
identity_client = boto3.client('cognito-identity', region_name=region_name)
identity_response = identity_client.get_id(AccountId=account_id,
    IdentityPoolId=identity_pool_id)

# We normally wouldn't log this, but to illustrate:
identity_id = identity_response['IdentityId']
print ('identity_id:', identity_id) # good idea not to log this

# Get the identity's credentials
credentials_response = identity_client.get_credentials_for_identity(IdentityId=identity_id)
credentials = credentials_response['Credentials']
access_key_id = credentials['AccessKeyId']
secret_key = credentials['SecretKey']
service = 'execute-api'
session_token = credentials['SessionToken']
expiration = credentials['Expiration']
# Again, we normally wouldn't log this:
print ('access_key_id', access_key_id)
print ('secret_key', secret_key)
print ('session_token', session_token)
print ('expiration', expiration)
# The access_key_id will look something like 'AKIABC123DE456FG7890', similar to
# Services→IAM→Users→(AWS_USER_NAME)→Security credentials→Access key ID

# Get the authorisation object
auth = AWS4Auth(access_key_id, secret_key, region_name, service,
    session_token=session_token)
current_app['auth'] = auth
# Just an illustration again:
print ('auth: %(service)s(%(date)s) %(region)s:%(access_id)s' % auth.__dict__)

# We'll use that object to send a request to our app. This app doesn't
# exist in real life, though, so you'll need to edit the following quite
# heavily:

# Services→Cognito→Manage your User Pools→(your-user-pool)→Apps→App name
app_name = 'my-app-name'

api_path = 'dev/helloworld'
method = 'GET'
headers = {}
body = ''
url = 'https://%s.%s.%s.amazonaws.com/%s' % (app_name, service, region_name,
    api_path)
response = requests.request(method, url, auth=auth, data=body, headers=headers)

identity_pool_id如何获得

如果您还没有可以给您 "identity_pool_id" 的联合池, 下面的执行代码会给你 identity_pool_id

import boto3
boto3.setup_default_session(
    aws_access_key_id='AKIAJ7TBC72BPWNEWIDQ', 
    aws_secret_access_key='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', 
    region_name='ap-southeast-2')

client = boto3.client('cognito-identity')
response = client.list_identity_pools(MaxResults=3,)

print("IdentityPoolId-- ", response)

下一个代码运行得非常好。

希望得到帮助:

from pprint import pprint
import requests
from pycognito import Cognito


USER_POOL_ID = 'eu-central-1_XXXXXXXXXXX'
CLIENT_ID = 'XXXXXXXXXXXX'
CLIENT_SECRET = 'XXXXXXXXXXX'

u = Cognito(USER_POOL_ID,CLIENT_ID, client_secret=CLIENT_SECRET, username='cognito user name')
u.authenticate('cognito user password')

id_token = u.id_token

headers = {'Authorization':  'Bearer ' + id_token}
api_url = 'https://XXXXXXXXXXX.execute-api.eu-central-1.amazonaws.com/stage/XXXXXXXXXXX'

r = requests.get(api_url, headers=headers)
pprint(dict(r.headers))
print(r.status_code)
print(r.text)