Introduce firewall component for opening/closing ports

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2019-05-21 09:08:35 -07:00 committed by James Valleroy
parent 4c4a59e5fe
commit ca2c7dbeb0
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
48 changed files with 647 additions and 401 deletions

View File

@ -147,8 +147,6 @@ def main():
log.init() log.init()
service.init()
web_framework.init() web_framework.init()
logger.info('FreedomBox Service (Plinth) version - %s', __version__) logger.info('FreedomBox Service (Plinth) version - %s', __version__)

View File

@ -74,10 +74,7 @@ class App:
""" """
for component in self.components.values(): for component in self.components.values():
if not component.is_leader: if not component.is_leader:
if enabled: component.set_enabled(enabled)
component.enable()
else:
component.disable()
class Component: class Component:
@ -93,10 +90,10 @@ class Component:
self.component_id = component_id self.component_id = component_id
def enable(self): def enable(self):
"""Enable the component.""" """Run operations to enable the component."""
def disable(self): def disable(self):
"""Disable the component.""" """Run operations to disable the component."""
class FollowerComponent(Component): class FollowerComponent(Component):
@ -117,12 +114,16 @@ class FollowerComponent(Component):
"""Return whether the component is enabled.""" """Return whether the component is enabled."""
return self._is_enabled return self._is_enabled
def set_enabled(self, enabled):
"""Update the internal enabled state of the component."""
self._is_enabled = enabled
def enable(self): def enable(self):
"""Enable the component.""" """Run operations to enable the component."""
self._is_enabled = True self._is_enabled = True
def disable(self): def disable(self):
"""Disable the component.""" """Run operations to disable the component."""
self._is_enabled = False self._is_enabled = False

View File

@ -18,7 +18,13 @@
FreedomBox app for Apache server. FreedomBox app for Apache server.
""" """
from django.utils.translation import ugettext_lazy as _
from plinth import actions from plinth import actions
from plinth import app as app_module
from plinth import cfg
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy
version = 7 version = 7
@ -26,9 +32,38 @@ is_essential = True
managed_packages = ['apache2', 'php-fpm'] managed_packages = ['apache2', 'php-fpm']
app = None
class ApacheApp(app_module.App):
"""FreedomBox app for Apache web server."""
def __init__(self):
"""Create components for the app."""
super().__init__()
web_server_ports = Firewall('firewall-web', _('Web Server'),
ports=['http', 'https'], is_external=True)
self.add(web_server_ports)
freedombox_ports = Firewall(
'firewall-plinth',
format_lazy(
_('{box_name} Web Interface (Plinth)'), box_name=_(
cfg.box_name)), ports=['http', 'https'], is_external=True)
self.add(freedombox_ports)
def init():
"""Initailze firewall module"""
global app
app = ApacheApp()
app.set_enabled(True)
def setup(helper, old_version=None): def setup(helper, old_version=None):
"""Configure the module.""" """Configure the module."""
helper.install(managed_packages) helper.install(managed_packages)
actions.superuser_run('apache', actions.superuser_run(
['setup', '--old-version', str(old_version)]) 'apache',
['setup', '--old-version', str(old_version)])

View File

@ -24,6 +24,7 @@ from plinth import actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, menu from plinth import cfg, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from plinth.views import ServiceView from plinth.views import ServiceView
@ -69,6 +70,10 @@ class AvahiApp(app_module.App):
'avahi:index', parent_url_name='system') 'avahi:index', parent_url_name='system')
self.add(menu_item) self.add(menu_item)
firewall = Firewall('firewall-avahi', name, ports=['mdns'],
is_external=False)
self.add(firewall)
def init(): def init():
"""Intialize the service discovery module.""" """Intialize the service discovery module."""
@ -77,8 +82,7 @@ def init():
app.set_enabled(True) app.set_enabled(True)
global service # pylint: disable=W0603 global service # pylint: disable=W0603
service = service_module.Service(managed_services[0], name, ports=['mdns'], service = service_module.Service(managed_services[0], name)
is_external=False)
def setup(helper, old_version=None): def setup(helper, old_version=None):

View File

@ -26,6 +26,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, menu from plinth import cfg, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from .manifest import backup from .manifest import backup
@ -97,6 +98,10 @@ class BindApp(app_module.App):
parent_url_name='system') parent_url_name='system')
self.add(menu_item) self.add(menu_item)
firewall = Firewall('firewall-bind', name, ports=['dns'],
is_external=False)
self.add(firewall)
def init(): def init():
"""Intialize the BIND module.""" """Intialize the BIND module."""
@ -106,8 +111,7 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name)
ports=['dns'], is_external=False)
app.set_enabled(True) # XXX: Perform better check app.set_enabled(True) # XXX: Perform better check
@ -117,9 +121,7 @@ def setup(helper, old_version=None):
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name,
ports=['dns'], is_external=True,
enable=enable, disable=disable) enable=enable, disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', actions.superuser_run, 'bind', ['setup']) helper.call('post', actions.superuser_run, 'bind', ['setup'])
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -26,6 +26,7 @@ from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules import names from plinth.modules import names
from plinth.modules.firewall.components import Firewall
from plinth.signals import domain_added, domain_removed, domainname_change from plinth.signals import domain_added, domain_removed, domainname_change
from plinth.utils import format_lazy from plinth.utils import format_lazy
@ -80,6 +81,10 @@ class CockpitApp(app_module.App):
clients=clients, login_required=True) clients=clients, login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-cockpit', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
def init(): def init():
"""Intialize the module.""" """Intialize the module."""
@ -89,9 +94,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
if is_enabled(): if is_enabled():
@ -112,11 +116,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'cockpit', ['setup'] + domains) helper.call('post', actions.superuser_run, 'cockpit', ['setup'] + domains)
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -24,6 +24,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from .manifest import backup, clients from .manifest import backup, clients
@ -73,6 +74,11 @@ class CoquelicotApp(app_module.App):
clients=clients, login_required=True) clients=clients, login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-coquelicot', name,
ports=['http', 'https'], is_external=True)
self.add(firewall)
def init(): def init():
"""Intialize the module.""" """Intialize the module."""
@ -82,11 +88,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -99,12 +103,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'coquelicot', ['enable']) helper.call('post', actions.superuser_run, 'coquelicot', ['enable'])
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -70,18 +70,15 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name)
is_external=True)
def setup(helper, old_version=None): def setup(helper, old_version=None):
"""Install and configure the module.""" """Install and configure the module."""
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name)
is_external=True)
service.enable() service.enable()
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -24,6 +24,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group from plinth.modules.users import register_group
from .manifest import backup, clients from .manifest import backup, clients
@ -75,6 +76,10 @@ class DelugeApp(app_module.App):
allowed_groups=[group[0]]) allowed_groups=[group[0]])
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-deluge', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the Deluge module.""" """Initialize the Deluge module."""
@ -85,9 +90,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -99,11 +103,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'deluge', ['enable']) helper.call('post', actions.superuser_run, 'deluge', ['enable'])
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -24,6 +24,7 @@ from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.errors import DomainNotRegisteredError from plinth.errors import DomainNotRegisteredError
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
domain_name_file = "/etc/diaspora/domain_name" domain_name_file = "/etc/diaspora/domain_name"
@ -92,6 +93,10 @@ class DiasporaApp(app_module.App):
icon='diaspora', url=None, clients=clients, login_required=True) icon='diaspora', url=None, clients=clients, login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-diaspora', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
class Shortcut(frontpage.Shortcut): class Shortcut(frontpage.Shortcut):
"""Frontpage shortcut to use configured domain name for URL.""" """Frontpage shortcut to use configured domain name for URL."""
@ -110,9 +115,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
if is_enabled(): if is_enabled():
@ -131,11 +135,9 @@ def setup_domain_name(domain_name):
actions.superuser_run('diaspora', ['setup', '--domain-name', domain_name]) actions.superuser_run('diaspora', ['setup', '--domain-name', domain_name])
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
service.notify_enabled(None, True)
app.enable() app.enable()

