如何将AWS API Gateway访问限制在特定的CloudFront分发或Route53子域上?

9
我有一个API网关API设置,我想限制访问。 我在AWS Route 53中设置了一个子域名,它指向一个CloudFront分发,我的应用程序位于其中。该应用程序会向API发送POST请求。
我尝试根据示例“AWS API白名单”添加资源策略到我的API,但似乎无法正确使用语法,我一直收到错误。
我还尝试创建IAM用户并使用AWS_IAM权限锁定API,但随后需要创建签名请求,这似乎需要更多的工作,而通过资源策略应该更容易些?
以下是我尝试附加到我的API的资源策略示例:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity {{CloudFrontID}}"
            },
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*/*/*"
            ]
        }
    ]
}

这会返回以下错误: 无效的策略文件。请检查策略语法并确保主体是有效的。
3个回答

4
问题在于OAI不能在CustomOrigin中使用。如果您没有将User-Agent转发到API Gateway CustomOrigin,则最简单的方法是在API Gateway中添加资源策略,该策略仅允许aws:UserAgent为"Amazon CloudFront"的请求。
注意:User-Agent很容易被伪造。这种方法仅旨在防止“正常访问”,例如随机网络爬虫尝试抓取您的站点。
User-Agent标头保证为Amazon CloudFront。请参见自定义源的请求和响应行为中的引用。
行为如果您未配置CloudFront基于标头值进行缓存:CloudFront将此标头字段的值替换为Amazon CloudFront。如果您希望CloudFront根据用户使用的设备缓存内容,请参阅基于设备类型配置缓存。

这是完整的资源策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-west-2:123456789012:abcdefghij/*/*/*",
            "Condition": {
                "StringEquals": {
                    "aws:UserAgent": "Amazon CloudFront"
                }
            }
        }
    ]
}

以下是在serverless.yml中配置它的方法:

provider:
  resourcePolicy:
    - Effect: Allow
      Principal: "*"
      Action: execute-api:Invoke
      Resource:
        - execute-api:/*/*/*
      Condition:
        StringEquals:
          aws:UserAgent: "Amazon CloudFront"

3

"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity {{CloudFrontID}}"

这个概念的问题在于它是一个公共的HTTP请求。除非是签名请求,否则AWS不会知道任何IAM或ARN资源,它只知道它有一个标准的HTTP请求。如果您使用curl -v命令进行请求,您将看到请求参数类似于:

    GET
    /test/mappedcokerheaders
    HTTP/2
    Host: APIID.execute-api.REGION.amazonaws.com
    User-Agent: curl/7.61.1
    Accept: */*

您可以过滤用户代理,就像我在此处中定义的那样。

我会检查从CloudFront请求中传入的所有值,与您直接使用curl向API发送的请求进行比较,通过在响应头中捕获api gw请求ID,并在API Gateway访问日志中查找这些ID。不过,您需要启用访问日志,并定义要记录的参数,您可以参考这里来了解如何操作。请注意,保留HTML标记。

谢谢,我会尝试一下。 - Jon B

1
我在AWS Route 53中设置了一个子域名,指向我的应用所在的CloudFront分发。该应用会向API发送POST请求。
据我理解,您拥有一个可从Web浏览器( https://your-service.com)调用的公共服务。
您希望当客户端浏览器位于https://your-site.com时,服务才会响应。例如,当浏览器位于https://another-site.com时,服务不会响应。
如果是这种情况,您需要阅读更多关于CORS的信息
这并不能防止一个陌生人/网页客户端直接访问和调用您的服务 https://your-service.com。为了保护该服务,您需要适当的 身份验证系统

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接