mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-09-19 04:59:01 +00:00
security: Remove restricted access setting and configuration
Closes: #2276. Functionality all over the system keeps failing due this approach. The latest is changing hostname in ejabberd Mnesia database fails (#2276). Further, users connecting FreedomBox to a monitor can't use a GUI. Tests: - Without patches, enable restricted access. Apply patches and setup.py install. Security app is updated. Restricted access is disabled and /etc/security/access.d/{50freedombox.conf, 10freedombox-security.conf, 10freedombox-performance.conf} are removed. It is possible to login into non-admin account via SSH. - On a fresh install, the configuration files are not found. - Security page does not show 'restrict console logins' option. - Updating security app setting works. Message 'Configuration updated.' is shown. - First boot succeeds. Restrict console login is not enabled. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
c20f640641
commit
253540fb3d
2
debian/freedombox.maintscript
vendored
2
debian/freedombox.maintscript
vendored
@ -23,3 +23,5 @@ rm_conffile /etc/apache2/sites-available/plinth.conf 22.16~
|
|||||||
rm_conffile /etc/apache2/sites-available/plinth-ssl.conf 22.16~
|
rm_conffile /etc/apache2/sites-available/plinth-ssl.conf 22.16~
|
||||||
rm_conffile /etc/fail2ban/jail.d/wordpress-auth-freedombox.conf 22.22~
|
rm_conffile /etc/fail2ban/jail.d/wordpress-auth-freedombox.conf 22.22~
|
||||||
rm_conffile /etc/fail2ban/filter.d/wordpress-auth-freedombox.conf 22.22~
|
rm_conffile /etc/fail2ban/filter.d/wordpress-auth-freedombox.conf 22.22~
|
||||||
|
rm_conffile /etc/security/access.d/10freedombox-performance.conf 22.25~
|
||||||
|
rm_conffile /etc/security/access.d/10freedombox-security.conf 22.25~
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
+:pcp:cron
|
|
||||||
@ -22,7 +22,7 @@ class SecurityApp(app_module.App):
|
|||||||
|
|
||||||
app_id = 'security'
|
app_id = 'security'
|
||||||
|
|
||||||
_version = 7
|
_version = 8
|
||||||
|
|
||||||
can_be_disabled = False
|
can_be_disabled = False
|
||||||
|
|
||||||
@ -57,11 +57,8 @@ class SecurityApp(app_module.App):
|
|||||||
|
|
||||||
service_privileged.reload('fail2ban')
|
service_privileged.reload('fail2ban')
|
||||||
|
|
||||||
# Migrate to new config file.
|
# Drop the legacy restriction access configuration
|
||||||
enabled = privileged.get_restricted_access_enabled()
|
privileged.disable_restricted_access()
|
||||||
set_restricted_access(False)
|
|
||||||
if enabled:
|
|
||||||
set_restricted_access(True)
|
|
||||||
|
|
||||||
|
|
||||||
def enable_fail2ban():
|
def enable_fail2ban():
|
||||||
@ -70,14 +67,6 @@ def enable_fail2ban():
|
|||||||
service_privileged.enable('fail2ban')
|
service_privileged.enable('fail2ban')
|
||||||
|
|
||||||
|
|
||||||
def set_restricted_access(enabled):
|
|
||||||
"""Enable or disable restricted access."""
|
|
||||||
if enabled:
|
|
||||||
privileged.enable_restricted_access()
|
|
||||||
else:
|
|
||||||
privileged.disable_restricted_access()
|
|
||||||
|
|
||||||
|
|
||||||
def get_apps_report():
|
def get_apps_report():
|
||||||
"""Return a security report for each app."""
|
"""Return a security report for each app."""
|
||||||
lines = subprocess.check_output(['debsecan']).decode().split('\n')
|
lines = subprocess.check_output(['debsecan']).decode().split('\n')
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
# allow debsecan cron job
|
|
||||||
+:daemon:cron
|
|
||||||
@ -9,12 +9,6 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
|
|
||||||
class SecurityForm(forms.Form):
|
class SecurityForm(forms.Form):
|
||||||
"""Security configuration form"""
|
"""Security configuration form"""
|
||||||
restricted_access = forms.BooleanField(
|
|
||||||
label=_('Restrict console logins (recommended)'), required=False,
|
|
||||||
help_text=_('When this option is enabled, only users in the "admin" '
|
|
||||||
'group will be able to log in to console or via SSH. '
|
|
||||||
'Console users may be able to access some services '
|
|
||||||
'without further authorization.'))
|
|
||||||
fail2ban_enabled = forms.BooleanField(
|
fail2ban_enabled = forms.BooleanField(
|
||||||
label=_('Fail2Ban (recommended)'), required=False,
|
label=_('Fail2Ban (recommended)'), required=False,
|
||||||
help_text=_('When this option is enabled, Fail2Ban will limit '
|
help_text=_('When this option is enabled, Fail2Ban will limit '
|
||||||
|
|||||||
@ -12,18 +12,6 @@ OLD_ACCESS_CONF_SNIPPET = '-:ALL EXCEPT root fbx (admin) (sudo):ALL'
|
|||||||
ACCESS_CONF_SNIPPETS = [OLD_ACCESS_CONF_SNIPPET, ACCESS_CONF_SNIPPET]
|
ACCESS_CONF_SNIPPETS = [OLD_ACCESS_CONF_SNIPPET, ACCESS_CONF_SNIPPET]
|
||||||
|
|
||||||
|
|
||||||
@privileged
|
|
||||||
def enable_restricted_access():
|
|
||||||
"""Restrict console login to users in admin or sudo group."""
|
|
||||||
try:
|
|
||||||
os.mkdir(os.path.dirname(ACCESS_CONF_FILE))
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
with open(ACCESS_CONF_FILE, 'w', encoding='utf-8') as conffile:
|
|
||||||
conffile.write(ACCESS_CONF_SNIPPET + '\n')
|
|
||||||
|
|
||||||
|
|
||||||
@privileged
|
@privileged
|
||||||
def disable_restricted_access():
|
def disable_restricted_access():
|
||||||
"""Don't restrict console login to users in admin or sudo group."""
|
"""Don't restrict console login to users in admin or sudo group."""
|
||||||
@ -39,18 +27,3 @@ def disable_restricted_access():
|
|||||||
os.remove(ACCESS_CONF_FILE)
|
os.remove(ACCESS_CONF_FILE)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_restricted_access_enabled():
|
|
||||||
"""Return whether restricted access is enabled."""
|
|
||||||
with open(ACCESS_CONF_FILE_OLD, 'r', encoding='utf-8') as conffile:
|
|
||||||
if any(line.strip() in ACCESS_CONF_SNIPPETS
|
|
||||||
for line in conffile.readlines()):
|
|
||||||
return True
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(ACCESS_CONF_FILE, 'r', encoding='utf-8') as conffile:
|
|
||||||
return any(line.strip() in ACCESS_CONF_SNIPPETS
|
|
||||||
for line in conffile.readlines())
|
|
||||||
except FileNotFoundError:
|
|
||||||
return False
|
|
||||||
|
|||||||
@ -16,39 +16,7 @@ def fixture_background(session_browser):
|
|||||||
functional.login(session_browser)
|
functional.login(session_browser)
|
||||||
|
|
||||||
|
|
||||||
def test_restricted_console_logins(session_browser):
|
|
||||||
"""Test enabling and disabling restricted console logins."""
|
|
||||||
_enable_restricted_logins(session_browser, False)
|
|
||||||
assert not _get_restricted_logins(session_browser)
|
|
||||||
|
|
||||||
_enable_restricted_logins(session_browser, True)
|
|
||||||
assert _get_restricted_logins(session_browser)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.backups
|
@pytest.mark.backups
|
||||||
def test_backup_restore(session_browser):
|
def test_backup_restore(session_browser):
|
||||||
"""Test backup and restore of configuration."""
|
"""Test backup and restore of configuration."""
|
||||||
_enable_restricted_logins(session_browser, True)
|
|
||||||
functional.backup_create(session_browser, 'security', 'test_security')
|
functional.backup_create(session_browser, 'security', 'test_security')
|
||||||
|
|
||||||
_enable_restricted_logins(session_browser, False)
|
|
||||||
functional.backup_restore(session_browser, 'security', 'test_security')
|
|
||||||
|
|
||||||
assert _get_restricted_logins(session_browser)
|
|
||||||
|
|
||||||
|
|
||||||
def _enable_restricted_logins(browser, should_enable):
|
|
||||||
"""Enable/disable restricted logins in security module."""
|
|
||||||
functional.nav_to_module(browser, 'security')
|
|
||||||
if should_enable:
|
|
||||||
browser.check('security-restricted_access')
|
|
||||||
else:
|
|
||||||
browser.uncheck('security-restricted_access')
|
|
||||||
|
|
||||||
functional.submit(browser, form_class='form-configuration')
|
|
||||||
|
|
||||||
|
|
||||||
def _get_restricted_logins(browser):
|
|
||||||
"""Return whether restricted console logins is enabled."""
|
|
||||||
functional.nav_to_module(browser, 'security')
|
|
||||||
return browser.find_by_name('security-restricted_access').first.checked
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@ from plinth.modules.upgrades import is_backports_requested
|
|||||||
from plinth.privileged import service as service_privileged
|
from plinth.privileged import service as service_privileged
|
||||||
from plinth.views import AppView
|
from plinth.views import AppView
|
||||||
|
|
||||||
from . import privileged
|
|
||||||
from .forms import SecurityForm
|
from .forms import SecurityForm
|
||||||
|
|
||||||
|
|
||||||
@ -43,31 +42,19 @@ class SecurityAppView(AppView):
|
|||||||
|
|
||||||
def get_status(request):
|
def get_status(request):
|
||||||
"""Return the current status."""
|
"""Return the current status."""
|
||||||
return {
|
return {'fail2ban_enabled': action_utils.service_is_enabled('fail2ban')}
|
||||||
'restricted_access': privileged.get_restricted_access_enabled(),
|
|
||||||
'fail2ban_enabled': action_utils.service_is_enabled('fail2ban')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _apply_changes(request, old_status, new_status):
|
def _apply_changes(request, old_status, new_status):
|
||||||
"""Apply the form changes."""
|
"""Apply the form changes."""
|
||||||
if old_status['restricted_access'] != new_status['restricted_access']:
|
|
||||||
try:
|
|
||||||
security.set_restricted_access(new_status['restricted_access'])
|
|
||||||
except Exception as exception:
|
|
||||||
messages.error(
|
|
||||||
request,
|
|
||||||
_('Error setting restricted access: {exception}').format(
|
|
||||||
exception=exception))
|
|
||||||
else:
|
|
||||||
messages.success(request, _('Updated security configuration'))
|
|
||||||
|
|
||||||
if old_status['fail2ban_enabled'] != new_status['fail2ban_enabled']:
|
if old_status['fail2ban_enabled'] != new_status['fail2ban_enabled']:
|
||||||
if new_status['fail2ban_enabled']:
|
if new_status['fail2ban_enabled']:
|
||||||
service_privileged.enable('fail2ban')
|
service_privileged.enable('fail2ban')
|
||||||
else:
|
else:
|
||||||
service_privileged.disable('fail2ban')
|
service_privileged.disable('fail2ban')
|
||||||
|
|
||||||
|
messages.success(request, _('Configuration updated.'))
|
||||||
|
|
||||||
|
|
||||||
def report(request):
|
def report(request):
|
||||||
"""Serve the security report page."""
|
"""Serve the security report page."""
|
||||||
|
|||||||
@ -18,7 +18,6 @@ from django.utils.translation import gettext_lazy
|
|||||||
import plinth.forms
|
import plinth.forms
|
||||||
import plinth.modules.ssh.privileged as ssh_privileged
|
import plinth.modules.ssh.privileged as ssh_privileged
|
||||||
from plinth.modules import first_boot
|
from plinth.modules import first_boot
|
||||||
from plinth.modules.security import set_restricted_access
|
|
||||||
from plinth.utils import is_user_admin
|
from plinth.utils import is_user_admin
|
||||||
|
|
||||||
from . import get_last_admin_user, privileged
|
from . import get_last_admin_user, privileged
|
||||||
@ -392,15 +391,6 @@ class FirstBootForm(ValidNewUsernameCheckMixin, auth.forms.UserCreationForm):
|
|||||||
self.login_user(self.cleaned_data['username'],
|
self.login_user(self.cleaned_data['username'],
|
||||||
self.cleaned_data['password1'])
|
self.cleaned_data['password1'])
|
||||||
|
|
||||||
# Restrict console login to users in admin or sudo group
|
|
||||||
try:
|
|
||||||
set_restricted_access(True)
|
|
||||||
except Exception as error:
|
|
||||||
messages.error(
|
|
||||||
self.request,
|
|
||||||
_('Failed to restrict console access: {error}'.format(
|
|
||||||
error=error)))
|
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def login_user(self, username, password):
|
def login_user(self, username, password):
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import subprocess
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from plinth import action_utils
|
from plinth import action_utils
|
||||||
from plinth.modules.security import privileged as security_privileged
|
|
||||||
from plinth.modules.users import privileged
|
from plinth.modules.users import privileged
|
||||||
from plinth.tests import config as test_config
|
from plinth.tests import config as test_config
|
||||||
|
|
||||||
@ -87,18 +86,6 @@ def _try_login_to_ssh(username, password, returncode=0):
|
|||||||
return process.returncode == returncode
|
return process.returncode == returncode
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name='disable_restricted_access', autouse=True)
|
|
||||||
def fixture_disable_restricted_access(needs_root, load_cfg):
|
|
||||||
"""Disable console login restrictions."""
|
|
||||||
restricted_access = security_privileged.get_restricted_access_enabled()
|
|
||||||
if restricted_access:
|
|
||||||
security_privileged.disable_restricted_access()
|
|
||||||
yield
|
|
||||||
security_privileged.enable_restricted_access()
|
|
||||||
else:
|
|
||||||
yield
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name='auto_cleanup_users_groups', autouse=True)
|
@pytest.fixture(name='auto_cleanup_users_groups', autouse=True)
|
||||||
def fixture_auto_cleanup_users_groups(needs_root, load_cfg):
|
def fixture_auto_cleanup_users_groups(needs_root, load_cfg):
|
||||||
"""Remove all the users and groups created during tests."""
|
"""Remove all the users and groups created during tests."""
|
||||||
|
|||||||
4
setup.py
4
setup.py
@ -2,6 +2,8 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
"""
|
"""
|
||||||
FreedomBox Service setup file.
|
FreedomBox Service setup file.
|
||||||
|
|
||||||
|
isort:skip_file
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
@ -55,6 +57,8 @@ REMOVED_FILES = [
|
|||||||
'/etc/apt/preferences.d/50freedombox3.pref',
|
'/etc/apt/preferences.d/50freedombox3.pref',
|
||||||
'/etc/apache2/sites-available/plinth.conf',
|
'/etc/apache2/sites-available/plinth.conf',
|
||||||
'/etc/apache2/sites-available/plinth-ssl.conf',
|
'/etc/apache2/sites-available/plinth-ssl.conf',
|
||||||
|
'/etc/security/access.d/10freedombox-performance.conf',
|
||||||
|
'/etc/security/access.d/10freedombox-security.conf',
|
||||||
]
|
]
|
||||||
|
|
||||||
LOCALE_PATHS = ['plinth/locale']
|
LOCALE_PATHS = ['plinth/locale']
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user