View File

@ -28,6 +28,7 @@ from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules import config from plinth.modules import config
from plinth.modules.firewall.components import Firewall
from plinth.signals import (domainname_change, post_hostname_change, from plinth.signals import (domainname_change, post_hostname_change,
pre_hostname_change) pre_hostname_change)
from plinth.utils import format_lazy from plinth.utils import format_lazy
@ -94,6 +95,11 @@ class EjabberdApp(app_module.App):
login_required=True) login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-ejabberd', name,
ports=['xmpp-client', 'xmpp-server',
'xmpp-bosh'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the ejabberd module""" """Initialize the ejabberd module"""
@ -103,11 +109,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service( service = service_module.Service('ejabberd', name,
'ejabberd', name, is_enabled=is_enabled, enable=enable,
ports=['xmpp-client', 'xmpp-server', disable=disable)
'xmpp-bosh'], is_external=True, is_enabled=is_enabled,
enable=enable, disable=disable)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -127,12 +131,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'ejabberd', ['setup']) helper.call('post', actions.superuser_run, 'ejabberd', ['setup'])
global service global service
if service is None: if service is None:
service = service_module.Service( service = service_module.Service('ejabberd', name,
'ejabberd', name, is_enabled=is_enabled, enable=enable,
ports=['xmpp-client', 'xmpp-server', disable=disable)
'xmpp-bosh'], is_external=True, is_enabled=is_enabled,
enable=enable, disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -18,15 +18,11 @@
FreedomBox app to configure a firewall. FreedomBox app to configure a firewall.
""" """
import logging
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import plinth.service as service_module
from plinth import actions from plinth import actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, menu from plinth import cfg, menu
from plinth.signals import service_enabled
from plinth.utils import Version, format_lazy from plinth.utils import Version, format_lazy
from .manifest import backup from .manifest import backup
@ -49,8 +45,6 @@ description = [
manual_page = 'Firewall' manual_page = 'Firewall'
LOGGER = logging.getLogger(__name__)
_port_details = {} _port_details = {}
app = None app = None
@ -73,8 +67,6 @@ def init():
app = FirewallApp() app = FirewallApp()
app.set_enabled(True) app.set_enabled(True)
service_enabled.connect(on_service_enabled)
def setup(helper, old_version=None): def setup(helper, old_version=None):
"""Install and configure the module.""" """Install and configure the module."""
@ -139,51 +131,6 @@ def remove_service(port, zone):
_run(['remove-service', port, '--zone', zone], superuser=True) _run(['remove-service', port, '--zone', zone], superuser=True)
def on_service_enabled(sender, service_id, enabled, **kwargs):
"""
Enable/disable firewall ports when a service is
enabled/disabled.
"""
del sender # Unused
del kwargs # Unused
internal_enabled_services = get_enabled_services(zone='internal')
external_enabled_services = get_enabled_services(zone='external')
LOGGER.info('Service enabled - %s, %s', service_id, enabled)
service = service_module.services[service_id]
for port in service.ports:
if enabled:
if port not in internal_enabled_services:
add_service(port, zone='internal')
if (service.is_external and port not in external_enabled_services):
add_service(port, zone='external')
else:
# service already configured.
pass
else:
if port in internal_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):
remove_service(port, zone='internal')
if port in external_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 and service_.is_external
]
if not any(enabled_services_on_port):
remove_service(port, zone='external')
def _run(arguments, superuser=False): def _run(arguments, superuser=False):
"""Run an given command and raise exception if there was an error""" """Run an given command and raise exception if there was an error"""
command = 'firewall' command = 'firewall'

View File

@ -0,0 +1,106 @@
#
# This file is part of FreedomBox.
#
# 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/>.
#
"""
App component for other apps to use firewall functionality.
"""
import logging
from plinth import app
from plinth.modules import firewall
logger = logging.getLogger(__name__)
class Firewall(app.FollowerComponent):
"""Component to open/close firewall ports for an app."""
_all_firewall_components = {}
def __init__(self, component_id, name=None, ports=None, is_external=False):
"""Initialize the firewall component."""
super().__init__(component_id)
if not ports:
ports = []
self.name = name
self.ports = ports
self.is_external = is_external
self._all_firewall_components[component_id] = self
@property
def ports_details(self):
"""Retrieve details of ports associated with this component.."""
ports_details = []
for port in self.ports:
ports_details.append({
'name': port,
'details': firewall.get_port_details(port),
})
return ports_details
@classmethod
def list(cls):
"""Return a list of all firewall ports."""
return cls._all_firewall_components.values()
def enable(self):
"""Open firewall ports when the component is enabled."""
super().enable()
internal_enabled_ports = firewall.get_enabled_services(zone='internal')
external_enabled_ports = firewall.get_enabled_services(zone='external')
logger.info('Firewall ports opened - %s, %s', self.name, self.ports)
for port in self.ports:
if port not in internal_enabled_ports:
firewall.add_service(port, zone='internal')
if (self.is_external and port not in external_enabled_ports):
firewall.add_service(port, zone='external')
def disable(self):
"""Close firewall ports when the component is disabled."""
super().disable()
internal_enabled_ports = firewall.get_enabled_services(zone='internal')
external_enabled_ports = firewall.get_enabled_services(zone='external')
logger.info('Firewall ports closed - %s, %s', self.name, self.ports)
for port in self.ports:
if port in internal_enabled_ports:
enabled_components_on_port = [
component.is_enabled()
for component in self._all_firewall_components.values()
if port in component.ports
and self.component_id != component.component_id
]
if not any(enabled_components_on_port):
firewall.remove_service(port, zone='internal')
if port in external_enabled_ports:
enabled_components_on_port = [
component.is_enabled()
for component in self._all_firewall_components.values()
if port in component.ports and self.component_id !=
component.component_id and component.is_external
]
if not any(enabled_components_on_port):
firewall.remove_service(port, zone='external')

View File

@ -46,19 +46,19 @@
</thead> </thead>
<tbody> <tbody>
{% for service in services|dictsort:"name" %} {% for component in components|dictsort:"name" %}
{% if service.ports %} {% if component.ports %}
<tr> <tr>
<td> <td>
<center> <center>
<button data-toggle="collapse" <button data-toggle="collapse"
data-target=".{{service.service_id}}" data-target=".{{component.component_id}}"
class="btn btn-info btn-xs">+</button> class="btn btn-info btn-xs">+</button>
</center> </center>
</td> </td>
<td><strong>{{ service.name }}</strong></td> <td><strong>{{ component.name }}</strong></td>
<td> <td>
{% if service.is_enabled %} {% if component.is_enabled %}
<span class='label label-success'> <span class='label label-success'>
{% trans "Enabled" %}</span> {% trans "Enabled" %}</span>
{% else %} {% else %}
@ -67,19 +67,19 @@
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
{% for port in service.ports_details %} {% for port in component.ports_details %}
<tr class="collapse out {{service.service_id}}" <tr class="collapse out {{component.component_id}}"
style="background-color: #f9f9f9" > style="background-color: #f9f9f9" >
<td></td> <td></td>
<td class='cell-indented'><em>{{ port.name }}</em> ({{ port.details }})</td> <td class='cell-indented'><em>{{ port.name }}</em> ({{ port.details }})</td>
<td> <td>
{% if port.name in internal_enabled_services and port.name in external_enabled_services %} {% if port.name in internal_enabled_ports and port.name in external_enabled_ports %}
<span class='label label-success'> <span class='label label-success'>
{% trans "Permitted" %}</span> {% trans "Permitted" %}</span>
{% elif port.name in internal_enabled_services %} {% elif port.name in internal_enabled_ports %}
<span class='label label-warning'> <span class='label label-warning'>
{% trans "Permitted (internal only)" %}</span> {% trans "Permitted (internal only)" %}</span>
{% elif port.name in external_enabled_services %} {% elif port.name in external_enabled_ports %}
<span class='label label-warning'> <span class='label label-warning'>
{% trans "Permitted (external only)" %}</span> {% trans "Permitted (external only)" %}</span>
{% else %} {% else %}

View File

@ -0,0 +1,139 @@
#
# This file is part of FreedomBox.
#
# 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/>.
#
"""
Tests for firewall app component.
"""
from unittest.mock import call, patch
import pytest
from plinth.modules.firewall.components import Firewall
@pytest.fixture(name='empty_firewall_list', autouse=True)
def fixture_empty_firewall_list():
"""Remove all entries in firewall list before starting a test."""
Firewall._all_firewall_components = {}
def test_init_without_arguments():
"""Test initializing the component without arguments."""
with pytest.raises(ValueError):
Firewall(None)
firewall = Firewall('test-component')
assert firewall.component_id == 'test-component'
assert firewall.name is None
assert firewall.ports == []
assert not firewall.is_external
assert len(Firewall._all_firewall_components.items()) == 1
assert Firewall._all_firewall_components['test-component'] == firewall
def test_init():
"""Test initializing the component."""
firewall = Firewall('test-component', 'test-name',
['test-port1', 'test-port2'], is_external=True)
assert firewall.name == 'test-name'
assert firewall.ports == ['test-port1', 'test-port2']
assert firewall.is_external
@patch('plinth.modules.firewall.get_port_details')
def test_port_details(get_port_details):
"""Test retrieving port details for a firewall component."""
return_values = {'test-port1': '1234/tcp', 'test-port2': '5678/udp'}
def get_port_details_side_effect(port):
return return_values[port]
get_port_details.side_effect = get_port_details_side_effect
firewall = Firewall('test-component', ports=['test-port1', 'test-port2'])
assert firewall.ports_details == [{
'name': 'test-port1',
'details': '1234/tcp'
}, {
'name': 'test-port2',
'details': '5678/udp'
}]
@patch('plinth.modules.firewall.add_service')
@patch('plinth.modules.firewall.get_enabled_services')
def test_enable(get_enabled_services, add_service):
"""Test enabling a firewall component."""
def get_enabled_services_side_effect(zone):
return {'internal': ['test-port1'], 'external': ['test-port2']}[zone]
get_enabled_services.side_effect = get_enabled_services_side_effect
# Internal
firewall = Firewall('test-firewall-1', ports=['test-port1', 'test-port2'],
is_external=False)
firewall.enable()
calls = [call('test-port2', zone='internal')]
add_service.assert_has_calls(calls)
# External
add_service.reset_mock()
firewall = Firewall('test-firewall-2', ports=['test-port1', 'test-port2'],
is_external=True)
firewall.enable()
calls = [
call('test-port1', zone='external'),
call('test-port2', zone='internal')
]
add_service.assert_has_calls(calls)
@patch('plinth.modules.firewall.remove_service')
@patch('plinth.modules.firewall.add_service')
@patch('plinth.modules.firewall.get_enabled_services')
def test_disable(get_enabled_services, add_service, remove_service):
"""Test disabling a firewall component."""
Firewall('firewall-1', ports=['test-port1'], is_external=False)
Firewall('firewall-2', ports=['test-port2'], is_external=False).enable()
Firewall('firewall-3', ports=['test-port4'], is_external=True)
Firewall('firewall-4', ports=['test-port5'], is_external=True).enable()
def get_enabled_services_side_effect(zone):
return {
'internal': ['test-port1', 'test-port2'],
'external': ['test-port4', 'test-port5']
}[zone]
get_enabled_services.side_effect = get_enabled_services_side_effect
all_ports = [
'test-port1', 'test-port2', 'test-port3', 'test-port4', 'test-port5',
'test-port6'
]
# Internal
firewall = Firewall('test-firewall-1', ports=all_ports, is_external=False)
firewall.disable()
calls = [call('test-port1', zone='internal')]
remove_service.assert_has_calls(calls)
# External
remove_service.reset_mock()
firewall = Firewall('test-firewall-2', ports=all_ports, is_external=True)
firewall.disable()
calls = [
call('test-port1', zone='internal'),
call('test-port4', zone='external')
]
remove_service.assert_has_calls(calls)

View File

@ -23,6 +23,8 @@ from django.template.response import TemplateResponse
import plinth.service as service_module import plinth.service as service_module
from plinth.modules import firewall from plinth.modules import firewall
from . import components
def index(request): def index(request):
"""Serve introduction page""" """Serve introduction page"""
@ -34,15 +36,15 @@ def index(request):
'firewall_status': 'not_running' 'firewall_status': 'not_running'
}) })
internal_enabled_services = firewall.get_enabled_services(zone='internal') internal_enabled_ports = firewall.get_enabled_services(zone='internal')
external_enabled_services = firewall.get_enabled_services(zone='external') external_enabled_ports = firewall.get_enabled_services(zone='external')
return TemplateResponse( return TemplateResponse(
request, 'firewall.html', { request, 'firewall.html', {
'title': firewall.name, 'title': firewall.name,
'description': firewall.description, 'description': firewall.description,
'services': list(service_module.services.values()), 'components': components.Firewall.list(),
'manual_page': firewall.manual_page, 'manual_page': firewall.manual_page,
'internal_enabled_services': internal_enabled_services, 'internal_enabled_ports': internal_enabled_ports,
'external_enabled_services': external_enabled_services 'external_enabled_ports': external_enabled_ports
}) })

View File

@ -24,6 +24,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.modules.i2p.resources import FAVORITES from plinth.modules.i2p.resources import FAVORITES
from plinth.modules.users import register_group from plinth.modules.users import register_group
@ -57,7 +58,6 @@ clients = clients
group = ('i2p', _('Manage I2P application')) group = ('i2p', _('Manage I2P application'))
service = None service = None
proxies_service = None
manual_page = 'I2P' manual_page = 'I2P'
@ -92,6 +92,15 @@ class I2PApp(app_module.App):
allowed_groups=[group[0]]) allowed_groups=[group[0]])
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-i2p-web', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
firewall = Firewall('firewall-i2p-proxies', name,
ports=tunnels_to_manage.values(),
is_external=False)
self.add(firewall)
def init(): def init():
"""Intialize the module.""" """Intialize the module."""
@ -99,18 +108,12 @@ def init():
app = I2PApp() app = I2PApp()
register_group(group) register_group(group)
global service, proxies_service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
proxies_service = service_module.Service(
'i2p-proxies', name, ports=tunnels_to_manage.values(),
is_external=False, is_enabled=is_enabled, is_running=is_running)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -144,19 +147,12 @@ def setup(helper, old_version=None):
'--value', '0.0.0.0' '--value', '0.0.0.0'
]) ])
helper.call('post', enable) helper.call('post', enable)
global service, proxies_service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
proxies_service = service_module.Service(
'i2p-proxies', name, ports=tunnels_to_manage.values(),
is_external=False, is_enabled=is_enabled, is_running=is_running)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', proxies_service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -25,6 +25,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group from plinth.modules.users import register_group
from plinth.utils import format_lazy from plinth.utils import format_lazy
@ -83,6 +84,10 @@ class IkiwikiApp(app_module.App):
for site in sites: for site in sites:
self.add_shortcut(site) self.add_shortcut(site)
firewall = Firewall('firewall-ikiwiki', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
def add_shortcut(self, site): def add_shortcut(self, site):
"""Add an ikiwiki shortcut to frontpage.""" """Add an ikiwiki shortcut to frontpage."""
shortcut = frontpage.Shortcut('shortcut-ikiwiki-' + site, site, shortcut = frontpage.Shortcut('shortcut-ikiwiki-' + site, site,
@ -106,9 +111,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service( service = service_module.Service('ikiwiki', name,
'ikiwiki', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable,
is_enabled=is_enabled, enable=enable, disable=disable) disable=disable)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -119,10 +124,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'ikiwiki', ['setup']) helper.call('post', actions.superuser_run, 'ikiwiki', ['setup'])
global service global service
if service is None: if service is None:
service = service_module.Service( service = service_module.Service('ikiwiki', name,
'ikiwiki', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable,
is_enabled=is_enabled, enable=enable, disable=disable) disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -25,6 +25,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from plinth.views import ServiceView from plinth.views import ServiceView
@ -76,6 +77,10 @@ class InfinotedApp(app_module.App):
login_required=False) login_required=False)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-infinoted', name,
ports=['infinoted-plinth'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the infinoted module.""" """Initialize the infinoted module."""
@ -85,9 +90,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'infinoted-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
if service.is_enabled(): if service.is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -106,11 +110,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'infinoted', ['setup']) helper.call('post', actions.superuser_run, 'infinoted', ['setup'])
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'infinoted-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -26,6 +26,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from .manifest import backup, clients from .manifest import backup, clients
@ -66,6 +67,10 @@ class JSXCApp(app_module.App):
icon='jsxc', url=reverse_lazy('jsxc:jsxc'), clients=clients) icon='jsxc', url=reverse_lazy('jsxc:jsxc'), clients=clients)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-jsxc', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the JSXC module""" """Initialize the JSXC module"""
@ -75,9 +80,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service( service = service_module.Service('jsxc', name, is_enabled=is_enabled,
'jsxc', name, ports=['http', 'https'], is_external=True, enable=enable, disable=disable)
is_enabled=is_enabled, enable=enable, disable=disable)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -88,9 +92,8 @@ def setup(helper, old_version=None):
global service global service
if not service: if not service:
service = service_module.Service( service = service_module.Service('jsxc', name, is_enabled=is_enabled,
'jsxc', name, ports=['http', 'https'], is_external=True, enable=enable, disable=disable)
is_enabled=is_enabled, enable=enable, disable=disable)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -29,6 +29,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from .manifest import backup, clients from .manifest import backup, clients
@ -91,6 +92,10 @@ class MatrixSynapseApp(app_module.App):
login_required=True) login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-matrixsynapse', name,
ports=['matrix-synapse-plinth'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the matrix-synapse module.""" """Initialize the matrix-synapse module."""
@ -100,9 +105,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service('matrix-synapse', name, ports=[ service = service_module.Service('matrix-synapse', name,
'matrix-synapse-plinth' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -113,14 +117,12 @@ def setup(helper, old_version=None):
helper.install(managed_packages) helper.install(managed_packages)
global service global service
if service is None: if service is None:
service = service_module.Service('matrix-synapse', name, ports=[ service = service_module.Service('matrix-synapse', name,
'matrix-synapse-plinth' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
helper.call('post', actions.superuser_run, 'matrixsynapse', helper.call('post', actions.superuser_run, 'matrixsynapse',
['post-install']) ['post-install'])
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -24,6 +24,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from .manifest import backup, clients from .manifest import backup, clients
@ -78,6 +79,10 @@ class MediaWikiApp(app_module.App):
clients=clients, login_required=True) clients=clients, login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-mediawiki', name,
ports=['http', 'https'], is_external=True)
self.add(firewall)
class Shortcut(frontpage.Shortcut): class Shortcut(frontpage.Shortcut):
"""Frontpage shortcut for only logged users when in private mode.""" """Frontpage shortcut for only logged users when in private mode."""
@ -96,9 +101,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service( service = service_module.Service('mediawiki', name,
'mediawiki', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable,
is_enabled=is_enabled, enable=enable, disable=disable) disable=disable)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -111,16 +116,9 @@ def setup(helper, old_version=None):
helper.call('enable', actions.superuser_run, 'mediawiki', ['enable']) helper.call('enable', actions.superuser_run, 'mediawiki', ['enable'])
global service global service
if service is None: if service is None:
service = service_module.Service( service = service_module.Service('mediawiki', name,
'mediawiki', is_enabled=is_enabled, enable=enable,
name, disable=disable)
is_external=True,
is_enabled=is_enabled,
enable=enable,
disable=disable,
ports=['http', 'https'],
)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -26,6 +26,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from .manifest import backup, clients from .manifest import backup, clients
@ -95,6 +96,10 @@ class MinetestApp(app_module.App):
login_required=False) login_required=False)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-minetest', name,
ports=['minetest-plinth'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the module.""" """Initialize the module."""
@ -104,9 +109,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'minetest-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
if service.is_enabled(): if service.is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -116,10 +120,8 @@ def setup(helper, old_version=None):
helper.install(managed_packages) helper.install(managed_packages)
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'minetest-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -24,6 +24,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group from plinth.modules.users import register_group
from plinth.utils import format_lazy from plinth.utils import format_lazy
@ -82,6 +83,11 @@ class MLDonkeyApp(app_module.App):
clients=clients, allowed_groups=[group[0]]) clients=clients, allowed_groups=[group[0]])
self.add(shortcuts) self.add(shortcuts)
firewall = Firewall('firewall-mldonkey', name,
ports=['http', 'https'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the MLDonkey module.""" """Initialize the MLDonkey module."""
@ -92,11 +98,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -109,12 +113,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'mldonkey', ['enable']) helper.call('post', actions.superuser_run, 'mldonkey', ['enable'])
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -25,6 +25,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.views import ServiceView from plinth.views import ServiceView
from .manifest import backup, clients from .manifest import backup, clients
@ -79,6 +80,10 @@ class MumbleApp(app_module.App):
configure_url=reverse_lazy('mumble:index'), clients=clients) configure_url=reverse_lazy('mumble:index'), clients=clients)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-mumble', name, ports=['mumble-plinth'],
is_external=True)
self.add(firewall)
def init(): def init():
"""Intialize the Mumble module.""" """Intialize the Mumble module."""
@ -88,9 +93,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'mumble-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
if service.is_enabled(): if service.is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -110,10 +114,8 @@ def setup(helper, old_version=None):
helper.install(managed_packages) helper.install(managed_packages)
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'mumble-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -25,6 +25,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from .manifest import backup from .manifest import backup
@ -80,6 +81,10 @@ class OpenVPNApp(app_module.App):
configure_url=reverse_lazy('openvpn:index'), login_required=True) configure_url=reverse_lazy('openvpn:index'), login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-openvpn', name, ports=['openvpn'],
is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the OpenVPN module.""" """Initialize the OpenVPN module."""
@ -89,8 +94,7 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name)
ports=['openvpn'], is_external=True)
if service.is_enabled() and is_setup(): if service.is_enabled() and is_setup():
app.set_enabled(True) app.set_enabled(True)
@ -103,7 +107,6 @@ def setup(helper, old_version=None):
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name,
ports=['openvpn'], is_external=True,
enable=enable, disable=disable) enable=enable, disable=disable)
if service.is_enabled() and is_setup(): if service.is_enabled() and is_setup():

