Skip to content

Commit

Permalink
docs: document experimental netlify support
Browse files Browse the repository at this point in the history
Signed-off-by: Andres Correa Casablanca <andreu@kindspells.dev>
  • Loading branch information
castarco committed Sep 17, 2024
1 parent 6e0f693 commit 0a9cd55
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 6 deletions.
11 changes: 10 additions & 1 deletion @kindspells/astro-shield/src/core.mts
Original file line number Diff line number Diff line change
Expand Up @@ -767,13 +767,22 @@ export const processStaticFiles = async (
if (securityHeaders?.enableOnStaticPages !== undefined) {
const provider = securityHeaders.enableOnStaticPages.provider
switch (provider) {
case 'netlify':
case 'netlify': {
if (
(securityHeaders.enableOnStaticPages.mode ?? '_headers') !==
'_headers'
) {
throw new Error(
'Netlify provider only supports "_headers" mode for now',
)
}
await patchNetlifyHeadersConfig(
resolve(distDir, '_headers'),
securityHeaders,
h,
)
break
}
case 'vercel':
throw new Error('Vercel provider is still not supported')
default:
Expand Down
10 changes: 8 additions & 2 deletions @kindspells/astro-shield/src/main.mts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@ import { fileURLToPath } from 'node:url'
import type { AstroIntegration } from 'astro'

import { getAstroConfigSetup, processStaticFiles } from '#as/core'
import type { ShieldOptions, SRIOptions } from './types.mts'
import type {
SecurityHeadersOptions,
ShieldOptions,
SRIOptions,
} from './types.mts'

type AstroHooks = AstroIntegration['hooks']

const getAstroBuildDone = (
sri: Required<SRIOptions>,
securityHeaders: SecurityHeadersOptions | undefined,
): NonNullable<AstroHooks['astro:build:done']> =>
(async ({ dir, logger }) =>
await processStaticFiles(logger, {
distDir: fileURLToPath(dir),
sri,
securityHeaders,
})) satisfies NonNullable<AstroHooks['astro:build:done']>

const logWarn = (msg: string): void =>
Expand Down Expand Up @@ -69,7 +75,7 @@ export const shield = ({
hooks: {
...(_sri.enableStatic === true
? {
'astro:build:done': getAstroBuildDone(_sri),
'astro:build:done': getAstroBuildDone(_sri, securityHeaders),
}
: undefined),
...(_sri.enableMiddleware === true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default defineConfig({
integrations: [
shield({
sri: {
enableMiddleware: true, // MUST be enabled!
enableMiddleware: true, // MUST be enabled for dynamic pages!
hashesModule: modulePath, // SHOULD be set!
},
Expand All @@ -42,6 +42,7 @@ export default defineConfig({
// - If set, it controls how the CSP (Content Security Policy) header will
// be generated in the middleware.
// - If not set, no CSP header will be generated in the middleware.
// (there is no need to specify its inner options)
contentSecurityPolicy: {
// - If set, it controls the "default" CSP directives (they can be
// overriden at runtime).
Expand All @@ -65,6 +66,15 @@ export default defineConfig({
</Aside>

<Aside type="caution">
When enabling CSP headers, you must also set the `sri.enableMiddleware` option
to `true`. It is also recommended to set the `sri.hashesModule` option.
When enabling CSP headers, it is advisable to also set the
`sri.enableMiddleware` option to `true`. It is also recommended to set the
`sri.hashesModule` option.
</Aside>

<Aside type='tip'>
If you want to set CSP headers for your static content, check the specific
guide for your deployment platform:

- [Netlify](/guides/security-headers/netlify-static-content/)
- Vercel: Coming soon!
</Aside>
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
# SPDX-FileCopyrightText: 2024 KindSpells Labs S.L.
#
# SPDX-License-Identifier: MIT

title: Configuring CSP headers for static content on Netlify
description: How to configure the Content-Security-Policy headers of your static pages on Netlify with Astro-Shield
---

import { Aside, Code } from '@astrojs/starlight/components';

Ensuring that Netlify serves your static content with the correct
`Content-Security-Policy` headers requires some additional configuration.
Specifically, set `securityHeaders.enableOnStaticPages.provider` to the value
`"netlify"`.

See a more complete example:

<Code
lang="javascript"
code={`
import { resolve } from 'node:path'
import { defineConfig } from 'astro/config'
import { shield } from '@kindspells/astro-shield'
const rootDir = new URL('.', import.meta.url).pathname
const modulePath = resolve(rootDir, 'src', 'generated', 'sriHashes.mjs')
export default defineConfig({
integrations: [
shield({
sri: {
hashesModule: modulePath, // SHOULD be set!
},
// - If set, it controls how the security headers will be generated in the
// middleware.
// - If not set, no security headers will be generated in the middleware.
securityHeaders: {
// This option is required to configure CSP headers for your static
// content on Netlify.
enableOnStaticPages: { provider: "netlify" },
// - If set, it controls how the CSP (Content Security Policy) header will
// be generated in the middleware.
// - If not set, no CSP header will be configured for your static content.
// (there is no need to specify its inner options)
contentSecurityPolicy: {
// - If set, it controls the "default" CSP directives (they can be
// overriden at runtime).
// - If not set, the middleware will use a minimal set of default
// directives.
cspDirectives: {
'default-src': "'none'",
}
}
}
})
]
})
`}
/>

<Aside type='tip'>
To see how to configure CSP headers for your dynamic content, check the page
[Content-Security-Policy (CSP)](/guides/security-headers/content-security-policy/).
</Aside>

0 comments on commit 0a9cd55

Please sign in to comment.