如何限制 AWS API 网关对特定 CloudFront 分配或 Route53 子域的访问
How to limit AWS API Gateway access to specific CloudFront distribution or Route53 subdomain
我有一个 API 网关 api 设置,我想限制访问。我在 AWS Route 53 中设置了一个子域,它指向我的应用所在的 CloudFront 分配。此应用向 API.
发出 POST 请求
我已经考虑根据示例 'AWS API Whitelist' 为我的 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:/*/*/*"
]
}
]
}
这个returns下面的错误:
Invalid policy document. Please check the policy syntax and ensure that Principals are valid.
I have a subdomain setup in AWS Route 53 that points to a CloudFront
distribution where my app lives. This app makes a POST request to the
API.
据我所知,您有一个 public 服务可以从网络浏览器调用 (https://your-service.com)
您希望服务仅在客户端浏览器位于 https://your-site.com. The service will not respond when the browser for example is on https://another-site.com
时响应
如果是这样的话,
你需要阅读 more about CORS
但是,这不会阻止随机人员/Web 客户端访问并直接向 https://your-service.com 调用您的服务。为了保护服务不受此影响,您需要适当的 身份验证系统
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity {{CloudFrontID}}"
这个概念的问题在于这是一个 public 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: */*
您可以过滤用户代理,因为我确实看到定义了条件 here。
我会通过在响应中捕获 api gw 请求 ID 来检查云端请求中的所有值与 curl 直接发送到 API 的请求中的所有值 headers,并在您的 API 网关访问日志中寻找那些。不过,您必须启用访问日志,并定义要记录的参数,您可以查看如何操作 here.
问题是 OAI 无法在 CustomOrigin 中使用。如果您没有将 User-Agent
转发到 API 网关 CustomOrigin,那么对您来说最简单的方法是在 API 网关中添加一个资源策略,它只允许 aws:UserAgent: "Amazon CloudFront"
.
注意:User-Agent
可以很容易被欺骗。这种方法旨在仅防止“正常访问”,例如网络上的随机机器人试图抓取您的网站。
保证User-Agent
header是Amazon CloudFront
。请参阅 Request and Response Behavior for Custom Origins.
中的引用
Behavior If You Don't Configure CloudFront to Cache Based on Header Values: CloudFront replaces the value of this header field with Amazon CloudFront
. If you want CloudFront to cache your content based on the device the user is using, see Configuring Caching Based on the Device Type.
完整资源策略如下所示:
{
"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"
我有一个 API 网关 api 设置,我想限制访问。我在 AWS Route 53 中设置了一个子域,它指向我的应用所在的 CloudFront 分配。此应用向 API.
发出 POST 请求我已经考虑根据示例 'AWS API Whitelist' 为我的 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:/*/*/*"
]
}
]
}
这个returns下面的错误:
Invalid policy document. Please check the policy syntax and ensure that Principals are valid.
I have a subdomain setup in AWS Route 53 that points to a CloudFront distribution where my app lives. This app makes a POST request to the API.
据我所知,您有一个 public 服务可以从网络浏览器调用 (https://your-service.com)
您希望服务仅在客户端浏览器位于 https://your-site.com. The service will not respond when the browser for example is on https://another-site.com
时响应如果是这样的话, 你需要阅读 more about CORS
但是,这不会阻止随机人员/Web 客户端访问并直接向 https://your-service.com 调用您的服务。为了保护服务不受此影响,您需要适当的 身份验证系统
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity {{CloudFrontID}}"
这个概念的问题在于这是一个 public 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: */*
您可以过滤用户代理,因为我确实看到定义了条件 here。
我会通过在响应中捕获 api gw 请求 ID 来检查云端请求中的所有值与 curl 直接发送到 API 的请求中的所有值 headers,并在您的 API 网关访问日志中寻找那些。不过,您必须启用访问日志,并定义要记录的参数,您可以查看如何操作 here.
问题是 OAI 无法在 CustomOrigin 中使用。如果您没有将 User-Agent
转发到 API 网关 CustomOrigin,那么对您来说最简单的方法是在 API 网关中添加一个资源策略,它只允许 aws:UserAgent: "Amazon CloudFront"
.
注意:User-Agent
可以很容易被欺骗。这种方法旨在仅防止“正常访问”,例如网络上的随机机器人试图抓取您的网站。
保证User-Agent
header是Amazon CloudFront
。请参阅 Request and Response Behavior for Custom Origins.
Behavior If You Don't Configure CloudFront to Cache Based on Header Values: CloudFront replaces the value of this header field with
Amazon CloudFront
. If you want CloudFront to cache your content based on the device the user is using, see Configuring Caching Based on the Device Type.
完整资源策略如下所示:
{
"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"