@aws/nx-plugin 0.1.6 → 0.2.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.
Files changed (115) hide show
  1. package/LICENSE-THIRD-PARTY +114 -244
  2. package/generators.json +1 -7
  3. package/package.json +1 -1
  4. package/src/cloudscape-website/app/README.md +84 -48
  5. package/src/cloudscape-website/app/__snapshots__/generator.spec.ts.snap +157 -218
  6. package/src/cloudscape-website/app/files/app/README.md.template +44 -0
  7. package/src/cloudscape-website/app/files/app/src/layouts/App/index.tsx.template +40 -43
  8. package/src/cloudscape-website/app/files/app/src/layouts/App/navitems.ts.template +3 -3
  9. package/src/cloudscape-website/app/files/app/src/layouts/Routes/index.tsx.template +4 -6
  10. package/src/cloudscape-website/app/files/app/src/main.tsx.template +7 -10
  11. package/src/cloudscape-website/app/files/app/src/pages/Home/index.tsx.template +0 -2
  12. package/src/cloudscape-website/app/files/common/constructs/src/app/static-websites/__websiteNameKebabCase__.ts.template +13 -0
  13. package/src/cloudscape-website/app/files/common/constructs/src/{__websiteNameKebabCase__ → core}/static-website.ts.template +74 -144
  14. package/src/cloudscape-website/app/generator.js +74 -64
  15. package/src/cloudscape-website/app/generator.js.map +1 -1
  16. package/src/cloudscape-website/app/schema.d.ts +3 -4
  17. package/src/cloudscape-website/app/schema.json +1 -24
  18. package/src/cloudscape-website/cognito-auth/README.md +53 -32
  19. package/src/cloudscape-website/cognito-auth/__snapshots__/generator.spec.ts.snap +161 -125
  20. package/src/cloudscape-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +53 -39
  21. package/src/cloudscape-website/cognito-auth/files/common/constructs/src/core/user-identity.ts.template +168 -0
  22. package/src/cloudscape-website/cognito-auth/generator.js +129 -46
  23. package/src/cloudscape-website/cognito-auth/generator.js.map +1 -1
  24. package/src/cloudscape-website/cognito-auth/schema.d.ts +1 -0
  25. package/src/cloudscape-website/cognito-auth/schema.json +7 -1
  26. package/src/cloudscape-website/runtime-config/__snapshots__/generator.spec.ts.snap +15 -17
  27. package/src/cloudscape-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +7 -10
  28. package/src/cloudscape-website/runtime-config/files/app/hooks/useRuntimeConfig.tsx.template +13 -0
  29. package/src/cloudscape-website/runtime-config/generator.js +3 -1
  30. package/src/cloudscape-website/runtime-config/generator.js.map +1 -1
  31. package/src/infra/app/README.md +71 -46
  32. package/src/infra/app/__snapshots__/generator.spec.ts.snap +114 -252
  33. package/src/infra/app/files/app/README.md.template +76 -0
  34. package/src/infra/app/files/app/src/main.ts.template +18 -0
  35. package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/aws-prototyping.guard +1282 -0
  36. package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/cfn-nag.guard +6839 -0
  37. package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/hipaa-security.guard +2807 -0
  38. package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/nist-csf.guard +2585 -0
  39. package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/pci-dss-3-2-1.guard +2236 -0
  40. package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/wa-reliability-pillar.guard +885 -0
  41. package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/wa-security-pillar.guard +2205 -0
  42. package/src/infra/app/files/common/constructs/src/core/cfn-guard.ts.template +63 -0
  43. package/src/infra/app/generator.js +17 -3
  44. package/src/infra/app/generator.js.map +1 -1
  45. package/src/infra/app/schema.d.ts +10 -1
  46. package/src/infra/app/schema.json +16 -8
  47. package/src/trpc/backend/README.md +102 -80
  48. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +37 -17
  49. package/src/trpc/backend/files/backend/README.md.template +33 -0
  50. package/src/trpc/backend/files/common/constructs/src/app/trpc-apis/__apiNameKebabCase__.ts.template +18 -0
  51. package/src/trpc/backend/files/common/constructs/src/{__apiNameKebabCase__/index.ts.template → core/trpc-api.ts.template} +12 -16
  52. package/src/trpc/backend/files/schema/README.md.template +33 -0
  53. package/src/trpc/backend/generator.js +29 -43
  54. package/src/trpc/backend/generator.js.map +1 -1
  55. package/src/trpc/backend/schema.d.ts +3 -1
  56. package/src/trpc/backend/schema.json +8 -13
  57. package/src/trpc/react/README.md +46 -66
  58. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +104 -65
  59. package/src/trpc/react/files/src/components/TrpcClients/IsolatedTrpcProvider.tsx.template +75 -0
  60. package/src/trpc/react/files/src/components/TrpcClients/TrpcApis.tsx.template +1 -0
  61. package/src/trpc/react/files/src/components/TrpcClients/TrpcClientProviders.tsx.template +10 -0
  62. package/src/trpc/react/files/src/components/TrpcClients/index.tsx.template +5 -0
  63. package/src/trpc/react/files/src/hooks/useSigV4.tsx.template +38 -0
  64. package/src/trpc/react/files/src/hooks/use__apiNameClassName__.tsx.template +3 -0
  65. package/src/trpc/react/generator.js +123 -24
  66. package/src/trpc/react/generator.js.map +1 -1
  67. package/src/trpc/react/schema.json +2 -2
  68. package/src/ts/cjs-to-esm/generator.js.map +1 -1
  69. package/src/ts/lib/eslint.d.ts +1 -1
  70. package/src/ts/lib/eslint.js +59 -11
  71. package/src/ts/lib/eslint.js.map +1 -1
  72. package/src/ts/lib/files/README.md.template +33 -0
  73. package/src/ts/lib/generator.js +11 -4
  74. package/src/ts/lib/generator.js.map +1 -1
  75. package/src/ts/lib/schema.d.ts +1 -3
  76. package/src/ts/lib/schema.json +2 -15
  77. package/src/ts/lib/ts-project-utils.js.map +1 -1
  78. package/src/ts/lib/vitest.js +14 -0
  79. package/src/ts/lib/vitest.js.map +1 -1
  80. package/src/utils/ast.d.ts +13 -0
  81. package/src/utils/ast.js +102 -0
  82. package/src/utils/ast.js.map +1 -0
  83. package/src/utils/files/common/constructs/src/app/index.ts.template +0 -0
  84. package/src/utils/files/common/constructs/src/{runtime-config → core}/runtime-config.ts.template +3 -5
  85. package/src/utils/files/common/constructs/src/index.ts.template +2 -1
  86. package/src/utils/files/common/readme/README.md.template +33 -0
  87. package/src/utils/files/common/types/src/runtime-config.ts.template +1 -13
  88. package/src/utils/format.js.map +1 -1
  89. package/src/utils/names.d.ts +2 -0
  90. package/src/utils/names.js +27 -0
  91. package/src/utils/names.js.map +1 -0
  92. package/src/utils/npm-scope.js.map +1 -1
  93. package/src/utils/paths.js.map +1 -1
  94. package/src/utils/shared-constructs.js +37 -4
  95. package/src/utils/shared-constructs.js.map +1 -1
  96. package/src/utils/versions.d.ts +15 -9
  97. package/src/utils/versions.js +14 -8
  98. package/src/utils/versions.js.map +1 -1
  99. package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/cloudfront-web-acl.ts.template +0 -317
  100. package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/index.ts.template +0 -4
  101. package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/webacl_event_handler/index.ts.template +0 -301
  102. package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/index.ts.template +0 -4
  103. package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/user-identity.ts.template +0 -66
  104. package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/userpool-with-mfa.ts.template +0 -70
  105. package/src/gitlab/generator.d.ts +0 -8
  106. package/src/gitlab/generator.js +0 -16
  107. package/src/gitlab/generator.js.map +0 -1
  108. package/src/gitlab/schema.d.ts +0 -9
  109. package/src/gitlab/schema.json +0 -52
  110. package/src/infra/app/files/src/main.ts.template +0 -37
  111. package/src/trpc/react/files/src/components/TRPCClientProvider/index.tsx.template +0 -34
  112. package/src/trpc/react/files/src/hooks/useTrpc.tsx.template +0 -5
  113. /package/src/infra/app/files/{cdk.json → app/cdk.json} +0 -0
  114. /package/src/infra/app/files/{src → app/src}/stacks/application-stack.ts.template +0 -0
  115. /package/src/utils/files/common/constructs/src/{runtime-config → core}/index.ts.template +0 -0
