为Amazon API Gateway启用IAM身份验证

一、背景

新创建的Amazon API Gateway (以下简称API Gateway)的Regional级别的接口是可以通过互联网进行公开调用的。在API为应用内部调用的场景下,需要设置身份验证。主要的身份验证手段有:IAM身份验证、Lambda转发器验证(Backend可使用数据库)、OAuth/JWT认证。此外,在API Gateway上使用mTLS,配置双向证书,也可以显著提升安全性。

本文介绍如何开启IAM身份验证。

二、配置IAM身份验证

1、确认当前API Gateway的ID、接口、调用方法等信息

本文假设一个Regional类型的API Gateway接口已经创建完毕,当前是开放未设置认证的状态。

为构建IAM Policy用户授权,需要确认当前接口的信息。从Stages位置等多个地方都可以看到API Gateway的ID,也可以看到接口名称、调用方法等信息。如下截图。

2、配置可访问API Gateway的IAM Policy

首先为要访问API Gateway的用户,创建一个最小权限的IAM Policy。在开发、测试和生产环境中,不建议使用AdministratorAccess等具有AWS账号管理员权限的身份进行测试。因此接下来,为要访问访问API Gateway的用户(对应程序)创建专用的最小权限的IAM Policy策略。

进入IAM Policy界面,点击创建左侧Policy,点击右侧创建Policy。如下截图。

点击第二个标签页JSON,直接输入IAM策略,文本内容如下:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"           
      ],
      "Resource": [
        "arn:aws-cn:execute-api:cn-northwest-1:420029960748:dmtqi47mvg/prod-iamauth/GET/pets"
      ]
    }
  ]
}

请替换上一个步骤中确认的区域、AWS账户(12位数字)、API Gateway网关名称、接口名称、调用方法等信息为正确的值。

为了灵活对开发、测试、生产环境授权,IAM策略中的prod-iamauth是代表Stages阶段,GET是允许的方法,petResource。这几个字段可进行排列组合,实现授权的权限最小化管控。本例中,稍后打开了IAM授权后,还会重新部署另一个Stages,因此Stages阶段的名称将会从目前的prod-noauth变化为prod-iamauth。所以这里写IAM策略时候,直接按照新创建的名字去授权,旧的阶段不再授权。然后在要访问API Gateway的应用层进行流量切换,修改访问入口即可。

另外请注意,如果是在中国区,那么Resource中ARN的设置应为aws-cn,反之在Global区域则为aws。本文档按照AWS中国区编写,因此使用aws-cn。如下截图。

配置好IAM策略后,点击Next: Tags按钮下一步,在标签页面可跳过,然后来到名称界面,输入本策略名称,例如APIGW-prod-get-pets。请记住这个名称,稍后会使用这个策略。

最后点击右下角的Create policy按钮完成创建。

2、创建IAM用户、Access Key和Secret Key

创建IAM用户、Access Key和Secret Key(以下简称AKSK)是一个标准流程,请参考IAM相应文档。本文只需要创建一个具有AWS API访问权限的用户和对应的密钥即可,不需要访问AWS控制台。因此在创建IAM用户过程中,选项Enable console access不需要被选中。

如果您是AWS新用户,不熟悉2022年改版后的IAM操作界面,可参考这篇博客。

创建AKSK完成后将其保存好,因为IAM界面只在创建的第一次会显示完整的Secret Key,以后将不会显示。后续程序中将会使用这个AKSK测试对API Gateway的认证和访问。

3、在API Gateway上配资资源和方法,开启IAM身份验证

进入API Gateway界面,点击左侧Resource菜单,在右侧找到要管理的资源,例如首先配置 / 目录对应的GET方法。在页面右侧的Method Request下方可以看到,当前配置的Auth显示为None,这表示当前没有打开认证。此时点击Method Request文字链接,进入设置界面。如下截图。

Method Execution界面,点击Authentication的下拉框,从刚才没有认证的None选项,修改为Amazon IAM。然后点击边上的对勾按钮表示保存设置。如下截图。

修改完毕后,重新回到上一步的资源界面,可以看到图中的Auth认证已经改变,显示为Amazon IAM。如下截图。

4、更多接口的配置(可选用AWSCLI配置)

API Gateway的资源的修改,是针对单个资源和方法的,也就是上边的截图中的对于 / 目录的GET方法。对于其他资源和方法,依然还是处于没有认证的公开阶段,因此他们需要被逐一配置。如下截图。

逐一配置IAM认证的方法就是重复以上过程,把所有资源Resource对应的方法Method(即GET/POST等)逐一编辑认证选项,逐个添加。这里还提供另一种方法,可选用AWSCLI为接口批量设置。

在AWS控制台图形界面上,图中标记出来的ID就是后续要用到的资源编号。如下截图。

也通过AWSCLI查询本网关下所有的资源和方法:

aws apigateway get-resources --rest-api-id dmtqi47mvg

