使用来自 Python 的 IAM 角色访问 AWS API 网关

Access AWS API Gateway with IAM roles from Python

我有一个 AWS API 网关,我想使用 IAM Roles 保护它。

我正在寻找一个包来帮助我使用 Python 访问它。我试图避免实施整个 Version 4 Signing Process。我确定一定有一些我可以使用的库。

我查看了 aws-requests-auth,但它需要 "aws_service" 才能生成签名。我也查看了 boto3,但我无法找到任何方法来向一般请求添加身份验证 headers。

您可以使用 aws-requests-auth 为您对 API 网关的请求生成签名,并使用 execute-api 作为服务名称。

import requests
from aws_requests_auth.aws_auth import AWSRequestsAuth

auth = AWSRequestsAuth(aws_access_key='YOURKEY',
                       aws_secret_access_key='YOURSECRET',
                       aws_host='restapiid.execute-api.us-east-1.amazonaws.com',
                       aws_region='us-east-1',
                       aws_service='execute-api')

headers = {'params': 'ABC'}
response = requests.get('https://restapiid.execute-api.us-east-1.amazonaws.com/stage/resource_path',
                        auth=auth, headers=headers)

Ka Hou Ieong 的回复基础上,还有一件事让我感到困惑。我在使用 aws-requests-auth==0.3.0,在使用 requests.get(url, auth=auth) 时,我仍然得到 403

;TLDR;:我的 URL 有一个 querystring 并且它看起来 aws-requests-auth 没有或可能无法确保 querystring 参数 按升序排序 %-编码。

==> 因此,一旦我将 url 查询字符串更改为排序和 % 编码,我就得到了 200

详情: 我打开了 API 网关日志记录,我得到了

In [46]: resp = requests.get(url, auth=auth)

In [47]: resp.text
Out[47]: u'{"message":"The request signature we calculated
 does not match the signature you provided. Check your AWS Secret Access Key
 and signing method. Consult the service documentation for details.... 

(上面的新行和截断(...)是我的)

根据 Amazon Canonical Request for Signature Version 4 文档,

To construct the canonical query string, complete the following steps:

Sort the parameter names by character code point in ascending order. For example, a parameter name that begins with the uppercase letter F precedes a parameter name that begins with a lowercase letter b.

URI-encode each parameter name and value according to the following rules:

a. Do not URI-encode any of the unreserved characters that RFC 3986 defines: A-Z, a-z, 0-9, hyphen ( - ), underscore ( _ ), period ( . ), and tilde ( ~ ).

b. Percent-encode all other characters with %XY, where X and Y are hexadecimal characters (0-9 and uppercase A-F). For example, the space character must be encoded as %20 (not using '+', as some encoding schemes do) and extended UTF-8 characters must be in the form %XY%ZA%BC.

canonical 查询字符串用于生成 Authorization Signature,AWS 在计算 Signature Version 4 信号时应用相同的规则。 总之,我想当然aws-requests-authAuth当然不能改变你的url,你必须。

如果您想使用 IAM 角色进行调用,您应该使用 BotoAWSRequestsAuth from aws-requests-auth:

import requests
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
auth = BotoAWSRequestsAuth(
    aws_host="API_ID.execute-api.us-east-1.amazonaws.com",
    aws_region="us-east-1",
    aws_service="execute-api"
)
response = requests.get("https://API_ID.execute-api.us-east-1.amazonaws.com/STAGE/RESOURCE", auth=auth)

这将使用 botocore 从 AWS 元数据服务中检索密钥和机密,而不需要您自己传递它们。

感谢 aws-requests-auth 图书馆的建议。

另一个决定是使用 requests_aws4auth 包:

import requests
from requests_aws4auth import AWS4Auth

session = requests.Session()
session.auth = AWS4Auth(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, 'us-east-1', 'execute-api')

response = requests.get('https://restapiid.execute-api.us-east-1.amazonaws.com/stage/resource_path', auth=auth)

此外,您需要为您的 IAM 用户添加执行权限,例如(可以调用该区域中的所有 API 个端点):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:*:*"
      ]
    }
  ]
}

可以通过link

找到更多权限示例