View File

@ -70,8 +70,6 @@ def index(request):
@require_POST @require_POST
def setup(request): def setup(request):
"""Start the setup process.""" """Start the setup process."""
openvpn.service.notify_enabled(None, True)
global setup_process global setup_process
if not openvpn.is_setup() and not setup_process: if not openvpn.is_setup() and not setup_process:
setup_process = actions.superuser_run('openvpn', ['setup'], setup_process = actions.superuser_run('openvpn', ['setup'],

View File

@ -25,6 +25,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from plinth.views import ServiceView from plinth.views import ServiceView
@ -83,6 +84,10 @@ class PrivoxyApp(app_module.App):
configure_url=reverse_lazy('privoxy:index'), login_required=True) configure_url=reverse_lazy('privoxy:index'), login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-privoxy', name, ports=['privoxy'],
is_external=False)
self.add(firewall)
def init(): def init():
"""Intialize the module.""" """Intialize the module."""
@ -93,7 +98,6 @@ def init():
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name,
ports=['privoxy'], is_external=False,
enable=enable, disable=disable) enable=enable, disable=disable)
if service.is_enabled(): if service.is_enabled():
@ -107,9 +111,7 @@ def setup(helper, old_version=None):
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name,
ports=['privoxy'], is_external=False,
enable=enable, disable=disable) enable=enable, disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -25,6 +25,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from plinth.views import ServiceView from plinth.views import ServiceView
@ -87,6 +88,10 @@ class QuasselApp(app_module.App):
login_required=True) login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-quassel', name,
ports=['quassel-plinth'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the quassel module.""" """Initialize the quassel module."""
@ -96,9 +101,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'quassel-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
if service.is_enabled(): if service.is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -118,10 +122,8 @@ def setup(helper, old_version=None):
helper.install(managed_packages) helper.install(managed_packages)
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'quassel-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -30,6 +30,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from .manifest import backup, clients from .manifest import backup, clients
@ -90,6 +91,10 @@ class RadicaleApp(app_module.App):
clients=clients, login_required=True) clients=clients, login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-radicale', name,
ports=['http', 'https'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the radicale module.""" """Initialize the radicale module."""
@ -99,11 +104,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -137,12 +140,9 @@ def setup(helper, old_version=None):
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -25,6 +25,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.views import ServiceView from plinth.views import ServiceView
from .manifest import backup, clients from .manifest import backup, clients
@ -88,6 +89,11 @@ class ReproApp(app_module.App):
login_required=True) login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-repro', name,
ports=['sip', 'sips',
'rtp-plinth'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the repro module.""" """Initialize the repro module."""
@ -97,9 +103,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'sip', 'sips', 'rtp-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
if service.is_enabled(): if service.is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -120,10 +125,8 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'repro', ['setup']) helper.call('post', actions.superuser_run, 'repro', ['setup'])
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'sip', 'sips', 'rtp-plinth' enable=enable, disable=disable)
], is_external=True, enable=enable, disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -23,6 +23,7 @@ from django.utils.translation import ugettext_lazy as _
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, menu from plinth import cfg, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from .manifest import clients from .manifest import clients
@ -69,6 +70,10 @@ class RestoreApp(app_module.App):
parent_url_name='apps') parent_url_name='apps')
self.add(menu_item) self.add(menu_item)
firewall = Firewall('firewall-restore', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the reStore module.""" """Initialize the reStore module."""
@ -78,9 +83,7 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name)
ports=['http',
'https'], is_external=False)
def setup(helper, old_version=None): def setup(helper, old_version=None):
@ -88,6 +91,4 @@ def setup(helper, old_version=None):
helper.install(managed_packages) helper.install(managed_packages)
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, service = service_module.Service(managed_services[0], name)
ports=['http',
'https'], is_external=False)

