为Python Requests库提供Amazon Web Services版本4认证。
特性
- 支持所有使用AWS auth v4的AWS服务的Requests认证
- 独立的签名密钥对象
- 当超过作用域日期边界时自动重新生成密钥
- 支持STS临时凭证
实现基于头部的认证,不支持GET URL参数和POST参数认证。
支持的服务
该软件包已经测试可用于以下服务:
AppStream、AppSync、Auto-Scaling、CloudFormation、CloudFront、CloudHSM、CloudSearch、CloudTrail、CloudWatch监控、CloudWatch日志、CodeDeploy、Cognito Identity、Cognito Sync、Config、DataPipeline、Direct Connect、DynamoDB、Elastic Beanstalk、ElastiCache、EC2、EC2容器服务、Elastic Load Balancing、Elastic MapReduce、ElasticSearch、Elastic Transcoder、Glacier、Identity and Access Management (IAM)、Key Management Service (KMS)、Kinesis、Lambda、Opsworks、Redshift、Relational Database Service (RDS)、Route 53、Simple Storage Service (S3)、Simple Notification Service (SNS)、Simple Queue Service (SQS)、Storage Gateway、Security Token Service (STS)
以下服务不支持AWS auth版本4,无法与此软件包一起使用:
Simple Email Service (SES)、Simple Workflow Service (SWF)、Import/Export、SimpleDB、DevPay、Mechanical Turk
AWS Support API尚未测试,因为它需要高级订阅。
Python版本
在1.x语义版本中,最低Python支持将逐步提高:
- 1.0.x: 支持python2.7和python3.3+。
- 1.1.x: 不支持python2.7,仅尽力而为。支持python3.3+。
- 1.2.x: Requires-Python将设置为python3.3+,明确移除早期版本。python<3.7不受支持,仅尽力而为。
- 1.3.x: Requires-Python将设置为python3.7+,明确移除早期版本。(尽力而为待定)
安装
通过pip安装:
$ pip install requests-aws4auth
requests-aws4auth需要Kenneth Reitz的Requests库。
requests-aws4auth在Python 2.7和3.5及以上版本上进行了测试。
0.8版本的行为变化
0.8版本引入了请求日期检查和自动密钥重新生成行为作为默认设置。这对于在线程之间共享身份验证对象以及存储密钥有影响。有关详细信息,请参阅下面的相关部分。另请参阅GitHub问题#10中的讨论。
基本用法
>>> import requests
>>> from requests_aws4auth import AWS4Auth
>>> endpoint = 'http://s3-eu-west-1.amazonaws.com'
>>> auth = AWS4Auth('<访问ID>', '<访问密钥>', 'eu-west-1', 's3')
>>> response = requests.get(endpoint, auth=auth)
>>> response.text
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01">
<Owner>
<ID>bcaf1ffd86f461ca5fb16fd081034f</ID>
<DisplayName>webfile</DisplayName>
...
此示例将列出Amazon S3服务的eu-west-1
区域中的存储桶。
STS临时凭证
>>> from requests_aws4auth import AWS4Auth
>>> auth = AWS4Auth('<访问ID>', '<访问密钥>', 'eu-west-1', 's3',
session_token='<会话令牌>')
...
此示例展示了如何构造用于STS临时凭证的AWS4Auth对象。添加了带有会话令牌的x-amz-security-token
头。不管理临时凭证超时 - 如果临时凭证过期,需要重新生成并用新凭证重新构造AWS4Auth对象。
使用botocore RefreshableCredentials的动态STS凭证
>>> from requests_aws4auth import AWS4Auth
>>> from botocore.session import Session
>>> credentials = Session().get_credentials()
>>> auth = AWS4Auth(region='eu-west-1', service='es',
refreshable_credentials=credentials)
...
此示例展示了如何使用自动刷新凭证构造AWS4Auth实例,适用于使用AWS IAM assume-role的长时间运行应用程序。 RefreshableCredentials实例用于生成每个请求的有效静态凭证,无需在临时凭证过期时重新创建AWS4Auth实例。
日期处理
如果要进行身份验证的HTTP请求包含Date
或X-Amz-Date
头,AWS只会在头中的日期与签名密钥的作用域日期匹配时接受授权请求(参见AWS REST API日期文档)。
从requests-aws4auth的0.8版本开始,如果头部日期与作用域日期不匹配,AWS4Auth
实例将自动重新生成其签名密钥,使用与前一个密钥相同的作用域参数,除了日期将更改为匹配请求日期。如果请求不包含日期,则当前日期将添加到X-Amz-Date
头中的请求中,如果这与作用域日期不同,则重新生成签名密钥。
这意味着AWS4Auth
现在从X-Amz-Date
和Date
头的值中提取和解析日期。支持的日期格式有:
- RFC 7231(例如:Mon, 09 Sep 2011 23:36:00 GMT)
- RFC 850(例如:Sunday, 06-Nov-94 08:49:37 GMT)
- C 时间(例如:Wed Dec 4 00:00:00 2002)
- Amz-Date 格式(例如:20090325T010101Z)
- ISO 8601 / RFC 3339(例如:2009-03-25T10:11:12.13-01:00)
如果存在任一标头但 AWS4Auth
无法提取日期(因为所有存在的日期标头格式无法识别),AWS4Auth
将删除任何现有的 X-Amz-Date
和 Date
标头,并替换为单个包含当前日期的 X-Amz-Date
标头。可以使用 AWS4Auth
构造函数的 raise_invalid_date
关键字参数修改此行为。
自动密钥重新生成
如果您不希望在遇到请求日期与范围日期不匹配时自动重新生成签名密钥,请使用替代的 StrictAWS4Auth
类。该类与 AWS4Auth
相同,但在遇到日期不匹配时只会引发 DateMismatchError
。您也可以使用 PassiveAWS4Auth
类,它模仿 0.8 版本之前的 AWS4Auth
行为,只是签名并发送请求,无论日期是否匹配。在这种情况下,由调用代码来处理由日期不匹配导致的 AWS 身份验证失败响应。
密钥存储
为了允许自动密钥重新生成,密钥存储在 AWS4Auth
实例的签名密钥对象中。如果您不希望这样,请使用 store_secret_key
参数设置为 False 的 AWS4Signing
密钥来实例化:
>>> sig_key = AWS4SigningKey(secret_key, region, service, date, False)
>>> auth = StrictAWS4Auth(access_id, sig_key)
然后,当 AWS4Auth
类尝试重新生成其密钥时,将引发 NoSecretKeyError
。一种稍微更优雅的处理方式是使用替代的 StrictAWS4Auth
类,同样使用 store_secret_key = False
创建的 AWS4SigningKey
实例来实例化它。
多线程
如果您在线程之间共享 AWS4Auth
(甚至 StrictAWS4Auth
)实例,很可能会遇到问题。由于 AWS4Auth
实例可能会在签名请求过程中不可预测地重新生成其签名密钥,使用相同实例的线程可能会发现密钥在签名过程中被另一个线程更改,这可能导致未定义的行为。
可能可以使用锁定原语和 StrictAWS4Auth
类设置一个可行的实例共享机制,但是这位可怜的作者想不出一种既安全又不会在某个时刻阻塞所有线程至少一个 HTTP 请求持续时间的方案,这可能需要几秒钟。如果短时间内连续出现几个都需要密钥重新生成的请求,那么系统可能被迫进入串行操作相当长的时间。
简而言之,最好为每个需要进行身份验证的线程创建一个线程本地的 AWS4Auth
实例。
API 参考
请参阅 aws4auth.py
和 aws4signingkey.py
中的文档字符串。
测试
测试套件包含在 test 文件夹中。
该包通过了 AWS auth v4 测试套件中的所有测试,并包含针对支持的在线服务的测试。有关运行测试的详细信息,请参阅 test/requests_aws4auth_test.py
中的文档字符串。
如果您有访问权限并想尝试,测试中包含了 AWS Support API 的连接参数。文档说它支持 auth v4,所以如果您有订阅,它应该可以工作。请分享您的结果!
不支持的 AWS 功能 / 待办事项
- 目前不支持 Amazon S3 分块上传
- 新 AWS 服务的测试
- 即使只使用 AWS4SigningKey 也需要 Requests 库
- 连贯的文档
版本发布说明
- 更新
HISTORY.md
- 更新
requests_aws4auth/__init__.py
- 在 GitHub 上创建一个发布
Docker 环境:
docker run -v `pwd`:/opt/app/ -v ~/.pypirc:/root/.pypirc -it python:3.12 /bin/bash
准备工作:
python3 -m pip install --user --upgrade setuptools wheel testresources twine
构建和发布,凭据在 ~/.pypirc
中:
rm -f dist/*; \
python3 setup.py sdist bdist_wheel && \
python3 -m twine upload --repository testpypi dist/* && \
python3 -m twine upload --repository pypi dist/*