Add ALLOWED_HOSTS

the proxy responds with a 421, if a host header with an invalid host
name is encountered. If nothing is provided (see default .env) all hosts
are allowed. Examples:

ALLOWED_HOSTS="localhost:8000 127.0.0.1:8000"

ALLOWED_HOSTS="some.domain.example.com"

Add EXTERNAL_HTTPS_PORT. See .env for the configuration.
This commit is contained in:
Finn Stutzenstein 2021-04-08 07:41:55 +02:00
parent ee8702aff1
commit 91a15d24a8
No known key found for this signature in database
GPG Key ID: 9042F605C6324654
8 changed files with 157 additions and 25 deletions

View File

@ -33,8 +33,8 @@ first and initialize all submodules::
git submodule update --init git submodule update --init
Setup Docker images Setup Docker Compose
------------------- --------------------
You need to build the Docker images and have to setup some configuration. First, You need to build the Docker images and have to setup some configuration. First,
configure HTTPS by checking the `Using HTTPS`_ section. In this section are configure HTTPS by checking the `Using HTTPS`_ section. In this section are
@ -64,11 +64,15 @@ Afterwards, generate the configuration file::
m4 docker-compose.yml.m4 > docker-compose.yml m4 docker-compose.yml.m4 > docker-compose.yml
You can configure OpenSlides using the `.env` file. See `More settings`_. Another
hint: If you choose to deploy the default configuration, a https certificate is
needed, so make sure you have set it up beforehand.
Finally, you can start the instance using ``docker-compose``:: Finally, you can start the instance using ``docker-compose``::
docker-compose up docker-compose up
OpenSlides is accessible on http://localhost:8000/ (or https, if configured). OpenSlides is accessible on https://localhost/ (or https, if configured).
Use can also use daemonized instance:: Use can also use daemonized instance::

View File

