Skip to content

Instantly share code, notes, and snippets.

@BDQ
Last active September 2, 2021 12:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BDQ/11d00c7174652605a7af915f20cb7da3 to your computer and use it in GitHub Desktop.
Save BDQ/11d00c7174652605a7af915f20cb7da3 to your computer and use it in GitHub Desktop.
AWS S3 Object Lambda CDK (1.18.0) Example
const { S3 } = require("aws-sdk");
const axios = require("axios").default;
exports.handler = async (event: any) => {
console.log(event);
const s3 = new S3();
// Retrieve the operation context object from event. This has info to where the WriteGetObjectResponse request
// should be delivered and a presigned URL in `inputS3Url` where we can download the requested object from.
// The `userRequest` object has information related to the user which made this `GetObject` request to S3OL.
const { userRequest, getObjectContext } = event;
const { outputRoute, outputToken, inputS3Url } = getObjectContext;
console.log({ inputS3Url });
// Check for the presence of a `CustomHeader` header and deny or allow based on that header
const isTokenPresent = Object.keys(userRequest.headers).includes(
"SuperSecretToken"
);
console.log({ isTokenPresent });
if (isTokenPresent) {
// If the token is not present we send an error back to the user. Notice the `await` infront of the request as
// we want to wait for this request to finish sending before moving on.
await s3
.writeGetObjectResponse({
RequestRoute: outputRoute,
RequestToken: outputToken,
StatusCode: 403,
ErrorCode: "NoSuperSecretTokenFound",
ErrorMessage: "The request was not secret enough.",
})
.promise();
} else {
// If the user presented our custom `SuperSecretToken` header we send the requested object back to the user.
// Again notice the presence of `await`.
const presignedResponse = await axios.get(inputS3Url);
console.log(presignedResponse);
await s3
.writeGetObjectResponse({
RequestRoute: outputRoute,
RequestToken: outputToken,
Body: presignedResponse.data,
})
.promise();
}
// Gracefully exit the Lambda function
return { statusCode: 200 };
};
import { Effect, PolicyStatement } from "@aws-cdk/aws-iam";
import { NodejsFunction } from "@aws-cdk/aws-lambda-nodejs";
import { CfnAccessPoint, Bucket } from "@aws-cdk/aws-s3";
import { CfnAccessPoint as CfnObjectAccessPoint } from "@aws-cdk/aws-s3objectlambda";
import { CfnOutput, Construct, Stack, StackProps } from "@aws-cdk/core";
export class Resolver extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const bucket = new Bucket(this, "MrsBucket", {});
const transformer = new NodejsFunction(this, "transformer", {});
transformer.addToRolePolicy(
new PolicyStatement({
actions: ["s3-object-lambda:WriteGetObjectResponse"],
effect: Effect.ALLOW,
resources: ["*"],
})
);
bucket.grantReadWrite(transformer);
const supportingAccessPoint = new CfnAccessPoint(this, "baseAccessPoint", {
bucket: bucket.bucketName,
});
const objectAP = new CfnObjectAccessPoint(this, "objectAP", {
name: "lammy-access-pt",
objectLambdaConfiguration: {
supportingAccessPoint: supportingAccessPoint.attrArn,
transformationConfigurations: [
{
actions: ["GetObject"],
contentTransformation: {
AwsLambda: {
FunctionArn: transformer.functionArn,
FunctionPayload: "{}",
},
},
},
],
},
});
new CfnOutput(this, "objectAPOutput", {
value: objectAP.attrArn,
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment