Skip to content
This repository has been archived by the owner on Nov 2, 2023. It is now read-only.

Commit

Permalink
CDK for Terraform
Browse files Browse the repository at this point in the history
* Created a working version of the Lambda function
* Created a zip file of the Lambda code and uploaded to the S3 code
  bucket
* Added a CloudWatch Group and IAM role to be used by the Lambda
  function
* Added an IAM policy for logging to CloudWatch and attached to the IAM
  Role
* Enabled versioning on the S3 code bucket
* Ended up having to switch from using a SourceCodeHash to the S3
  version...
  * Tried to use both the asset and source hash of both the zip file as
    well as the uploaded S3 object and both were causing a continuous
    update of the function
    (hashicorp/terraform-provider-aws#7385)
  * Tried to manually create the base64 encoded hash from the Lambda
    code zip, but CDKTF was trying to access the zip before it was
    actually created
  * Seems like this is a better solution anyway, as the S3 bucket for
    the code should probably be versioned anyway
  • Loading branch information
archetypalsxe committed Sep 16, 2022
1 parent cf5946c commit ab711fb
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 7 deletions.
3 changes: 2 additions & 1 deletion cdk-terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Cloud Development Kit for Terraform (CDKTF)
* [Install CDKTF](https://learn.hashicorp.com/tutorials/terraform/cdktf-install?in=terraform/cdktf)

## Running Through CDKTF
* These should all be ran from the `cdk-terraform` directory
* Deploy the state stack to manage state:
* `cdktf deploy cdk-terraform-state`
* **This does have to be deployed before the Lambda stack**
Expand All @@ -18,7 +19,7 @@ Cloud Development Kit for Terraform (CDKTF)
* `cdktf destroy lambda cdk-terraform-state`

## Running Using Native Terraform
* Running a Terraform init with migrating the state:
* Running a Terraform init with migrating the state or reconfiguring:
* `terraform -chdir=cdktf.out/stacks/lambda init -migrate-state`
* `terraform -chdir=cdktf.out/stacks/lambda init -reconfigure`

Expand Down
12 changes: 11 additions & 1 deletion cdk-terraform/lib/s3Bucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { s3, kms } from "@cdktf/provider-aws";
export function createBucket(
stack: TerraformStack,
bucketName: string,
encrypt: boolean
encrypt: boolean,
versioning: boolean
) {

const bucket = new s3.S3Bucket(stack, bucketName, {
Expand All @@ -31,6 +32,15 @@ export function createBucket(
});
}

if (versioning) {
new s3.S3BucketVersioningA(stack, 'bucket-versioning', {
bucket: bucket.bucket,
versioningConfiguration: {
status: "Enabled"
},
});
}

new s3.S3BucketPublicAccessBlock(stack, 'statelock-public-access-block', {
bucket: bucket.bucket,
blockPublicAcls: true,
Expand Down
101 changes: 97 additions & 4 deletions cdk-terraform/stacks/lambda.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,111 @@
import { TerraformStack } from "cdktf";
import { AssetType, TerraformAsset, TerraformStack } from "cdktf";
import { Construct } from "constructs";
import { AwsProvider } from "@cdktf/provider-aws";
import { AwsProvider, s3, cloudwatch, iam, lambdafunction } from "@cdktf/provider-aws";
import * as s3Lib from "../lib/s3Bucket";
import path = require("path");

export interface LambdaProps {
readonly projectName: string,
}

const lambdaAssumePolicy = {
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}

const lambdaCloudWatchPolicy = {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*",
"Effect": "Allow",
"Sid": ""
}
]
}

const lambdaExecutionPolicyArn = 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'

export class LambdaStack extends TerraformStack {
constructor(scope: Construct, name: string, props: LambdaProps) {
super(scope, name);

new AwsProvider(this, 'aws', {});

s3Lib.createBucket(this, props.projectName + "-code", true);
const lambdaName = `${props.projectName}-lambda`

const codeBucket = s3Lib.createBucket(
this,
props.projectName + "-code",
true,
true
);

const lambdaZip = new TerraformAsset(this, "lambdaZip", {
path: path.resolve("../lambda"),
type: AssetType.ARCHIVE
});

const lambdaZipUpload = new s3.S3Object(this, "lambdaZipUpload", {
bucket: codeBucket.bucket,
key: "lambda.zip",
source: lambdaZip.path,
sourceHash: lambdaZip.assetHash
});

const logGroup = new cloudwatch.CloudwatchLogGroup(this, "lambdaCloudWatchGroup", {
name: `/aws/lambda/${lambdaName}`,
retentionInDays: 7
});

const lambdaRole = new iam.IamRole(this, "lambdaRole", {
name: `${props.projectName}-lambda`,
assumeRolePolicy: JSON.stringify(lambdaAssumePolicy)
});

const lambdaLoggingPolicy = new iam.IamPolicy(this, "lambdaLoggingPolicy", {
name: `${props.projectName}-lambda-logging`,
path: "/",
description: "Policy to allow the IAM role for Lambda to write to CloudWatch Logs",
policy: JSON.stringify(lambdaCloudWatchPolicy)
});

const loggingPolicyAttachment = new iam.IamRolePolicyAttachment(this, "loggingPolicyAttachment", {
policyArn: lambdaLoggingPolicy.arn,
role: lambdaRole.name
});

new iam.IamRolePolicyAttachment(this, "executionPolicyAttachment", {
policyArn: lambdaExecutionPolicyArn,
role: lambdaRole.name
});

new lambdafunction.LambdaFunction(this, "lambdaFunction", {
functionName: lambdaName,
role: lambdaRole.arn,
s3Bucket: codeBucket.bucket,
s3Key: lambdaZipUpload.key,
s3ObjectVersion: lambdaZipUpload.versionId,
// TODO Make it dynamic
handler: "index.handler",
// TODO Make this dynamic as well
runtime: "nodejs16.x",
dependsOn: [
logGroup,
loggingPolicyAttachment,
],
});
}
}
2 changes: 1 addition & 1 deletion cdk-terraform/stacks/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class State extends TerraformStack {

new AwsProvider(this, 'aws', {});

const stateBucket = s3Lib.createBucket(this, props.bucketName, true);
const stateBucket = s3Lib.createBucket(this, props.bucketName, true, false);

new TerraformOutput(this, "stateBucket", {
value: stateBucket.id
Expand Down
1 change: 1 addition & 0 deletions lambda/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
exports.handler = async (event) => {
console.log("Test log!!!");
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!!!'),
Expand Down

0 comments on commit ab711fb

Please sign in to comment.