mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
Rewrite plinth to use sudo and action scripts instead of exmachina for privileged accesss.
This commit is contained in:
parent
0954d9d383
commit
444365ec78
4
Makefile
4
Makefile
@ -29,9 +29,9 @@ install: default
|
||||
mkdir -p $(DESTDIR)$(PYDIR) $(DESTDIR)$(DATADIR) $(DESTDIR)/usr/bin \
|
||||
$(DESTDIR)/usr/share/doc/plinth $(DESTDIR)/usr/share/man/man1
|
||||
cp -a static themes $(DESTDIR)$(DATADIR)/
|
||||
cp -a actions $(DESTDIR)$(DATADIR)/
|
||||
cp -a sudoers.d $(DESTDIR)/etc/sudoers.d
|
||||
cp -a *.py modules templates $(DESTDIR)$(PYDIR)/
|
||||
mkdir -p $(DESTDIR)$(PYDIR)/exmachina
|
||||
cp -a vendor/exmachina/exmachina.py $(DESTDIR)$(PYDIR)/exmachina/.
|
||||
cp share/init.d/plinth $(DESTDIR)/etc/init.d
|
||||
install plinth $(DESTDIR)/usr/bin/
|
||||
mkdir -p $(DESTDIR)/var/lib/plinth/cherrypy_sessions $(DESTDIR)/var/log/plinth $(DESTDIR)/var/run
|
||||
|
||||
3
README
3
README
@ -43,9 +43,6 @@ get down into the details and configure things the average user never
|
||||
thinks about. For example, experts can turn off ntp or switch ntp
|
||||
servers. Basic users should never even know those options exist.
|
||||
|
||||
See comments in exmachina/exmachina.py for more details about the
|
||||
configuration management process seperation scheme.
|
||||
|
||||
## Getting Started
|
||||
|
||||
See the INSTALL file for additional details. Run:
|
||||
|
||||
10
actions/hostname-change
Executable file
10
actions/hostname-change
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
hostname="$1"
|
||||
|
||||
echo "$hostname" > /etc/hostname
|
||||
if [ -x /etc/init.d/hostname.sh ] ; then
|
||||
service hostname.sh start
|
||||
else
|
||||
service hostname start
|
||||
fi
|
||||
14
actions/timezone-change
Executable file
14
actions/timezone-change
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
zonename="$1"
|
||||
|
||||
tzpath="/usr/share/zoneinfo/$zonename"
|
||||
|
||||
if [ -e "$tzpath" ] ; then
|
||||
cp "$tzpath" /etc/localtime
|
||||
echo "$zonename" > /etc/timezone
|
||||
exit 0
|
||||
else
|
||||
echo "timezone not valid" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
@ -9,6 +9,7 @@ from gettext import gettext as _
|
||||
from filedict import FileDict
|
||||
from modules.auth import require
|
||||
from plugin_mount import PagePlugin, FormPlugin
|
||||
from privilegedactions import privilegedaction_run
|
||||
import cfg
|
||||
from forms import Form
|
||||
from model import User
|
||||
@ -48,20 +49,14 @@ def get_hostname():
|
||||
|
||||
def set_hostname(hostname):
|
||||
"Sets machine hostname to hostname"
|
||||
cfg.log.info("Writing '%s' to /etc/hostname with exmachina" % hostname)
|
||||
|
||||
cfg.log.info("Changing hostname to '%s'" % hostname)
|
||||
try:
|
||||
cfg.exmachina.augeas.set("/files/etc/hostname/*", hostname)
|
||||
cfg.exmachina.augeas.save()
|
||||
privilegedaction_run("hostname-change", [hostname])
|
||||
# don't persist/cache change unless it was saved successfuly
|
||||
sys_store = filedict_con(cfg.store_file, 'sys')
|
||||
sys_store['hostname'] = hostname
|
||||
if platform.linux_distribution()[0]=="Ubuntu" :
|
||||
cfg.exmachina.service.start("hostname")
|
||||
else:
|
||||
cfg.exmachina.initd.start("hostname.sh") # is hostname.sh debian-only?
|
||||
except OSError, e:
|
||||
raise cherrypy.HTTPError(500, "Hostname restart failed: %s" % e)
|
||||
raise cherrypy.HTTPError(500, "Updating hostname failed: %s" % e)
|
||||
|
||||
class general(FormPlugin, PagePlugin):
|
||||
url = ["/sys/config"]
|
||||
@ -79,7 +74,7 @@ class general(FormPlugin, PagePlugin):
|
||||
return '<p>' + _('Only members of the expert group are allowed to see and modify the system setup.') + '</p>'
|
||||
|
||||
sys_store = filedict_con(cfg.store_file, 'sys')
|
||||
hostname = cfg.exmachina.augeas.get("/files/etc/hostname/*")
|
||||
hostname = get_hostname()
|
||||
# this layer of persisting configuration in sys_store could/should be
|
||||
# removed -BLN
|
||||
defaults = {'time_zone': "slurp('/etc/timezone').rstrip()",
|
||||
@ -139,10 +134,10 @@ class general(FormPlugin, PagePlugin):
|
||||
raise
|
||||
else:
|
||||
message += msg
|
||||
time_zone = time_zone.strip()
|
||||
if time_zone != sys_store['time_zone']:
|
||||
src = os.path.join("/usr/share/zoneinfo", time_zone)
|
||||
cfg.log.info("Setting timezone to %s" % time_zone)
|
||||
cfg.exmachina.misc.set_timezone(time_zone)
|
||||
privilegedaction_run("timezone-change", [time_zone])
|
||||
sys_store['time_zone'] = time_zone
|
||||
return message or "Settings updated."
|
||||
|
||||
|
||||
23
plinth.py
23
plinth.py
@ -18,7 +18,6 @@ from logger import Logger
|
||||
#from modules.auth import AuthController, require, member_of, name_is
|
||||
|
||||
from withsqlite.withsqlite import sqlite_db
|
||||
from exmachina.exmachina import ExMachinaClient
|
||||
import socket
|
||||
|
||||
__version__ = "0.2.14"
|
||||
@ -84,8 +83,6 @@ def parse_arguments():
|
||||
parser = argparse.ArgumentParser(description='Plinth web interface for the FreedomBox.')
|
||||
parser.add_argument('--pidfile', default="",
|
||||
help='specify a file in which the server may write its pid')
|
||||
parser.add_argument('--listen-exmachina-key', default=False, action='store_true',
|
||||
help='listen for JSON-RPC shared secret key on stdin at startup')
|
||||
args=parser.parse_args()
|
||||
if args.pidfile:
|
||||
cfg.pidfile = args.pidfile
|
||||
@ -96,13 +93,6 @@ def parse_arguments():
|
||||
except AttributeError:
|
||||
cfg.pidfile = "plinth.pid"
|
||||
|
||||
if args.listen_exmachina_key:
|
||||
# this is where we optionally try to read in a shared secret key to
|
||||
# authenticate connections to exmachina
|
||||
cfg.exmachina_secret_key = sys.stdin.readline().strip()
|
||||
else:
|
||||
cfg.exmachina_secret_key = None
|
||||
|
||||
def setup():
|
||||
parse_arguments()
|
||||
|
||||
@ -113,19 +103,6 @@ def setup():
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
from vendor.exmachina.exmachina import ExMachinaClient
|
||||
except ImportError:
|
||||
cfg.exmachina = None
|
||||
print "unable to import exmachina client library, but continuing anyways..."
|
||||
else:
|
||||
try:
|
||||
cfg.exmachina = ExMachinaClient(
|
||||
secret_key=cfg.exmachina_secret_key or None)
|
||||
except socket.error:
|
||||
cfg.exmachina = None
|
||||
print "couldn't connect to exmachina daemon, but continuing anyways..."
|
||||
|
||||
os.chdir(cfg.python_root)
|
||||
cherrypy.config.update({'error_page.404': error_page_404})
|
||||
cherrypy.config.update({'error_page.500': error_page_500})
|
||||
|
||||
15
privilegedactions.py
Normal file
15
privilegedactions.py
Normal file
@ -0,0 +1,15 @@
|
||||
import sys
|
||||
import subprocess
|
||||
import cfg
|
||||
|
||||
def privilegedaction_run(action, options):
|
||||
cmd = ['sudo', '-n', "/usr/share/plinth/actions/%s" % action]
|
||||
if options:
|
||||
cmd.extend(options)
|
||||
cfg.log.info('running: %s ' % ' '.join(cmd))
|
||||
|
||||
output, error = \
|
||||
subprocess.Popen(cmd,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr= subprocess.PIPE).communicate()
|
||||
return output, error
|
||||
@ -7,21 +7,17 @@
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: plinth web frontend
|
||||
# Description:
|
||||
# Control the exmachina privileged execution daemon and the plinth
|
||||
# web frontend.
|
||||
# Control the plinth web frontend.
|
||||
### END INIT INFO
|
||||
|
||||
# This file is /etc/init.d/plinth
|
||||
DAEMON=/usr/local/bin/plinth.py
|
||||
EXMACHINA_DAEMON=/usr/local/bin/exmachina.py
|
||||
PID_FILE=/var/run/plinth.pid
|
||||
EXMACHINA_PID_FILE=/var/run/exmachina.pid
|
||||
|
||||
PLINTH_USER=www-data
|
||||
PLINTH_GROUP=www-data
|
||||
|
||||
test -x $DAEMON || exit 0
|
||||
test -x $EXMACHINA_DAEMON || exit 0
|
||||
|
||||
set -e
|
||||
|
||||
@ -31,17 +27,9 @@ start_plinth (){
|
||||
if [ -f $PID_FILE ]; then
|
||||
echo Already running with a pid of `cat $PID_FILE`.
|
||||
else
|
||||
if [ -f $EXMACHINA_PID_FILE ]; then
|
||||
echo exmachina was already running with a pid of `cat $EXMACHINA_PID_FILE`.
|
||||
kill -15 `cat $EXMACHINA_PID_FILE`
|
||||
rm -rf $EXMACHINA_PID_FILE
|
||||
fi
|
||||
SHAREDKEY=`$EXMACHINA_DAEMON --random-key`
|
||||
touch $PID_FILE
|
||||
chown $PLINTH_USER:$PLINTH_GROUP $PID_FILE
|
||||
echo $SHAREDKEY | $EXMACHINA_DAEMON --pidfile=$EXMACHINA_PID_FILE --group=$PLINTH_GROUP || rm $PID_FILE
|
||||
sleep 0.5
|
||||
echo $SHAREDKEY | sudo -u $PLINTH_USER -g $PLINTH_GROUP $DAEMON --pidfile=$PID_FILE
|
||||
sudo -u $PLINTH_USER -g $PLINTH_GROUP $DAEMON --pidfile=$PID_FILE
|
||||
fi
|
||||
}
|
||||
|
||||
@ -53,13 +41,6 @@ stop_plinth () {
|
||||
else
|
||||
echo "No pid file at $PID_FILE suggests plinth is not running."
|
||||
fi
|
||||
if [ -f $EXMACHINA_PID_FILE ]; then
|
||||
kill -15 `cat $EXMACHINA_PID_FILE` || true
|
||||
rm -rf $EXMACHINA_PID_FILE
|
||||
echo "killed exmachina"
|
||||
else
|
||||
echo "No pid file at $EXMACHINA_PID_FILE suggests exmachina is not running."
|
||||
fi
|
||||
}
|
||||
|
||||
test -x $DAEMON || exit 0
|
||||
|
||||
5
start.sh
5
start.sh
@ -1,10 +1,7 @@
|
||||
#! /bin/sh
|
||||
|
||||
#PYTHONPATH=vendor/exmachina:$PYTHONPATH
|
||||
#PYTHONPATH=$PYTHONPATH
|
||||
|
||||
export PYTHONPATH
|
||||
|
||||
sudo killall exmachina.py
|
||||
sudo vendor/exmachina/exmachina.py -v &
|
||||
python plinth.py
|
||||
sudo killall exmachina.py
|
||||
|
||||
1
sudoers.d/plinth
Normal file
1
sudoers.d/plinth
Normal file
@ -0,0 +1 @@
|
||||
plinth ALL=(ALL:ALL) NOPASSWD:/usr/share/plinth/actions/*
|
||||
Loading…
x
Reference in New Issue
Block a user