一、背景
上一篇文章是基础版,这篇文章增加授权方
二、创建授权方
1、新建Lambda函数,来验证授权方,运行时选择 Node.js 16.x
代码如下:当header中account和password匹配上,则allow,否则deny
exports.handler = function(event, context, callback) {
console.log('Received event:', JSON.stringify(event, null, 2));
// A simple request-based authorizer example to demonstrate how to use request
// parameters to allow or deny a request. In this example, a request is
// authorized if the client-supplied headerauth1 header, QueryString1
// query parameter, and stage variable of StageVar1 all match
// specified values of 'headerValue1', 'queryValue1', and 'stageValue1',
// respectively.
// Retrieve request parameters from the Lambda function input:
var headers = event.headers;
var queryStringParameters = event.queryStringParameters;
var pathParameters = event.pathParameters;
var stageVariables = event.stageVariables;
// Parse the input for the parameter values
var tmp = event.methodArn.split(':');
var apiGatewayArnTmp = tmp[5].split('/');
var awsAccountId = tmp[4];
var region = tmp[3];
var restApiId = apiGatewayArnTmp[0];
var stage = apiGatewayArnTmp[1];
var method = apiGatewayArnTmp[2];
var resource = '/'; // root resource
if (apiGatewayArnTmp[3]) {
resource += apiGatewayArnTmp[3];
}
// Perform authorization to return the Allow policy for correct parameters and
// the 'Unauthorized' error, otherwise.
var authResponse = {};
var condition = {};
condition.IpAddress = {};
if (headers.account === ""
&& headers.password === "") {
callback(null, generateAllow('me', event.methodArn));
}else {
callback("Unauthorized");
}
}
// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
// Required output:
var authResponse = {};
authResponse.principalId = principalId;
if (effect && resource) {
var policyDocument = {};
policyDocument.Version = '2012-10-17'; // default version
policyDocument.Statement = [];
var statementOne = {};
statementOne.Action = 'execute-api:Invoke'; // default action
statementOne.Effect = effect;
statementOne.Resource = resource;
policyDocument.Statement[0] = statementOne;
authResponse.policyDocument = policyDocument;
}
// Optional output with custom properties of the String, Number or Boolean type.
authResponse.context = {
"account": '',
"password": '',
"booleanKey": true
};
return authResponse;
}
var generateAllow = function(principalId, resource) {
return generatePolicy(principalId, 'Allow', resource);
}
var generateDeny = function(principalId, resource) {
return generatePolicy(principalId, 'Deny', resource);
}
2、创建授权方
授权方名称
类型:选择Lambda
Lambda函数:填写刚创建好的Lambda函数名称
Lambda调用角色:填写调用Lambda函数的角色
Lambda事件负载:选择请求
身份来源:选择标头,添加account和password
授权缓存:取消启用
三、配置授权方
选择 添加授权方的路径资源方法中的方法请求
授权选择配置好的授权方名称
请求验证程序:无
需要API密钥:否
HTTP请求标头:将account和password配置进来
三、测试API
测试通过两种方式:①Postman ②python代码
获取URL链接
1、Postman
进入Postman,添加PUT请求,复制URL链接,在其后添加上传到S3的路径,在headers中添加account和password,点击send,即可在下方看到请求结果
2、python代码:在headers中添加account和password
import requests
def call_api(_url, _headers, _files):
res = requests.put(_url, data=_files, headers=_headers)
return res
def unload_s3(local_file_name,S3_file_name):
# api gateway call url
url_ip = ""
# generate the url
url = url_ip + S3_file_name
# the file on your computer
uploadFile = open(local_file_name, "rb")
# request headers
headers = {"account": "",
"password": ""}
# call the api2s3 method
res = call_api(url, headers, uploadFile)
# print the result
if res.ok:
return ("Upload completed successfully!")
else:
return ("Upload failed!")
if __name__ == '__main__':
# local file name
local_file_name = ''
# S3 file_name to upload
S3_file_name = ''
unload_s3(local_file_name,S3_file_name)
四、通过CloudFormation创建API
yaml文件如下
AWSTemplateFormatVersion: '2010-09-09'
Description : Template to provision ETL Workflow for api gateway
Parameters:
Region:
Description: 'Specify the Region for resource.'
Type: String
Default: ase1
createDate:
Type: String
Default: '2022-07-15'
Iteration:
Type: String
Description: 'Specify the Iteration for Lambda.'
Default: '001'
S3Iteration:
Type: String
Description: 'Specify the Iteration for S3'
Default: '001'
IAMIteration:
Type: String
Description: 'Specify the Iteration for IAM roles.'
Default: '001'
Resources:
ApigatewayRestAPI:
Type: AWS::ApiGateway::RestApi
Properties:
Name: api-uploads3-{Iteration}
BinaryMediaTypes:
- "*/*"
Description: create api to load file to s3
Mode: overwrite
EndpointConfiguration:
Types:
- REGIONAL
MinimumCompressionSize: 0
ApigatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerCredentials: "arn:aws:iam::role/iamr-replication-${IAMIteration}"
AuthorizerResultTtlInSeconds : 0
AuthorizerUri: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:lamb-apigw-authorizer-${S3Iteration}/invocations"
Type : REQUEST
AuthType: custom
RestApiId:
!Ref ApigatewayRestAPI
Name: auth-request
IdentitySource : method.request.header.account,method.request.header.password
ApigatewayResourceFolder:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId:
!Ref ApigatewayRestAPI
PathPart: "{folder}"
ParentId: !GetAtt
- ApigatewayRestAPI
- RootResourceId
ApigatewayResourcePartition:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId:
!Ref ApigatewayRestAPI
PathPart: "{partition}"
ParentId:
!Ref ApigatewayResourceTablename
ApigatewayResourceTablename:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId:
!Ref ApigatewayRestAPI
PathPart: "{tablename}"
ParentId:
!Ref ApigatewayResourceFolder
ApigatewayResourceFilename:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId:
!Ref ApigatewayRestAPI
PathPart: "{filename}"
ParentId:
!Ref ApigatewayResourcePartition
ApigatewayMethodTablename:
Type: AWS::ApiGateway::Method
Properties:
AuthorizerId:
!Ref ApigatewayAuthorizer
AuthorizationType: custom
RequestParameters: {
"method.request.path.folder": true,
"method.request.path.tablename": true,
"method.request.header.account": true,
"method.request.header.password": true
}
HttpMethod: PUT
MethodResponses:
- StatusCode: 200
ResponseModels:
application/json: Empty
RestApiId:
!Ref ApigatewayRestAPI
ResourceId: !GetAtt
- ApigatewayResourceTablename
- ResourceId
Integration:
Type: AWS
Credentials: "arn:aws:iam::role/iamr-replication-${IAMIteration}"
IntegrationHttpMethod: PUT
IntegrationResponses:
- StatusCode: 200
PassthroughBehavior: when_no_match
Uri: "arn:aws:apigateway:${AWS::Region}:s3:path/s3-raw-${Iteration}/{folder}/{tablename}"
RequestParameters: {
"integration.request.path.folder" : "method.request.path.folder",
"integration.request.path.tablename" : "method.request.path.tablename"
}
ApigatewayMethodPartition:
Type: AWS::ApiGateway::Method
Properties:
AuthorizerId:
!Ref ApigatewayAuthorizer
AuthorizationType: custom
RequestParameters: {
"method.request.path.folder": true,
"method.request.path.tablename": true,
"method.request.path.partition": true,
"method.request.header.account": true,
"method.request.header.password": true
}
HttpMethod: PUT
MethodResponses:
- StatusCode: 200
ResponseModels:
application/json: Empty
RestApiId:
!Ref ApigatewayRestAPI
ResourceId: !GetAtt
- ApigatewayResourcePartition
- ResourceId
Integration:
Type: AWS
Credentials: "arn:aws:iam::role/iamr-replication-${IAMIteration}"
IntegrationHttpMethod: PUT
IntegrationResponses:
- StatusCode: 200
PassthroughBehavior: when_no_match
Uri: "arn:aws:apigateway:${AWS::Region}:s3:path/s3-raw-${Iteration}/{folder}/{tablename}/{partition}"
RequestParameters: {
"integration.request.path.partition" : "method.request.path.partition",
"integration.request.path.folder" : "method.request.path.folder",
"integration.request.path.tablename" : "method.request.path.tablename"
}
ApigatewayMethodFilename:
Type: AWS::ApiGateway::Method
Properties:
AuthorizerId:
!Ref ApigatewayAuthorizer
AuthorizationType: custom
RequestParameters: {
"method.request.path.folder": true,
"method.request.path.tablename": true,
"method.request.path.partition": true,
"method.request.path.filename": true,
"method.request.header.account": true,
"method.request.header.password": true
}
HttpMethod: PUT
MethodResponses:
- StatusCode: 200
ResponseModels:
application/json: Empty
RestApiId:
!Ref ApigatewayRestAPI
ResourceId: !GetAtt
- ApigatewayResourceFilename
- ResourceId
Integration:
Type: AWS
Credentials: "arn:aws:iam::role/iamr-replication-${IAMIteration}"
IntegrationHttpMethod: PUT
IntegrationResponses:
- StatusCode: 200
PassthroughBehavior: when_no_match
Uri: "arn:aws:apigateway:${AWS::Region}:s3:path/s3-raw-${Iteration}/{folder}/{tablename}/{partition}/{filename}"
RequestParameters: {
"integration.request.path.partition" : "method.request.path.partition",
"integration.request.path.filename" : "method.request.path.filename",
"integration.request.path.folder" : "method.request.path.folder",
"integration.request.path.tablename" : "method.request.path.tablename"
}
ApigatewayDeploymentv3:
DependsOn: ApigatewayMethodFilename
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId:
!Ref ApigatewayRestAPI
StageName : v3
PermissionToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName: lamb-apigw-authorizer-${Iteration}
Action: "lambda:InvokeFunction"
Principal: "apigateway.amazonaws.com"
SourceArn: !Sub
- "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${APiId}/authorizers/${AuthorizerId}"
- APiId:
!Ref ApigatewayRestAPI
AuthorizerId:
!Ref ApigatewayAuthorizer
Outputs:
RootResourceId:
Value: !GetAtt ApigatewayRestAPI.RootResourceId
AuthorizerId:
Value: !GetAtt ApigatewayAuthorizer.AuthorizerId