以上清单中,可以分别获取资源IDresource-id和支持的方法如GETPOST等。

有了ID后,即可使用AWSCLI批量配置使其打开IAM认证。为单个方法配置IAM认证的命令是:

aws apigateway update-method \
    --rest-api-id dmtqi47mvg \
    --resource-id vlifnq \
    --http-method OPTIONS \
    --patch-operations op="replace",path="/authorizationType",value="AWS_IAM"

配置之后显示如下信息,其中第二行显示认证已经是IAM类型。如下截图。

重复以上过程,对所有资源和方法都执行一遍配置。

4、将开启IAM认证的配资部署为新的Stages阶段

经过确认,所有接口部署完成。接下来要将Resource部署到Stages推向生产。在上一步的Resource界面,点击Actions按钮,从下拉框中选择Deploy API按钮,进行部署。如下截图。

在弹出的对话框中,输入要部署的Stages的名称,这里需要与前文配置IAM Policy的授权的Stages名称一致,这里使用prod-iamauth。如下截图。

部署完成。回到API Gateway界面,点击左侧的Stages按钮,可看到页面中间显示的新部署的prod-iamauth,点击资源和方案,可看到右侧显示的AuthenticationAmazon IAM,表示配置成功。如下截图。

至此配置部分完成。接下来进行测试。

5、AWS SignV4简介

在API Gateway打开了IAM认证后,要求客户端发送给服务器端的请求必须使用SignV4签名进行身份认证。也就是说,客户端不能直接通过CURL发送明文的AKSK到API Gateway,而是要经过HMAC-SHA256算法生成符合API Gateway要求的SignV4签名,然后带着签名才能发送到AWS云端。签名请求格式类似如下:

Authorization: AWS4-HMAC-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20220830/cn-northwest-1/execute-api/aws4_request,
SignedHeaders=host;x-amz-date,
Signature=calculated-signature

Sign V4签名才用的HMAC-SHA256算法具有足够的强度,因此经过加密的信息不会被破解。关于Sign V4的介绍,可参考本文末尾的文档。为了满足Sign V4签名的前提条件,本文后续将使用内置SignV4的客户端进行测试,并使用Python构建代码进行测试。

6、使用REST客户端软件请求

对API Gateway的请求可以通过REST客户端,例如Postman等软件。本文使用VSCode并通过THUNDER CLIENT插件实现。

在THUNDER CLIENT插件的界面上,选择方法是GET,输入API Gateway调用的资源地址,选择认证标签页Auth,然后在下方输入Access Key和Secret Key。然后点击Send按钮提交认证。此时右侧可以收到正确的请求返回信息。如下截图。

如果IAM和AKSK的认证信息不正确,则会收到错误信息。如下截图。

由此确认了带有IAM身份验证的API Gateway请求正常。

7、使用Python代码请求

Python程序调用AWS服务,包括但不限于API Gateway,需要额外安装requests库和aws_requests_auth。命令如下:

pip install requests aws_requests_auth -y

构建如下Python程序:

import requests
from aws_requests_auth.aws_auth import AWSRequestsAuth

# let's talk to our AWS Elasticsearch cluster
auth = AWSRequestsAuth(aws_access_key='access_key',
                       aws_secret_access_key='secret_key',
                       aws_host='dmtqi47mvg.execute-api.cn-northwest-1.amazonaws.com.cn',
                       aws_region='cn-northwest-1',
                       aws_service='execute-api')

response = requests.get('https://dmtqi47mvg.execute-api.cn-northwest-1.amazonaws.com.cn/prod-iamauth/pets',
                        auth=auth)
print(response.text)

以上代码不依赖于AWS Boto3 SDK,只需要构建正确的HTTP请求即可满足IAM身份认证要求的Sign V4签名。将配置信息带入后,运行程序,可看到正常返回结果。

如果IAM和AKSK的认证信息不正确,则会收到错误信息。如下截图。

由此确认了带有IAM身份验证的API Gateway请求正常。

至此所有配置过程完成。

三、参考文档

选择网关类型IAM Restful类型和HTTP类型:

https://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/http-api-vs-rest.html

为API Gateway使用IAM身份验证:

https://aws.amazon.com/cn/premiumsupport/knowledge-center/iam-authentication-api-gateway/?nc1=h_ls

访问API Gateway的IAM策略最佳实践和配置样例:

https://docs.aws.amazon.com/zhcn/apigateway/latest/developerguide/securityiamid-based-policy-examples.html#securityiam_service-with-iam-policy-best-practices

通过AWSCLI为API Gateway资源和方法配置IAM认证:

https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-method.html

AWS Sign V4简介,以及常见编程语言生成Sign V4签名的Sample Code:

https://docs.aws.amazon.com/zh_cn/general/latest/gr/create-signed-request.html

Python Sign V4签名代码样例(From Github):

https://github.com/DavidMuller/aws-requests-auth