summaryrefslogtreecommitdiff
path: root/cloudinit/SshUtil.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/SshUtil.py')
-rw-r--r--cloudinit/SshUtil.py227
1 files changed, 0 insertions, 227 deletions
diff --git a/cloudinit/SshUtil.py b/cloudinit/SshUtil.py
deleted file mode 100644
index a081fbe8..00000000
--- a/cloudinit/SshUtil.py
+++ /dev/null
@@ -1,227 +0,0 @@
-#!/usr/bin/python
-# vi: ts=4 expandtab
-#
-# Copyright (C) 2012 Canonical Ltd.
-# Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
-#
-# Author: Scott Moser <scott.moser@canonical.com>
-# Author: Juerg Hafliger <juerg.haefliger@hp.com>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3, as
-# published by the Free Software Foundation.
-#
-# 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-import os.path
-import cloudinit.util as util
-
-
-class AuthKeyEntry():
- # lines are options, keytype, base64-encoded key, comment
- # man page says the following which I did not understand:
- # The options field is optional; its presence is determined by whether
- # the line starts with a number or not (the options field never starts
- # with a number)
- options = None
- keytype = None
- base64 = None
- comment = None
- is_comment = False
- line_in = ""
-
- def __init__(self, line, def_opt=None):
- line = line.rstrip("\n\r")
- self.line_in = line
- if line.startswith("#") or line.strip() == "":
- self.is_comment = True
- else:
- ent = line.strip()
- toks = ent.split(None, 3)
- if len(toks) == 1:
- self.base64 = toks[0]
- elif len(toks) == 2:
- (self.base64, self.comment) = toks
- elif len(toks) == 3:
- (self.keytype, self.base64, self.comment) = toks
- elif len(toks) == 4:
- i = 0
- ent = line.strip()
- quoted = False
- # taken from auth_rsa_key_allowed in auth-rsa.c
- try:
- while (i < len(ent) and
- ((quoted) or (ent[i] not in (" ", "\t")))):
- curc = ent[i]
- nextc = ent[i + 1]
- if curc == "\\" and nextc == '"':
- i = i + 1
- elif curc == '"':
- quoted = not quoted
- i = i + 1
- except IndexError:
- self.is_comment = True
- return
-
- try:
- self.options = ent[0:i]
- (self.keytype, self.base64, self.comment) = \
- ent[i + 1:].split(None, 3)
- except ValueError:
- # we did not understand this line
- self.is_comment = True
-
- if self.options == None and def_opt:
- self.options = def_opt
-
- return
-
- def debug(self):
- print("line_in=%s\ncomment: %s\noptions=%s\nkeytype=%s\nbase64=%s\n"
- "comment=%s\n" % (self.line_in, self.is_comment, self.options,
- self.keytype, self.base64, self.comment)),
-
- def __repr__(self):
- if self.is_comment:
- return(self.line_in)
- else:
- toks = []
- for e in (self.options, self.keytype, self.base64, self.comment):
- if e:
- toks.append(e)
-
- return(' '.join(toks))
-
-
-def update_authorized_keys(fname, keys):
- # keys is a list of AuthKeyEntries
- # key_prefix is the prefix (options) to prepend
- try:
- fp = open(fname, "r")
- lines = fp.readlines() # lines have carriage return
- fp.close()
- except IOError:
- lines = []
-
- ka_stats = {} # keys_added status
- for k in keys:
- ka_stats[k] = False
-
- to_add = []
- for key in keys:
- to_add.append(key)
-
- for i in range(0, len(lines)):
- ent = AuthKeyEntry(lines[i])
- for k in keys:
- if k.base64 == ent.base64 and not k.is_comment:
- ent = k
- try:
- to_add.remove(k)
- except ValueError:
- pass
- lines[i] = str(ent)
-
- # now append any entries we did not match above
- for key in to_add:
- lines.append(str(key))
-
- if len(lines) == 0:
- return("")
- else:
- return('\n'.join(lines) + "\n")
-
-
-def setup_user_keys(keys, user, key_prefix, log=None):
- import pwd
- saved_umask = os.umask(077)
-
- pwent = pwd.getpwnam(user)
-
- ssh_dir = '%s/.ssh' % pwent.pw_dir
- if not os.path.exists(ssh_dir):
- os.mkdir(ssh_dir)
- os.chown(ssh_dir, pwent.pw_uid, pwent.pw_gid)
-
- try:
- ssh_cfg = parse_ssh_config()
- akeys = ssh_cfg.get("AuthorizedKeysFile", "%h/.ssh/authorized_keys")
- akeys = akeys.replace("%h", pwent.pw_dir)
- akeys = akeys.replace("%u", user)
- if not akeys.startswith('/'):
- akeys = os.path.join(pwent.pw_dir, akeys)
- authorized_keys = akeys
- except Exception:
- authorized_keys = '%s/.ssh/authorized_keys' % pwent.pw_dir
- if log:
- util.logexc(log)
-
- key_entries = []
- for k in keys:
- ke = AuthKeyEntry(k, def_opt=key_prefix)
- key_entries.append(ke)
-
- content = update_authorized_keys(authorized_keys, key_entries)
- util.write_file(authorized_keys, content, 0600)
-
- os.chown(authorized_keys, pwent.pw_uid, pwent.pw_gid)
- util.restorecon_if_possible(ssh_dir, recursive=True)
-
- os.umask(saved_umask)
-
-
-def parse_ssh_config(fname="/etc/ssh/sshd_config"):
- ret = {}
- fp = open(fname)
- for l in fp.readlines():
- l = l.strip()
- if not l or l.startswith("#"):
- continue
- key, val = l.split(None, 1)
- ret[key] = val
- fp.close()
- return(ret)
-
-if __name__ == "__main__":
- def main():
- import sys
- # usage: orig_file, new_keys, [key_prefix]
- # prints out merged, where 'new_keys' will trump old
- ## example
- ## ### begin auth_keys ###
- # ssh-rsa AAAAB3NzaC1xxxxxxxxxV3csgm8cJn7UveKHkYjJp8= smoser-work
- # ssh-rsa AAAAB3NzaC1xxxxxxxxxCmXp5Kt5/82cD/VN3NtHw== smoser@brickies
- # ### end authorized_keys ###
- #
- # ### begin new_keys ###
- # ssh-rsa nonmatch smoser@newhost
- # ssh-rsa AAAAB3NzaC1xxxxxxxxxV3csgm8cJn7UveKHkYjJp8= new_comment
- # ### end new_keys ###
- #
- # Then run as:
- # program auth_keys new_keys \
- # 'no-port-forwarding,command=\"echo hi world;\"'
- def_prefix = None
- orig_key_file = sys.argv[1]
- new_key_file = sys.argv[2]
- if len(sys.argv) > 3:
- def_prefix = sys.argv[3]
- fp = open(new_key_file)
-
- newkeys = []
- for line in fp.readlines():
- newkeys.append(AuthKeyEntry(line, def_prefix))
-
- fp.close()
- print update_authorized_keys(orig_key_file, newkeys)
-
- main()
-
-# vi: ts=4 expandtab