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
Setup Docker images
-------------------
Setup Docker Compose
--------------------
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
@ -64,11 +64,15 @@ Afterwards, generate the configuration file::
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``::
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::

View File

@ -1,4 +1,5 @@
import endpoint
import invalid_host*
reverse_proxy /system/* autoupdate:8002 {
flush_interval -1
@ -15,3 +16,5 @@ import endpoint
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 {
flush_interval -1
@server {
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
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
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
https://:8000 {
https://:8001 {
tls /certs/cert.pem /certs/key.pem
EOF
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 "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
exec "$@"

View File

@ -10,9 +10,40 @@
# 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=
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_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=
# 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(`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')
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
dnl ----------------------------------------
# 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_CHAT: "ifenvelse(`ENABLE_CHAT', 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_ROOM_PASSWORD: "ifenvelse(`JITSI_ROOM_PASSWORD',)"
JITSI_ROOM_NAME: "ifenvelse(`JITSI_ROOM_NAME',)"
@ -108,11 +117,17 @@ services:
- client
- autoupdate
- 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:
- front
- back
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:
<< : *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(`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')
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
dnl ----------------------------------------
# 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_CHAT: "ifenvelse(`ENABLE_CHAT', 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_ROOM_PASSWORD: "ifenvelse(`JITSI_ROOM_PASSWORD',)"
JITSI_ROOM_NAME: "ifenvelse(`JITSI_ROOM_NAME',)"
@ -101,11 +110,17 @@ x-pgnode-env: &default-pgnode-env
services:
proxy:
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:
- front
- back
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:
restart_policy:
condition: on-failure

View File

@ -77,7 +77,9 @@ def get_config_variables():
# TODO: Use Django's URLValidator here.
yield ConfigVariable(
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",
help_text="Used for QRCode in PDF of access data.",
weight=540,