diff --git a/slapos/recipe/kumofs/__init__.py b/slapos/recipe/kumofs/__init__.py index c8c341c52401c589e6b7afcc21aed606ab169893..6372f009c8652b48b54c1d3f6adc87fe87ba2daf 100644 --- a/slapos/recipe/kumofs/__init__.py +++ b/slapos/recipe/kumofs/__init__.py @@ -25,10 +25,12 @@ # ############################################################################## from slapos.recipe.librecipe import BaseSlapRecipe +import hashlib import os import pkg_resources +import sys import zc.buildout -import zc.recipe.egg +import ConfigParser class Recipe(BaseSlapRecipe): def getTemplateFilename(self, template_name): @@ -45,7 +47,7 @@ class Recipe(BaseSlapRecipe): key, certificate = self.requestCertificate('Login Based Access') stunnel_conf = self.installStunnel(self.getGlobalIPv6Address(), 12345, - kumo_conf_conf['kumo_gateway_port'], + kumo_conf['kumo_gateway_port'], certificate, key, ca_conf['ca_crl'], ca_conf['certificate_authority_path']) @@ -79,6 +81,153 @@ class Recipe(BaseSlapRecipe): self.logger.debug('Created link %r -> %r' % (link, target)) self.path_list.append(link) + + def installCrond(self): + timestamps = self.createDataDirectory('cronstamps') + cron_output = os.path.join(self.log_directory, 'cron-output') + self._createDirectory(cron_output) + catcher = zc.buildout.easy_install.scripts([('catchcron', + __name__ + '.catdatefile', 'catdatefile')], self.ws, sys.executable, + self.bin_directory, arguments=[cron_output])[0] + self.path_list.append(catcher) + cron_d = os.path.join(self.etc_directory, 'cron.d') + crontabs = os.path.join(self.etc_directory, 'crontabs') + self._createDirectory(cron_d) + self._createDirectory(crontabs) + # Use execute from erp5. + wrapper = zc.buildout.easy_install.scripts([('crond', + 'slapos.recipe.erp5.execute', 'execute')], self.ws, sys.executable, + self.wrapper_directory, arguments=[ + self.options['dcrond_binary'].strip(), '-s', cron_d, '-c', crontabs, + '-t', timestamps, '-f', '-l', '5', '-M', catcher] + )[0] + self.path_list.append(wrapper) + return cron_d + + def installLogrotate(self): + """Installs logortate main configuration file and registers its to cron""" + logrotate_d = os.path.abspath(os.path.join(self.etc_directory, + 'logrotate.d')) + self._createDirectory(logrotate_d) + logrotate_backup = self.createBackupDirectory('logrotate') + logrotate_conf = self.createConfigurationFile("logrotate.conf", + "include %s" % logrotate_d) + logrotate_cron = os.path.join(self.cron_d, 'logrotate') + state_file = os.path.join(self.data_root_directory, 'logrotate.status') + open(logrotate_cron, 'w').write('0 0 * * * %s -s %s %s' % + (self.options['logrotate_binary'], state_file, logrotate_conf)) + self.path_list.extend([logrotate_d, logrotate_conf, logrotate_cron]) + return logrotate_d, logrotate_backup + + def registerLogRotation(self, name, log_file_list, postrotate_script): + """Register new log rotation requirement""" + open(os.path.join(self.logrotate_d, name), 'w').write( + self.substituteTemplate(self.getTemplateFilename( + 'logrotate_entry.in'), + dict(file_list=' '.join(['"'+q+'"' for q in log_file_list]), + postrotate=postrotate_script, olddir=self.logrotate_backup))) + + def installCertificateAuthority(self, ca_country_code='XX', + ca_email='xx@example.com', ca_state='State', ca_city='City', + ca_company='Company'): + backup_path = self.createBackupDirectory('ca') + self.ca_dir = os.path.join(self.data_root_directory, 'ca') + self._createDirectory(self.ca_dir) + self.ca_request_dir = os.path.join(self.ca_dir, 'requests') + self._createDirectory(self.ca_request_dir) + config = dict(ca_dir=self.ca_dir, request_dir=self.ca_request_dir) + self.ca_private = os.path.join(self.ca_dir, 'private') + self.ca_certs = os.path.join(self.ca_dir, 'certs') + self.ca_crl = os.path.join(self.ca_dir, 'crl') + self.ca_newcerts = os.path.join(self.ca_dir, 'newcerts') + self.ca_key_ext = '.key' + self.ca_crt_ext = '.crt' + for d in [self.ca_private, self.ca_crl, self.ca_newcerts, self.ca_certs]: + self._createDirectory(d) + for f in ['crlnumber', 'serial']: + if not os.path.exists(os.path.join(self.ca_dir, f)): + open(os.path.join(self.ca_dir, f), 'w').write('01') + if not os.path.exists(os.path.join(self.ca_dir, 'index.txt')): + open(os.path.join(self.ca_dir, 'index.txt'), 'w').write('') + openssl_configuration = os.path.join(self.ca_dir, 'openssl.cnf') + config.update( + working_directory=self.ca_dir, + country_code=ca_country_code, + state=ca_state, + city=ca_city, + company=ca_company, + email_address=ca_email, + ) + self._writeFile(openssl_configuration, pkg_resources.resource_string( + __name__, 'template/openssl.cnf.ca.in') % config) + self.path_list.extend(zc.buildout.easy_install.scripts([ + ('certificate_authority', + __name__ + '.certificate_authority', 'runCertificateAuthority')], + self.ws, sys.executable, self.wrapper_directory, arguments=[dict( + openssl_configuration=openssl_configuration, + openssl_binary=self.options['openssl_binary'], + certificate=os.path.join(self.ca_dir, 'cacert.pem'), + key=os.path.join(self.ca_private, 'cakey.pem'), + crl=os.path.join(self.ca_crl), + request_dir=self.ca_request_dir + )])) + # configure backup + backup_cron = os.path.join(self.cron_d, 'ca_rdiff_backup') + open(backup_cron, 'w').write( + '''0 0 * * * %(rdiff_backup)s %(source)s %(destination)s'''%dict( + rdiff_backup=self.options['rdiff_backup_binary'], + source=self.ca_dir, + destination=backup_path)) + self.path_list.append(backup_cron) + + return dict( + ca_certificate=os.path.join(config['ca_dir'], 'cacert.pem'), + ca_crl=os.path.join(config['ca_dir'], 'crl'), + certificate_authority_path=config['ca_dir'] + ) + + def requestCertificate(self, name): + hash = hashlib.sha512(name).hexdigest() + key = os.path.join(self.ca_private, hash + self.ca_key_ext) + certificate = os.path.join(self.ca_certs, hash + self.ca_crt_ext) + parser = ConfigParser.RawConfigParser() + parser.add_section('certificate') + parser.set('certificate', 'name', name) + parser.set('certificate', 'key_file', key) + parser.set('certificate', 'certificate_file', certificate) + parser.write(open(os.path.join(self.ca_request_dir, hash), 'w')) + return key, certificate + + def installStunnel(self, ip, port, external_port, + ca_certificate, key, ca_crl, ca_path): + """Installs stunnel""" + template_filename = self.getTemplateFilename('stunnel.conf.in') + log = os.path.join(self.log_directory, 'stunnel.log') + pid_file = os.path.join(self.run_directory, 'stunnel.pid') + stunnel_conf = dict( + ipv6=ip, + ipv4=self.getLocalIPv4Address, + port=port, + pid_file=pid_file, + log=log, + cert = ca_certificate, + key = key, + ca_crl = ca_crl, + ca_path = ca_path, + external_port = external_port, + ) + stunnel_conf_path = self.createConfigurationFile("stunnel.conf", + self.substituteTemplate(template_filename, + stunnel_conf)) + wrapper = zc.buildout.easy_install.scripts([('stunnel', + 'slapos.recipe.erp5.execute', 'execute')], self.ws, sys.executable, + self.wrapper_directory, arguments=[ + self.options['stunnel_binary'].strip(), stunnel_conf_path] + )[0] + self.path_list.append(wrapper) + + return stunnel_conf + def installKumo(self, ip, kumo_manager_port=13101, kumo_server_port=13201, kumo_server_listen_port=13202, kumo_gateway_port=13301): # XXX: kumo is not storing pid in file, unless it is not running as daemon