【问题标题】:API Gateway cross account accessAPI Gateway 跨账户访问
【发布时间】:2021-08-08 05:33:10
【问题描述】:

我有两个 AWS 账户,例如 account-a 和 account-b。 account-a 想要访问部署在 account-b 中的 API 网关上的 API。现在可以从 account-a 访问 account-b 中的 API。我想为 API 添加白名单以仅允许 account-a。当我添加资源策略,仅将 API 的 account-a 列入白名单时,它总是抛出错误“不允许匿名用户”。有人可以告诉我是否遵循正确的方法。如果我遗漏了什么,请告诉我。

我将身份验证添加为“AWS_IAM”并具有以下资源策略。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::****:role/****"
            },
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:ap-southeast-1:****:***/*/*/*"
        }
    ]
}

现在报错了

“缺少身份验证令牌”

.

我的要求是使用 aws 帐户白名单或源 vpc 过滤来保护部署在 AWS API 网关中的 API。请帮助提供所需的信息以及在生成 api 请求时是否有任何特殊处理(如签署请求)。一个简单的例子将不胜感激。

【问题讨论】:

  • 嗨 vignesh 欢迎来到 stackoverflow,是的,api 网关上的资源策略可用于跨帐户访问,以进一步发现我需要您通过编辑问题发布资源策略的问题
  • 您能否也发布一下您的方法授权中当前配置的内容?
  • 请发布您正在尝试连接的客户端代码。

标签: amazon-web-services api aws-api-gateway


【解决方案1】:

此错误是因为在客户端,您需要使用 AWS 身份验证标头对请求进行签名。 通常对于对 aws 服务的调用,当您使用 AWS sdk 时,它会自动对请求进行签名。不幸的是,到目前为止,亚马逊还没有正式的方式来签署这个调用 API 的请求,如您所见here。 您可以通过以下方式使用aws-requests-auth 等第三方库:

from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
auth = BotoAWSRequestsAuth(aws_host='api.example.com',
                           aws_region='us-east-1',
                           aws_service='execute-api')

import requests
response = requests.post('https://api.example.com/test', json={"foo": "bar"}, auth=auth)

如果您希望在 lambda 函数中使用它,可以将其添加为层,将其安装到目标文件夹,然后压缩文件夹并将其用作 lambda 层。

【讨论】:

    【解决方案2】:

    正如@Sam 提到的,您需要生成一个签名并将其与您的http 请求一起发送。您可以通过两种方式做到这一点。

    1. 您可以生成签名并将签名与您的 http 请求一起作为标头发送
    2. 您可以使用可以生成签名并发送请求的库

    方法一——生成签名

    ### generate signature
    const aws4  = require('aws4')
    const signature = aws4.sign({
      host: 'https://apiId.execute-api.ap-southeast-2.amzonaws.com',
      method: 'GET',
      path: '/development/hello',
      headers: {
      
      },
      region: 'ap-southeast-2',
      service: 'execute-api'
    }, {
      secretAccessKey: "your access key",
      accessKeyId: "your secret key",
      sessionToken: "your session token if you are using temporary credentials"
    
    })
    
    // output
    { "host":
       "something.execute-api.ap-southeast-2.amzonaws.com",
      "method": "GET",
      "path": "/development/hello",
      "headers": {
         "Host":
          "something.execute-api.ap-southeast-2.amzonaws.com",
         "X-Amz-Security-Token":
          "security token",
         "Authorization":
          "AWS4-HMAC-SHA256 Credential=ASIARNZFFFFFEGFG23JY/20191212/ap-southeast-2/execute-api/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token;x-apigw-api-id, Signature=7fd8e51c2bf4faefaRRRRRf92c700799b78234d204"
      },
      "region": "ap-southeast-2",
      "service": "execute-api"
    }
    

    AuthorizationX-Amz-DateX-Amz-Security-Token 作为您的http 请求的标头。

    方法二——使用可以生成签名并发送请求的库

    var apigClientFactory = require('aws-api-gateway-client').default;
    
    var apigClient = apigClientFactory.newClient({
        invokeUrl:'https://apiId.execute-api.ap-southeast-2.amzonaws.com/development', // REQUIRED
        accessKey: 'your access key', // REQUIRED
        secretKey: 'your secret key', // REQUIRED
        sessionToken: 'your session token if you are using temporary credentials',
        region: 'ap-southeast-2', // REQUIRED: The region where the API is deployed.
        systemClockOffset: 0, // OPTIONAL: An offset value in milliseconds to apply to signing time
        retries: 4, // OPTIONAL: Number of times to retry before failing. Uses axon-retry plugin.
        retryCondition: (err) => { // OPTIONAL: Callback to further control if request should be retried.  Uses axon-retry plugin.
          return err.response && err.response.status === 500;
        }
    });
    
    
    (() => {
      apigClient.invokeApi(null, `/hello`, 'GET', {
        headers: {
        }
      })
      .then(function(result){
        console.log('result: ', result)
          //This is where you would put a success callback
      }).catch( function(result){
        console.log('result: ', result)
          //This is where you would put an error callback
      });
    })()
    

    希望对你有帮助,祝你好运

    【讨论】:

      【解决方案3】:

      您必须生成签名请求。下面是可以在本地运行的 Python 代码

      import boto3
      from botocore.auth import SigV4Auth
      from botocore.awsrequest import AWSRequest
      import requests
      
      session = boto3.Session(profile_name="YOUR PROFILE NAME")
      credentials = session.get_credentials()
      creds = credentials.get_frozen_credentials()
      
      
      def signed_request(method, url, data=None, params=None, headers=None):
          request = AWSRequest(method=method, url=url, data=data, params=params, headers=headers)
          SigV4Auth(creds, "YOUR API NAME", "us-east-1").add_auth(request)
          return requests.request(method=method, url=url, headers=dict(request.headers), data=data)
      
      
      def main():
          url = f"YOUR API URL"
          data = '{"data":"John"}'
          headers = {'Content-Type': 'application/json'}
          response = signed_request(method='POST', url=url, data=data, headers=headers)
          print(response.text)
      
      
      if __name__ == "__main__":
          main()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-20
        相关资源
        最近更新 更多