@ -1,4 +1,5 @@
import endpoint import endpoint
import invalid_host*
reverse_proxy /system/* autoupdate:8002 { reverse_proxy /system/* autoupdate:8002 {
flush_interval -1 flush_interval -1
@ -15,3 +16,5 @@ import endpoint
reverse_proxy client:4200 reverse_proxy client:4200
} }
import redirect*

View File

@ -1,15 +1,15 @@
localhost:8000 :8000 {
reverse_proxy /system/* autoupdate:8002 {
flush_interval -1
}
reverse_proxy /system/* autoupdate:8002 { @server {
flush_interval -1 path /apps/*
path /rest/*
path /server-version.txt
path /media/*
}
reverse_proxy @server server:8000
reverse_proxy client:4200
} }
@server {
path /apps/*
path /rest/*
path /server-version.txt
path /media/*
}
reverse_proxy @server server:8000
reverse_proxy client:4200

View File

@ -2,15 +2,77 @@
set -e set -e
if [[ -z "$EXTERNAL_HTTP_PORT" ]] && [[ -z "$EXTERNAL_HTTPS_PORT" ]]; then
echo "EXTERNAL_HTTP_PORT and EXTERNAL_HTTPS_PORT are not set. Aborting."
exit 1
fi
if [[ -f "/certs/key.pem" ]] && [[ -f "/certs/cert.pem" ]]; then if [[ -f "/certs/key.pem" ]] && [[ -f "/certs/cert.pem" ]]; then
certs_exists=1
fi
if [[ -n "$EXTERNAL_HTTPS_PORT" ]] && [[ -z "$certs_exists" ]]; then
echo "Configured https, but no certificates found. Aborting"
exit 1
fi
# config: https
if [[ -n "$EXTERNAL_HTTPS_PORT" ]] ; then
cat <<EOF >> /etc/caddy/endpoint cat <<EOF >> /etc/caddy/endpoint
https://:8000 { https://:8001 {
tls /certs/cert.pem /certs/key.pem tls /certs/cert.pem /certs/key.pem
EOF EOF
echo "Configured https" echo "Configured https"
else fi
# config: http and no https
if [[ -n "$EXTERNAL_HTTP_PORT" ]] && [[ -z "$EXTERNAL_HTTPS_PORT" ]] ; then
echo "http://:8000 {" > /etc/caddy/endpoint echo "http://:8000 {" > /etc/caddy/endpoint
echo "Configured http" echo "Configured http only"
fi
# config: https and additionally http -> create redirect-file
if [[ -n "$EXTERNAL_HTTP_PORT" ]] && [[ -n "$EXTERNAL_HTTPS_PORT" ]] ; then
cat <<EOF >> /etc/caddy/redirect
http://:8000 {
redir https://$INSTANCE_DOMAIN{uri}
}
EOF
echo "Configured http to https redirect"
fi
# Add allowed hosts from $ALLOWED_HOSTS
# If the variable is empty, all hosts are allowed.
# The hosts are ORed, so the request is valid, if one host matches.
# Example: ALLOWED_HOSTS="localhost:8000 127.0.0.1:8000"
#
# @invalid-host {
# not {
# header Host localhost:8000
# header Host 127.0.0.1:8000
# }
# }
# respond @invalid-host "Misdirected Request" 421 {
# close
# }
if [[ ! -z "$ALLOWED_HOSTS" ]]; then
cat <<EOF >> /etc/caddy/invalid_host
@invalid-host {
not {
EOF
for host in $ALLOWED_HOSTS; do
echo " host $host" >> /etc/caddy/invalid_host
done
cat <<EOF >> /etc/caddy/invalid_host
}
}
respond @invalid-host "Misdirected Request" 421 {
close
}
EOF
echo "Configured allowed hosts: $ALLOWED_HOSTS"
else
echo "All hosts allowed"
fi fi
exec "$@" exec "$@"

View File

@ -10,9 +10,40 @@
# General # General
# ------- # -------
# The domain your OpenSlides installation in reachable. E.g. example.com or
# 127.0.0.1 for a local deployment. This domain is used when generating links
# in emails and so on, so it should be the public facing domain. The default
# is 127.0.0.1
# If you do not have any port-changing proxies, this setting should be kept in
# sync with the EXTERNAL_*_PORTS below
INSTANCE_DOMAIN= INSTANCE_DOMAIN=
PROJECT_STACK_NAME=
# The schema (http or https) to use for generating public links. The default
# is https.
INSTANCE_URL_SCHEME=
# The ports the setup binds to to listen for http/https requests. To not bind
# to http or https, leave the port empty. Behavior of port-combinations:
# - If both ports are set, the server listens to https. Additionally, a http to
# https redirect is activated on the http port.
# - If no ports are set, the https port defaults to 443.
# - If exactly one port is set, the server listens to the given port.
# If the https port is set, there must be a ssl certificate. See the README
# for more information.
EXTERNAL_HTTP_PORT= EXTERNAL_HTTP_PORT=
EXTERNAL_HTTPS_PORT=
# A list of hosts, that are allowed to accept. If there is a not accepted host,
# a 421 response will be returned.
# The default is an empty list, so all hosts are accepted.
# Example with two hosts: ALLOWED_HOSTS="127.0.0.1:443 example.com"
ALLOWED_HOSTS=
# The name for the docker stack used.
PROJECT_STACK_NAME=
# The default registry. Defaults to "openslides".
DEFAULT_DOCKER_REGISTRY= DEFAULT_DOCKER_REGISTRY=
# Docker Images # Docker Images

View File

@ -42,6 +42,14 @@ ifelse(read_env(`PGNODE_3_ENABLED'), 1, `,pgnode3')')
define(`PROJECT_DIR', ifdef(`PROJECT_DIR',PROJECT_DIR,.)) define(`PROJECT_DIR', ifdef(`PROJECT_DIR',PROJECT_DIR,.))
define(`ADMIN_SECRET_AVAILABLE', `syscmd(`test -f 'PROJECT_DIR`/secrets/adminsecret.env')sysval') define(`ADMIN_SECRET_AVAILABLE', `syscmd(`test -f 'PROJECT_DIR`/secrets/adminsecret.env')sysval')
define(`USER_SECRET_AVAILABLE', `syscmd(`test -f 'PROJECT_DIR`/secrets/usersecret.env')sysval') define(`USER_SECRET_AVAILABLE', `syscmd(`test -f 'PROJECT_DIR`/secrets/usersecret.env')sysval')
dnl set EXTERNAL_HTTPS_PORT to 443 if EXTERNAL_HTTPS_PORT and EXTERNAL_HTTP_PORT are empty
define(
`EXTERNAL_HTTPS_PORT',
ifelse(read_env(`EXTERNAL_HTTPS_PORT')read_env(`EXTERNAL_HTTP_PORT'),,443,read_env(`EXTERNAL_HTTPS_PORT'))dnl
)
define(`EXTERNAL_HTTP_PORT',read_env(`EXTERNAL_HTTP_PORT'))
divert(0)dnl divert(0)dnl
dnl ---------------------------------------- dnl ----------------------------------------
# This configuration was created from a template file. Before making changes, # This configuration was created from a template file. Before making changes,
@ -75,7 +83,8 @@ x-osserver-env: &default-osserver-env
ENABLE_ELECTRONIC_VOTING: "ifenvelse(`ENABLE_ELECTRONIC_VOTING', False)" ENABLE_ELECTRONIC_VOTING: "ifenvelse(`ENABLE_ELECTRONIC_VOTING', False)"
ENABLE_CHAT: "ifenvelse(`ENABLE_CHAT', False)" ENABLE_CHAT: "ifenvelse(`ENABLE_CHAT', False)"
ENABLE_SAML: "ifenvelse(`ENABLE_SAML', False)" ENABLE_SAML: "ifenvelse(`ENABLE_SAML', False)"
INSTANCE_DOMAIN: "ifenvelse(`INSTANCE_DOMAIN', http://example.com:8000)" INSTANCE_DOMAIN: "ifenvelse(`INSTANCE_DOMAIN', 127.0.0.1)"
INSTANCE_URL_SCHEME: "ifenvelse(`INSTANCE_URL_SCHEME', https)"
JITSI_DOMAIN: "ifenvelse(`JITSI_DOMAIN',)" JITSI_DOMAIN: "ifenvelse(`JITSI_DOMAIN',)"
JITSI_ROOM_PASSWORD: "ifenvelse(`JITSI_ROOM_PASSWORD',)" JITSI_ROOM_PASSWORD: "ifenvelse(`JITSI_ROOM_PASSWORD',)"
JITSI_ROOM_NAME: "ifenvelse(`JITSI_ROOM_NAME',)" JITSI_ROOM_NAME: "ifenvelse(`JITSI_ROOM_NAME',)"
@ -108,11 +117,17 @@ services:
- client - client
- autoupdate - autoupdate
- media - media
environment:
INSTANCE_DOMAIN: "ifenvelse(`INSTANCE_DOMAIN', 127.0.0.1:443)"
`EXTERNAL_HTTP_PORT': "EXTERNAL_HTTP_PORT"
`EXTERNAL_HTTPS_PORT': "EXTERNAL_HTTPS_PORT"
ALLOWED_HOSTS: "ifenvelse(`ALLOWED_HOSTS',)"
networks: networks:
- front - front
- back - back
ports: ports:
- "127.0.0.1:ifenvelse(`EXTERNAL_HTTP_PORT', 8000):8000" ifelse(EXTERNAL_HTTP_PORT,,,- "127.0.0.1:EXTERNAL_HTTP_PORT:8000")
ifelse(EXTERNAL_HTTPS_PORT,,,- "127.0.0.1:EXTERNAL_HTTPS_PORT:8001")
server: server:
<< : *default-osserver << : *default-osserver

View File

@ -42,6 +42,14 @@ ifelse(read_env(`PGNODE_3_ENABLED'), 1, `,pgnode3')')
define(`PROJECT_DIR', ifdef(`PROJECT_DIR',PROJECT_DIR,.)) define(`PROJECT_DIR', ifdef(`PROJECT_DIR',PROJECT_DIR,.))
define(`ADMIN_SECRET_AVAILABLE', `syscmd(`test -f 'PROJECT_DIR`/secrets/adminsecret.env')sysval') define(`ADMIN_SECRET_AVAILABLE', `syscmd(`test -f 'PROJECT_DIR`/secrets/adminsecret.env')sysval')
define(`USER_SECRET_AVAILABLE', `syscmd(`test -f 'PROJECT_DIR`/secrets/usersecret.env')sysval') define(`USER_SECRET_AVAILABLE', `syscmd(`test -f 'PROJECT_DIR`/secrets/usersecret.env')sysval')
dnl set EXTERNAL_HTTPS_PORT to 443 if EXTERNAL_HTTPS_PORT and EXTERNAL_HTTP_PORT are empty
define(
`EXTERNAL_HTTPS_PORT',
ifelse(read_env(`EXTERNAL_HTTPS_PORT')read_env(`EXTERNAL_HTTP_PORT'),,443,read_env(`EXTERNAL_HTTPS_PORT'))dnl
)
define(`EXTERNAL_HTTP_PORT',read_env(`EXTERNAL_HTTP_PORT'))
divert(0)dnl divert(0)dnl
dnl ---------------------------------------- dnl ----------------------------------------
# This configuration was created from a template file. Before making changes, # This configuration was created from a template file. Before making changes,
@ -74,7 +82,8 @@ x-osserver-env: &default-osserver-env
ENABLE_ELECTRONIC_VOTING: "ifenvelse(`ENABLE_ELECTRONIC_VOTING', False)" ENABLE_ELECTRONIC_VOTING: "ifenvelse(`ENABLE_ELECTRONIC_VOTING', False)"
ENABLE_CHAT: "ifenvelse(`ENABLE_CHAT', False)" ENABLE_CHAT: "ifenvelse(`ENABLE_CHAT', False)"
ENABLE_SAML: "ifenvelse(`ENABLE_SAML', False)" ENABLE_SAML: "ifenvelse(`ENABLE_SAML', False)"
INSTANCE_DOMAIN: "ifenvelse(`INSTANCE_DOMAIN', http://example.com:8000)" INSTANCE_DOMAIN: "ifenvelse(`INSTANCE_DOMAIN', 127.0.0.1)"
INSTANCE_URL_SCHEME: "ifenvelse(`INSTANCE_URL_SCHEME', https)"
JITSI_DOMAIN: "ifenvelse(`JITSI_DOMAIN',)" JITSI_DOMAIN: "ifenvelse(`JITSI_DOMAIN',)"
JITSI_ROOM_PASSWORD: "ifenvelse(`JITSI_ROOM_PASSWORD',)" JITSI_ROOM_PASSWORD: "ifenvelse(`JITSI_ROOM_PASSWORD',)"
JITSI_ROOM_NAME: "ifenvelse(`JITSI_ROOM_NAME',)" JITSI_ROOM_NAME: "ifenvelse(`JITSI_ROOM_NAME',)"
@ -101,11 +110,17 @@ x-pgnode-env: &default-pgnode-env
services: services:
proxy: proxy:
image: PROXY_IMAGE image: PROXY_IMAGE
environment:
INSTANCE_DOMAIN: "ifenvelse(`INSTANCE_DOMAIN', 127.0.0.1:443)"
`EXTERNAL_HTTP_PORT': "EXTERNAL_HTTP_PORT"
`EXTERNAL_HTTPS_PORT': "EXTERNAL_HTTPS_PORT"
ALLOWED_HOSTS: "ifenvelse(`ALLOWED_HOSTS',)"
networks: networks:
- front - front
- back - back
ports: ports:
- "0.0.0.0:ifenvelse(`EXTERNAL_HTTP_PORT', 8000):8000" ifelse(EXTERNAL_HTTP_PORT,,,- "127.0.0.1:EXTERNAL_HTTP_PORT:8000")
ifelse(EXTERNAL_HTTPS_PORT,,,- "127.0.0.1:EXTERNAL_HTTPS_PORT:8001")
deploy: deploy:
restart_policy: restart_policy:
condition: on-failure condition: on-failure

View File

@ -77,7 +77,9 @@ def get_config_variables():
# TODO: Use Django's URLValidator here. # TODO: Use Django's URLValidator here.
yield ConfigVariable( yield ConfigVariable(
name="users_pdf_url", name="users_pdf_url",
default_value=os.getenv("INSTANCE_DOMAIN", default="http://example.com:8000"), default_value=os.getenv("INSTANCE_URL_SCHEME", default="https")
+ "://"
+ os.getenv("INSTANCE_DOMAIN", default="127.0.0.1"),
label="System URL", label="System URL",
help_text="Used for QRCode in PDF of access data.", help_text="Used for QRCode in PDF of access data.",
weight=540, weight=540,