feat(server): csp template (#2856)
Implements the ability for advanced users to override the CSP and easily include the required nonce.pull/2891/head
parent
6043b43d94
commit
bed7a8ae32
|
@ -71,6 +71,12 @@ server:
|
||||||
## The path to the DER base64/PEM format public certificate.
|
## The path to the DER base64/PEM format public certificate.
|
||||||
certificate: ""
|
certificate: ""
|
||||||
|
|
||||||
|
## Server headers configuration/customization.
|
||||||
|
headers:
|
||||||
|
|
||||||
|
## The CSP Template. Read the docs.
|
||||||
|
csp_template: ""
|
||||||
|
|
||||||
##
|
##
|
||||||
## Log Configuration
|
## Log Configuration
|
||||||
##
|
##
|
||||||
|
|
|
@ -24,6 +24,8 @@ server:
|
||||||
tls:
|
tls:
|
||||||
key: ""
|
key: ""
|
||||||
certificate: ""
|
certificate: ""
|
||||||
|
headers:
|
||||||
|
csp_template: ""
|
||||||
```
|
```
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
@ -209,6 +211,25 @@ required: situational
|
||||||
|
|
||||||
The path to the public certificate for TLS connections. Must be in DER base64/PEM format.
|
The path to the public certificate for TLS connections. Must be in DER base64/PEM format.
|
||||||
|
|
||||||
|
|
||||||
|
### headers
|
||||||
|
|
||||||
|
#### csp_template
|
||||||
|
<div markdown="1">
|
||||||
|
type: string
|
||||||
|
{: .label .label-config .label-purple }
|
||||||
|
default: ""
|
||||||
|
{: .label .label-config .label-blue }
|
||||||
|
required: no
|
||||||
|
{: .label .label-config .label-green }
|
||||||
|
</div>
|
||||||
|
|
||||||
|
This customizes the value of the Content-Security-Policy header. It will replace all instances of `${NONCE}` with the
|
||||||
|
nonce value of the Authelia react bundle. This is an advanced option to customize and you should do sufficient research
|
||||||
|
about how browsers utilize and understand this header before attempting to customize it.
|
||||||
|
|
||||||
|
For example, the default CSP template is `default-src 'self'; object-src 'none'; style-src 'self' 'nonce-${NONCE}'`.
|
||||||
|
|
||||||
## Additional Notes
|
## Additional Notes
|
||||||
|
|
||||||
### Buffer Sizes
|
### Buffer Sizes
|
||||||
|
|
|
@ -71,6 +71,12 @@ server:
|
||||||
## The path to the DER base64/PEM format public certificate.
|
## The path to the DER base64/PEM format public certificate.
|
||||||
certificate: ""
|
certificate: ""
|
||||||
|
|
||||||
|
## Server headers configuration/customization.
|
||||||
|
headers:
|
||||||
|
|
||||||
|
## The CSP Template. Read the docs.
|
||||||
|
csp_template: ""
|
||||||
|
|
||||||
##
|
##
|
||||||
## Log Configuration
|
## Log Configuration
|
||||||
##
|
##
|
||||||
|
|
|
@ -13,6 +13,7 @@ type ServerConfiguration struct {
|
||||||
DisableHealthcheck bool `koanf:"disable_healthcheck"`
|
DisableHealthcheck bool `koanf:"disable_healthcheck"`
|
||||||
|
|
||||||
TLS ServerTLSConfiguration `koanf:"tls"`
|
TLS ServerTLSConfiguration `koanf:"tls"`
|
||||||
|
Headers ServerHeadersConfiguration `koanf:"headers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerTLSConfiguration represents the configuration of the http servers TLS options.
|
// ServerTLSConfiguration represents the configuration of the http servers TLS options.
|
||||||
|
@ -21,6 +22,11 @@ type ServerTLSConfiguration struct {
|
||||||
Key string `koanf:"key"`
|
Key string `koanf:"key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServerHeadersConfiguration represents the customization of the http server headers.
|
||||||
|
type ServerHeadersConfiguration struct {
|
||||||
|
CSPTemplate string `koanf:"csp_template"`
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultServerConfiguration represents the default values of the ServerConfiguration.
|
// DefaultServerConfiguration represents the default values of the ServerConfiguration.
|
||||||
var DefaultServerConfiguration = ServerConfiguration{
|
var DefaultServerConfiguration = ServerConfiguration{
|
||||||
Host: "0.0.0.0",
|
Host: "0.0.0.0",
|
||||||
|
|
|
@ -171,6 +171,7 @@ var ValidKeys = []string{
|
||||||
"server.disable_healthcheck",
|
"server.disable_healthcheck",
|
||||||
"server.tls.key",
|
"server.tls.key",
|
||||||
"server.tls.certificate",
|
"server.tls.certificate",
|
||||||
|
"server.headers.csp_template",
|
||||||
|
|
||||||
// TOTP Keys.
|
// TOTP Keys.
|
||||||
"totp.issuer",
|
"totp.issuer",
|
||||||
|
|
|
@ -23,3 +23,9 @@ X_AUTHELIA_HEALTHCHECK_HOST=%s
|
||||||
X_AUTHELIA_HEALTHCHECK_PORT=%d
|
X_AUTHELIA_HEALTHCHECK_PORT=%d
|
||||||
X_AUTHELIA_HEALTHCHECK_PATH=%s
|
X_AUTHELIA_HEALTHCHECK_PATH=%s
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const (
|
||||||
|
cspDefaultTemplate = "default-src 'self'; object-src 'none'; style-src 'self' 'nonce-%s'"
|
||||||
|
cspDefaultDevTemplate = "default-src 'self' 'unsafe-eval'; object-src 'none'; style-src 'self' 'nonce-%s'"
|
||||||
|
cspNoncePlaceholder = "${NONCE}"
|
||||||
|
)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/logging"
|
"github.com/authelia/authelia/v4/internal/logging"
|
||||||
|
@ -72,10 +73,12 @@ func ServeTemplatedFile(publicDir, file, assetPath, duoSelfEnrollment, rememberM
|
||||||
switch {
|
switch {
|
||||||
case publicDir == swaggerAssets:
|
case publicDir == swaggerAssets:
|
||||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("base-uri 'self'; default-src 'self'; img-src 'self' https://validator.swagger.io data:; object-src 'none'; script-src 'self' 'unsafe-inline' 'nonce-%s'; style-src 'self' 'nonce-%s'", nonce, nonce))
|
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("base-uri 'self'; default-src 'self'; img-src 'self' https://validator.swagger.io data:; object-src 'none'; script-src 'self' 'unsafe-inline' 'nonce-%s'; style-src 'self' 'nonce-%s'", nonce, nonce))
|
||||||
|
case ctx.Configuration.Server.Headers.CSPTemplate != "":
|
||||||
|
ctx.Response.Header.Add("Content-Security-Policy", strings.ReplaceAll(ctx.Configuration.Server.Headers.CSPTemplate, cspNoncePlaceholder, nonce))
|
||||||
case os.Getenv("ENVIRONMENT") == dev:
|
case os.Getenv("ENVIRONMENT") == dev:
|
||||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("default-src 'self' 'unsafe-eval'; object-src 'none'; style-src 'self' 'nonce-%s'", nonce))
|
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf(cspDefaultDevTemplate, nonce))
|
||||||
default:
|
default:
|
||||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("default-src 'self' ; object-src 'none'; style-src 'self' 'nonce-%s'", nonce))
|
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf(cspDefaultTemplate, nonce))
|
||||||
}
|
}
|
||||||
|
|
||||||
err := tmpl.Execute(ctx.Response.BodyWriter(), struct{ Base, BaseURL, CSPNonce, DuoSelfEnrollment, LogoOverride, RememberMe, ResetPassword, Session, Theme string }{Base: base, BaseURL: baseURL, CSPNonce: nonce, DuoSelfEnrollment: duoSelfEnrollment, LogoOverride: logoOverride, RememberMe: rememberMe, ResetPassword: resetPassword, Session: session, Theme: theme})
|
err := tmpl.Execute(ctx.Response.BodyWriter(), struct{ Base, BaseURL, CSPNonce, DuoSelfEnrollment, LogoOverride, RememberMe, ResetPassword, Session, Theme string }{Base: base, BaseURL: baseURL, CSPNonce: nonce, DuoSelfEnrollment: duoSelfEnrollment, LogoOverride: logoOverride, RememberMe: rememberMe, ResetPassword: resetPassword, Session: session, Theme: theme})
|
||||||
|
|
Loading…
Reference in New Issue