shadowsocks: Move user settings to state directory

Fixes #1775

Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Joseph Nuthalapati 2020-02-26 21:44:42 +05:30 committed by James Valleroy
parent 0c1591324d
commit 50e5608331
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
4 changed files with 38 additions and 15 deletions

View File

@ -7,12 +7,15 @@ Helper script for configuring Shadowsocks.
import argparse import argparse
import json import json
import os import os
import subprocess
import sys import sys
from plinth import action_utils from plinth import action_utils
from plinth.modules import shadowsocks from plinth.modules import shadowsocks
SHADOWSOCKS_CONFIG = '/etc/shadowsocks-libev/freedombox.json' SHADOWSOCKS_CONFIG_SYMLINK = '/etc/shadowsocks-libev/freedombox.json'
SHADOWSOCKS_CONFIG_ACTUAL = \
'/var/lib/private/shadowsocks-libev/freedombox/freedombox.json'
def parse_arguments(): def parse_arguments():
@ -26,6 +29,11 @@ def parse_arguments():
subparsers.add_parser('merge-config', subparsers.add_parser('merge-config',
help='Merge JSON config from stdin with existing') help='Merge JSON config from stdin with existing')
# Migrations
subparsers.add_parser(
'migrate-1-2',
help='Move shadowsocks config file to a secure location')
subparsers.required = True subparsers.required = True
return parser.parse_args() return parser.parse_args()
@ -35,23 +43,25 @@ def subcommand_setup(_):
# Only client socks5 proxy is supported for now. Disable the # Only client socks5 proxy is supported for now. Disable the
# server component. # server component.
action_utils.service_disable('shadowsocks-libev') action_utils.service_disable('shadowsocks-libev')
if not os.path.islink(SHADOWSOCKS_CONFIG_SYMLINK):
os.symlink(SHADOWSOCKS_CONFIG_ACTUAL, SHADOWSOCKS_CONFIG_SYMLINK)
def subcommand_get_config(arguments): def subcommand_get_config(_):
"""Read and print Shadowsocks configuration.""" """Read and print Shadowsocks configuration."""
try: try:
print(open(SHADOWSOCKS_CONFIG, 'r').read()) print(open(SHADOWSOCKS_CONFIG_SYMLINK, 'r').read())
except Exception: except Exception:
sys.exit(1) sys.exit(1)
def subcommand_merge_config(arguments): def subcommand_merge_config(_):
"""Configure Shadowsocks.""" """Configure Shadowsocks."""
config = sys.stdin.read() config = sys.stdin.read()
config = json.loads(config) config = json.loads(config)
try: try:
current_config = open(SHADOWSOCKS_CONFIG, 'r').read() current_config = open(SHADOWSOCKS_CONFIG_SYMLINK, 'r').read()
current_config = json.loads(current_config) current_config = json.loads(current_config)
except (OSError, json.JSONDecodeError): except (OSError, json.JSONDecodeError):
current_config = {} current_config = {}
@ -59,16 +69,20 @@ def subcommand_merge_config(arguments):
new_config = current_config new_config = current_config
new_config.update(config) new_config.update(config)
new_config = json.dumps(new_config, indent=4, sort_keys=True) new_config = json.dumps(new_config, indent=4, sort_keys=True)
open(SHADOWSOCKS_CONFIG_SYMLINK, 'w').write(new_config)
# XXX: Config file with password is world-readable. This is the action_utils.service_restart(shadowsocks.managed_services[0])
# same as the default config file, but find a way to avoid this.
# See https://salsa.debian.org/freedombox-team/plinth/-/merge_requests/1724
old_umask = os.umask(0o022)
try:
open(SHADOWSOCKS_CONFIG, 'w').write(new_config)
finally:
os.umask(old_umask)
def subcommand_migrate_1_2(_):
"""Move shadowsocks config file to a secure location."""
if os.path.isfile(SHADOWSOCKS_CONFIG_SYMLINK): # ignoring symlinks
os.makedirs('/var/lib/private/shadowsocks-libev/freedombox/',
exist_ok=True)
os.replace(SHADOWSOCKS_CONFIG_SYMLINK, SHADOWSOCKS_CONFIG_ACTUAL)
os.symlink(SHADOWSOCKS_CONFIG_ACTUAL, SHADOWSOCKS_CONFIG_SYMLINK)
subprocess.check_call(['systemctl', 'daemon-reload'])
action_utils.service_restart(shadowsocks.managed_services[0]) action_utils.service_restart(shadowsocks.managed_services[0])

View File

@ -15,7 +15,7 @@ from plinth.utils import format_lazy
from .manifest import backup # noqa, pylint: disable=unused-import from .manifest import backup # noqa, pylint: disable=unused-import
version = 1 version = 2
managed_services = ['shadowsocks-libev-local@freedombox'] managed_services = ['shadowsocks-libev-local@freedombox']
@ -89,6 +89,11 @@ def init():
def setup(helper, old_version=None): def setup(helper, old_version=None):
"""Install and configure the module.""" """Install and configure the module."""
if old_version == 1:
helper.call('migration', actions.superuser_run, 'shadowsocks',
['migrate-1-2'])
helper.install(managed_packages) helper.install(managed_packages)
helper.call('post', actions.superuser_run, 'shadowsocks', ['setup']) helper.call('post', actions.superuser_run, 'shadowsocks', ['setup'])
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -0,0 +1,2 @@
[Service]
StateDirectory=shadowsocks-libev/%i

View File

@ -7,7 +7,9 @@ from plinth.modules.backups.api import validate as validate_backup
backup = validate_backup({ backup = validate_backup({
'secrets': { 'secrets': {
'files': ['/etc/shadowsocks-libev/freedombox.json'] 'files': [
'/var/lib/private/shadowsocks-libev/freedombox/freedombox.json'
]
}, },
'services': ['shadowsocks-libev-local@freedombox'] 'services': ['shadowsocks-libev-local@freedombox']
}) })