mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
Merge: Sunil's firewall branch.
This commit is contained in:
commit
9350052e59
3
Makefile
3
Makefile
@ -17,7 +17,7 @@ default: config dirs template css docs
|
||||
all: default
|
||||
|
||||
predepend:
|
||||
sudo sh -c "apt-get install augeas-tools libpython2.7 pandoc psmisc python2.7 python-augeas python-passlib python-bcrypt python-bjsonrpc python-cheetah python-cherrypy3 python-simplejson sudo"
|
||||
sudo sh -c "apt-get install augeas-tools libpython2.7 pandoc psmisc python2.7 python-augeas python-bcrypt python-bjsonrpc python-cheetah python-cherrypy3 python-django python-passlib python-simplejson sudo"
|
||||
git submodule init
|
||||
git submodule update
|
||||
touch predepend
|
||||
@ -32,6 +32,7 @@ install: default apache-install freedombox-setup-install
|
||||
cp -a sudoers.d $(DESTDIR)/etc/sudoers.d
|
||||
cp -a *.py modules templates $(DESTDIR)$(PYDIR)/
|
||||
cp share/init.d/plinth $(DESTDIR)/etc/init.d
|
||||
cp -a lib/* $(DESTDIR)/usr/lib
|
||||
install plinth $(DESTDIR)/usr/bin/
|
||||
mkdir -p $(DESTDIR)/var/lib/plinth/cherrypy_sessions $(DESTDIR)/var/log/plinth $(DESTDIR)/var/run
|
||||
mkdir -p $(DESTDIR)/var/lib/plinth/data
|
||||
|
||||
96
actions/firewall
Executable file
96
actions/firewall
Executable file
@ -0,0 +1,96 @@
|
||||
#!/usr/bin/python
|
||||
# -*- mode: python -*-
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
"""
|
||||
Configuration helper for Plinth firewall inteface
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
"""Return parsed command line arguments as dictionary"""
|
||||
parser = argparse.ArgumentParser()
|
||||
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
||||
|
||||
# Get installed status
|
||||
subparsers.add_parser('get-installed',
|
||||
help='Get whether firewalld is installed')
|
||||
|
||||
# Get status
|
||||
subparsers.add_parser('get-status', help='Get whether firewalld is running')
|
||||
|
||||
# Get service status
|
||||
subparsers.add_parser('get-enabled-services', help='Get list of enabled services')
|
||||
|
||||
# Add a service
|
||||
add_service = subparsers.add_parser('add-service', help='Add a service')
|
||||
add_service.add_argument('service', help='Name of the service to add')
|
||||
|
||||
# Remove a service status
|
||||
remove_service = subparsers.add_parser('remove-service', help='Remove a service')
|
||||
remove_service.add_argument('service', help='Name of the service to remove')
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def subcommand_get_installed(_):
|
||||
"""Print whether firewalld is installed"""
|
||||
with open('/dev/null', 'w') as file_handle:
|
||||
status = subprocess.call(['which', 'firewalld'], stdout=file_handle)
|
||||
|
||||
print 'installed' if not status else 'not installed'
|
||||
|
||||
|
||||
def subcommand_get_status(_):
|
||||
"""Print status of the firewalld service"""
|
||||
subprocess.call(['firewall-cmd', '--state'])
|
||||
|
||||
|
||||
def subcommand_get_enabled_services(_):
|
||||
"""Print the status of variours services"""
|
||||
subprocess.call(['firewall-cmd', '--list-services'])
|
||||
|
||||
|
||||
def subcommand_add_service(arguments):
|
||||
"""Permit a service in the firewall"""
|
||||
subprocess.call(['firewall-cmd', '--add-service', arguments.service])
|
||||
subprocess.call(['firewall-cmd', '--permanent', '--add-service', arguments.service])
|
||||
|
||||
|
||||
def subcommand_remove_service(arguments):
|
||||
"""Block a service in the firewall"""
|
||||
subprocess.call(['firewall-cmd', '--remove-service', arguments.service])
|
||||
subprocess.call(['firewall-cmd', '--permanent', '--remove-service', arguments.service])
|
||||
|
||||
|
||||
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()
|
||||
6
lib/firewalld/services/xmpp-bosh.xml
Normal file
6
lib/firewalld/services/xmpp-bosh.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<service>
|
||||
<short>XMPP (Jabber) web client</short>
|
||||
<description>Extensible Messaging and Presence Protocol (XMPP) web client protocol allows web based chat clients such as JWChat to connect to the XMPP (Jabber) server. This is also know as the Bidirectional-streams Over Synchronous HTTP (BOSH) protocol. Enable this if you run an XMPP (Jabber) server and you wish web clients to connect to your server.</description>
|
||||
<port protocol="tcp" port="5280"/>
|
||||
</service>
|
||||
6
lib/firewalld/services/xmpp-client.xml
Normal file
6
lib/firewalld/services/xmpp-client.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<service>
|
||||
<short>XMPP (Jabber) client</short>
|
||||
<description>Extensible Messaging and Presence Protocol (XMPP) client connection protocol allows XMPP (Jabber) clients such as Empathy, Pidgin, Kopete and Jitsi to connect to an XMPP (Jabber) server. Enable this if you run an XMPP (Jabber) server and you wish clients to be able to connect to the server and communicate with each other.</description>
|
||||
<port protocol="tcp" port="5222"/>
|
||||
</service>
|
||||
6
lib/firewalld/services/xmpp-server.xml
Normal file
6
lib/firewalld/services/xmpp-server.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<service>
|
||||
<short>XMPP (Jabber) server</short>
|
||||
<description>Extensible Messaging and Presence Protocol (XMPP) server connection protocols allows multiple XMPP (Jabber) servers to work in a fedrated fashion. Users on one server will be able to see the presence of and communicate with users on another servers. Enable this if you run an XMPP (Jabber) server and you wish users on your server to communicate with users on other XMPP servers.</description>
|
||||
<port protocol="tcp" port="5269"/>
|
||||
</service>
|
||||
48
lib/freedombox/first-run.d/90_firewall
Executable file
48
lib/freedombox/first-run.d/90_firewall
Executable file
@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Setup firewall rules for all the enabled services
|
||||
|
||||
# Ideally all non essential services are enabled from Plinth
|
||||
# which automatically takes care of enabling appropirate firewall
|
||||
# ports. This file is used then for essential services and services
|
||||
# that are not yet configurable from Plinth.
|
||||
|
||||
# HTTP (JWChat, ownCloud)
|
||||
firewall-cmd --permanent --add-service=http
|
||||
|
||||
# HTTPS (Plinth, JWChat, ownCloud)
|
||||
firewall-cmd --permanent --add-service=https
|
||||
|
||||
# Tor
|
||||
firewall-cmd --permanent --add-port=9050/tcp
|
||||
|
||||
# NTP
|
||||
firewall-cmd --permanent --add-service=ntp
|
||||
|
||||
# DNS
|
||||
firewall-cmd --permanent --add-service=dns
|
||||
|
||||
# mDNS
|
||||
firewall-cmd --permanent --add-service=mdns
|
||||
|
||||
# DHCP
|
||||
firewall-cmd --permanent --add-service=dhcp
|
||||
|
||||
# Bootp Server and Client (not enabled)
|
||||
#firewall-cmd --permanent --add-port=67/tcp
|
||||
#firewall-cmd --permanent --add-port=67/udp
|
||||
#firewall-cmd --permanent --add-port=68/tcp
|
||||
#firewall-cmd --permanent --add-port=68/udp
|
||||
|
||||
# LDAP (not enabled)
|
||||
#firewall-cmd --permanent --add-service=ldap
|
||||
#firewall-cmd --permanent --add-service=ldaps
|
||||
|
||||
# OpenVPN (not enabled)
|
||||
#firewall-cmd --permanent --add-service=openvpn
|
||||
|
||||
# Privoxy
|
||||
firewall-cmd --permanent --add-port=8118/tcp
|
||||
|
||||
# Obfsproxy
|
||||
firewall-cmd --permanent --add-port=40202/tcp
|
||||
1
modules/firewall.py
Symbolic link
1
modules/firewall.py
Symbolic link
@ -0,0 +1 @@
|
||||
installed/system/firewall.py
|
||||
@ -5,6 +5,7 @@ from plugin_mount import PagePlugin, FormPlugin
|
||||
from forms import Form
|
||||
import actions
|
||||
import cfg
|
||||
import service
|
||||
from util import Message
|
||||
|
||||
class Owncloud(PagePlugin, FormPlugin):
|
||||
@ -15,13 +16,22 @@ class Owncloud(PagePlugin, FormPlugin):
|
||||
self.register_page("apps.owncloud")
|
||||
cfg.html_root.apps.menu.add_item("Owncloud", "icon-picture", "/apps/owncloud", 35)
|
||||
|
||||
self.service = service.Service('owncloud', _('ownCloud'),
|
||||
['http', 'https'],
|
||||
enabled=self.is_enabled)
|
||||
|
||||
def is_enabled(self):
|
||||
"""Return whether ownCloud is enabled"""
|
||||
output, error = actions.run('owncloud-setup', 'status')
|
||||
if error:
|
||||
raise Exception('Error getting ownCloud status: %s' % error)
|
||||
|
||||
return 'enable' in output.split()
|
||||
|
||||
@cherrypy.expose
|
||||
@require()
|
||||
def index(self, **kwargs):
|
||||
output, error = actions.run("owncloud-setup", 'status')
|
||||
if error:
|
||||
raise Exception("something is wrong: " + error)
|
||||
owncloud_enable = "enable" in output.split()
|
||||
owncloud_enable = self.is_enabled()
|
||||
|
||||
if 'submitted' in kwargs:
|
||||
owncloud_enable = self.process_form(kwargs)
|
||||
@ -65,4 +75,8 @@ class Owncloud(PagePlugin, FormPlugin):
|
||||
opts.append('no'+key)
|
||||
actions.superuser_run("owncloud-setup", opts, async=True)
|
||||
|
||||
# Send a signal to other modules that the service is
|
||||
# enabled/disabled
|
||||
self.service.notify_enabled(self, checkedinfo['enable'])
|
||||
|
||||
return checkedinfo['enable']
|
||||
|
||||
@ -41,7 +41,7 @@ class PageKite(PagePlugin):
|
||||
self.register_page("router.setup.pagekite")
|
||||
self.register_page("router.setup.pagekite.configure")
|
||||
cfg.html_root.router.setup.menu.add_item(
|
||||
"Public Visibility (PageKite)", "icon-flag",
|
||||
_("Public Visibility (PageKite)"), "icon-flag",
|
||||
"/router/setup/pagekite", 50)
|
||||
|
||||
@cherrypy.expose
|
||||
@ -51,15 +51,15 @@ class PageKite(PagePlugin):
|
||||
del kwargs # Unused
|
||||
|
||||
main = _("""
|
||||
<p>PageKite is a system for exposing FreedomBox services when you
|
||||
<p>PageKite is a system for exposing {box_name} services when you
|
||||
don't have a direct connection to the Internet. You only need this
|
||||
service if your FreedomBox services are unreachable from the rest of
|
||||
service if your {box_name} services are unreachable from the rest of
|
||||
the Internet. This includes the following situations: </p>
|
||||
|
||||
<ul>
|
||||
<li>FreedomBox is behind a restricted firewall.</li>
|
||||
<li>{box_name} is behind a restricted firewall.</li>
|
||||
|
||||
<li>FreedomBox is connected to a (wireless) router which you don't
|
||||
<li>{box_name} is connected to a (wireless) router which you don't
|
||||
control.</li>
|
||||
|
||||
<li>Your ISP does not provide you an external IP address and instead
|
||||
@ -76,20 +76,20 @@ using a combination of tunnels and reverse proxies. Currently,
|
||||
exposing web server and SSH server are supported. An intermediary
|
||||
server with direct Internet access is required. Currently, only
|
||||
pagekite.net server is supported and you will need an account
|
||||
there. In future, it might be possible to use your buddy's FreedomBox
|
||||
there. In future, it might be possible to use your buddy's {box_name}
|
||||
for this.</p>
|
||||
|
||||
<p><a class='btn btn-primary btn-lg'
|
||||
href="{server_dir}/router/setup/pagekite/configure">Configure
|
||||
PageKite</a></p>
|
||||
""".format(server_dir=cfg.server_dir))
|
||||
""").format(box_name=cfg.box_name, server_dir=cfg.server_dir)
|
||||
|
||||
sidebar_right = _('''
|
||||
<strong>PageKite</strong>
|
||||
<p><a href="{server_dir}/router/setup/pagekite/configure">Configure
|
||||
PageKite</a> </p>'''.format(server_dir=cfg.server_dir))
|
||||
PageKite</a> </p>''').format(server_dir=cfg.server_dir)
|
||||
|
||||
return self.fill_template(title="Public Visibility (PageKite)",
|
||||
return self.fill_template(title=_("Public Visibility (PageKite)"),
|
||||
main=main, sidebar_right=sidebar_right)
|
||||
|
||||
|
||||
@ -157,9 +157,9 @@ $('#pagekite-enable').change(function() {
|
||||
if not status:
|
||||
return _('''
|
||||
<p>PageKite is not installed, please install it. PageKite comes
|
||||
pre-installed with FreedomBox. On any Debian based system (such as
|
||||
FreedomBox) you may install it using the command 'aptitude install
|
||||
pagekite'</p>''')
|
||||
pre-installed with {box_name}. On any Debian based system (such as
|
||||
{box_name}) you may install it using the command 'aptitude install
|
||||
pagekite'</p>''').format(box_name=cfg.box_name)
|
||||
|
||||
try:
|
||||
message = kwargs['message'].text
|
||||
|
||||
@ -5,6 +5,7 @@ from plugin_mount import PagePlugin, FormPlugin
|
||||
import cfg
|
||||
from forms import Form
|
||||
import actions
|
||||
import service
|
||||
from util import Message
|
||||
|
||||
class xmpp(PagePlugin):
|
||||
@ -15,6 +16,24 @@ class xmpp(PagePlugin):
|
||||
self.register_page("services.xmpp.register")
|
||||
cfg.html_root.services.menu.add_item("XMPP", "icon-comment", "/services/xmpp", 40)
|
||||
|
||||
self.client_service = service.Service(
|
||||
'xmpp-client', _('Chat Server - client connections'), enabled=True)
|
||||
self.server_service = service.Service(
|
||||
'xmpp-server', _('Chat Server - server connections'), enabled=True)
|
||||
self.bosh_service = service.Service(
|
||||
'xmpp-bosh', _('Chat Server - web interface'), enabled=True)
|
||||
|
||||
# XXX: This is not correct. This essentially triggers firewall
|
||||
# to enable XMPP ports. This happen on every start of
|
||||
# Plinth. XMPP should be an option to be enabled on Plinth. If
|
||||
# and when the user enables the following notifications must
|
||||
# sent. If XMPP has be on by default in FreedomBox, then
|
||||
# initial setup process that sets up XMPP also must open the
|
||||
# firewall ports by default.
|
||||
self.client_service.notify_enabled(self, enabled=True)
|
||||
self.server_service.notify_enabled(self, enabled=True)
|
||||
self.bosh_service.notify_enabled(self, enabled=True)
|
||||
|
||||
@cherrypy.expose
|
||||
@require()
|
||||
def index(self, **kwargs):
|
||||
|
||||
191
modules/installed/system/firewall.py
Normal file
191
modules/installed/system/firewall.py
Normal file
@ -0,0 +1,191 @@
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
"""
|
||||
Plinth module to configure a firewall
|
||||
"""
|
||||
|
||||
import cherrypy
|
||||
from gettext import gettext as _
|
||||
|
||||
import actions
|
||||
import cfg
|
||||
from modules.auth import require
|
||||
from plugin_mount import PagePlugin
|
||||
import service as service_module
|
||||
|
||||
|
||||
class Firewall(PagePlugin):
|
||||
"""Firewall menu entry and introduction page"""
|
||||
order = 40
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
PagePlugin.__init__(self, *args, **kwargs)
|
||||
|
||||
self.register_page('sys.firewall')
|
||||
cfg.html_root.sys.menu.add_item(_('Firewall'), 'icon-flag',
|
||||
'/sys/firewall', 50)
|
||||
|
||||
service_module.ENABLED.connect(self.on_service_enabled)
|
||||
|
||||
@cherrypy.expose
|
||||
@require()
|
||||
def index(self, **kwargs):
|
||||
"""Serve introcution page"""
|
||||
del kwargs # Unused
|
||||
|
||||
# XXX: Use templates here instead of generating HTML
|
||||
main = _('''
|
||||
<p>Firewall is a network security system that controls the incoming
|
||||
and outgoing network traffic on your {box_name}. Keeping a firewall
|
||||
enabled and properly configured reduces risk of security threat from
|
||||
the Internet.</p>
|
||||
|
||||
<p>The following the current status:</p>
|
||||
''').format(box_name=cfg.box_name)
|
||||
|
||||
if not self.get_installed_status():
|
||||
status = _('''
|
||||
<p>Firewall is not installed. Please install it. Firewall comes
|
||||
pre-installed with {box_name}. On any Debian based system (such as
|
||||
{box_name}) you may install it using the command 'aptitude install
|
||||
firewalld'</p>''').format(box_name=cfg.box_name)
|
||||
|
||||
return self.fill_template(title=_("Firewall"), main=main + status)
|
||||
|
||||
if not self.get_enabled_status():
|
||||
status = _('''
|
||||
<p>Firewall daemon is not running. Please run it. Firewall comes
|
||||
enabled by default on {box_name}. On any Debian based system (such as
|
||||
{box_name}) you may run it using the command 'service firewalld start'
|
||||
or in case of system with systemd 'systemctl start firewalld'</p>
|
||||
''').format(box_name=cfg.box_name)
|
||||
|
||||
return self.fill_template(title=_("Firewall"), main=main + status)
|
||||
|
||||
enabled_services = self.get_enabled_services()
|
||||
services_info = '<ul>'
|
||||
for service in service_module.SERVICES.values():
|
||||
if service.is_enabled():
|
||||
service_text = _('Enabled')
|
||||
service_class = 'firewall-permitted'
|
||||
else:
|
||||
service_text = _('Disabled')
|
||||
service_class = 'firewall-blocked'
|
||||
|
||||
port_info = []
|
||||
for port in service.ports:
|
||||
if port in enabled_services:
|
||||
text = _('Permitted')
|
||||
css_class = 'firewall-permitted'
|
||||
else:
|
||||
text = _('Blocked')
|
||||
css_class = 'firewall-blocked'
|
||||
|
||||
info = _('''
|
||||
<li>{port}: <span class={css_class}>{text}</span></li>
|
||||
''').format(port=port, css_class=css_class, text=text)
|
||||
port_info.append(info)
|
||||
|
||||
port_info = '<ul>{port_info}</ul>'.format(
|
||||
port_info=''.join(port_info))
|
||||
|
||||
services_info += _('''
|
||||
<li>
|
||||
{name}: <span class={service_class}>{service_text}</span>
|
||||
{port_info}
|
||||
</li>
|
||||
''').format(
|
||||
name=service.name, service_class=service_class,
|
||||
service_text=service_text, port_info=port_info)
|
||||
|
||||
services_info += '</ul>'
|
||||
|
||||
footnote = '''
|
||||
<p><em>The operation of the firewall is automatic. When you enable a
|
||||
service it is automatically permitted in the firewall and you disable
|
||||
a service is automatically disabled in the firewall.</em></p>'''
|
||||
|
||||
return self.fill_template(title=_("Firewall"), main=main +
|
||||
services_info + footnote)
|
||||
|
||||
def get_installed_status(self):
|
||||
"""Return whether firewall is installed"""
|
||||
output = self._run(['get-installed'])
|
||||
return output.split()[0] == 'installed'
|
||||
|
||||
def get_enabled_status(self):
|
||||
"""Return whether firewall is installed"""
|
||||
output = self._run(['get-status'])
|
||||
return output.split()[0] == 'running'
|
||||
|
||||
def get_enabled_services(self):
|
||||
"""Return the status of various services currently enabled"""
|
||||
output = self._run(['get-enabled-services'])
|
||||
return output.split()
|
||||
|
||||
def add_service(self, port):
|
||||
"""Enable a service in firewall"""
|
||||
self._run(['add-service', port])
|
||||
|
||||
def remove_service(self, port):
|
||||
"""Remove a service in firewall"""
|
||||
self._run(['remove-service', port])
|
||||
|
||||
def on_service_enabled(self, sender, service_id, enabled, **kwargs):
|
||||
"""
|
||||
Enable/disable firewall ports when a service is
|
||||
enabled/disabled.
|
||||
"""
|
||||
del sender # Unused
|
||||
del kwargs # Unused
|
||||
|
||||
enabled_services = self.get_enabled_services()
|
||||
|
||||
cfg.log.info('Service enabled - %s, %s' % (service_id, enabled))
|
||||
for port in service_module.SERVICES[service_id].ports:
|
||||
if enabled:
|
||||
if port not in enabled_services:
|
||||
self.add_service(port)
|
||||
else:
|
||||
if port in enabled_services:
|
||||
enabled_services_on_port = [
|
||||
service_.is_enabled()
|
||||
for service_ in service_module.SERVICES.values()
|
||||
if port in service_.ports and
|
||||
service_id != service_.service_id]
|
||||
if not any(enabled_services_on_port):
|
||||
self.remove_service(port)
|
||||
|
||||
@staticmethod
|
||||
def _run(arguments, superuser=True):
|
||||
"""Run an given command and raise exception if there was an error"""
|
||||
command = 'firewall'
|
||||
|
||||
cfg.log.info('Running command - %s, %s, %s' % (command, arguments,
|
||||
superuser))
|
||||
|
||||
if superuser:
|
||||
output, error = actions.superuser_run(command, arguments)
|
||||
else:
|
||||
output, error = actions.run(command, arguments)
|
||||
|
||||
if error:
|
||||
raise Exception('Error setting/getting firewalld confguration - %s'
|
||||
% error)
|
||||
|
||||
return output
|
||||
@ -12,6 +12,7 @@ from cherrypy.process.plugins import Daemonizer
|
||||
Daemonizer(cherrypy.engine).subscribe()
|
||||
|
||||
import plugin_mount
|
||||
import service
|
||||
import util as u
|
||||
|
||||
from logger import Logger
|
||||
@ -177,6 +178,9 @@ def setup():
|
||||
cherrypy.engine.signal_handler.subscribe()
|
||||
|
||||
def main():
|
||||
# Initialize basic services
|
||||
service.init()
|
||||
|
||||
setup()
|
||||
|
||||
cherrypy.engine.start()
|
||||
|
||||
73
service.py
Normal file
73
service.py
Normal file
@ -0,0 +1,73 @@
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
"""
|
||||
Framework for working with servers and theirs services
|
||||
"""
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
import django.dispatch
|
||||
|
||||
ENABLED = django.dispatch.Signal(providing_args=['service_id', 'enabled'])
|
||||
|
||||
SERVICES = {}
|
||||
|
||||
|
||||
class Service(object):
|
||||
"""
|
||||
Representation of an application service provided by the machine
|
||||
containing information such as current status and ports required
|
||||
for operation.
|
||||
"""
|
||||
|
||||
def __init__(self, service_id, name, ports=None, enabled=True):
|
||||
if not ports:
|
||||
ports = [service_id]
|
||||
|
||||
self.service_id = service_id
|
||||
self.name = name
|
||||
self.ports = ports
|
||||
self._enabled = enabled
|
||||
|
||||
# Maintain a complete list of services
|
||||
SERVICES[service_id] = self
|
||||
|
||||
def is_enabled(self):
|
||||
"""Return whether the service is enabled"""
|
||||
if callable(self._enabled):
|
||||
return self._enabled()
|
||||
|
||||
return self._enabled
|
||||
|
||||
def notify_enabled(self, sender, enabled):
|
||||
"""Notify observers about change in state of service"""
|
||||
if not callable(self._enabled):
|
||||
self._enabled = enabled
|
||||
|
||||
ENABLED.send_robust(sender=sender, service_id=self.service_id,
|
||||
enabled=enabled)
|
||||
|
||||
|
||||
def init():
|
||||
"""Register some misc. services that don't fit elsewhere"""
|
||||
Service('http', _('Web Server'), ['http'], True)
|
||||
Service('https', _('Web Server over Secure Socket Layer'),
|
||||
['https'], True)
|
||||
Service('ssh', _('Secure Shell (SSH) Server'), ['ssh'], True)
|
||||
Service('plinth', _('FreedomBox Web Interface (Plinth)'),
|
||||
['https'], True)
|
||||
8
themes/default/css/bootstrap.css
vendored
8
themes/default/css/bootstrap.css
vendored
@ -3494,3 +3494,11 @@ a.thumbnail:hover {
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.firewall-permitted {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.firewall-blocked {
|
||||
color: red;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user