Tutorial: Create a REST API as an Amazon S3 Proxy in API Gateway
The original tutorial for this setup is already mentioned in AWS documentation(Link)
Since, it usually takes a lot of time to follow the instructions and test it. So I am adding the Swagger + API Gateway Extensions yaml file which you can quickly import and test it out.
---swagger: "2.0"info:version: "2020-03-04T20:03:34Z"title: "S3Proxy"host: "wuzukp9zmh.execute-api.us-east-1.amazonaws.com"basePath: "/dev"schemes:- "https"paths:/:get:produces:- "application/pdf"- "application/json"responses:200:description: "200 response"schema:$ref: "#/definitions/Empty"headers:Content-Length:type: "string"Timestamp:type: "string"Content-Type:type: "string"400:description: "400 response"500:description: "500 response"x-amazon-apigateway-integration:credentials: "<API_ROLE_WITH_FULL_S3_PERMISSIONS>"uri: "arn:aws:apigateway:us-east-1:s3:path//"responses:4\d{2}:statusCode: "400"default:statusCode: "200"responseParameters:method.response.header.Content-Type: "integration.response.header.Content-Type"method.response.header.Content-Length: "integration.response.header.Content-Length"method.response.header.Timestamp: "integration.response.header.Date"5\d{2}:statusCode: "500"passthroughBehavior: "when_no_match"httpMethod: "GET"type: "aws"/{folder}:get:produces:- "application/json"parameters:- name: "folder"in: "path"required: truetype: "string"responses:200:description: "200 response"schema:$ref: "#/definitions/Empty"400:description: "400 response"500:description: "500 response"x-amazon-apigateway-integration:credentials: "<API_ROLE_WITH_FULL_S3_PERMISSIONS>"uri: "arn:aws:apigateway:us-east-1:s3:path/{bucket}"responses:4\d{2}:statusCode: "400"default:statusCode: "200"5\d{2}:statusCode: "500"requestParameters:integration.request.path.bucket: "method.request.path.folder"passthroughBehavior: "when_no_match"httpMethod: "GET"type: "aws"put:produces:- "application/json"parameters:- name: "folder"in: "path"required: truetype: "string"responses:200:description: "200 response"schema:$ref: "#/definitions/Empty"400:description: "400 response"500:description: "500 response"security:- sigv4: []x-amazon-apigateway-integration:credentials: "<API_ROLE_WITH_FULL_S3_PERMISSIONS>"uri: "arn:aws:apigateway:us-east-1:s3:path/{bucket}"responses:4\d{2}:statusCode: "400"default:statusCode: "200"5\d{2}:statusCode: "500"requestParameters:integration.request.path.bucket: "method.request.path.folder"passthroughBehavior: "when_no_match"httpMethod: "PUT"type: "aws"delete:produces:- "application/json"parameters:- name: "folder"in: "path"required: truetype: "string"responses:200:description: "200 response"schema:$ref: "#/definitions/Empty"400:description: "400 response"500:description: "500 response"x-amazon-apigateway-integration:credentials: "<API_ROLE_WITH_FULL_S3_PERMISSIONS>"uri: "arn:aws:apigateway:us-east-1:s3:path/{bucket}"responses:4\d{2}:statusCode: "400"default:statusCode: "200"5\d{2}:statusCode: "500"requestParameters:integration.request.path.bucket: "method.request.path.folder"passthroughBehavior: "when_no_match"httpMethod: "DELETE"type: "aws"/{folder}/{item}:get:produces:- "application/pdf"- "application/json"parameters:- name: "item"in: "path"required: truetype: "string"- name: "folder"in: "path"required: truetype: "string"responses:200:description: "200 response"schema:$ref: "#/definitions/Empty"400:description: "400 response"500:description: "500 response"x-amazon-apigateway-integration:credentials: "<API_ROLE_WITH_FULL_S3_PERMISSIONS>"uri: "arn:aws:apigateway:us-east-1:s3:path/{bucket}/{object}"responses:4\d{2}:statusCode: "400"default:statusCode: "200"5\d{2}:statusCode: "500"requestParameters:integration.request.path.object: "method.request.path.item"integration.request.path.bucket: "method.request.path.folder"passthroughBehavior: "when_no_match"httpMethod: "GET"type: "aws"put:produces:- "application/json"parameters:- name: "item"in: "path"required: truetype: "string"- name: "folder"in: "path"required: truetype: "string"responses:200:description: "200 response"schema:$ref: "#/definitions/Empty"400:description: "400 response"500:description: "500 response"x-amazon-apigateway-integration:credentials: "<API_ROLE_WITH_FULL_S3_PERMISSIONS>"uri: "arn:aws:apigateway:us-east-1:s3:path/{bucket}/{object}"responses:4\d{2}:statusCode: "400"default:statusCode: "200"5\d{2}:statusCode: "500"requestParameters:integration.request.path.object: "method.request.path.item"integration.request.path.bucket: "method.request.path.folder"passthroughBehavior: "when_no_match"httpMethod: "PUT"type: "aws"securityDefinitions:sigv4:type: "apiKey"name: "Authorization"in: "header"x-amazon-apigateway-authtype: "awsSigv4"definitions:Empty:type: "object"title: "Empty Schema"x-amazon-apigateway-binary-media-types:- "*/*"
Please use some file editor and replace the “<API_ROLE_WITH_FULL_S3_PERMISSIONS>” with actual ROLE ARN which has following permissions.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
Please note that the above role should contain the trust relationship as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Once you import and deploy the api again, you can test it using curl or postman:
The following code is for uploading file to S3 bucket name random-audit-s3.
curl --location --request PUT 'https://wuzukp9zmh.execute-api.us-east-1.amazonaws.com/dev/random-audit-s3/test.pdf' \
--header 'Content-Type: application/pdf' \
--form '=@/Randomtest.pdf'
The following code is for fetching file test.pdf from S3 bucket
curl --location --request GET 'https://wuzukp9zmh.execute-api.us-east-1.amazonaws.com/dev/random-audit-s3/test.pdf'