Merge branch '880-header-security' into 'develop'
Resolve "Improve the security via HTTP headers" Closes #880 See merge request funkwhale/funkwhale!826
This commit is contained in:
commit
5b7fad0bef
|
@ -222,14 +222,15 @@ INSTALLED_APPS = (
|
|||
# MIDDLEWARE CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
MIDDLEWARE = (
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
"corsheaders.middleware.CorsMiddleware",
|
||||
"funkwhale_api.common.middleware.SPAFallbackMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"corsheaders.middleware.CorsMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
"funkwhale_api.users.middleware.RecordActivityMiddleware",
|
||||
)
|
||||
|
||||
|
@ -398,6 +399,8 @@ ASGI_APPLICATION = "config.routing.application"
|
|||
|
||||
# This ensures that Django will be able to detect a secure connection
|
||||
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||
SECURE_BROWSER_XSS_FILTER = True
|
||||
SECURE_CONTENT_TYPE_NOSNIFF = True
|
||||
|
||||
# AUTHENTICATION CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Hardened security thanks to CSP and additional HTTP headers (#880)
|
|
@ -43,3 +43,58 @@ Then, edit your ``/etc/systemd/system/funkwhale-server.service`` and replace the
|
|||
``ExecStart=/srv/funkwhale/virtualenv/bin/gunicorn config.asgi:application -w ${FUNKWHALE_WEB_WORKERS} -k uvicorn.workers.UvicornWorker -b ${FUNKWHALE_API_IP}:${FUNKWHALE_API_PORT}``
|
||||
|
||||
Then reload the configuration change with ``sudo systemctl daemon-reload`` and ``sudo systemctl restart funkwhale-server``.
|
||||
|
||||
|
||||
Content-Security-Policy and additional security headers [manual action suggested]
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To improve the security and reduce the attack surface in case of a successfull exploit, we suggest
|
||||
you add the following Content-Security-Policy to your nginx configuration.
|
||||
|
||||
**On non-docker setups**, in ``/etc/nginx/sites-available/funkwhale.conf``::
|
||||
|
||||
server {
|
||||
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
location /front/ {
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
# … existing content here
|
||||
}
|
||||
|
||||
# Also create a new location for the embeds to ensure external iframes work
|
||||
# Simply copy-paste the /front/ location, but replace the following lines:
|
||||
location /front/embed.html {
|
||||
add_header X-Frame-Options "ALLOW";
|
||||
alias ${FUNKWHALE_FRONTEND_PATH}/embed.html;
|
||||
}
|
||||
}
|
||||
|
||||
Then reload nginx with ``systemctl reload nginx``.
|
||||
|
||||
**On docker setups**, in ``/srv/funkwhalenginx/funkwhale.template``::
|
||||
|
||||
server {
|
||||
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
location /front/ {
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
# … existing content here
|
||||
}
|
||||
|
||||
# Also create a new location for the embeds to ensure external iframes work
|
||||
# Simply copy-paste the /front/ location, but replace the following lines:
|
||||
location /front/embed.html {
|
||||
add_header X-Frame-Options "ALLOW";
|
||||
alias /frontent/embed.html;
|
||||
}
|
||||
}
|
||||
|
||||
Then reload nginx with ``docker-compose restart nginx``.
|
||||
|
|
|
@ -23,6 +23,10 @@ server {
|
|||
|
||||
root /frontend;
|
||||
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
|
||||
location / {
|
||||
include /etc/nginx/funkwhale_proxy.conf;
|
||||
# this is needed if you have file import via upload enabled
|
||||
|
@ -31,12 +35,27 @@ server {
|
|||
}
|
||||
|
||||
location /front/ {
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
add_header X-Frame-Options "ALLOW";
|
||||
alias /frontend/;
|
||||
expires 30d;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
|
||||
}
|
||||
|
||||
location /front/embed.html {
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
add_header X-Frame-Options "ALLOW";
|
||||
alias /frontend/embed.html;
|
||||
expires 30d;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
|
||||
}
|
||||
|
||||
location /federation/ {
|
||||
include /etc/nginx/funkwhale_proxy.conf;
|
||||
proxy_pass http://funkwhale-api/federation/;
|
||||
|
|
|
@ -29,6 +29,9 @@ server {
|
|||
# HSTS
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
|
||||
# Security related headers
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
|
||||
# compression settings
|
||||
gzip on;
|
||||
gzip_comp_level 5;
|
||||
|
|
|
@ -41,6 +41,9 @@ server {
|
|||
# HSTS
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
root ${FUNKWHALE_FRONTEND_PATH};
|
||||
|
||||
# compression settings
|
||||
|
@ -78,11 +81,25 @@ server {
|
|||
}
|
||||
|
||||
location /front/ {
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
alias ${FUNKWHALE_FRONTEND_PATH}/;
|
||||
expires 30d;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
|
||||
}
|
||||
location /front/embed.html {
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
add_header X-Frame-Options "ALLOW";
|
||||
alias ${FUNKWHALE_FRONTEND_PATH}/embed.html;
|
||||
expires 30d;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
|
||||
}
|
||||
|
||||
location /federation/ {
|
||||
include /etc/nginx/funkwhale_proxy.conf;
|
||||
|
@ -111,7 +128,7 @@ server {
|
|||
internal;
|
||||
alias ${MEDIA_ROOT};
|
||||
}
|
||||
|
||||
|
||||
# Comment the previous location and uncomment this one if you're storing
|
||||
# media files in a S3 bucket
|
||||
# location ~ /_protected/media/(.+) {
|
||||
|
|
3
dev.yml
3
dev.yml
|
@ -49,7 +49,7 @@ services:
|
|||
args:
|
||||
install_dev_deps: 1
|
||||
entrypoint: compose/django/dev-entrypoint.sh
|
||||
command: python /app/manage.py runserver 0.0.0.0:${FUNKWHALE_API_PORT-5000}
|
||||
command: uvicorn --reload config.asgi:application --host 0.0.0.0 --port 5000 --reload-dir config/ --reload-dir=funkwhale_api/
|
||||
volumes:
|
||||
- ./api:/app
|
||||
- "${MUSIC_DIRECTORY_SERVE_PATH-./data/music}:/music:ro"
|
||||
|
@ -119,6 +119,7 @@ services:
|
|||
- "${MUSIC_DIRECTORY_SERVE_PATH-./data/music}:/music:ro"
|
||||
- ./deploy/funkwhale_proxy.conf:/etc/nginx/funkwhale_proxy.conf:ro
|
||||
- "${MEDIA_ROOT-./api/funkwhale_api/media}:/protected/media:ro"
|
||||
- "./front:/frontend:ro"
|
||||
networks:
|
||||
- federation
|
||||
- internal
|
||||
|
|
|
@ -69,9 +69,24 @@ http {
|
|||
text/x-component
|
||||
text/x-cross-domain-policy;
|
||||
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
location /front/ {
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
# uncomment the following line and comment the proxy-pass one
|
||||
# to use the frontend build with "yarn build"
|
||||
#alias /frontend/dist/;
|
||||
proxy_pass http://funkwhale-front/front/;
|
||||
}
|
||||
location /front/embed.html {
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
add_header X-Frame-Options "ALLOW";
|
||||
proxy_pass http://funkwhale-front/front/embed.html;
|
||||
}
|
||||
location /front-server/ {
|
||||
proxy_pass http://funkwhale-front/;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ Vue.config.productionTip = false
|
|||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
template: '<EmbedFrame/>',
|
||||
render (h) {
|
||||
return h('EmbedFrame')
|
||||
},
|
||||
components: { EmbedFrame }
|
||||
})
|
||||
|
|
|
@ -122,7 +122,9 @@ store.dispatch('instance/fetchFrontSettings').finally(() => {
|
|||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
template: '<App/>',
|
||||
render (h) {
|
||||
return h('App')
|
||||
},
|
||||
components: { App }
|
||||
})
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ if (process.env.BUNDLE_ANALYZE === '1') {
|
|||
}
|
||||
module.exports = {
|
||||
baseUrl: process.env.BASE_URL || '/front/',
|
||||
productionSourceMap: false,
|
||||
pages: {
|
||||
embed: {
|
||||
entry: 'src/embed.js',
|
||||
|
@ -30,11 +31,7 @@ module.exports = {
|
|||
},
|
||||
configureWebpack: {
|
||||
plugins: plugins,
|
||||
resolve: {
|
||||
alias: {
|
||||
'vue$': 'vue/dist/vue.esm.js'
|
||||
}
|
||||
}
|
||||
devtool: false
|
||||
},
|
||||
devServer: {
|
||||
disableHostCheck: true,
|
||||
|
|
Loading…
Reference in New Issue