mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 13:55:21 +02:00
feat(csp): enable CSP by default BE-11961 (#872)
This commit is contained in:
parent
4d11aa8655
commit
ea4b334c7e
8 changed files with 56 additions and 5 deletions
|
@ -35,6 +35,7 @@ type (
|
|||
JWTAuthLookup(*http.Request) (*portainer.TokenData, error)
|
||||
TrustedEdgeEnvironmentAccess(dataservices.DataStoreTx, *portainer.Endpoint) error
|
||||
RevokeJWT(string)
|
||||
DisableCSP()
|
||||
}
|
||||
|
||||
// RequestBouncer represents an entity that manages API request accesses
|
||||
|
@ -72,7 +73,7 @@ func NewRequestBouncer(dataStore dataservices.DataStore, jwtService portainer.JW
|
|||
jwtService: jwtService,
|
||||
apiKeyService: apiKeyService,
|
||||
hsts: featureflags.IsEnabled("hsts"),
|
||||
csp: featureflags.IsEnabled("csp"),
|
||||
csp: true,
|
||||
}
|
||||
|
||||
go b.cleanUpExpiredJWT()
|
||||
|
@ -80,6 +81,11 @@ func NewRequestBouncer(dataStore dataservices.DataStore, jwtService portainer.JW
|
|||
return b
|
||||
}
|
||||
|
||||
// DisableCSP disables Content Security Policy
|
||||
func (bouncer *RequestBouncer) DisableCSP() {
|
||||
bouncer.csp = false
|
||||
}
|
||||
|
||||
// PublicAccess defines a security check for public API endpoints.
|
||||
// No authentication is required to access these endpoints.
|
||||
func (bouncer *RequestBouncer) PublicAccess(h http.Handler) http.Handler {
|
||||
|
@ -528,7 +534,7 @@ func MWSecureHeaders(next http.Handler, hsts, csp bool) http.Handler {
|
|||
}
|
||||
|
||||
if csp {
|
||||
w.Header().Set("Content-Security-Policy", "script-src 'self' cdn.matomo.cloud")
|
||||
w.Header().Set("Content-Security-Policy", "script-src 'self' cdn.matomo.cloud; frame-ancestors 'none';")
|
||||
}
|
||||
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
|
|
|
@ -530,3 +530,34 @@ func TestJWTRevocation(t *testing.T) {
|
|||
|
||||
require.Equal(t, 1, revokeLen())
|
||||
}
|
||||
|
||||
func TestCSPHeaderDefault(t *testing.T) {
|
||||
b := NewRequestBouncer(nil, nil, nil)
|
||||
|
||||
srv := httptest.NewServer(
|
||||
b.PublicAccess(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})),
|
||||
)
|
||||
defer srv.Close()
|
||||
|
||||
resp, err := http.Get(srv.URL + "/")
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
require.Contains(t, resp.Header, "Content-Security-Policy")
|
||||
}
|
||||
|
||||
func TestCSPHeaderDisabled(t *testing.T) {
|
||||
b := NewRequestBouncer(nil, nil, nil)
|
||||
b.DisableCSP()
|
||||
|
||||
srv := httptest.NewServer(
|
||||
b.PublicAccess(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})),
|
||||
)
|
||||
defer srv.Close()
|
||||
|
||||
resp, err := http.Get(srv.URL + "/")
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
require.NotContains(t, resp.Header, "Content-Security-Policy")
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue