@byaga/cdk-patterns 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byaga/cdk-patterns",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Collection of common patterns used when making AWS CloudFormation templates using CDK",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -15,9 +15,11 @@
15
15
  "author": "VeryFineHat",
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
+ "@types/fs-extra": "^11.0.2",
18
19
  "aws-cdk": "^2.92.0",
19
20
  "aws-cdk-lib": "^2.92.0",
20
- "constructs": "^10.2.69"
21
+ "constructs": "^10.2.69",
22
+ "fs-extra": "^11.1.1"
21
23
  },
22
24
  "devDependencies": {
23
25
  "@types/node": "^20.5.0",
@@ -1,31 +1,31 @@
1
1
  import {Certificate, CertificateValidation} from "aws-cdk-lib/aws-certificatemanager";
2
2
  import {HostedZone, IHostedZone} from "aws-cdk-lib/aws-route53";
3
- import {CfnOutput} from "aws-cdk-lib";
4
- import IDeployStack from "./IDeployStack";
3
+ import {Output} from "./Output";
4
+ import DeployStack from "./DeployStack";
5
5
  import IDomainConfig from "./IDomainConfig";
6
6
 
7
7
  export class ApiCertificate extends Certificate {
8
8
  hostedZone: IHostedZone
9
9
  domain: string
10
10
 
11
- constructor(stack: IDeployStack, id: string, domain: IDomainConfig) {
11
+ constructor(stack: DeployStack, id: string, domain: IDomainConfig) {
12
12
  const certDomain = [domain.domainName]
13
13
  if (domain.subdomain) certDomain.splice(0, 0, domain.subdomain)
14
14
  const domainName = certDomain.join('.')
15
15
 
16
+ console.log('Getting Hosted Zone', domain.hostedZone.name)
16
17
  const hostedZone: IHostedZone = HostedZone.fromHostedZoneAttributes(stack, stack.genId(id, 'hosted-zone'), {
17
18
  hostedZoneId: domain.hostedZone.id,
18
19
  zoneName: domain.hostedZone.name
19
20
  })
21
+ console.log('Defining Certificate For', domainName)
20
22
  super(stack, stack.genId(id), {
21
23
  domainName,
22
24
  validation: CertificateValidation.fromDns(hostedZone)
23
25
  });
24
26
 
25
27
  this.domain = domainName
26
- new CfnOutput(this, stack.genId(id, "certificate-output"), {
27
- value: this.certificateArn ,
28
- exportName: stack.genName(id)})
28
+ new Output(stack, id, this.certificateArn)
29
29
  this.hostedZone = hostedZone
30
30
  }
31
31
  }
@@ -2,17 +2,17 @@ import {Stack} from 'aws-cdk-lib';
2
2
  import IStackArguments from './IStackArguments'
3
3
  import {IConstruct} from "constructs";
4
4
 
5
- export class IDeployStack extends Stack {
5
+ export class DeployStack extends Stack {
6
6
  registry: { [t: string]: { [n: string]: any } } = {}
7
7
  stage: string
8
8
  name: string
9
9
 
10
10
  genName(...name: string[]): string {
11
- return IDeployStack.genStackResourceName(this.name, this.stage, name.filter(n => !!n).join('-'))
11
+ return DeployStack.genStackResourceName(this.name, this.stage, name.filter(n => !!n).join('-'))
12
12
  }
13
13
 
14
14
  genId(...name: string[]): string {
15
- return IDeployStack.genStackResourceId(this.name, this.stage, name.filter(n => !!n).join('-'))
15
+ return DeployStack.genStackResourceId(this.name, this.stage, name.filter(n => !!n).join('-'))
16
16
  }
17
17
 
18
18
  static genStackResourceName(stackName: string, resource: string, stage = 'develop') {
@@ -53,4 +53,4 @@ export class IDeployStack extends Stack {
53
53
  return instance;
54
54
  }
55
55
  }
56
- export default IDeployStack
56
+ export default DeployStack
package/src/Output.ts ADDED
@@ -0,0 +1,11 @@
1
+ import {CfnOutput} from 'aws-cdk-lib/core';
2
+ import {DeployStack} from './DeployStack';
3
+
4
+ export class Output extends CfnOutput {
5
+ constructor(stack: DeployStack, name: string, value: string) {
6
+ super(stack, stack.genId(name, 'output'), {
7
+ value,
8
+ exportName: stack.genName(name)
9
+ })
10
+ }
11
+ }
package/src/Role.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import {FederatedPrincipal, IPrincipal, Role as CdkRole} from "aws-cdk-lib/aws-iam";
2
- import {CfnOutput, Duration} from "aws-cdk-lib";
3
- import {IDeployStack} from "./IDeployStack";
2
+ import {Duration} from "aws-cdk-lib";
3
+ import {Output} from './Output'
4
+ import {DeployStack} from "./DeployStack";
4
5
  import {IManagedPolicy} from "aws-cdk-lib/aws-iam/lib/managed-policy";
5
6
  import {PolicyDocument} from "aws-cdk-lib/aws-iam/lib/policy-document";
6
7
 
@@ -137,7 +138,7 @@ interface IRoleProps {
137
138
  }
138
139
 
139
140
  export class Role extends CdkRole {
140
- constructor(stack: IDeployStack, id: string, props: IRoleProps) {
141
+ constructor(stack: DeployStack, id: string, props: IRoleProps) {
141
142
  console.log('Defining Role', stack.genId(id))
142
143
  if (!props.assumedBy) {
143
144
  props.assumedBy = new FederatedPrincipal(
@@ -159,9 +160,6 @@ export class Role extends CdkRole {
159
160
  roleName: stack.genName(props.roleName || id),
160
161
  assumedBy: props.assumedBy
161
162
  })
162
- new CfnOutput(stack, stack.genId(id, 'arn-output'), {
163
- value: this.roleArn,
164
- exportName: stack.genName(id, 'arn')
165
- })
163
+ new Output(stack, `${id}-arn`, this.roleArn)
166
164
  }
167
165
  }
@@ -0,0 +1,99 @@
1
+ import {RemovalPolicy} from "aws-cdk-lib/core";
2
+ import {Output} from './Output'
3
+ import {DeployStack} from "./DeployStack";
4
+ import {execSync} from "child_process";
5
+ import * as fs from 'fs-extra'
6
+ import * as path from 'path'
7
+ import {Bucket} from "aws-cdk-lib/aws-s3"
8
+ import {BucketDeployment, Source} from "aws-cdk-lib/aws-s3-deployment"
9
+ import ApiCertificate from "./ApiCertificate";
10
+ import {
11
+ CloudFrontAllowedMethods,
12
+ CloudFrontWebDistribution,
13
+ OriginAccessIdentity,
14
+ SSLMethod,
15
+ ViewerCertificate,
16
+ ViewerProtocolPolicy
17
+ } from "aws-cdk-lib/aws-cloudfront"
18
+ import IDomainConfig from "./IDomainConfig";
19
+ import {PolicyStatement} from "aws-cdk-lib/aws-iam";
20
+ import {ARecord, RecordTarget} from "aws-cdk-lib/aws-route53";
21
+ import {CloudFrontTarget} from "aws-cdk-lib/aws-route53-targets";
22
+
23
+ interface StaticWebSiteConfig {
24
+ srcDir?: string,
25
+ domain: IDomainConfig,
26
+ env: NodeJS.ProcessEnv
27
+ }
28
+
29
+ export class StaticWebSite {
30
+ constructor(stack: DeployStack, id: string, props: StaticWebSiteConfig) {
31
+ console.log('Deploying Static Web Site', id)
32
+ const srcDir = path.resolve("../src/", props.srcDir || '')
33
+ const buildDir = path.resolve("../dist/", props.srcDir || '')
34
+
35
+ console.log('Installing Prod Dependencies', id)
36
+ execSync('npm i --production --quiet', {
37
+ cwd: srcDir
38
+ })
39
+ console.log('Building UI Source', id)
40
+ execSync('npm run export', {
41
+ cwd: srcDir,
42
+ //env: props.env
43
+ })
44
+ fs.copySync(path.resolve(srcDir, "./out"), buildDir);
45
+
46
+ console.log('Creating HTTPS Certificate', id + '-certificate')
47
+ const certificate = new ApiCertificate(stack, id + '-certificate', props.domain);
48
+ console.log('Deploying Site Content Bucket', stack.genId(id, "content-bucket"))
49
+ const s3BucketSource = new Bucket(stack, stack.genId(id, "content-bucket"), {
50
+ bucketName: certificate.domain,
51
+ websiteIndexDocument: "index.html",
52
+ websiteErrorDocument: "error.html",
53
+ publicReadAccess: true,
54
+ removalPolicy: RemovalPolicy.DESTROY,
55
+ autoDeleteObjects: true
56
+ });
57
+ new Output(stack, `${id}-content-bucket`, s3BucketSource.bucketName);
58
+
59
+ const cloudFrontPolicy = new PolicyStatement({
60
+ actions: ['s3:GetBucket*', 's3:GetObject*', 's3:List*'],
61
+ resources: [s3BucketSource.bucketArn, s3BucketSource.bucketArn + '/*'],
62
+ })
63
+
64
+ new BucketDeployment(stack, stack.genId(id, 'bucket-deployment'), {
65
+ sources: [Source.asset(buildDir)],
66
+ destinationBucket: s3BucketSource
67
+ })
68
+ const originAccessIdentity = new OriginAccessIdentity(stack, "WebsiteOAI");
69
+ cloudFrontPolicy.addArnPrincipal(originAccessIdentity.cloudFrontOriginAccessIdentityS3CanonicalUserId)
70
+
71
+ const distro = new CloudFrontWebDistribution(stack, stack.genId(id, 'cloudfront-web-distribution'), {
72
+ enabled: true,
73
+ //priceClass:
74
+ originConfigs: [{
75
+ s3OriginSource: {
76
+ s3BucketSource,
77
+ originAccessIdentity
78
+ },
79
+ behaviors: [{
80
+ allowedMethods: CloudFrontAllowedMethods.GET_HEAD_OPTIONS,
81
+ isDefaultBehavior: true
82
+ }]
83
+ }],
84
+ viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
85
+ viewerCertificate: ViewerCertificate.fromAcmCertificate(certificate, {
86
+ aliases: [certificate.domain],
87
+ sslMethod: SSLMethod.SNI
88
+ })
89
+ })
90
+ new Output(stack, `${id}-base-url`, "https://" + certificate.domain);
91
+
92
+ console.log('Setting Route53 A-Name Record', props.domain.domainName)
93
+ new ARecord(stack, stack.genId('alias'), {
94
+ zone: certificate.hostedZone,
95
+ recordName: certificate.domain,
96
+ target: RecordTarget.fromAlias(new CloudFrontTarget(distro))
97
+ })
98
+ }
99
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export {ApiCertificate} from "./ApiCertificate";
2
- export {IDeployStack} from "./IDeployStack";
2
+ export {DeployStack} from "./DeployStack";
3
3
  export {IDomainConfig} from "./IDomainConfig";
4
4
  export {IHostedZoneConfig} from "./IHostedZoneConfig";
5
5
  export {IStackArguments} from "./IStackArguments";
6
6
  export {Role} from "./Role";
7
+ export {StaticWebSite} from "./StaticWebSite";
8
+ export {Output} from "./Output";