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

Commit

Permalink
AWS NOTION project is live using CDK
Browse files Browse the repository at this point in the history
  • Loading branch information
ildarsafin committed Feb 5, 2022
1 parent 4a48a1b commit e916b0d
Show file tree
Hide file tree
Showing 14 changed files with 7,648 additions and 33 deletions.
4 changes: 4 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
AWS_REGION = eu-central-1
AWS_ACCOUNT = value
AWS_SSL_CERTIFICATE_ARN = value
AWS_SSL_CERTIFICATE_ARN = value
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
*.js
!jest.config.js
*.d.ts
node_modules

# CDK asset staging directory
.cdk.staging
cdk.out

.env
9 changes: 9 additions & 0 deletions bin/ci.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env node
import "source-map-support/register"
import cdk = require("aws-cdk-lib")
import { CIStack } from "../lib/ci-stack"

const app = new cdk.App()
new CIStack(app, "NotionSitesOnAwsStack", {
repositoryName: "notion-sites-on-aws",
})
16 changes: 16 additions & 0 deletions bin/lambda.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env node
import "source-map-support/register"
import cdk = require("aws-cdk-lib")
import { NotionSitesOnAwsStack } from "../lib/notion-sites-on-aws-stack"

export const lambdaApiStackName = "NotionSitesOnAwsStack"
export const lambdaFunctionName = "NotionSitesOnAwsFunction"

const app = new cdk.App()
new NotionSitesOnAwsStack(app, lambdaApiStackName, {
functionName: lambdaFunctionName,
env: {
region: process.env.AWS_REGION,
account: process.env.AWS_ACCOUNT,
},
})
21 changes: 0 additions & 21 deletions bin/notion-sites-on-aws.ts

This file was deleted.

