From 9fe7743a67c2cd421578fe7f924e979b54bb8cde Mon Sep 17 00:00:00 2001 From: Antoine Catton <acatton@tiolive.com> Date: Thu, 3 Nov 2011 13:54:47 +0100 Subject: [PATCH] Add dropbear generic recipe --- setup.py | 2 + slapos/recipe/dropbear.py | 121 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 slapos/recipe/dropbear.py diff --git a/setup.py b/setup.py index 1303f354..bc3d7ae5 100644 --- a/setup.py +++ b/setup.py @@ -47,6 +47,8 @@ setup(name=name, 'cron.d = slapos.recipe.dcron:Part', 'download = slapos.recipe.download:Recipe', 'davstorage = slapos.recipe.davstorage:Recipe', + 'dropbear = slapos.recipe.dropbear:Recipe', + 'dropbear.add_authorized_key = slapos.recipe.dropbear:AddAuthorizedKey', 'duplicity = slapos.recipe.duplicity:Recipe', 'erp5 = slapos.recipe.erp5:Recipe', 'erp5testnode = slapos.recipe.erp5testnode:Recipe', diff --git a/slapos/recipe/dropbear.py b/slapos/recipe/dropbear.py new file mode 100644 index 00000000..ac323b8f --- /dev/null +++ b/slapos/recipe/dropbear.py @@ -0,0 +1,121 @@ +############################################################################## +# +# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved. +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# guarantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program 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. +# +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## +import os +import itertools +from slapos.recipe.librecipe import GenericBaseRecipe + +class AuthorizedKeysFile(object): + + def __init__(self, filename): + self.filename = filename + + def append(self, key): + """Append the key to the file if the key's not in the file + """ + # Create the file it it does not exist + try: + file_ = os.open(self.filename, os.O_CREAT | os.O_EXCL) + os.close(file_) + except: + pass + + with open(self.filename, 'r') as keyfile: + # itertools.imap avoid loading all the authorized_keys file in + # memory which would be counterproductive. + present = (key.strip() in itertools.imap(lambda k: k.strip(), + keyfile)) + try: + keyfile.seek(-1, os.SEEK_END) + ended_by_newline = (keyfile.read() == '\n') + except IOError: + ended_by_newline = True + + if not present: + with open(self.filename, 'a') as keyfile: + if not ended_by_newline: + keyfile.write('\n') + keyfile.write(key.strip()) + +class Recipe(GenericBaseRecipe): + + def install(self): + path_list = [] + + dropbear_cmd = [self.options['dropbear-binary']] + # Don't fork into background + dropbear_cmd.append('-F') + # Log on stderr + dropbear_cmd.append('-E') + # Don't display motd + dropbear_cmd.append('-m') + # Disable password login + dropbear_cmd.extend(['-s', '-g']) + # Disable port forwarding + dropbear_cmd.extend(['-j', '-k']) + + host = self.options['host'] + if ':' in host: + host = '[%s]' % host + port = self.options['port'] + binding_address = '%s:%s' % (host, port) + dropbear_cmd.extend(['-p', binding_address]) + # Single user mode + dropbear_cmd.append('-n') + + if 'dss-keyfile' in self.options: + dropbear_cmd.extend(['-d', self.options['dss-keyfile']]) + else: + dropbear_cmd.extend(['-r', self.options['rsa-keyfile']]) + + env = {} + if 'home' in self.options: + env['DROPBEAR_OVERRIDE_HOME'] = self.options['home'] + + if 'shell' in self.options: + env['DROPBEAR_OVERRIDE_SHELL'] = self.options['shell'] + + wrapper = self.createPythonScript( + self.options['wrapper'], + 'slapos.recipe.librecipe.execute.executee', + (dropbear_cmd, env, ) + ) + path_list.append(wrapper) + + return path_list + +class AddAuthorizedKey(GenericBaseRecipe): + + def install(self): + path_list = [] + + ssh = self.createDirectory(self.options['home'], '.ssh') + path_list.append(ssh) + + authorized_keys = AuthorizedKeysFile(os.path.join(ssh, 'authorized_keys')) + authorized_keys.append(self.options['key']) + + return path_list -- 2.30.9