@@ -1,8 +1,3 @@
1
- /*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
2
- SPDX-License-Identifier: Apache-2.0 */
3
- import { useCognitoAuthContext } from '@aws-northstar/ui';
4
- import getBreadcrumbs from '@aws-northstar/ui/components/AppLayout/utils/getBreadcrumbs';
5
- import NavHeader from '@aws-northstar/ui/components/AppLayout/components/NavHeader';
6
1
  import * as React from 'react';
7
2
  import { createContext, useCallback, useEffect, useState } from 'react';
8
3
  import { NavItems } from './navitems';
@@ -13,11 +8,42 @@ import {
13
8
  BreadcrumbGroup,
14
9
  BreadcrumbGroupProps,
15
10
  SideNavigation,
11
+ TopNavigation,
16
12
  } from '@cloudscape-design/components';
17
13
  import AppLayout, {
18
14
  AppLayoutProps,
19
15
  } from '@cloudscape-design/components/app-layout';
20
- import { useLocation, useNavigate } from 'react-router-dom';
16
+ import { matchPath, useLocation, useNavigate } from 'react-router-dom';
17
+
18
+ const getBreadcrumbs = (
19
+ pathName: string,
20
+ search: string,
21
+ defaultBreadcrumb: string,
22
+ availableRoutes?: string[]
23
+ ) => {
24
+ const segments = [
25
+ defaultBreadcrumb,
26
+ ...pathName.split('/').filter((segment) => segment !== ''),
27
+ ];
28
+
29
+ return segments.map((segment, i) => {
30
+ const href =
31
+ i === 0
32
+ ? '/'
33
+ : `/${segments
34
+ .slice(1, i + 1)
35
+ .join('/')
36
+ .replace('//', '/')}`;
37
+
38
+ const matched =
39
+ !availableRoutes || availableRoutes.find((r) => matchPath(r, href));
40
+
41
+ return {
42
+ href: matched ? `${href}${search}` : '#',
43
+ text: segment,
44
+ };
45
+ });
46
+ };
21
47
 