6 changes: 6 additions & 0 deletions cdk.context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"hosted-zone:account=056244583577:domainName=ildarsafin.tech:region=eu-central-1": {
"Id": "/hostedzone/Z08437272BS1HAA544AU8",
"Name": "ildarsafin.tech."
}
}
2 changes: 1 addition & 1 deletion cdk.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"app": "npx ts-node --prefer-ts-exts bin/notion-sites-on-aws.ts",
"app": "npx ts-node --prefer-ts-exts bin/ci.ts",
"watch": {
"include": [
"**"
Expand Down
119 changes: 119 additions & 0 deletions lib/ci-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { CodeCommitSourceAction, CodeBuildAction } from "aws-cdk-lib/aws-codepipeline-actions"
import { PolicyStatement } from "aws-cdk-lib/aws-iam"
import { ArnFormat, Stack, StackProps } from "aws-cdk-lib"
import { PipelineProject, LinuxBuildImage } from "aws-cdk-lib/aws-codebuild"
import { Artifact, Pipeline } from "aws-cdk-lib/aws-codepipeline"
import { Repository } from "aws-cdk-lib/aws-codecommit"
import { Construct } from "constructs"
import { lambdaApiStackName, lambdaFunctionName } from "../bin/lambda"

interface CIStackProps extends StackProps {
repositoryName: string
}

export class CIStack extends Stack {
constructor(scope: Construct, name: string, props: CIStackProps) {
super(scope, name, props)

const pipeline = new Pipeline(this, "Pipeline", {})

const repo = Repository.fromRepositoryName(
this,
"NotionAwsServiceRepository",
props.repositoryName
)
const sourceOutput = new Artifact("SourceOutput")
const sourceAction = new CodeCommitSourceAction({
actionName: "CodeCommit",
repository: repo,
output: sourceOutput,
})
pipeline.addStage({
stageName: "Source",
actions: [sourceAction],
})

this.createBuildStage(pipeline, sourceOutput)
}

private createBuildStage(pipeline: Pipeline, sourceOutput: Artifact) {
const project = new PipelineProject(this, `BuildProject`, {
environment: {
buildImage: LinuxBuildImage.STANDARD_3_0,
},
})

const cdkDeployPolicy = new PolicyStatement()
cdkDeployPolicy.addActions(
"cloudformation:GetTemplate",
"cloudformation:CreateChangeSet",
"cloudformation:DescribeChangeSet",
"cloudformation:ExecuteChangeSet",
"cloudformation:DescribeStackEvents",
"cloudformation:DeleteChangeSet",
"cloudformation:DescribeStacks",
"s3:*Object",
"s3:ListBucket",
"s3:getBucketLocation",
"lambda:UpdateFunctionCode",
"lambda:GetFunction",
"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:GetFunctionConfiguration",
"lambda:AddPermission",
"lambda:RemovePermission"
)
cdkDeployPolicy.addResources(
this.formatArn({
service: "cloudformation",
resource: "stack",
resourceName: "CDKToolkit/*",
}),
this.formatArn({
service: "cloudformation",
resource: "stack",
resourceName: `${lambdaApiStackName}/*`,
}),
this.formatArn({
service: "lambda",
resource: "function",
arnFormat: ArnFormat.COLON_RESOURCE_NAME,
resourceName: lambdaFunctionName,
}),
"arn:aws:s3:::cdktoolkit-stagingbucket-*"
)
const editOrCreateLambdaDependencies = new PolicyStatement()
editOrCreateLambdaDependencies.addActions(
"iam:GetRole",
"iam:PassRole",
"iam:CreateRole",
"iam:AttachRolePolicy",
"iam:PutRolePolicy",
"apigateway:GET",
"apigateway:DELETE",
"apigateway:PUT",
"apigateway:POST",
"apigateway:PATCH",
"s3:CreateBucket",
"s3:PutBucketTagging"
)
editOrCreateLambdaDependencies.addResources("*")
project.addToRolePolicy(cdkDeployPolicy)
project.addToRolePolicy(editOrCreateLambdaDependencies)

const buildOutput = new Artifact(`BuildOutput`)
const buildAction = new CodeBuildAction({
actionName: `Build`,
project,
input: sourceOutput,
outputs: [buildOutput],
})

pipeline.addStage({
stageName: "build",
actions: [buildAction],
})

return buildOutput
}
}
89 changes: 80 additions & 9 deletions lib/notion-sites-on-aws-stack.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,87 @@
import { Stack, StackProps } from 'aws-cdk-lib';
import { LambdaIntegration, MethodLoggingLevel, RestApi } from "aws-cdk-lib/aws-apigateway"
import { AnyPrincipal, Effect, PolicyStatement } from "aws-cdk-lib/aws-iam"
import { Function, Runtime, AssetCode, Code } from "aws-cdk-lib/aws-lambda"
import s3 = require("aws-cdk-lib/aws-s3")

import { Duration, Stack, StackProps } from "aws-cdk-lib"
import cloudfront = require('aws-cdk-lib/aws-cloudfront')

import iam = require('aws-cdk-lib/aws-iam')

import { CloudFrontToApiGateway } from '@aws-solutions-constructs/aws-cloudfront-apigateway';

import acm = require('aws-cdk-lib/aws-certificatemanager')

import { Construct } from 'constructs';
// import * as sqs from 'aws-cdk-lib/aws-sqs';

require('dotenv').config()

interface LambdaApiStackProps extends StackProps {
functionName: string
}

export class NotionSitesOnAwsStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
private restApi: RestApi
private lambdaFunction: Function
private bucket: s3.Bucket

constructor(scope: Construct, id: string, props: LambdaApiStackProps) {
super(scope, id, props)

this.bucket = new s3.Bucket(this, "notion-sites-on-aws")

this.restApi = new RestApi(this, this.stackName + "RestApi", {
deployOptions: {
stageName: "prod",
metricsEnabled: true,
loggingLevel: MethodLoggingLevel.INFO,
dataTraceEnabled: true,
},
binaryMediaTypes: ['image/*', 'video/*']
})
const lambdaPolicy = new PolicyStatement()
lambdaPolicy.addActions("s3:ListBucket")
lambdaPolicy.addResources(this.bucket.bucketArn)

this.lambdaFunction = new Function(this, props.functionName, {
functionName: props.functionName,
handler: "handler.handler",
runtime: Runtime.NODEJS_14_X,
code: new AssetCode(`./src`),
memorySize: 256,
timeout: Duration.seconds(10),
environment: {
BUCKET: this.bucket.bucketName,
DOMAIN_NAME: (process.env.DOMAIN_NAME || '')
},
initialPolicy: [lambdaPolicy]
})
const pathname = this.restApi.root.addResource('{pathname}');

this.restApi.root.addMethod("ANY", new LambdaIntegration(this.lambdaFunction))

pathname.addMethod("ANY", new LambdaIntegration(this.lambdaFunction, { proxy: true }))

const certificate = acm.Certificate.fromCertificateArn(this, 'Certificate', (process.env.AWS_SSL_CERTIFICATE_ARN || ''));

// The code that defines your stack goes here

// example resource
// const queue = new sqs.Queue(this, 'NotionSitesOnAwsQueue', {
// visibilityTimeout: cdk.Duration.seconds(300)
// });
new CloudFrontToApiGateway(this, 'notion-site-distribution', {
existingApiGatewayObj: this.restApi,
cloudFrontDistributionProps: {
certificate: certificate,
domainNames: [process.env.DOMAIN_NAME],
defaultBehavior: {
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
forwardedValues: {
queryString: true,
cookies: {
forward: "forward",
},
headers: ['Accept', 'Referer', 'Authorization', 'Content-Type', 'Origin', 'Access - Control-Request-Method', 'Sec-Fetch-Site', 'Access-Control-Request-Headers', 'Sec - Fetch-Dest', 'Sec-Fetch-Mode'],
}
},
});
}
}
Loading

0 comments on commit e916b0d

Please sign in to comment.