View File

@ -24,6 +24,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from .manifest import backup, clients from .manifest import backup, clients
@ -81,6 +82,10 @@ class RoundcubeApp(app_module.App):
clients=clients, login_required=True) clients=clients, login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-roundcube', name,
ports=['http', 'https'], is_external=True)
self.add(firewall)
def init(): def init():
"""Intialize the module.""" """Intialize the module."""
@ -90,9 +95,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service( service = service_module.Service('roundcube', name,
'roundcube', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable,
is_enabled=is_enabled, enable=enable, disable=disable) disable=disable)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -105,9 +110,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'roundcube', ['setup']) helper.call('post', actions.superuser_run, 'roundcube', ['setup'])
global service global service
if service is None: if service is None:
service = service_module.Service( service = service_module.Service('roundcube', name,
'roundcube', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable,
is_enabled=is_enabled, enable=enable, disable=disable) disable=disable)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -26,6 +26,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group from plinth.modules.users import register_group
from .manifest import PUBLIC_ACCESS_SETTING_FILE, backup, clients from .manifest import PUBLIC_ACCESS_SETTING_FILE, backup, clients
@ -75,6 +76,10 @@ class SearxApp(app_module.App):
allowed_groups=[group[0]]) allowed_groups=[group[0]])
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-searx', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
def set_shortcut_login_required(self, login_required): def set_shortcut_login_required(self, login_required):
"""Change the login_required property of shortcut.""" """Change the login_required property of shortcut."""
shortcut = self.remove('shortcut-searx') shortcut = self.remove('shortcut-searx')
@ -91,9 +96,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
if is_enabled(): if is_enabled():
@ -113,9 +117,8 @@ def setup(helper, old_version=None):
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -24,6 +24,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from .manifest import clients from .manifest import clients
@ -69,6 +70,10 @@ class ShaarliApp(app_module.App):
clients=clients, login_required=True) clients=clients, login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-shaarli', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the module.""" """Initialize the module."""
@ -78,9 +83,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service( service = service_module.Service('shaarli', name,
'shaarli', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable,
is_enabled=is_enabled, enable=enable, disable=disable) disable=disable)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -91,10 +96,9 @@ def setup(helper, old_version=None):
helper.install(managed_packages) helper.install(managed_packages)
global service global service
if service is None: if service is None:
service = service_module.Service( service = service_module.Service('shaarli', name,
'shaarli', name, ports=['http', 'https'], is_external=True, is_enabled=is_enabled, enable=enable,
is_enabled=is_enabled, enable=enable, disable=disable) disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -25,6 +25,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from .manifest import backup from .manifest import backup
@ -78,6 +79,11 @@ class ShadowsocksApp(app_module.App):
login_required=True) login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-shadowsocks', name,
ports=['shadowsocks-local-plinth'],
is_external=False)
self.add(firewall)
def init(): def init():
"""Intialize the module.""" """Intialize the module."""
@ -87,10 +93,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service('shadowsocks', name, ports=[ service = service_module.Service(
'shadowsocks-local-plinth' 'shadowsocks', name, is_enabled=is_enabled, is_running=is_running,
], is_external=False, is_enabled=is_enabled, is_running=is_running, enable=enable, disable=disable)
enable=enable, disable=disable)
if service.is_enabled(): if service.is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -102,10 +107,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'shadowsocks', ['setup']) helper.call('post', actions.superuser_run, 'shadowsocks', ['setup'])
global service global service
if service is None: if service is None:
service = service_module.Service('shadowsocks', name, ports=[ service = service_module.Service(
'shadowsocks-local-plinth' 'shadowsocks', name, is_enabled=is_enabled, is_running=is_running,
], is_external=False, is_enabled=is_enabled, is_running=is_running, enable=enable, disable=disable)
enable=enable, disable=disable)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -22,8 +22,9 @@ from django.utils.translation import ugettext_lazy as _
from plinth import actions from plinth import actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, menu from plinth import menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.views import ServiceView from plinth.views import ServiceView
from .manifest import backup from .manifest import backup
@ -62,6 +63,10 @@ class SSHApp(app_module.App):
'ssh:index', parent_url_name='system') 'ssh:index', parent_url_name='system')
self.add(menu_item) self.add(menu_item)
firewall = Firewall('firewall-ssh', name, ports=['ssh'],
is_external=True)
self.add(firewall)
def init(): def init():
"""Intialize the ssh module.""" """Intialize the ssh module."""
@ -70,8 +75,7 @@ def init():
app.set_enabled(True) app.set_enabled(True)
global service global service
service = service_module.Service(managed_services[0], name, ports=['ssh'], service = service_module.Service(managed_services[0], name)
is_external=True)
def setup(helper, old_version=None): def setup(helper, old_version=None):

