2018-12-03 01:11:38 -06:00
|
|
|
# -*- coding: utf-8; -*-
|
|
|
|
################################################################################
|
|
|
|
#
|
|
|
|
# Rattail -- Retail Software Framework
|
2020-10-08 13:15:06 -05:00
|
|
|
# Copyright © 2010-2020 Lance Edgar
|
2018-12-03 01:11:38 -06:00
|
|
|
#
|
|
|
|
# This file is part of Rattail.
|
|
|
|
#
|
|
|
|
# Rattail is free software: you can redistribute it and/or modify it under the
|
|
|
|
# terms of the GNU General Public License as published by the Free Software
|
|
|
|
# Foundation, either version 3 of the License, or (at your option) any later
|
|
|
|
# version.
|
|
|
|
#
|
|
|
|
# Rattail 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 General Public License for more
|
|
|
|
# details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License along with
|
|
|
|
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#
|
|
|
|
################################################################################
|
|
|
|
"""
|
|
|
|
Fabric Library for SSH
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
2020-10-08 13:15:06 -05:00
|
|
|
def cache_host_key(c, host, port=None, user=None, **kwargs):
|
2018-12-03 01:11:38 -06:00
|
|
|
"""
|
|
|
|
Cache the SSH host key for the given host, for the given user.
|
|
|
|
"""
|
2020-10-08 13:15:06 -05:00
|
|
|
if 'for_user' in kwargs:
|
|
|
|
pass # TODO: deprecation warning
|
|
|
|
|
|
|
|
if not user and kwargs.get('for_user'):
|
|
|
|
user = kwargs['for_user']
|
|
|
|
|
|
|
|
port = '-p {}'.format(port) if port else ''
|
|
|
|
|
|
|
|
# first try to run basic command over ssh; if it works then we don't
|
|
|
|
# actually need to update/cache the host key
|
|
|
|
cmd = 'ssh {} {} whoami'.format(port, host)
|
|
|
|
if user:
|
|
|
|
result = c.sudo(cmd, warn=True, user=None if user == 'root' else user)
|
|
|
|
else:
|
|
|
|
result = c.run(cmd, warn=True)
|
|
|
|
if result.failed:
|
|
|
|
|
2020-10-09 16:09:34 -05:00
|
|
|
# basic command failed, but in some cases that is simply b/c normal
|
|
|
|
# commands are not allowed, although the ssh connection itself was
|
|
|
|
# established okay. here we check for that situation.
|
2020-10-09 16:38:19 -05:00
|
|
|
if "Disallowed command" not in result.stderr:
|
2020-10-09 16:09:34 -05:00
|
|
|
|
|
|
|
# okay then we now think that the ssh connection itself was not
|
|
|
|
# made, which presumably means we *do* need to cache the host key,
|
|
|
|
# so try that now
|
|
|
|
cmd = 'ssh -o StrictHostKeyChecking=no {} {} whoami'.format(port, host)
|
|
|
|
if user:
|
2020-10-09 16:38:19 -05:00
|
|
|
c.sudo(cmd, user=None if user == 'root' else user, warn=True)
|
2020-10-09 16:09:34 -05:00
|
|
|
else:
|
2020-10-09 16:38:19 -05:00
|
|
|
c.run(cmd, warn=True)
|
2018-12-03 01:11:38 -06:00
|
|
|
|
|
|
|
|
|
|
|
def restart(c):
|
|
|
|
"""
|
|
|
|
Restart the OpenSSH service
|
|
|
|
"""
|
|
|
|
c.sudo('systemctl restart ssh.service')
|
|
|
|
|
|
|
|
|
|
|
|
def configure(c, allow_root=False):
|
|
|
|
"""
|
|
|
|
Configure the OpenSSH service
|
|
|
|
"""
|
2019-08-10 02:41:26 -05:00
|
|
|
set_config(c, 'PermitRootLogin', 'without-password' if allow_root else 'no')
|
|
|
|
set_config(c, 'PasswordAuthentication', 'no')
|
|
|
|
restart(c)
|
2018-12-03 01:11:38 -06:00
|
|
|
|
|
|
|
|
2019-08-10 02:41:26 -05:00
|
|
|
def set_config(c, setting, value, path='/etc/ssh/sshd_config'):
|
|
|
|
"""
|
|
|
|
Configure the given SSH setting with the given value.
|
|
|
|
"""
|
|
|
|
# first check if the setting is already defined
|
|
|
|
if c.run("grep '^{} ' {}".format(setting, path), warn=True).failed:
|
2018-12-03 01:11:38 -06:00
|
|
|
|
2019-08-10 02:41:26 -05:00
|
|
|
# nope, not yet defined. maybe we can uncomment a definition?
|
|
|
|
# (note, this looks only for '#Foo' and not '# Foo' for instance)
|
|
|
|
if c.run("grep '^#{} ' {}".format(setting, path), warn=True).failed:
|
|
|
|
|
|
|
|
# nope, must tack on a new definition at end of file
|
|
|
|
c.sudo("""bash -c 'echo "{} {}" >> {}'""".format(setting, value, path))
|
|
|
|
|
|
|
|
else: # yep, uncomment existing definition, but also overwrite
|
2019-09-09 14:17:35 -05:00
|
|
|
c.sudo("sed -i.bak -e 's/^#{0} .*/{0} {1}/' {2}".format(setting, value, path))
|
2019-08-10 02:41:26 -05:00
|
|
|
|
|
|
|
else: # setting is defined, so overwrite it
|
|
|
|
c.sudo("sed -i.bak -e 's/^{0} .*/{0} {1}/' {2}".format(setting, value, path))
|