File: privileged.py

package info (click to toggle)
freedombox 26.3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 83,092 kB
  • sloc: python: 48,542; javascript: 1,730; xml: 481; makefile: 290; sh: 137; php: 32
file content (97 lines) | stat: -rw-r--r-- 2,726 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Configuration helper for Coturn daemon."""

import pathlib
import random
import shutil
import string

import augeas

from plinth import action_utils
from plinth.actions import privileged

CONFIG_FILE = pathlib.Path('/etc/coturn/freedombox.conf')


def _key_path(key):
    """Return the augeas path for a key."""
    return '/files' + str(CONFIG_FILE) + '/' + key


@privileged
def 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()

    aug = augeas_load()

    # 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.set(_key_path('listening-ip[1]'), '::')
    # Keep ::1 because at least two IP addresses of same class are needed for
    # enabling alternate port (port + 1). This is in turn needed for NAT
    # Behavior Discovery (RFC 5780).
    aug.set(_key_path('listening-ip[2]'), '::1')

    aug.save()

    action_utils.service_try_restart('coturn')


@privileged
def get_config() -> dict[str, str]:
    """Return the current configuration."""
    aug = augeas_load()
    config = {
        'static_auth_secret': aug.get(_key_path('static-auth-secret')),
        'realm': aug.get(_key_path('realm')),
    }
    return config


@privileged
def set_domain(domain_name: str):
    """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'), 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


@privileged
def uninstall():
    """Remove configuration file."""
    CONFIG_FILE.unlink(missing_ok=True)