@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.
- package/LICENSE-THIRD-PARTY +114 -244
- package/generators.json +1 -7
- package/package.json +1 -1
- package/src/cloudscape-website/app/README.md +84 -48
- package/src/cloudscape-website/app/__snapshots__/generator.spec.ts.snap +157 -218
- package/src/cloudscape-website/app/files/app/README.md.template +44 -0
- package/src/cloudscape-website/app/files/app/src/layouts/App/index.tsx.template +40 -43
- package/src/cloudscape-website/app/files/app/src/layouts/App/navitems.ts.template +3 -3
- package/src/cloudscape-website/app/files/app/src/layouts/Routes/index.tsx.template +4 -6
- package/src/cloudscape-website/app/files/app/src/main.tsx.template +7 -10
- package/src/cloudscape-website/app/files/app/src/pages/Home/index.tsx.template +0 -2
- package/src/cloudscape-website/app/files/common/constructs/src/app/static-websites/__websiteNameKebabCase__.ts.template +13 -0
- package/src/cloudscape-website/app/files/common/constructs/src/{__websiteNameKebabCase__ → core}/static-website.ts.template +74 -144
- package/src/cloudscape-website/app/generator.js +74 -64
- package/src/cloudscape-website/app/generator.js.map +1 -1
- package/src/cloudscape-website/app/schema.d.ts +3 -4
- package/src/cloudscape-website/app/schema.json +1 -24
- package/src/cloudscape-website/cognito-auth/README.md +53 -32
- package/src/cloudscape-website/cognito-auth/__snapshots__/generator.spec.ts.snap +161 -125
- package/src/cloudscape-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +53 -39
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/core/user-identity.ts.template +168 -0
- package/src/cloudscape-website/cognito-auth/generator.js +129 -46
- package/src/cloudscape-website/cognito-auth/generator.js.map +1 -1
- package/src/cloudscape-website/cognito-auth/schema.d.ts +1 -0
- package/src/cloudscape-website/cognito-auth/schema.json +7 -1
- package/src/cloudscape-website/runtime-config/__snapshots__/generator.spec.ts.snap +15 -17
- package/src/cloudscape-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +7 -10
- package/src/cloudscape-website/runtime-config/files/app/hooks/useRuntimeConfig.tsx.template +13 -0
- package/src/cloudscape-website/runtime-config/generator.js +3 -1
- package/src/cloudscape-website/runtime-config/generator.js.map +1 -1
- package/src/infra/app/README.md +71 -46
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +114 -252
- package/src/infra/app/files/app/README.md.template +76 -0
- package/src/infra/app/files/app/src/main.ts.template +18 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/aws-prototyping.guard +1282 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/cfn-nag.guard +6839 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/hipaa-security.guard +2807 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/nist-csf.guard +2585 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/pci-dss-3-2-1.guard +2236 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/wa-reliability-pillar.guard +885 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/wa-security-pillar.guard +2205 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard.ts.template +63 -0
- package/src/infra/app/generator.js +17 -3
- package/src/infra/app/generator.js.map +1 -1
- package/src/infra/app/schema.d.ts +10 -1
- package/src/infra/app/schema.json +16 -8
- package/src/trpc/backend/README.md +102 -80
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +37 -17
- package/src/trpc/backend/files/backend/README.md.template +33 -0
- package/src/trpc/backend/files/common/constructs/src/app/trpc-apis/__apiNameKebabCase__.ts.template +18 -0
- package/src/trpc/backend/files/common/constructs/src/{__apiNameKebabCase__/index.ts.template → core/trpc-api.ts.template} +12 -16
- package/src/trpc/backend/files/schema/README.md.template +33 -0
- package/src/trpc/backend/generator.js +29 -43
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/backend/schema.d.ts +3 -1
- package/src/trpc/backend/schema.json +8 -13
- package/src/trpc/react/README.md +46 -66
- package/src/trpc/react/__snapshots__/generator.spec.ts.snap +104 -65
- package/src/trpc/react/files/src/components/TrpcClients/IsolatedTrpcProvider.tsx.template +75 -0
- package/src/trpc/react/files/src/components/TrpcClients/TrpcApis.tsx.template +1 -0
- package/src/trpc/react/files/src/components/TrpcClients/TrpcClientProviders.tsx.template +10 -0
- package/src/trpc/react/files/src/components/TrpcClients/index.tsx.template +5 -0
- package/src/trpc/react/files/src/hooks/useSigV4.tsx.template +38 -0
- package/src/trpc/react/files/src/hooks/use__apiNameClassName__.tsx.template +3 -0
- package/src/trpc/react/generator.js +123 -24
- package/src/trpc/react/generator.js.map +1 -1
- package/src/trpc/react/schema.json +2 -2
- package/src/ts/cjs-to-esm/generator.js.map +1 -1
- package/src/ts/lib/eslint.d.ts +1 -1
- package/src/ts/lib/eslint.js +59 -11
- package/src/ts/lib/eslint.js.map +1 -1
- package/src/ts/lib/files/README.md.template +33 -0
- package/src/ts/lib/generator.js +11 -4
- package/src/ts/lib/generator.js.map +1 -1
- package/src/ts/lib/schema.d.ts +1 -3
- package/src/ts/lib/schema.json +2 -15
- package/src/ts/lib/ts-project-utils.js.map +1 -1
- package/src/ts/lib/vitest.js +14 -0
- package/src/ts/lib/vitest.js.map +1 -1
- package/src/utils/ast.d.ts +13 -0
- package/src/utils/ast.js +102 -0
- package/src/utils/ast.js.map +1 -0
- package/src/utils/files/common/constructs/src/app/index.ts.template +0 -0
- package/src/utils/files/common/constructs/src/{runtime-config → core}/runtime-config.ts.template +3 -5
- package/src/utils/files/common/constructs/src/index.ts.template +2 -1
- package/src/utils/files/common/readme/README.md.template +33 -0
- package/src/utils/files/common/types/src/runtime-config.ts.template +1 -13
- package/src/utils/format.js.map +1 -1
- package/src/utils/names.d.ts +2 -0
- package/src/utils/names.js +27 -0
- package/src/utils/names.js.map +1 -0
- package/src/utils/npm-scope.js.map +1 -1
- package/src/utils/paths.js.map +1 -1
- package/src/utils/shared-constructs.js +37 -4
- package/src/utils/shared-constructs.js.map +1 -1
- package/src/utils/versions.d.ts +15 -9
- package/src/utils/versions.js +14 -8
- package/src/utils/versions.js.map +1 -1
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/cloudfront-web-acl.ts.template +0 -317
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/index.ts.template +0 -4
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/webacl_event_handler/index.ts.template +0 -301
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/index.ts.template +0 -4
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/user-identity.ts.template +0 -66
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/userpool-with-mfa.ts.template +0 -70
- package/src/gitlab/generator.d.ts +0 -8
- package/src/gitlab/generator.js +0 -16
- package/src/gitlab/generator.js.map +0 -1
- package/src/gitlab/schema.d.ts +0 -9
- package/src/gitlab/schema.json +0 -52
- package/src/infra/app/files/src/main.ts.template +0 -37
- package/src/trpc/react/files/src/components/TRPCClientProvider/index.tsx.template +0 -34
- package/src/trpc/react/files/src/hooks/useTrpc.tsx.template +0 -5
- /package/src/infra/app/files/{cdk.json → app/cdk.json} +0 -0
- /package/src/infra/app/files/{src → app/src}/stacks/application-stack.ts.template +0 -0
- /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
|
-
<
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
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:
|
|
8
|
-
];
|
|
7
|
+
{ text: 'Home', type: 'link', href: '/' },
|
|
8
|
+
];
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
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
|
-
<
|
|
16
|
-
<
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
</I18nProvider>
|
|
21
|
-
</NorthStarThemeProvider>
|
|
14
|
+
<I18nProvider locale="en" messages={[messages]}>
|
|
15
|
+
<BrowserRouter>
|
|
16
|
+
<App />
|
|
17
|
+
</BrowserRouter>
|
|
18
|
+
</I18nProvider>
|
|
22
19
|
</React.StrictMode>
|
|
23
20
|
);
|
|
@@ -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
|
-
|
|
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 {
|
|
19
|
-
import {
|
|
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(
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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:
|
|
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
|
-
|
|
114
|
-
|
|
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 (
|
|
133
|
+
if (
|
|
134
|
+
Token.isUnresolved(value) ||
|
|
135
|
+
(typeof value === 'string' && value.endsWith('}}'))
|
|
136
|
+
) {
|
|
142
137
|
_payload[key] = new CfnJson(this, `ResolveToken-${key}`, {
|
|
143
|
-
|
|
138
|
+
value,
|
|
144
139
|
}).value;
|
|
145
|
-
} else if (typeof value ===
|
|
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
|
-
|
|
158
|
-
|
|
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
|
-
|
|
161
|
-
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
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
|
}
|