22
48
  /**
23
49
  * Context for updating/retrieving the AppLayout.
@@ -32,10 +58,6 @@ export const AppLayoutContext = createContext({
32
58
  * Defines the App layout and contains logic for routing.
33
59
  */
34
60
  const App: React.FC = () => {
35
- const [username, setUsername] = useState<string | undefined>();
36
- const [email, setEmail] = useState<string | undefined>();
37
- const { getAuthenticatedUser } = useCognitoAuthContext();
38
-
39
61
  const navigate = useNavigate();
40
62
  const [activeHref, setActiveHref] = useState('/');
41
63
  const [activeBreadcrumbs, setActiveBreadcrumbs] = useState<
@@ -44,17 +66,6 @@ const App: React.FC = () => {
44
66
  const [appLayoutProps, setAppLayoutProps] = useState<AppLayoutProps>({});
45
67
  const location = useLocation();
46
68
 
47
- useEffect(() => {
48
- const authUser = getAuthenticatedUser();
49
- setUsername(authUser?.getUsername());
50
-
51
- authUser?.getSession(() => {
52
- authUser.getUserAttributes((_, attributes) => {
53
- setEmail(attributes?.find((a) => a.Name === 'email')?.Value);
54
- });
55
- });
56
- }, [getAuthenticatedUser, setUsername, setEmail]);
57
-
58
69
  const setAppLayoutPropsSafe = useCallback(
59
70
  (props: AppLayoutProps) => {
60
71
  JSON.stringify(appLayoutProps) !== JSON.stringify(props) &&
@@ -75,9 +86,6 @@ const App: React.FC = () => {
75
86
  e.preventDefault();
76
87
  setAppLayoutPropsSafe({
77
88
  contentType: undefined,
78
- splitPanelOpen: false,
79
- splitPanelSize: undefined,
80
- splitPanelPreferences: undefined,
81
89
  });
82
90
  navigate(e.detail.href);
83
91
  }
@@ -89,23 +97,14 @@ const App: React.FC = () => {
89
97
  <AppLayoutContext.Provider
90
98
  value={{ appLayoutProps, setAppLayoutProps: setAppLayoutPropsSafe }}
91
99
  >
92
- <NavHeader
93
- title={Config.applicationName}
94
- logo={Config.logo}
95
- user={
96
- username
97
- ? {
98
- username,
99
- email,
100
- }
101
- : undefined
102
- }
103
- onSignout={() =>
104
- new Promise(() => {
105
- getAuthenticatedUser()?.signOut();
106
- window.location.href = '/';
107
- })
108
- }
100
+ <TopNavigation
101
+ identity={{
102
+ href: '/',
103
+ title: Config.applicationName,
104
+ logo: {
105
+ src: Config.logo,
106
+ },
107
+ }}
109
108
  />
110
109
  <AppLayout
111
110
  breadcrumbs={
@@ -121,8 +120,6 @@ const App: React.FC = () => {
121
120
  />
122
121
  }
123
122
  content={<Routes />}
124
- splitPanelOpen={false}
125
- splitPanelPreferences={{ position: 'bottom' }}
126
123
  {...appLayoutProps}
127
124
  />
128
125
  </AppLayoutContext.Provider>
@@ -1,8 +1,8 @@
1
- import { SideNavigationProps } from "@cloudscape-design/components";
1
+ import { SideNavigationProps } from '@cloudscape-design/components';
2
2
 
3
3
  /**
4
4
  * Define your Navigation Items here
5
5
  */
6
6
  export const NavItems: SideNavigationProps.Item[] = [
7
- { text: "Home", type: "link", href: "/" }
8
- ];
7
+ { text: 'Home', type: 'link', href: '/' },
8
+ ];
@@ -1,8 +1,6 @@
1
- /*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
2
- SPDX-License-Identifier: Apache-2.0 */
3
- import * as React from "react";
4
- import { Route, Routes as ReactRoutes } from "react-router-dom";
5
- import Home from "../../pages/Home";
1
+ import * as React from 'react';
2
+ import { Route, Routes as ReactRoutes } from 'react-router-dom';
3
+ import Home from '../../pages/Home';
6
4
 
7
5
  /**
8
6
  * Defines the Routes.
@@ -15,4 +13,4 @@ const Routes: React.FC = () => {
15
13
  );
16
14
  };
17
15
 
18
- export default Routes;
16
+ export default Routes;
@@ -1,6 +1,3 @@
1
- /*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
2
- SPDX-License-Identifier: Apache-2.0 */
3
- import { NorthStarThemeProvider } from '@aws-northstar/ui';
4
1
  import React from 'react';
5
2
  import { createRoot } from 'react-dom/client';
6
3
  import { BrowserRouter } from 'react-router-dom';
@@ -8,16 +5,16 @@ import { I18nProvider } from '@cloudscape-design/components/i18n';
8
5
  import messages from '@cloudscape-design/components/i18n/messages/all.en';
9
6
  import App from './layouts/App';
10
7
 
8
+ import '@cloudscape-design/global-styles/index.css';
9
+
11
10
  const root = document.getElementById('root');
12
11
  root &&
13
12
  createRoot(root).render(
14
13
  <React.StrictMode>
15
- <NorthStarThemeProvider>
16
- <I18nProvider locale="en" messages={[messages]}>
17
- <BrowserRouter>
18
- <App />
19
- </BrowserRouter>
20
- </I18nProvider>
21
- </NorthStarThemeProvider>
14
+ <I18nProvider locale="en" messages={[messages]}>
15
+ <BrowserRouter>
16
+ <App />
17
+ </BrowserRouter>
18
+ </I18nProvider>
22
19
  </React.StrictMode>
23
20
  );
@@ -1,5 +1,3 @@
1
- /*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
2
- SPDX-License-Identifier: Apache-2.0 */
3
1
  import {
4
2
  Container,
5
3
  ContentLayout,
@@ -0,0 +1,13 @@
1
+ import * as url from 'url';
2
+ import { Construct } from 'constructs';
3
+ import { StaticWebsite } from '../../core/index.js';
4
+
5
+ export class <%= websiteNameClassName %> extends StaticWebsite {
6
+ constructor(scope: Construct, id: string) {
7
+ super(scope, id, {
8
+ websiteFilePath: url.fileURLToPath(
9
+ new URL('../../../../../../<%= websiteContentPath %>', import.meta.url)
10
+ ),
11
+ });
12
+ }
13
+ }
@@ -1,8 +1,4 @@
1
- /*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
2
- SPDX-License-Identifier: Apache-2.0 */
3
- import * as url from 'url';
4
- import { PDKNag } from '@aws/pdk/pdk-nag';
5
- import { CfnJson, CfnOutput, Lazy, RemovalPolicy, Stack, Token } from 'aws-cdk-lib';
1
+ import { CfnJson, CfnOutput, RemovalPolicy, Stack, Token } from 'aws-cdk-lib';
6
2
  import { Distribution, ViewerProtocolPolicy } from 'aws-cdk-lib/aws-cloudfront';
7
3
  import { S3BucketOrigin } from 'aws-cdk-lib/aws-cloudfront-origins';
8
4
  import {
@@ -13,13 +9,16 @@ import {
13
9
  ObjectOwnership,
14
10
  } from 'aws-cdk-lib/aws-s3';
15
11
  import { BucketDeployment, Source } from 'aws-cdk-lib/aws-s3-deployment';
16
- import { NagSuppressions } from 'cdk-nag';
17
12
  import { Construct } from 'constructs';
18
- import { CloudfrontWebAcl } from './cloudfront-web-acl.js';
19
- import { RuntimeConfig } from '../runtime-config/index.js';
20
-
13
+ import { RuntimeConfig } from './runtime-config.js';
14
+ import { Key } from 'aws-cdk-lib/aws-kms';
15
+ import { CfnWebACL } from 'aws-cdk-lib/aws-wafv2';
21
16
  const DEFAULT_RUNTIME_CONFIG_FILENAME = 'runtime-config.json';
22
17
 
18
+ export interface StaticWebsiteProps {
19
+ readonly websiteFilePath: string;
20
+ }
21
+
23
22
  /**
24
23
  * Deploys a Static Website using by default a private S3 bucket as an origin and Cloudfront as the entrypoint.
25
24
  *
@@ -33,61 +32,68 @@ export class StaticWebsite extends Construct {
33
32
  public readonly cloudFrontDistribution: Distribution;
34
33
  public readonly bucketDeployment: BucketDeployment;
35
34
 
36
- constructor(scope: Construct, id: string) {
35
+ constructor(
36
+ scope: Construct,
37
+ id: string,
38
+ { websiteFilePath }: StaticWebsiteProps
39
+ ) {
37
40
  super(scope, id);
38
-
39
41
  this.node.setContext(
40
42
  '@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy',
41
43
  true
42
44
  );
43
45
 
46
+ const websiteKey = new Key(this, 'WebsiteKey', {
47
+ enableKeyRotation: true,
48
+ });
49
+
44
50
  const accessLogsBucket = new Bucket(this, 'AccessLogsBucket', {
45
51
  versioned: false,
46
52
  enforceSSL: true,
47
53
  autoDeleteObjects: true,
48
54
  removalPolicy: RemovalPolicy.DESTROY,
49
- encryption: BucketEncryption.S3_MANAGED,
55
+ encryption: BucketEncryption.KMS,
56
+ encryptionKey: websiteKey,
50
57
  objectOwnership: ObjectOwnership.OBJECT_WRITER,
51
58
  publicReadAccess: false,
52
59
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
53
60
  });
54
-
55
61
  // S3 Bucket to hold website files
56
62
  this.websiteBucket = new Bucket(this, 'WebsiteBucket', {
57
63
  versioned: true,
58
64
  enforceSSL: true,
59
65
  autoDeleteObjects: true,
60
66
  removalPolicy: RemovalPolicy.DESTROY,
61
- encryption: BucketEncryption.S3_MANAGED,
67
+ encryption: BucketEncryption.KMS,
68
+ encryptionKey: websiteKey,
62
69
  objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
63
70
  publicReadAccess: false,
64
71
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
65
72
  serverAccessLogsPrefix: 'website-access-logs',
66
73
  serverAccessLogsBucket: accessLogsBucket,
67
74
  });
68
-
69
75
  // Web ACL
70
- const webAclArn = new CloudfrontWebAcl(this, 'WebsiteAcl').webAclArn;
76
+ const wafStack = new CloudfrontWebAcl(this, 'waf');
71
77
 
72
78
  // Cloudfront Distribution
73
79
  const logBucket = new Bucket(this, 'DistributionLogBucket', {
74
80
  enforceSSL: true,
75
81
  autoDeleteObjects: true,
76
82
  removalPolicy: RemovalPolicy.DESTROY,
77
- encryption: BucketEncryption.S3_MANAGED,
83
+ encryption: BucketEncryption.KMS,
84
+ encryptionKey: websiteKey,
78
85
  objectOwnership: ObjectOwnership.BUCKET_OWNER_PREFERRED,
79
86
  publicReadAccess: false,
80
87
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
81
88
  serverAccessLogsPrefix: 'distribution-access-logs',
82
89
  serverAccessLogsBucket: accessLogsBucket,
83
90
  });
84
-
85
91
  const defaultRootObject = 'index.html';
86
92
  this.cloudFrontDistribution = new Distribution(
87
93
  this,
88
94
  'CloudfrontDistribution',
89
95
  {
90
- webAclId: webAclArn,
96
+ webAclId: wafStack.wafArn,
91
97
  enableLogging: true,
92
98
  logBucket: logBucket,
93
99
  defaultBehavior: {
@@ -104,45 +110,34 @@ export class StaticWebsite extends Construct {
104
110
  ],
105
111
  }
106
112
  );
107
-
108
113
  // Deploy Website
109
- const runtimeConfig = RuntimeConfig.ensure(this).config;
110
114
  this.bucketDeployment = new BucketDeployment(this, 'WebsiteDeployment', {
111
115
  sources: [
112
- Source.asset(
113
- url.fileURLToPath(
114
- new URL('../../../../../<%= websiteContentPath %>', import.meta.url)
115
- )
116
+ Source.asset(websiteFilePath),
117
+ Source.jsonData(
118
+ DEFAULT_RUNTIME_CONFIG_FILENAME,
119
+ this.resolveTokens(RuntimeConfig.ensure(this).config)
116
120
  ),
117
- ...(Object.keys(runtimeConfig).length > 0
118
- ? [Source.jsonData(DEFAULT_RUNTIME_CONFIG_FILENAME, this.lazilyRender(runtimeConfig))]
119
- : []),
120
121
  ],
121
122
  destinationBucket: this.websiteBucket,
122
123
  // Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
123
124
  distribution: this.cloudFrontDistribution,
124
125
  });
125
-
126
126
  new CfnOutput(this, 'DistributionDomainName', {
127
127
  value: this.cloudFrontDistribution.domainName,
128
128
  });
129
-
130
- this.suppressCDKNagViolations();
131
129
  }
132
-
133
- private lazilyRender = (payload: any) => Lazy.any({
134
- produce: () => this.resolveTokens(payload),
135
- });
136
-
137
130
  private resolveTokens = (payload: any) => {
138
131
  const _payload: Record<string, any> = {};
139
-
140
132
  Object.entries(payload).forEach(([key, value]) => {
141
- if (Token.isUnresolved(value) || (typeof value === "string" && value.endsWith("}}"))) {
133
+ if (
134
+ Token.isUnresolved(value) ||
135
+ (typeof value === 'string' && value.endsWith('}}'))
136
+ ) {
142
137
  _payload[key] = new CfnJson(this, `ResolveToken-${key}`, {
143
- value,
138
+ value,
144
139
  }).value;
145
- } else if (typeof value === "object") {
140
+ } else if (typeof value === 'object') {
146
141
  _payload[key] = this.resolveTokens(value);
147
142
  } else if (Array.isArray(value)) {
148
143
  _payload[key] = value.map((v) => this.resolveTokens(v));
@@ -150,114 +145,49 @@ export class StaticWebsite extends Construct {
150
145
  _payload[key] = value;
151
146
  }
152
147
  });
153
-
154
148
  return _payload;
155
- }
149
+ };
150
+ }
156
151
 
157
- private suppressCDKNagViolations = () => {
158
- const stack = Stack.of(this);
152
+ export class CloudfrontWebAcl extends Stack {
153
+ public readonly wafArn;
154
+ constructor(scope: Construct, id: string) {
155
+ super(scope, id, {
156
+ env: {
157
+ region: 'us-east-1',
158
+ account: Stack.of(scope).account,
159
+ },
160
+ crossRegionReferences: true,
161
+ });
159
162
 
160
- NagSuppressions.addResourceSuppressions(
161
- this,
162
- [
163
+ this.wafArn = new CfnWebACL(this, 'WebAcl', {
164
+ defaultAction: { allow: {} },
165
+ scope: 'CLOUDFRONT',
166
+ visibilityConfig: {
167
+ cloudWatchMetricsEnabled: true,
168
+ metricName: id,
169
+ sampledRequestsEnabled: true,
170
+ },
171
+ rules: [
163
172
  {
164
- id: 'AwsPrototyping-CloudFrontDistributionGeoRestrictions',
165
- reason:
166
- 'Suppressed to allow unrestricted access. Not recommended in production.',
173
+ name: 'CRSRule',
174
+ priority: 0,
175
+ statement: {
176
+ managedRuleGroupStatement: {
177
+ name: 'AWSManagedRulesCommonRuleSet',
178
+ vendorName: 'AWS',
179
+ },
180
+ },
181
+ visibilityConfig: {
182
+ cloudWatchMetricsEnabled: true,
183
+ metricName: 'MetricForWebACLCDK-CRS',
184
+ sampledRequestsEnabled: true,
185
+ },
186
+ overrideAction: {
187
+ none: {},
188
+ },
167
189
  },
168
190
  ],
169
- true
170
- );
171
-
172
- [
173
- 'AwsSolutions-CFR4',
174
- 'AwsPrototyping-CloudFrontDistributionHttpsViewerNoOutdatedSSL',
175
- ].forEach((RuleId) => {
176
- NagSuppressions.addResourceSuppressions(this.cloudFrontDistribution, [
177
- {
178
- id: RuleId,
179
- reason:
180
- 'Certificate is not mandatory therefore the Cloudfront certificate will be used.',
181
- },
182
- ]);
183
- });
184
-
185
- ['AwsSolutions-L1', 'AwsPrototyping-LambdaLatestVersion'].forEach(
186
- (RuleId) => {
187
- NagSuppressions.addResourceSuppressions(
188
- this,
189
- [
190
- {
191
- id: RuleId,
192
- reason:
193
- 'Latest runtime cannot be configured. CDK will need to upgrade the BucketDeployment construct accordingly.',
194
- },
195
- ],
196
- true
197
- );
198
- }
199
- );
200
-
201
- ['AwsSolutions-IAM5', 'AwsPrototyping-IAMNoWildcardPermissions'].forEach(
202
- (RuleId) => {
203
- NagSuppressions.addResourceSuppressions(
204
- this,
205
- [
206
- {
207
- id: RuleId,
208
- reason:
209
- 'All Policies have been scoped to a Bucket. Given Buckets can contain arbitrary content, wildcard resources with bucket scope are required.',
210
- appliesTo: [
211
- {
212
- regex: '/^Action::s3:.*$/g',
213
- },
214
- {
215
- regex: `/^Resource::.*$/g`,
216
- },
217
- ],
218
- },
219
- ],
220
- true
221
- );
222
- }
223
- );
224
-
225
- ['AwsSolutions-IAM4', 'AwsPrototyping-IAMNoManagedPolicies'].forEach(
226
- (RuleId) => {
227
- NagSuppressions.addResourceSuppressions(
228
- this,
229
- [
230
- {
231
- id: RuleId,
232
- reason:
233
- 'Buckets can contain arbitrary content, therefore wildcard resources under a bucket are required.',
234
- appliesTo: [
235
- {
236
- regex: `/^Policy::arn:${PDKNag.getStackPartitionRegex(
237
- stack
238
- )}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole$/g`,
239
- },
240
- ],
241
- },
242
- ],
243
- true
244
- );
245
- }
246
- );
247
-
248
- ['AwsSolutions-S1', 'AwsPrototyping-S3BucketLoggingEnabled'].forEach(
249
- (RuleId) => {
250
- NagSuppressions.addResourceSuppressions(
251
- this,
252
- [
253
- {
254
- id: RuleId,
255
- reason: 'Access Log buckets should not have s3 bucket logging',
256
- },
257
- ],
258
- true
259
- );
260
- }
261
- );
262
- };
191
+ }).attrArn;
192
+ }
263
193
  }