Simplify sshd config loading to make it use one set of functions/objects/classes

This commit is contained in:
Joshua Harlow
2012-06-21 12:30:32 -07:00
parent 4014179a6c
commit 56c8607164
2 changed files with 61 additions and 31 deletions

View File

@@ -20,6 +20,7 @@
import sys import sys
from cloudinit import ssh_util
from cloudinit import util from cloudinit import util
from string import letters, digits # pylint: disable=W0402 from string import letters, digits # pylint: disable=W0402
@@ -101,39 +102,31 @@ def handle(_name, cfg, cloud, log, args):
pw_auth = 'no' pw_auth = 'no'
if change_pwauth: if change_pwauth:
new_lines = []
replaced_auth = False replaced_auth = False
replacement = "PasswordAuthentication %s" % (pw_auth)
# See http://linux.die.net/man/5/sshd_config # See: man sshd_config
conf_fn = cloud.paths.join(True, '/etc/ssh/sshd_config') conf_fn = cloud.paths.join(True, ssh_util.DEF_SSHD_CFG)
# Todo: use the common ssh_util function for this parsing... old_lines = ssh_util.parse_ssh_config(conf_fn)
old_lines = util.load_file(conf_fn).splitlines() new_lines = []
for i, line in enumerate(old_lines): i = 0
if not line.strip() or line.startswith("#"): for (i, line) in enumerate(old_lines):
new_lines.append(line)
continue
splitup = line.split(None, 1)
if len(splitup) <= 1:
new_lines.append(line)
continue
(cmd, args) = splitup
# Keywords are case-insensitive and arguments are case-sensitive # Keywords are case-insensitive and arguments are case-sensitive
cmd = cmd.lower().strip() if line.key == 'passwordauthentication':
if cmd == 'passwordauthentication': log.debug("Replacing auth line %s with %s", i + 1, pw_auth)
log.debug("Replacing auth line %s with %s", i + 1, replacement)
replaced_auth = True replaced_auth = True
new_lines.append(replacement) line.value = pw_auth
else: new_lines.append(line)
new_lines.append(line)
if not replaced_auth: if not replaced_auth:
log.debug("Adding new auth line %s", replacement) log.debug("Adding new auth line %s", i + 1)
replaced_auth = True replaced_auth = True
new_lines.append(replacement) new_lines.append(ssh_util.SshdConfigLine('',
'PasswordAuthentication',
pw_auth))
util.write_file(cloud.paths.join(False, '/etc/ssh/sshd_config'), lines = [str(e) for e in new_lines]
"\n".join(new_lines)) ssh_rw_fn = cloud.paths.join(False, ssh_util.DEF_SSHD_CFG)
util.write_file(ssh_rw_fn, "\n".join(lines))
try: try:
cmd = ['service'] cmd = ['service']

View File

@@ -29,6 +29,8 @@ from cloudinit import log as logging
from cloudinit import util from cloudinit import util
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
# See: man sshd_config
DEF_SSHD_CFG = "/etc/ssh/sshd_config" DEF_SSHD_CFG = "/etc/ssh/sshd_config"
@@ -233,7 +235,7 @@ def setup_user_keys(keys, user, key_prefix, paths):
# The following tokens are defined: %% is replaced by a literal # The following tokens are defined: %% is replaced by a literal
# '%', %h is replaced by the home directory of the user being # '%', %h is replaced by the home directory of the user being
# authenticated and %u is replaced by the username of that user. # authenticated and %u is replaced by the username of that user.
ssh_cfg = parse_ssh_config(sshd_conf_fn) ssh_cfg = parse_ssh_config_map(sshd_conf_fn)
akeys = ssh_cfg.get("authorizedkeysfile", '') akeys = ssh_cfg.get("authorizedkeysfile", '')
akeys = akeys.strip() akeys = akeys.strip()
if not akeys: if not akeys:
@@ -258,19 +260,54 @@ def setup_user_keys(keys, user, key_prefix, paths):
util.chownbyid(authorized_keys, pwent.pw_uid, pwent.pw_gid) util.chownbyid(authorized_keys, pwent.pw_uid, pwent.pw_gid)
class SshdConfigLine(object):
def __init__(self, line, k=None, v=None):
self.line = line
self._key = k
self.value = v
@property
def key(self):
if self._key is None:
return None
# Keywords are case-insensitive
return self._key.lower()
def __str__(self):
if self._key is None:
return str(self.line)
else:
v = str(self._key)
if self.value:
v += " " + str(self.value)
return v
def parse_ssh_config(fname): def parse_ssh_config(fname):
# See: man sshd_config
# The file contains keyword-argument pairs, one per line. # The file contains keyword-argument pairs, one per line.
# Lines starting with '#' and empty lines are interpreted as comments. # Lines starting with '#' and empty lines are interpreted as comments.
# Note: key-words are case-insensitive and arguments are case-sensitive # Note: key-words are case-insensitive and arguments are case-sensitive
ret = {} lines = []
if not os.path.isfile(fname): if not os.path.isfile(fname):
return ret return lines
for line in util.load_file(fname).splitlines(): for line in util.load_file(fname).splitlines():
line = line.strip() line = line.strip()
if not line or line.startswith("#"): if not line or line.startswith("#"):
lines.append(SshdConfigLine(line))
continue continue
(key, val) = line.split(None, 1) (key, val) = line.split(None, 1)
key = key.strip().lower() lines.append(SshdConfigLine(line, key, val))
if key: return lines
ret[key] = val
def parse_ssh_config_map(fname):
lines = parse_ssh_config(fname)
if not lines:
return {}
ret = {}
for line in lines:
if not line.key:
continue
ret[line.key] = line.value
return ret return ret