@inizioevoke/evosynth 1.8.0 → 2.0.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.
@@ -11,7 +11,33 @@ import type { ResourceProps } from "../types.d.ts";
11
11
 
12
12
  export type EnvironmentVariables = Record<string, { value: any, type?: BuildEnvironmentVariableType }>;
13
13
 
14
- interface SsmParameter extends SsmStringParameter {
14
+ export type CodeBuildImageId =
15
+ 'aws/codebuild/amazonlinux2-aarch64-standard:1.0' |
16
+ 'aws/codebuild/amazonlinux2-x86_64-standard:2.0' |
17
+ 'aws/codebuild/amazonlinux2-x86_64-standard:3.0' |
18
+ 'aws/codebuild/amazonlinux-x86_64-standard:4.0' |
19
+ 'aws/codebuild/amazonlinux-x86_64-standard:5.0' |
20
+ 'aws/codebuild/amazonlinux-x86_64-standard:6.0' |
21
+ 'aws/codebuild/amazonlinux-x86_64-standard:corretto8' |
22
+ 'aws/codebuild/amazonlinux-x86_64-standard:corretto11' |
23
+ 'aws/codebuild/amazonlinux-aarch64-standard:2.0' |
24
+ 'aws/codebuild/amazonlinux-aarch64-standard:3.0' |
25
+ 'aws/codebuild/standard:3.0' |
26
+ 'aws/codebuild/standard:4.0' |
27
+ 'aws/codebuild/standard:5.0' | // nodejs 12, 14
28
+ 'aws/codebuild/standard:6.0' | // nodejs 16
29
+ 'aws/codebuild/standard:7.0' | // nodejs 18, 20, 22, 24
30
+ 'aws/codebuild/standard:8.0' | // nodejs 22, 24
31
+ 'aws/codebuild/windows-base:2019-1.0' |
32
+ 'aws/codebuild/windows-base:2019-2.0' |
33
+ 'aws/codebuild/windows-base:2019-3.0' |
34
+ 'aws/codebuild/windows-base:2022-1.0' |
35
+ (string & {});
36
+
37
+ export type CodeBuildComputeType = 'SMALL' | 'MEDIUM' | 'LARGE' | 'X_LARGE' | 'X2_LARGE' | (string & {});
38
+ export type CodeBuildNodeJs = 12 | 14 | 16 | 18 | 20 | 22 | 24 | (number & {});
39
+
40
+ export interface CodeBuildSsmParameter extends SsmStringParameter {
15
41
  encrypted?: boolean;
16
42
  }
17
43
  export interface EcrBuildImage {
@@ -21,13 +47,15 @@ export interface EcrBuildImage {
21
47
  export interface CodeBuildPipelineProjectProps extends ResourceProps {
22
48
  projectName?: string;
23
49
  buildSpec?: string | object;
24
- buildImage?: ('STANDARD_5_0' | 'STANDARD_6_0' | 'STANDARD_7_0') | IBuildImage;
25
50
  ecrBuildImage?: EcrBuildImage,
26
- computeType?: ('SMALL' | 'MEDIUM' | 'LARGE' | 'X_LARGE' | 'X2_LARGE') | string;
51
+ buildImage?: IBuildImage;
52
+ buildImageNodeJS?: CodeBuildNodeJs;
53
+ buildImageId?: CodeBuildImageId;
54
+ computeType?: CodeBuildComputeType;
27
55
  environmentVariables?: EnvironmentVariables;
28
56
  cloudFrontDistributionArn?: string;
29
57
  s3BucketName?: string;
30
- ssmParameters?: SsmParameter[];
58
+ ssmParameters?: CodeBuildSsmParameter[];
31
59
  }
32
60
 
33
61
  export class CodeBuildPipelineProject extends Construct {
@@ -58,12 +86,27 @@ export class CodeBuildPipelineProject extends Construct {
58
86
  Repository.fromRepositoryName(this, 'EcrRepository', props.ecrBuildImage.repository);
59
87
  buildImage = LinuxBuildImage.fromEcrRepository(repository, props.ecrBuildImage.tag);
60
88
  } else if (props.buildImage) {
61
- if (typeof props.buildImage == 'string') {
62
- buildImage = LinuxBuildImage[props.buildImage ?? 'STANDARD_7_0']
63
- } else {
64
- buildImage = props.buildImage as IBuildImage;
89
+ buildImage = props.buildImage as IBuildImage;
90
+ } else if (props.buildImageNodeJS) {
91
+ let standard = 8;
92
+ switch (props.buildImageNodeJS) {
93
+ case 12:
94
+ case 14:
95
+ standard = 5;
96
+ break;
97
+ case 16:
98
+ standard = 6;
99
+ break;
100
+ case 18:
101
+ case 20:
102
+ standard = 7;
103
+ break;
65
104
  }
66
- }
105
+ buildImage = LinuxBuildImage.fromCodeBuildImageId(`aws/codebuild/standard:${standard}.0`);
106
+ } else if (props.buildImageId) {
107
+ buildImage = LinuxBuildImage.fromCodeBuildImageId(props.buildImageId);
108
+ }
109
+
67
110
 
68
111
  this.project = new PipelineProject(this, 'CodeBuildPipelineProjectProps', {
69
112
  projectName: props.projectName,
@@ -1,7 +1,7 @@
1
1
  import { RemovalPolicy, PhysicalName, Aws } from "aws-cdk-lib";
2
2
  import { Construct } from 'constructs';
3
3
  import { IProject } from "aws-cdk-lib/aws-codebuild";
4
- import { Artifact, Pipeline } from "aws-cdk-lib/aws-codepipeline";
4
+ import { Artifact, Pipeline, PipelineType } from "aws-cdk-lib/aws-codepipeline";
5
5
  import { CodeBuildAction, CodeStarConnectionsSourceAction } from "aws-cdk-lib/aws-codepipeline-actions";
6
6
  import { Bucket } from 'aws-cdk-lib/aws-s3';
7
7
  import { StringParameter } from 'aws-cdk-lib/aws-ssm';
@@ -45,7 +45,8 @@ export class CodePipelineProject extends Construct {
45
45
 
46
46
  this.pipeline = new Pipeline(this, 'CodePipelineProject', {
47
47
  pipelineName: props.pipelineName,
48
- artifactBucket: this.s3Bucket
48
+ artifactBucket: this.s3Bucket,
49
+ pipelineType: PipelineType.V2
49
50
  });
50
51
 
51
52
  tagResource(this.pipeline, props.tags);
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Environment } from "aws-cdk-lib";
2
2
 
3
- export * from './lib/tags.ts';
3
+ export * from './lib/tags.js';
4
+ export * from './cli/index.js';
4
5
 
5
6
  interface GetEnvParams {
6
7
  account?: number | string;
@@ -17,18 +17,7 @@ import { CloudFrontWebAcl } from '../../constructs/waf.js';
17
17
  import { domainAsId } from '../../lib/utils.js';
18
18
  import { addEvoStackTags } from '../../lib/tags.ts';
19
19
  import { S3BucketOrigin } from 'aws-cdk-lib/aws-cloudfront-origins';
20
- import type { BasicAuthCredentials, CspHeaders } from '../../types.d.ts';
21
-
22
-
23
- type AWSManagedResponseHeadersPolicy =
24
- 'CORS_ALLOW_ALL_ORIGINS' |
25
- 'CORS_ALLOW_ALL_ORIGINS_AND_SECURITY_HEADERS' |
26
- 'CORS_ALLOW_ALL_ORIGINS_WITH_PREFLIGHT' |
27
- 'CORS_ALLOW_ALL_ORIGINS_WITH_PREFLIGHT_AND_SECURITY_HEADERS' |
28
- 'SECURITY_HEADERS';
29
-
30
- type UUID = `${string}-${string}-${string}-${string}-${string}`;
31
- type CloudFrontFunctionEventType = keyof typeof FunctionEventType;
20
+ import type { BasicAuthCredentials, CspHeaders, CloudFrontFunctionEventType, UUID, AWSManagedResponseHeadersPolicy } from '../../types.d.ts';
32
21
 
33
22
  export interface WebGlobalStackProps {
34
23
  envType: 'NOT_PROD' | 'PROD';
@@ -38,14 +27,14 @@ export interface WebGlobalStackProps {
38
27
  domainName: string;
39
28
  basicAuth?: string | BasicAuthCredentials | SsmStringParameter;
40
29
  cloudfrontFunction?: {
41
- eventType: CloudFrontFunctionEventType[];
42
30
  code: string;
31
+ eventType: CloudFrontFunctionEventType[];
43
32
  }
44
33
  redirects?: CloudFrontFunctionRedirects;
45
34
  redirectsCsvPath?: string;
46
35
  // attachWebAcl?: boolean | string;
47
36
  webAcl?: boolean | string | SsmStringParameter;
48
- responseHeadersPolicy?: false | AWSManagedResponseHeadersPolicy | 'NONE' | UUID | SsmStringParameter;
37
+ responseHeadersPolicy?: false | AWSManagedResponseHeadersPolicy | UUID | SsmStringParameter;
49
38
  responseHeadersPolicyProps?: ResponseHeadersPolicyProps;
50
39
  responseCspHeaders?: CspHeaders;
51
40
  destroy?: boolean;
@@ -82,69 +71,65 @@ export class WebGlobalStack extends Stack {
82
71
  this.s3Bucket = _s3Bucket.bucket;
83
72
 
84
73
  let responseHeadersPolicy: IResponseHeadersPolicy | undefined = undefined;
85
- if (props.responseHeadersPolicy !== 'NONE') { // I don't know why you would want to not have the policy but just in case
86
- if (props.responseHeadersPolicy) {
87
- if (typeof props.responseHeadersPolicy == 'string') {
88
- if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(props.responseHeadersPolicy)) {
89
- responseHeadersPolicy = ResponseHeadersPolicy.fromResponseHeadersPolicyId(this, 'response-headers-policy-by-id', props.responseHeadersPolicy);
90
- } else {
91
- responseHeadersPolicy = ResponseHeadersPolicy[props.responseHeadersPolicy as keyof typeof ResponseHeadersPolicy] as IResponseHeadersPolicy ?? ResponseHeadersPolicy.SECURITY_HEADERS;
92
- }
93
- } else if (props.responseHeadersPolicy.path) {
94
- responseHeadersPolicy = ResponseHeadersPolicy.fromResponseHeadersPolicyId(this, 'response-headers-policy-by-id', StringParameter.valueForStringParameter(this, props.responseHeadersPolicy.path, props.responseHeadersPolicy.version));
74
+ if (props.responseHeadersPolicy) {
75
+ if (typeof props.responseHeadersPolicy == 'string') {
76
+ if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(props.responseHeadersPolicy)) {
77
+ responseHeadersPolicy = ResponseHeadersPolicy.fromResponseHeadersPolicyId(this, 'response-headers-policy-by-id', props.responseHeadersPolicy);
78
+ } else {
79
+ responseHeadersPolicy = ResponseHeadersPolicy[props.responseHeadersPolicy as keyof typeof ResponseHeadersPolicy] as IResponseHeadersPolicy ?? ResponseHeadersPolicy.SECURITY_HEADERS;
95
80
  }
81
+ } else if (props.responseHeadersPolicy.path) {
82
+ responseHeadersPolicy = ResponseHeadersPolicy.fromResponseHeadersPolicyId(this, 'response-headers-policy-by-id', StringParameter.valueForStringParameter(this, props.responseHeadersPolicy.path, props.responseHeadersPolicy.version));
96
83
  }
97
- if (!responseHeadersPolicy) {
98
- // const baseHeadersBehavior: ResponseSecurityHeadersBehavior = {
99
- // strictTransportSecurity: {
100
- // override: true,
101
- // accessControlMaxAge: Duration.seconds(31536000)
102
- // },
103
- // contentTypeOptions: {
104
- // override: true
105
- // },
106
- // frameOptions: {
107
- // override: true,
108
- // frameOption: HeadersFrameOption.SAMEORIGIN,
109
- // },
110
- // referrerPolicy: {
111
- // override: true,
112
- // referrerPolicy: HeadersReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN
113
- // },
114
- // xssProtection: {
115
- // override: true,
116
- // protection: true,
117
- // modeBlock: true
118
- // }
119
- // };
120
-
121
- const responseHeadersPolicyName = `${domainAsId(props.domainName)}-response-headers-policy`;
122
-
123
- if (props.responseHeadersPolicyProps) {
124
- responseHeadersPolicy = new ResponseHeadersPolicy(this, 'response-headers-policy', {
125
- ...ResponseHeadersPolicy.SECURITY_HEADERS,
126
- ...props.responseHeadersPolicyProps,
127
- responseHeadersPolicyName: props.responseHeadersPolicyProps.responseHeadersPolicyName || responseHeadersPolicyName
128
- });
129
- } else if (props.responseCspHeaders) {
130
- responseHeadersPolicy = new ResponseHeadersPolicy(this, 'response-headers-policy', {
131
- securityHeadersBehavior: {
132
- ...ResponseHeadersPolicy.SECURITY_HEADERS,
133
- contentSecurityPolicy: {
134
- override: true,
135
- contentSecurityPolicy: Object.entries(props.responseCspHeaders).map(([directive, values]) => {
136
- return `${directive} ${values.join(' ')};`
137
- }).join(' ')
138
- },
139
- },
140
- responseHeadersPolicyName
141
- });
142
- } else {
143
- responseHeadersPolicy = ResponseHeadersPolicy.SECURITY_HEADERS;
84
+ } else {
85
+ const baseHeadersBehavior: ResponseSecurityHeadersBehavior = {
86
+ strictTransportSecurity: {
87
+ override: true,
88
+ accessControlMaxAge: Duration.seconds(31536000)
89
+ },
90
+ contentTypeOptions: {
91
+ override: true
92
+ },
93
+ frameOptions: {
94
+ override: true,
95
+ frameOption: HeadersFrameOption.SAMEORIGIN,
96
+ },
97
+ referrerPolicy: {
98
+ override: true,
99
+ referrerPolicy: HeadersReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN
100
+ },
101
+ xssProtection: {
102
+ override: true,
103
+ protection: true,
104
+ modeBlock: true
144
105
  }
106
+ };
107
+
108
+ const responseHeadersPolicyName = `${domainAsId(props.domainName)}-response-headers-policy`;
109
+
110
+ if (props.responseHeadersPolicyProps) {
111
+ responseHeadersPolicy = new ResponseHeadersPolicy(this, 'response-headers-policy', {
112
+ ...baseHeadersBehavior,
113
+ ...props.responseHeadersPolicyProps,
114
+ responseHeadersPolicyName: props.responseHeadersPolicyProps.responseHeadersPolicyName || responseHeadersPolicyName
115
+ });
116
+ } else if (props.responseCspHeaders) {
117
+ responseHeadersPolicy = new ResponseHeadersPolicy(this, 'response-headers-policy', {
118
+ securityHeadersBehavior: {
119
+ ...baseHeadersBehavior,
120
+ contentSecurityPolicy: {
121
+ override: true,
122
+ contentSecurityPolicy: Object.entries(props.responseCspHeaders).map(([directive, values]) => {
123
+ return `${directive} ${values.join(' ')};`
124
+ }).join(' ')
125
+ },
126
+ },
127
+ responseHeadersPolicyName
128
+ });
145
129
  }
146
- this.responseHeadersPolicy = responseHeadersPolicy;
147
130
  }
131
+ // TODO: Figure out why the the policy is not getting updated in the CloudFront behavior
132
+ this.responseHeadersPolicy = responseHeadersPolicy;
148
133
 
149
134
  const defaultBehavior: BehaviorOptions = {
150
135
  origin: S3BucketOrigin.withOriginAccessControl(this.s3Bucket),
package/src/types.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+
2
+ import { FunctionEventType } from 'aws-cdk-lib/aws-cloudfront';
3
+
1
4
  export type DeepPartial<T> = T extends object ? {
2
5
  [P in keyof T]?: DeepPartial<T[P]>;
3
6
  } : T;
@@ -6,6 +9,11 @@ export type WithRequiredProperty<Type, Key extends keyof Type> = Omit<Type, Key>
6
9
  [Property in Key]-?: Type[Property];
7
10
  };
8
11
 
12
+ export type UUID = `${string}-${string}-${string}-${string}-${string}`; // & { readonly __brand: unique symbol };
13
+
14
+ export type EvosynthTagKey = 'Account' | 'Brand' | (string & {});
15
+ export type CloudFrontFunctionEventType = keyof typeof FunctionEventType;
16
+
9
17
  export interface ResourceProps {
10
18
  destroy?: boolean;
11
19
  tags?: Record<string, string>;
@@ -18,4 +26,11 @@ export interface BasicAuthCredentials {
18
26
 
19
27
  export type CspDirective = 'connect-src' | 'default-src' | 'font-src' | 'frame-src' | 'img-src' | 'media-src' | 'object-src' | 'script-src' | 'style-src';
20
28
  export type CspDirectiveValue = "'self'" | "'none'" | "'unsafe-inline'" | "https:";
21
- export type CspHeaders = Partial<Record<CspDirective, CspDirectiveValue[] | string[]>>;
29
+ export type CspHeaders = Partial<Record<CspDirective, CspDirectiveValue[] | string[]>>;
30
+
31
+ export type AWSManagedResponseHeadersPolicy =
32
+ 'CORS_ALLOW_ALL_ORIGINS' |
33
+ 'CORS_ALLOW_ALL_ORIGINS_AND_SECURITY_HEADERS' |
34
+ 'CORS_ALLOW_ALL_ORIGINS_WITH_PREFLIGHT' |
35
+ 'CORS_ALLOW_ALL_ORIGINS_WITH_PREFLIGHT_AND_SECURITY_HEADERS' |
36
+ 'SECURITY_HEADERS';