mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-04-29 10:10:19 +00:00
ssh: Option for disabling password authentication
Closes: #572 [sunil: Reload instead of restart, fix i18n strings] [sunil: Load augeas minimally, minor cosmetic fixes] Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org> Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
parent
caa336babc
commit
ddb95752a8
37
actions/ssh
37
actions/ssh
@ -15,7 +15,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Configuration helper for SSH server.
|
Configuration helper for SSH server.
|
||||||
"""
|
"""
|
||||||
@ -28,6 +27,8 @@ import stat
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import augeas
|
||||||
|
|
||||||
from plinth import action_utils
|
from plinth import action_utils
|
||||||
|
|
||||||
|
|
||||||
@ -47,6 +48,13 @@ def parse_arguments():
|
|||||||
set_keys.add_argument('--username')
|
set_keys.add_argument('--username')
|
||||||
set_keys.add_argument('--keys')
|
set_keys.add_argument('--keys')
|
||||||
|
|
||||||
|
subparsers.add_parser('get-password-config',
|
||||||
|
help='Get SSH password auth configuration')
|
||||||
|
|
||||||
|
set_password_config = subparsers.add_parser(
|
||||||
|
'set-password-config', help='Set SSH password auth configuration')
|
||||||
|
set_password_config.add_argument('--value')
|
||||||
|
|
||||||
subparsers.required = True
|
subparsers.required = True
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
@ -107,6 +115,33 @@ def subcommand_set_keys(arguments):
|
|||||||
os.chmod(key_file_path, stat.S_IRUSR | stat.S_IWUSR)
|
os.chmod(key_file_path, stat.S_IRUSR | stat.S_IWUSR)
|
||||||
|
|
||||||
|
|
||||||
|
def _load_augeas():
|
||||||
|
"""Initialize augeas for this app's configuration file."""
|
||||||
|
aug = augeas.Augeas(
|
||||||
|
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
|
aug.set('/augeas/load/Sshd/lens', 'Sshd.lns')
|
||||||
|
aug.set('/augeas/load/Sshd/incl[last() + 1]', '/etc/ssh/sshd_config')
|
||||||
|
aug.load()
|
||||||
|
|
||||||
|
return aug
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_get_password_config(_):
|
||||||
|
"""Retrieve value of password authentication from sshd configuration."""
|
||||||
|
aug = _load_augeas()
|
||||||
|
field_path = '/files/etc/ssh/sshd_config/PasswordAuthentication'
|
||||||
|
get_value = aug.get(field_path)
|
||||||
|
print(get_value or 'yes')
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_set_password_config(arguments):
|
||||||
|
"""Set value of password authentication in sshd configuration."""
|
||||||
|
aug = _load_augeas()
|
||||||
|
aug.set('/files/etc/ssh/sshd_config/PasswordAuthentication',
|
||||||
|
arguments.value)
|
||||||
|
aug.save()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Parse arguments and perform all duties."""
|
"""Parse arguments and perform all duties."""
|
||||||
arguments = parse_arguments()
|
arguments = parse_arguments()
|
||||||
|
|||||||
@ -105,3 +105,9 @@ def get_host_keys():
|
|||||||
host_keys.append(match.groupdict())
|
host_keys.append(match.groupdict())
|
||||||
|
|
||||||
return host_keys
|
return host_keys
|
||||||
|
|
||||||
|
|
||||||
|
def is_password_authentication_disabled():
|
||||||
|
"""Return if ssh password authentication is enabled."""
|
||||||
|
return actions.superuser_run('ssh',
|
||||||
|
['get-password-config']).strip() == 'no'
|
||||||
|
|||||||
35
plinth/modules/ssh/forms.py
Normal file
35
plinth/modules/ssh/forms.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
FreedomBox configuration form for OpenSSH server.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from plinth.forms import AppForm
|
||||||
|
|
||||||
|
|
||||||
|
class SSHServerForm(AppForm):
|
||||||
|
"""SSH server configuration form."""
|
||||||
|
password_auth_disabled = forms.BooleanField(
|
||||||
|
label=_('Disable password authentication'),
|
||||||
|
help_text=_('Improves security by preventing password guessing. '
|
||||||
|
'Ensure that you have setup SSH keys in your '
|
||||||
|
'administrator user account before enabling this option.'),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
@ -17,10 +17,16 @@
|
|||||||
"""
|
"""
|
||||||
Views for the SSH module
|
Views for the SSH module
|
||||||
"""
|
"""
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from plinth import action_utils, actions
|
||||||
from plinth.modules import ssh
|
from plinth.modules import ssh
|
||||||
from plinth.views import AppView
|
from plinth.views import AppView
|
||||||
|
|
||||||
|
from . import is_password_authentication_disabled
|
||||||
|
from .forms import SSHServerForm
|
||||||
|
|
||||||
|
|
||||||
class SshAppView(AppView):
|
class SshAppView(AppView):
|
||||||
app_id = 'ssh'
|
app_id = 'ssh'
|
||||||
@ -28,9 +34,43 @@ class SshAppView(AppView):
|
|||||||
description = ssh.description
|
description = ssh.description
|
||||||
port_forwarding_info = ssh.port_forwarding_info
|
port_forwarding_info = ssh.port_forwarding_info
|
||||||
template_name = 'ssh.html'
|
template_name = 'ssh.html'
|
||||||
|
form_class = SSHServerForm
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['host_keys'] = ssh.get_host_keys()
|
context['host_keys'] = ssh.get_host_keys()
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def get_initial(self):
|
||||||
|
"""Initial form value"""
|
||||||
|
initial = super().get_initial()
|
||||||
|
initial.update({
|
||||||
|
'password_auth_disabled': is_password_authentication_disabled(),
|
||||||
|
})
|
||||||
|
|
||||||
|
return initial
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
"""Apply changes from the form"""
|
||||||
|
old_config = self.get_initial()
|
||||||
|
new_config = form.cleaned_data
|
||||||
|
|
||||||
|
def is_field_changed(field):
|
||||||
|
return old_config[field] != new_config[field]
|
||||||
|
|
||||||
|
passwd_auth_changed = is_field_changed('password_auth_disabled')
|
||||||
|
if passwd_auth_changed:
|
||||||
|
if new_config['password_auth_disabled']:
|
||||||
|
passwd_auth = 'no'
|
||||||
|
message = _('SSH authentication with password disabled.')
|
||||||
|
else:
|
||||||
|
passwd_auth = 'yes'
|
||||||
|
message = _('SSH authentication with password enabled.')
|
||||||
|
|
||||||
|
actions.superuser_run(
|
||||||
|
'ssh', ['set-password-config', '--value', passwd_auth])
|
||||||
|
actions.superuser_run('service', ['reload', 'ssh'])
|
||||||
|
messages.success(self.request, message)
|
||||||
|
|
||||||
|
return super().form_valid(form)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user