我有两个AWS账户,例如考虑账户a和账户b。帐户a要访问帐户b中部署在API网关上的API。现在可以从帐户a访问帐户b中的API。我想为该API添加白名单,以仅允许帐户-a。当我添加资源策略时,仅将API的帐户a列入白名单时,它总是抛出错误“不允许用户匿名”。有人可以让我知道是否遵循正确的方法。请让我知道是否错过了任何事情。
我将auth添加为“ 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请求(例如对请求进行签名)时帮助提供所需的信息以及是否进行任何特殊处理。一个简单的例子将不胜感激。
答案 0 :(得分:0)
引起此错误的原因是,在客户端,您需要使用AWS身份验证标头对请求进行签名。 通常,对于AWS服务的调用,当您使用AWS sdk时,它将自动对请求进行签名。不幸的是,到目前为止,here尚无官方的亚马逊方式来签署此调用API的请求。 您可以通过以下方式使用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层。
答案 1 :(得分:0)
如@Sam所述,您需要生成一个签名并将其与您的http请求一起发送。您可以通过两种方式执行此操作。
### 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"
}
在您的http请求中包含Authorization
,X-Amz-Date
和X-Amz-Security-Token
作为标头。
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
});
})()
希望这会有所帮助,祝你好运
答案 2 :(得分:0)
您必须生成一个签名的请求。下面是你可以在本地运行的 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()