View File

@ -298,10 +298,8 @@ def setup(helper, old_version=None):
global service global service
if service is None: if service is None:
service = service_module.Service( service = service_module.Service(
managed_services[0], name, ports=[], is_external=True, managed_services[0], name, is_enabled=is_enabled, enable=enable,
is_enabled=is_enabled, enable=enable, disable=disable, disable=disable, is_running=is_running)
is_running=is_running)
helper.call('post', service.notify_enabled, None, True)
disks = get_disks() disks = get_disks()
root_device = get_root_device(disks) root_device = get_root_device(disks)
if is_expandable(root_device): if is_expandable(root_device):

View File

@ -24,6 +24,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group from plinth.modules.users import register_group
from plinth.utils import format_lazy from plinth.utils import format_lazy
@ -85,6 +86,10 @@ class SyncthingApp(app_module.App):
login_required=True, allowed_groups=[group[0]]) login_required=True, allowed_groups=[group[0]])
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-syncthing', name,
ports=['http', 'https'], is_external=True)
self.add(firewall)
def init(): def init():
"""Intialize the module.""" """Intialize the module."""
@ -95,11 +100,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -111,12 +114,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'syncthing', ['enable']) helper.call('post', actions.superuser_run, 'syncthing', ['enable'])
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'http', 'https' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -27,6 +27,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.utils import format_lazy from plinth.utils import format_lazy
from .errors import TahoeConfigurationError from .errors import TahoeConfigurationError
@ -77,6 +78,10 @@ class TahoeApp(app_module.App):
icon='tahoe-lafs', url=None, login_required=True) icon='tahoe-lafs', url=None, login_required=True)
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-tahoe', name, ports=['tahoe-plinth'],
is_external=True)
self.add(firewall)
class Shortcut(frontpage.Shortcut): class Shortcut(frontpage.Shortcut):
"""Frontpage shortcut to use configured domain name for URL.""" """Frontpage shortcut to use configured domain name for URL."""
@ -123,11 +128,9 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup' and is_setup(): if setup_helper.get_state() != 'needs-setup' and is_setup():
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'tahoe-plinth' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
if is_enabled(): if is_enabled():
app.set_enabled(True) app.set_enabled(True)
@ -151,12 +154,9 @@ def post_setup(configured_domain_name):
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(
'tahoe-plinth' managed_services[0], name, is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable, disable=disable, is_running=is_running)
disable=disable,
is_running=is_running)
service.notify_enabled(None, True)
app.enable() app.enable()

