From fe5f2d88cba29b5eff8ca99df8c10c7b1c5f9e1b Mon Sep 17 00:00:00 2001 From: Scott Rees <6165315+reesscot@users.noreply.github.com> Date: Wed, 8 Dec 2021 16:18:15 -0800 Subject: [PATCH] docs: custom security headers (#963) * Add custom security headers * Add dev mode headers, move csp to document * Remove Google fonts * Allow codesandbox iframe --- customHttp.yml | 17 +++++++++++ docs/next.config.js | 31 +++++++++++++++++++ docs/src/pages/_document.page.tsx | 49 +++++++++++++++++++++++-------- docs/src/theme.ts | 12 -------- 4 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 customHttp.yml diff --git a/customHttp.yml b/customHttp.yml new file mode 100644 index 00000000000..e09173bd073 --- /dev/null +++ b/customHttp.yml @@ -0,0 +1,17 @@ +# Custom headers when serving docs through Amplify Hosting +# +# See: https://docs.aws.amazon.com/amplify/latest/userguide/custom-headers.html#setting-custom-headers +applications: + - appRoot: docs + customHeaders: + - pattern: "**/*" + headers: + - key: "Strict-Transport-Security" + value: "max-age=31536000; includeSubDomains" + - key: "X-Frame-Options" + value: "SAMEORIGIN" + - key: "X-XSS-Protection" + value: "1; mode=block" + - key: "X-Content-Type-Options" + value: "nosniff" + # CSP set in _document.page.tsx meta tag diff --git a/docs/next.config.js b/docs/next.config.js index 6cc64b10f58..e29c630a25b 100644 --- a/docs/next.config.js +++ b/docs/next.config.js @@ -19,6 +19,37 @@ module.exports = withNextPluginPreval({ ignoreBuildErrors: true, }, + async headers() { + return [ + { + // Apply these headers to all routes in your application. + source: '/(.*)', + headers: [ + // IMPORTANT: + // These are ONLY used for the Dev server and MUST + // be kept in sync with customHttp.yml + { + key: 'Strict-Transport-Security', + value: 'max-age=63072000; includeSubDomains', + }, + { + key: 'X-Frame-Options', + value: 'SAMEORIGIN', + }, + { + key: 'X-XSS-Protection', + value: '1; mode=block', + }, + { + key: 'X-Content-Type-Options', + value: 'nosniff', + }, + // for 'Content-Security-Policy', see _document.page.tsx + ], + }, + ]; + }, + // These redirects are because of the IA change from previous docs redirects() { return [ diff --git a/docs/src/pages/_document.page.tsx b/docs/src/pages/_document.page.tsx index b30f621f155..5605fcc6ca6 100644 --- a/docs/src/pages/_document.page.tsx +++ b/docs/src/pages/_document.page.tsx @@ -1,3 +1,5 @@ +import crypto from 'crypto'; +import type { HtmlProps } from 'next/dist/shared/lib/utils'; import Document, { Html, Head, Main, NextScript } from 'next/document'; const favicon = @@ -5,24 +7,47 @@ const favicon = ? '/svg/favicon-dev.svg' : '/svg/favicon.svg'; +const cspHashOf = (text) => { + const hash = crypto.createHash('sha256'); + hash.update(text); + return `sha256-${hash.digest('base64')}`; +}; + +// See: https://github.com/vercel/next.js/blob/master/examples/with-strict-csp/pages/_document.js +const getCSPContent = (context: Readonly) => { + const cspInlineScriptHash = cspHashOf( + NextScript.getInlineScriptSource(context) + ); + + // Dev environment + if (process.env.NODE_ENV !== 'production') { + return `default-src 'self'; + style-src 'self' 'unsafe-inline'; + font-src 'self' data:; + frame-src *.codesandbox.io; + script-src 'unsafe-eval' 'self' '${cspInlineScriptHash}' + `; + } + + // Prod environment + return `default-src 'self'; + style-src 'self' 'unsafe-inline'; + font-src 'self'; + frame-src *.codesandbox.io; + script-src 'self' '${cspInlineScriptHash}' + `; +}; + class MyDocument extends Document { render() { return ( - - {/* Adding custom variable fonts from google */} - {/* Including multiple to show theming capabilities */} - - - +
diff --git a/docs/src/theme.ts b/docs/src/theme.ts index 0a746b0762b..e8cebca825e 100644 --- a/docs/src/theme.ts +++ b/docs/src/theme.ts @@ -116,12 +116,6 @@ export const theme: Theme = { { selector: '.classic [data-amplify-theme="amplify-docs"]', tokens: { - fonts: { - default: { - variable: { value: `'Open Sans'` }, - static: { value: `'Open Sans'` }, - }, - }, colors: { brand: { primary: usePalette('blue'), @@ -143,12 +137,6 @@ export const theme: Theme = { { selector: '.terminal [data-amplify-theme="amplify-docs"]', tokens: { - fonts: { - default: { - variable: { value: "'Work Sans'" }, - static: { value: "'Work Sans'" }, - }, - }, colors: { green: { 10: { value: '#C7EFCA' },