mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
- Shows URLs and shared secret that communication servers like matrix-synapse should be configured to. Later we will implement auto-configuring those servers. - Allow selecting domain for the sake of TLS/DTLS certificate installation. - Simplify systemd service file options. Drop log file and pid file support as they are not needed with systemd. Add security options. - Set custom configuration file by overriding systemd service file options so that we don't have a problem with conffile prompts. - Implement functional tests (and automatic diagnostics). - Custom icon selected from the Noun project as Coturn project does not have one. - Backup/restore configuration file and certificates. - Document some questions regarding configuration options. Tests performed: - App is not listed in the app page if 'advanced' flag is disabled. - App name, icon and short description shows up correctly in apps page. - App name, icon, short description, description, manual link, enable/disable button and diagnostics link show up currently in app page. - Verify that configuration used by coturn server is the FreedomBox configuration by checking the cert path in the log output. - PID file is not created in /var/run/turnserver/. It goes into /dev/null according to the log output. - No log file is created other than what is collected by systemd from command line. - systemctl show coturn.service shows all the intended restrictions such as NoNewPrivileges, Protect* options. - Run functional tests. - Ensure that backup of configuration file works by taking backup, changing the secret and restoring. During backup and restore coturn should be stopped and started as per logs. - Build Debian package. No warnings about the copyright file. - Enabling the app enables the service and runs it. - Disabling the app disables the service and stop it. - All diagnostics tests pass. - Diagnostic tests show firewall port coturn-freedombox for internal and external networks, service coturn, and each listening port for udp4, udp6, tcp4 and tcp6. - Information in the firewall page shows up properly. Enabling the app opens firewall ports, and disabling it closes them. - When the app is installed, if a cert domain is available, it will be used. When multiple domains are available, one of them is picked. - Status shows 4 URLs with the currently selected domain and secret key. - Changing domain to another domain succeeds and reflects in the status information. - When no domain is configured. Installing the app succeeds. No domain is shown in the list of domains. - When domain is changed, the certificates files in /etc/coturn/certs are overwritten. - Certificates have the ownership turnserver:turnserver. Public key is cert.pem has 644 permissions. Private is pkey.pem has 600 permissions. /etc/coturn/certs is owned by root:root. - Let's encrypt certificates are setup immediately after install. - Port forwarding information shows all ports except for relay ports. - Trying to create a user with username 'turnserver' throws an error. This happens even when coturn is not installed yet. - After installing coturn, the configuration file /etc/coturn/freedombox.conf is created with ownership root:turnserver and permissions 640. The directory /etc/coturn is created with ownership root:root and permissions 755. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> [jvalleroy: Fix copied form_valid comment] Signed-off-by: James Valleroy <jvalleroy@mailbox.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
117 lines
3.2 KiB
Python
Executable File
117 lines
3.2 KiB
Python
Executable File
#!/usr/bin/python3
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""
|
|
Configuration helper for Coturn daemon.
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
import pathlib
|
|
import random
|
|
import shutil
|
|
import string
|
|
|
|
import augeas
|
|
|
|
from plinth import action_utils
|
|
|
|
CONFIG_FILE = pathlib.Path('/etc/coturn/freedombox.conf')
|
|
|
|
|
|
def parse_arguments():
|
|
"""Return parsed command line arguments as dictionary."""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
|
|
|
subparsers.add_parser('setup', help='Setup Coturn server')
|
|
subparsers.add_parser('get-config',
|
|
help='Return the current configuration')
|
|
subparser = subparsers.add_parser('set-domain', help='Set the TLS domain')
|
|
subparser.add_argument('domain_name', help='TLS domain name to set')
|
|
|
|
subparsers.required = True
|
|
return parser.parse_args()
|
|
|
|
|
|
def _key_path(key):
|
|
"""Return the augeas path for a key."""
|
|
return '/files' + str(CONFIG_FILE) + '/' + key
|
|
|
|
|
|
def subcommand_setup(_):
|
|
"""Setup Coturn server."""
|
|
CONFIG_FILE.parent.mkdir(exist_ok=True)
|
|
if not CONFIG_FILE.exists():
|
|
CONFIG_FILE.touch(0o640)
|
|
shutil.chown(CONFIG_FILE, group='turnserver')
|
|
|
|
action_utils.service_daemon_reload()
|
|
action_utils.service_try_restart('coturn')
|
|
|
|
aug = augeas_load()
|
|
|
|
# XXX: Should we set listen, relay IP address to :: or dynamically
|
|
# XXX: Should we set external-ip
|
|
aug.set(_key_path('min-port'), '49152')
|
|
aug.set(_key_path('max-port'), '50175')
|
|
aug.set(_key_path('use-auth-secret'), 'true')
|
|
if not aug.get(_key_path('static-auth-secret')):
|
|
secret = ''.join(
|
|
random.choice(string.ascii_letters + string.digits)
|
|
for _ in range(64))
|
|
aug.set(_key_path('static-auth-secret'), secret)
|
|
|
|
aug.set(_key_path('cert'), '/etc/coturn/certs/cert.pem')
|
|
aug.set(_key_path('pkey'), '/etc/coturn/certs/pkey.pem')
|
|
aug.set(_key_path('no-tlsv1'), 'true')
|
|
aug.set(_key_path('no-tlsv1_1'), 'true')
|
|
aug.set(_key_path('no-cli'), 'true')
|
|
|
|
aug.save()
|
|
|
|
|
|
def subcommand_get_config(_):
|
|
"""Return the current configuration in JSON format."""
|
|
aug = augeas_load()
|
|
config = {
|
|
'static_auth_secret': aug.get(_key_path('static-auth-secret')),
|
|
'realm': aug.get(_key_path('realm')),
|
|
}
|
|
print(json.dumps(config))
|
|
|
|
|
|
def subcommand_set_domain(arguments):
|
|
"""Set the TLS domain.
|
|
|
|
This value is usually not stored. So, set realm value even though it is not
|
|
needed to set realm for REST API based authentication.
|
|
|
|
"""
|
|
aug = augeas_load()
|
|
aug.set(_key_path('realm'), arguments.domain_name)
|
|
aug.save()
|
|
|
|
|
|
def augeas_load():
|
|
"""Initialize Augeas."""
|
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
|
aug.set('/augeas/load/Simplevars/lens', 'Simplevars.lns')
|
|
aug.set('/augeas/load/Simplevars/incl[last() + 1]', str(CONFIG_FILE))
|
|
aug.load()
|
|
|
|
return aug
|
|
|
|
|
|
def main():
|
|
"""Parse arguments and perform all duties."""
|
|
arguments = parse_arguments()
|
|
|
|
subcommand = arguments.subcommand.replace('-', '_')
|
|
subcommand_method = globals()['subcommand_' + subcommand]
|
|
subcommand_method(arguments)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|