View File

@ -26,6 +26,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import menu from plinth import menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.modules.names import SERVICES from plinth.modules.names import SERVICES
from plinth.signals import domain_added, domain_removed from plinth.signals import domain_added, domain_removed
@ -75,6 +76,15 @@ class TorApp(app_module.App):
'tor:index', parent_url_name='apps') 'tor:index', parent_url_name='apps')
self.add(menu_item) self.add(menu_item)
firewall = Firewall('firewall-tor-socks', _('Tor Socks Proxy'),
ports=['tor-socks'], is_external=False)
self.add(firewall)
firewall = Firewall('firewall-tor-relay', _('Tor Bridge Relay'),
ports=['tor-orport', 'tor-obfs3',
'tor-obfs4'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the module.""" """Initialize the module."""
@ -90,15 +100,14 @@ def init():
global socks_service global socks_service
socks_service = service_module.Service( socks_service = service_module.Service(
'tor-socks', _('Tor Socks Proxy'), ports=['tor-socks'], 'tor-socks', _('Tor Socks Proxy'), is_enabled=utils.is_enabled,
is_external=False, is_enabled=utils.is_enabled,
is_running=utils.is_running) is_running=utils.is_running)
global bridge_service global bridge_service
bridge_service = service_module.Service( bridge_service = service_module.Service('tor-bridge',
'tor-bridge', _('Tor Bridge Relay'), _('Tor Bridge Relay'),
ports=['tor-orport', 'tor-obfs3', 'tor-obfs4'], is_external=True, is_enabled=utils.is_enabled,
is_enabled=utils.is_enabled, is_running=utils.is_running) is_running=utils.is_running)
# Register hidden service name with Name Services module. # Register hidden service name with Name Services module.
status = utils.get_status() status = utils.get_status()
@ -132,23 +141,17 @@ def setup(helper, old_version=None):
global socks_service global socks_service
if socks_service is None: if socks_service is None:
socks_service = service_module.Service( socks_service = service_module.Service('tor-socks',
'tor-socks', _('Tor Anonymity Network'), ports=['tor-socks'], _('Tor Anonymity Network'),
is_external=False, is_enabled=utils.is_enabled, is_enabled=utils.is_enabled,
is_running=utils.is_running) is_running=utils.is_running)
if not old_version:
helper.call('post', socks_service.notify_enabled, None, True)
global bridge_service global bridge_service
if bridge_service is None: if bridge_service is None:
bridge_service = service_module.Service( bridge_service = service_module.Service('tor-bridge',
'tor-bridge', _('Tor Bridge Relay'), _('Tor Bridge Relay'),
ports=['tor-orport', 'tor-obfs3', 'tor-obfs4'], is_external=True, is_enabled=utils.is_enabled,
is_enabled=utils.is_enabled, is_running=utils.is_running) is_running=utils.is_running)
if not old_version:
helper.call('post', bridge_service.notify_enabled, None, True)
helper.call('post', update_hidden_service_domain) helper.call('post', update_hidden_service_domain)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -160,8 +160,6 @@ def _collect_config_result(request):
status = tor_utils.get_status() status = tor_utils.get_status()
tor.socks_service.notify_enabled(None, status['enabled'])
tor.bridge_service.notify_enabled(None, status['enabled'])
tor.update_hidden_service_domain(status) tor.update_hidden_service_domain(status)
if not return_code: if not return_code:

View File

@ -26,6 +26,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import frontpage, menu from plinth import frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group from plinth.modules.users import register_group
from .manifest import backup, clients from .manifest import backup, clients
@ -77,6 +78,10 @@ class TransmissionApp(app_module.App):
login_required=True, allowed_groups=[group[0]]) login_required=True, allowed_groups=[group[0]])
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-transmission', name,
ports=['http', 'https'], is_external=True)
self.add(firewall)
def init(): def init():
"""Initialize the Transmission module.""" """Initialize the Transmission module."""
@ -87,9 +92,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
if is_enabled(): if is_enabled():
@ -111,11 +115,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'transmission', ['enable']) helper.call('post', actions.superuser_run, 'transmission', ['enable'])
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -25,6 +25,7 @@ from plinth import action_utils, actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth import service as service_module from plinth import service as service_module
from plinth.modules.firewall.components import Firewall
from plinth.modules.users import register_group from plinth.modules.users import register_group
from plinth.utils import Version, format_lazy from plinth.utils import Version, format_lazy
@ -83,6 +84,10 @@ class TTRSSApp(app_module.App):
allowed_groups=[group[0]]) allowed_groups=[group[0]])
self.add(shortcut) self.add(shortcut)
firewall = Firewall('firewall-ttrss', name, ports=['http', 'https'],
is_external=True)
self.add(firewall)
def init(): def init():
"""Intialize the module.""" """Intialize the module."""
@ -93,9 +98,8 @@ def init():
global service global service
setup_helper = globals()['setup_helper'] setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup': if setup_helper.get_state() != 'needs-setup':
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
if is_enabled(): if is_enabled():
@ -110,11 +114,9 @@ def setup(helper, old_version=None):
helper.call('post', actions.superuser_run, 'ttrss', ['enable']) helper.call('post', actions.superuser_run, 'ttrss', ['enable'])
global service global service
if service is None: if service is None:
service = service_module.Service(managed_services[0], name, ports=[ service = service_module.Service(managed_services[0], name,
'http', 'https' is_enabled=is_enabled, enable=enable,
], is_external=True, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)
helper.call('post', service.notify_enabled, None, True)
helper.call('post', app.enable) helper.call('post', app.enable)

View File

@ -64,7 +64,7 @@ def init():
app.set_enabled(True) app.set_enabled(True)
global service global service
service = service_module.Service('auto-upgrades', name, is_external=False, service = service_module.Service('auto-upgrades', name,
is_enabled=is_enabled, enable=enable, is_enabled=is_enabled, enable=enable,
disable=disable) disable=disable)

View File

@ -20,11 +20,7 @@ Framework for working with servers and their services.
import collections import collections
from django.utils.translation import ugettext_lazy as _ from plinth import action_utils, actions
from plinth import action_utils, actions, cfg
from plinth.signals import service_enabled
from plinth.utils import format_lazy
services = {} services = {}
@ -32,8 +28,7 @@ services = {}
class Service(): class Service():
""" """
Representation of an application service provided by the machine Representation of an application service provided by the machine
containing information such as current status and ports required containing information such as current status.
for operation.
- service_id: unique service name. If possible this should be the name of - service_id: unique service name. If possible this should be the name of
the service's systemd unit file (without the extension). the service's systemd unit file (without the extension).
@ -44,18 +39,13 @@ class Service():
- is_running (optional): Boolean or a method returning Boolean - is_running (optional): Boolean or a method returning Boolean
""" """
def __init__(self, service_id, name, ports=None, is_external=False, def __init__(self, service_id, name, is_enabled=None, enable=None,
is_enabled=None, enable=None, disable=None, is_running=None): disable=None, is_running=None):
if ports is None:
ports = []
if is_enabled is None: if is_enabled is None:
is_enabled = self._default_is_enabled is_enabled = self._default_is_enabled
self.service_id = service_id self.service_id = service_id
self.name = name self.name = name
self.ports = ports
self.is_external = is_external
self._is_enabled = is_enabled self._is_enabled = is_enabled
self._enable = enable self._enable = enable
self._disable = disable self._disable = disable
@ -65,32 +55,17 @@ class Service():
assert service_id not in services assert service_id not in services
services[service_id] = self services[service_id] = self
@property
def ports_details(self):
"""Retrieve details of ports associated with service."""
from plinth.modules import firewall
ports_details = []
for port in self.ports:
ports_details.append({
'name': port,
'details': firewall.get_port_details(port),
})
return ports_details
def enable(self): def enable(self):
if self._enable is None: if self._enable is None:
actions.superuser_run('service', ['enable', self.service_id]) actions.superuser_run('service', ['enable', self.service_id])
else: else:
self._call_or_return(self._enable) self._call_or_return(self._enable)
self.notify_enabled(None, True)
def disable(self): def disable(self):
if self._disable is None: if self._disable is None:
actions.superuser_run('service', ['disable', self.service_id]) actions.superuser_run('service', ['disable', self.service_id])
else: else:
self._call_or_return(self._disable) self._call_or_return(self._disable)
self.notify_enabled(None, False)
def is_enabled(self): def is_enabled(self):
"""Return whether the service is enabled.""" """Return whether the service is enabled."""
@ -105,11 +80,6 @@ class Service():
return self._call_or_return(self._is_running) return self._call_or_return(self._is_running)
def notify_enabled(self, sender, enabled):
"""Notify observers about change in state of service."""
service_enabled.send_robust(sender=sender, service_id=self.service_id,
enabled=enabled)
@staticmethod @staticmethod
def _call_or_return(obj): def _call_or_return(obj):
"""Calls obj if it's callable, returns it if it's Boolean.""" """Calls obj if it's callable, returns it if it's Boolean."""
@ -131,16 +101,3 @@ class Service():
"""Returns a list of interfaces in a firewall zone.""" """Returns a list of interfaces in a firewall zone."""
from plinth.modules import firewall from plinth.modules import firewall
return firewall.get_interfaces('internal') return firewall.get_interfaces('internal')
def init():
"""Register some misc. services that don't fit elsewhere."""
Service('http', _('Web Server'), ports=['http'], is_external=True,
is_enabled=True)
Service('https', _('Web Server over Secure Socket Layer'), ports=['https'],
is_external=True, is_enabled=True)
Service(
'plinth',
format_lazy(
_('{box_name} Web Interface (Plinth)'), box_name=_(cfg.box_name)),
ports=['https'], is_external=True, is_enabled=True)

View File

@ -20,7 +20,6 @@ Django signals emitted within FreedomBox.
from django.dispatch import Signal from django.dispatch import Signal
service_enabled = Signal(providing_args=['service_id', 'enabled'])
pre_module_loading = Signal() pre_module_loading = Signal()
post_module_loading = Signal() post_module_loading = Signal()
post_setup = Signal(providing_args=['module_name']) post_setup = Signal(providing_args=['module_name'])

View File

@ -153,6 +153,15 @@ def test_follower_component_initialization():
assert component.is_enabled() assert component.is_enabled()
def test_follower_component_set_enabled():
"""Test setting internal enabled state a follower component."""
component = FollowerComponent('test-follower-1', False)
component.set_enabled(True)
assert component.is_enabled()
component.set_enabled(False)
assert not component.is_enabled()
def test_follower_component_enable(): def test_follower_component_enable():
"""Test enabling a follower component.""" """Test enabling a follower component."""
component = FollowerComponent('test-follower-1', False) component = FollowerComponent('test-follower-1', False)