def check_signature(pkg): """Check package signature if /etc/ssl/certs exists""" if not os.path.exists('/etc/ssl/certs'): return True if not waptpackage.PackageEntry( waptfile=pkg.localpath).check_control_signature( SSLCABundle('/etc/ssl/certs')): return False return True
def resign_crl(): """Check validity of CRL and resign it if it will expire before next round. """ if (conf['clients_signing_key'] and conf['clients_signing_certificate'] and conf['clients_signing_crl'] and \ os.path.isfile(conf['clients_signing_key']) and os.path.isfile(conf['clients_signing_certificate'])): signing_key = SSLPrivateKey(conf['clients_signing_key']) signing_cert = SSLCertificate(conf['clients_signing_certificate']) server_ca = SSLCABundle(conf['clients_signing_certificate']) logger.info('Resigning CRL %s' % conf['clients_signing_crl']) try: crl = SSLCRL(conf['clients_signing_crl'], cakey=signing_key, cacert=signing_cert) if not crl.crl or crl.next_update <= datetime.datetime.utcnow( ) + datetime.timedelta(hours=1): crl.revoke_cert(crl_ttl_days=conf['clients_signing_crl_days']) crl.save_as_pem() except Exception as e: logger.warning('Unable to sign CRL %s: %s' % (conf['clients_signing_crl'], repr(e)))
def add_ads_groups(waptconfigfile, hostdicts_list, sign_certs=None, sign_key=None, key_password=None, wapt_server_user=None, wapt_server_passwd=None, cabundle=None): if sign_certs is None: sign_bundle_fn = inifile_readstring(waptconfigfile, u'global', u'personal_certificate_path') sign_bundle = SSLCABundle(sign_bundle_fn) sign_certs = sign_bundle.certificates() # we assume a unique signer. if cabundle is None: cabundle = sign_bundle if not sign_certs: raise Exception(u'No personal signer certificate found in %s' % sign_bundle_fn) if sign_key is None: sign_key = sign_certs[0].matching_key_in_dirs( private_key_password=key_password) try: import waptconsole progress_hook = waptconsole.UpdateProgress private_key_password_callback = waptconsole.GetPrivateKeyPassword except ImportError as e: def print_progress(show=False, n=0, max=100, msg=''): if show: print('%s %s/%s\r' % (msg, n, max), end='') else: if not msg: msg = 'Done' print("%s%s" % (msg, ' ' * (80 - len(msg)))) progress_hook = print_progress private_key_password_callback = None main_repo = WaptRemoteRepo(name='wapt', cabundle=cabundle) main_repo.load_config_from_file(waptconfigfile) main_repo.private_key_password_callback = private_key_password_callback host_repo = WaptHostRepo(name='wapt-host', host_id=[h['uuid'] for h in hostdicts_list], cabundle=cabundle) host_repo.load_config_from_file(waptconfigfile) host_repo.private_key_password_callback = private_key_password_callback total_hosts = len(host_repo.packages()) discarded_uuids = [p.package for p in host_repo.discarded] packages = [] discarded = [] unchanged = [] try: progress_hook(True, 0, len(hostdicts_list), 'Editing %s hosts' % len(hostdicts_list)) i = 0 for h in hostdicts_list: try: host_package = None host_id = h['uuid'] hostname = h['computer_name'] groups = get_computer_groups(hostname) host_package = host_repo.get( host_id, PackageEntry(package=host_id, section='host')) if progress_hook(True, i, len(hostdicts_list), 'Checking %s' % host_package.package): break wapt_groups = ensure_list(host_package['depends']) additional = [ group for group in groups if not group in wapt_groups and ( main_repo.get(group, None) is not None) ] if additional: logger.info(u'Adding %s to %s' % (','.join(additional), host_package.package)) if progress_hook(True, i, len(hostdicts_list), 'Editing %s' % host_package.package): break wapt_groups.extend(additional) host_package.depends = ','.join(wapt_groups) host_package.build_management_package() host_package.inc_build() host_file = host_package.build_management_package() host_package.sign_package(sign_certs, sign_key) packages.append(host_package) else: unchanged.append(host_package.package) except Exception as e: if host_package: discarded.append(host_package.package) logger.critical(u'Discarding because %s' % ensure_unicode(e)) # upload all in one step... progress_hook(True, 3, 3, 'Upload %s host packages' % len(packages)) server = WaptServer().load_config_from_file(waptconfigfile) server.private_key_password_callback = private_key_password_callback server.upload_packages(packages, auth=(wapt_server_user, wapt_server_passwd), progress_hook=progress_hook) return dict(updated=packages, discarded=discarded, unchanged=unchanged) finally: logger.debug('Cleanup') try: i = 0 for s in packages: i += 1 progress_hook(True, i, len(packages), 'Cleanup') if os.path.isfile(s.localpath): os.remove(s.localpath) progress_hook(False) except WindowsError as e: logger.critical('Unable to remove temporary directory %s: %s' % (s, repr(e))) progress_hook(False)
def edit_hosts_depends( waptconfigfile, hosts_list, append_depends=[], remove_depends=[], append_conflicts=[], remove_conflicts=[], sign_certs=None, sign_key=None, key_password=None, wapt_server_user=None, wapt_server_passwd=None, cabundle=None, ): """Add or remove packages from host packages Args: Returns: dict: { updated: of uuid of machines actually updated unchanged : list of uuid skipped because of no change needed discarded : list of uuid discarded due to errors} >>> edit_hosts_depends('c:/wapt/wapt-get.ini','htlaptop.tranquilit.local','toto','tis-7zip','admin','password') """ if sign_certs is None: sign_bundle_fn = inifile_readstring(waptconfigfile, u'global', u'personal_certificate_path') sign_bundle = SSLCABundle(sign_bundle_fn) sign_certs = sign_bundle.certificates() # we assume a unique signer. if cabundle is None: cabundle = sign_bundle if not sign_certs: raise Exception(u'No personal signer certificate found in %s' % sign_bundle_fn) try: import waptconsole progress_hook = waptconsole.UpdateProgress private_key_password_callback = waptconsole.GetPrivateKeyPassword except ImportError as e: def print_progress(show=False, n=0, max=100, msg=''): if show: print('%s %s/%s\r' % (msg, n, max), end='') else: if not msg: msg = 'Done' print("%s%s" % (msg, ' ' * (80 - len(msg)))) progress_hook = print_progress private_key_password_callback = None if sign_key is None: sign_key = sign_certs[0].matching_key_in_dirs( private_key_password=key_password, password_callback=private_key_password_callback) progress_hook(True, 0, len(hosts_list), 'Loading %s hosts packages' % len(hosts_list)) host_repo = WaptHostRepo(name='wapt-host', host_id=[h['uuid'] for h in hosts_list], cabundle=cabundle) host_repo.private_key_password_callback = private_key_password_callback host_repo.load_config_from_file(waptconfigfile) total_hosts = len(host_repo.packages()) discarded_uuids = [p.package for p in host_repo.discarded] append_depends = ensure_list(append_depends) remove_depends = ensure_list(remove_depends) append_conflicts = ensure_list(append_conflicts) remove_conflicts = ensure_list(remove_conflicts) packages = [] discarded = [] unchanged = [] progress_hook(True, 0, len(hosts_list), 'Editing %s hosts' % len(hosts_list)) i = 0 try: for hostrec in hosts_list: host_id = hostrec['uuid'] i += 1 # don't change discarded packages. if host_id in discarded_uuids: discarded.append(host_id) else: host = host_repo.get(host_id) if host is None: host = PackageEntry(package=host_id, section='host') if progress_hook(True, i, len(hosts_list), 'Editing %s' % host.package): break logger.debug(u'Edit host %s : +%s -%s' % (host.package, append_depends, remove_depends)) depends = host.depends conflicts = host.conflicts conflicts = add_to_csv_list(conflicts, append_conflicts) conflicts = remove_from_csv_list(conflicts, remove_conflicts) depends = remove_from_csv_list(depends, ensure_list(conflicts)) depends = add_to_csv_list(depends, append_depends) depends = remove_from_csv_list(depends, remove_depends) conflicts = remove_from_csv_list(conflicts, ensure_list(depends)) if depends != host.depends or conflicts != host.conflicts: host.depends = depends host.conflicts = conflicts host.inc_build() host_file = host.build_management_package() host.sign_package(sign_certs, sign_key) packages.append(host) else: unchanged.append(host.package) # upload all in one step... progress_hook(True, 3, 3, 'Upload %s host packages' % len(packages)) server = WaptServer().load_config_from_file(waptconfigfile) server.private_key_password_callback = private_key_password_callback server.upload_packages(packages, auth=(wapt_server_user, wapt_server_passwd), progress_hook=progress_hook) return dict(updated=[p.package for p in packages], discarded=discarded, unchanged=unchanged) finally: logger.debug('Cleanup') try: i = 0 for s in packages: i += 1 progress_hook(True, i, len(packages), 'Cleanup') if os.path.isfile(s.localpath): os.remove(s.localpath) progress_hook(False) except WindowsError as e: logger.critical('Unable to remove temporary directory %s: %s' % (s, repr(e))) progress_hook(False)
def duplicate_from_file(package_filename, new_prefix='test', target_directory=None, authorized_certs=None, set_maturity=None): r"""Duplicate a downloaded package to match prefix defined in waptconfigfile renames all dependencies Returns: str: source directory >>> from common import Wapt >>> wapt = Wapt(config_filename = r'C:\Users\htouvet\AppData\Local\waptconsole\waptconsole.ini') >>> sources = duplicate_from_external_repo(wapt.config_filename,r'C:\tranquilit\wapt\tests\packages\tis-wapttest.wapt') >>> res = wapt.build_upload(sources,wapt_server_user='******',wapt_server_passwd='password') >>> res[0]['package'].depends u'test-wapttestsub,test-7zip' """ def rename_package(oldname, prefix): sp = oldname.split('-', 1) if len(sp) == 2: return "%s-%s" % (prefix, sp[-1]) else: return oldname source_package = PackageEntry(waptfile=package_filename) # authorized_certs is a directoyr instead a list of certificates. if authorized_certs is not None and authorized_certs != '' and not isinstance( authorized_certs, list): bundle = SSLCABundle() bundle.add_pems(makepath(authorized_certs, '*.crt'), trust_first=True) bundle.add_pems(makepath(authorized_certs, '*.cer'), trust_first=True) bundle.add_pems(makepath(authorized_certs, '*.pem'), trust_all=True) else: bundle = authorized_certs or None source_package.unzip_package(target_dir=target_directory, cabundle=bundle) source_package.invalidate_signature() package = PackageEntry(waptfile=source_package.sourcespath) oldname = source_package.package package.package = rename_package(oldname, new_prefix) package.inc_build() if set_maturity is not None: package.maturity = set_maturity result = package['sourcespath'] # renames dependencies if package.depends: newdepends = [] depends = ensure_list(package.depends) for dependname in depends: newname = rename_package(dependname, new_prefix) newdepends.append(newname) package.depends = ','.join(newdepends) # renames conflicts if package.conflicts: newconflicts = [] conflicts = ensure_list(package.conflicts) for dependname in conflicts: newname = rename_package(dependname, new_prefix) newconflicts.append(newname) package.conflicts = ','.join(newconflicts) package.save_control_to_wapt() return result
adddepend.remove("") removedepend.remove("") adddepend.remove("") removedepend.remove("") if len(removedepend)<=0: print("Pas de suppr") if len(adddepend)<=0: print("Pas d'ajout") #Configuration certpub="/root/mykey.crt" privatekey="/root/mykey.pem" passwordkey='password' #definition de variable pour la clé privé ca_bundle = SSLCABundle() signers_bundle = SSLCABundle() signers_bundle.add_certificates_from_pem(pem_filename=certpub) key = SSLPrivateKey(privatekey) #selection de l'ordinateur à modifier pe = PackageEntry(waptfile = "/var/www/html/wapt-host/%s.wapt" % uuid_machine) depends = pe.depends.split(',') conflicts = pe.conflicts.split(',') if len(adddepend)>0: for dep in adddepend: if dep in pe.conflicts: conflicts.remove(dep) if not dep in depends: depends.append(dep)
def main(): parser=OptionParser(usage=__doc__,prog = 'wapt-signpackage') parser.add_option("-c","--certificate", dest="public_key", default='', help="Path to the PEM RSA certificate to embed identitiy in control. (default: %default)") parser.add_option("-k","--private-key", dest="private_key", default='', help="Path to the PEM RSA private key to sign packages. (default: %default)") #parser.add_option("-w","--private-key-passwd", dest="private_key_passwd", default='', help="Path to the password of the private key. (default: %default)") parser.add_option("-l","--loglevel", dest="loglevel", default=None, type='choice', choices=['debug','warning','info','error','critical'], metavar='LOGLEVEL',help="Loglevel (default: warning)") parser.add_option("-m","--message-digest", dest="md", default='sha256', help="Message digest type for signatures. (default: %default)") parser.add_option("-s","--scan-packages", dest="doscan", default=False, action='store_true', help="Rescan packages and update local Packages index after signing. (default: %default)") parser.add_option("-r","--remove-setup", dest="removesetup", default=False, action='store_true', help="Remove setup.py. (default: %default)") parser.add_option("-i","--inc-release", dest="increlease", default=False, action='store_true', help="Increase release number when building package (default: %default)") parser.add_option("--maturity", dest="set_maturity", default=None, help="Set/change package maturity when signing package. (default: None)") parser.add_option( "--keep-signature-date", dest="keep_signature_date",default=False, action='store_true', help="Keep the current package signature date, and file changetime (default: %default)") parser.add_option( "--if-needed", dest="if_needed", default=False, action='store_true',help="Re-sign package only if needed (default: warning)") (options,args) = parser.parse_args() loglevel = options.loglevel if len(logger.handlers) < 1: hdlr = logging.StreamHandler(sys.stderr) hdlr.setFormatter(logging.Formatter( u'%(asctime)s %(levelname)s %(message)s')) logger.addHandler(hdlr) if loglevel: setloglevel(logger,loglevel) else: setloglevel(logger,'warning') if len(args) < 1: print(parser.usage) sys.exit(1) if not options.public_key and not options.private_key: print('ERROR: No certificate found or specified') sys.exit(1) if options.private_key and os.path.isfile(options.private_key): key = SSLPrivateKey(options.private_key) else: cert = SSLCertificate(options.public_key or options.private_key) key = cert.matching_key_in_dirs() if not key: print('ERROR: No private key found or specified') sys.exit(1) args = ensure_list(args) ca_bundle = SSLCABundle() signers_bundle = SSLCABundle() signers_bundle.add_certificates_from_pem(pem_filename=options.public_key) waptpackages = [] for arg in args: waptpackages.extend(glob.glob(arg)) errors = [] package_dirs = [] for waptpackage in waptpackages: package_dir = os.path.abspath(os.path.dirname(waptpackage)) if not package_dir in package_dirs: package_dirs.append(package_dir) print('Processing %s'%waptpackage) try: sign_needed=False pe = PackageEntry(waptfile = waptpackage) if options.removesetup: if pe.has_file('setup.py'): with pe.as_zipfile(mode='a') as waptfile: waptfile.remove('setup.py') sign_needed=True if not sign_needed and options.if_needed: try: pe.check_control_signature(trusted_bundle=signers_bundle,signers_bundle=signers_bundle) for md in ensure_list(options.md): if not pe.has_file(pe.get_signature_filename(md)): raise Exception('Missing signature for md %s' % md) logger.info('Skipping %s, already signed properly' % pe.asrequirement()) sign_needed = False except Exception as e: logger.info('Sign is needed for %s because %s' % (pe.asrequirement(),e)) sign_needed = True if options.increlease: pe.inc_build() sign_needed = True if options.set_maturity is not None and pe.maturity != options.set_maturity: pe.maturity = options.set_maturity sign_needed = True if not options.if_needed or sign_needed: pe.sign_package(private_key=key,certificate = signers_bundle.certificates(),mds = ensure_list(options.md),keep_signature_date=options.keep_signature_date) newfn = pe.make_package_filename() if newfn != pe.filename: newfn_path = os.path.join(package_dir,newfn) if not os.path.isfile(newfn_path): print(u"Renaming file from %s to %s to match new package's properties" % (pe.filename,newfn)) shutil.move(os.path.join(package_dir,pe.filename),newfn_path) else: print('WARNING: unable to rename file from %s to %s because target already exists' % (pe.filename,newfn)) print('Done') except Exception as e: print(u'Error: %s'%ensure_unicode(e.message)) errors.append([waptpackage,repr(e)]) if options.doscan: for package_dir in package_dirs: if os.path.isfile(os.path.join(package_dir,'Packages')): print(u'Launching the update of Packages index in %s ...'% ensure_unicode(package_dir)) repo = WaptLocalRepo(package_dir) repo.update_packages_index() print('Done') else: print("Don't forget to rescan your repository with wapt-scanpackages %s" % os.path.dirname(waptpackages[0])) if errors: print('Package not processed properly: ') for fn,error in errors: print(u'%s : %s' % (fn,error)) sys.exit(1) else: sys.exit(0)
def on_trigger_host_action(self,args,result_callback=None): try: start_time = time.time() actions = args if not isinstance(actions,list): actions =[actions] logger.debug('Host actions "%s" triggered by SocketIO' % ",".join([action['action'] for action in actions])) # check signatures if not self.wapt: raise Exception('Wapt not available') verified_by = None for action in actions: name = action['action'] verified_by = None signer_cert_chain = SSLCABundle().add_pem(action['signer_certificate']).certificates() chain = self.wapt.cabundle.check_certificates_chain(signer_cert_chain) if chain: required_attributes = ['uuid','action'] if name in ['trigger_install_packages','trigger_remove_packages','trigger_forget_packages']: required_attributes.append('packages') if name in ['trigger_change_description']: required_attributes.append('computer_description') if name in waptservice_remote_actions: required_attributes.extend(waptservice_remote_actions[name].required_attributes) verified_by = chain[0].verify_claim(action,max_age_secs=waptconfig.signature_clockskew, required_attributes=required_attributes) if not verified_by: raise SSLVerifyException('Bad signature for action %s, aborting' % action) if verified_by: verified_by = verified_by.get('verified_by',None) result = [] for action in actions: uuid = action['uuid'] if uuid != self.wapt.host_uuid: raise Exception('Task is not targeted to this host. task''s uuid does not match host''uuid') name = action['action'] if name in ['trigger_cancel_all_tasks']: data = [t.as_dict() for t in self.task_manager.cancel_all_tasks()] result.append(data) elif name in ['trigger_host_update','trigger_host_register']: if name == 'trigger_host_update': task = WaptUpdate() elif name == 'trigger_host_register': task = WaptRegisterComputer(computer_description = action.get('computer_description',None)) task.force = action.get('force',False) task.notify_user = action.get('notify_user',False) task.notify_server_on_finish = action.get('notify_server',False) task.created_by = verified_by data = self.task_manager.add_task(task).as_dict() result.append(data) elif name in ['trigger_change_description']: desc = action.get('computer_description',None) if desc is not None: setuphelpers.set_computer_description(desc) msg = u'Computer description of %s changed to %s' % (setuphelpers.get_hostname(),setuphelpers.get_computer_description()) if not setuphelpers.get_computer_description() == desc: raise Exception(u'Computer description has not been changed') result.append(dict(success=True, msg = msg, result = msg, )) if action.get('notify_server',False): task = WaptUpdate(created_by=verified_by) task.notify_server_on_finish = True self.task_manager.add_task(task) result.append(task.as_dict()) elif name == 'trigger_host_upgrade': notify_user = action.get('notify_user',False) notify_server_on_finish = action.get('notify_server',False) force = action.get('force',False) self.wapt.update(force=False) upgrades = self.wapt.list_upgrade() to_install = upgrades['upgrade']+upgrades['additional']+upgrades['install'] for req in to_install: result.append(self.task_manager.add_task(WaptPackageInstall(req,force=force,notify_user=notify_user,created_by=verified_by)).as_dict()) self.task_manager.add_task(WaptAuditPackage(packagename=req,force=False, notify_user=notify_user, notify_server_on_finish=False, priority=200, created_by=verified_by)).as_dict() result.append(self.task_manager.add_task(WaptUpgrade(notify_user=notify_user,created_by=verified_by,priority=200)).as_dict()) result.append(self.task_manager.add_task(WaptCleanup(notify_user=False,created_by=verified_by,priority=200)).as_dict()) elif name in ['trigger_install_packages','trigger_remove_packages','trigger_forget_packages']: packagenames = ensure_list(action['packages']) for packagename in packagenames: if name == 'trigger_install_packages': task = WaptPackageInstall(packagename=packagename) elif name == 'trigger_remove_packages': task = WaptPackageRemove(packagename=packagename) elif name == 'trigger_forget_packages': task = WaptPackageForget(packagenames=packagename) task.force = action.get('force',False) task.notify_user = action.get('notify_user',False) task.notify_server_on_finish = action.get('notify_server',False) task.created_by=verified_by result.append(self.task_manager.add_task(task).as_dict()) if name == 'trigger_install_packages': self.task_manager.add_task(WaptAuditPackage(packagename=packagename,force=task.force, notify_user=task.notify_user, notify_server_on_finish=task.notify_server_on_finish, priority=200)).as_dict() elif name == 'trigger_waptservicerestart': msg = setuphelpers.create_onetime_task('waptservicerestart','cmd.exe','/C net stop waptservice & net start waptservice') result.append(dict(success=True,msg = msg,result = msg)) elif name in waptservice_remote_actions: waptservice_remote_actions[name].trigger_action(self,action,verified_by) else: raise EWaptException('Unhandled remote action %s' % name) #self.emit('trigger_update_result',{'result':data}) if result_callback: result_callback(make_response(result,uuid=self.wapt.host_uuid,request_time=time.time()-start_time)) except BaseException as e: logger.info('Exception for actions %s: %s' % (repr(args),repr(e))) if result_callback: result_callback(make_response_from_exception(e,uuid=self.wapt.host_uuid,request_time=time.time()-start_time))
def on_trigger_host_action(self,args,result_callback=None): try: start_time = time.time() actions = args if not isinstance(actions,list): actions =[actions] # check signatures if not self.wapt: raise Exception('Wapt not available') verified_by = None for action in actions: logger.info('Host actions "%s" triggered by SocketIO by %s' % (action['action'],action['signer'])) name = action['action'] verified_by = None # full cert chain provided with the signed action if action.get('signer_certificate',None): signer_cert_ca = SSLCABundle() signer_cert_ca.add_certificates_from_pem(action['signer_certificate']) signer_cert_chain = signer_cert_ca.certificates() else: # only sha256 fingerprint provided. (lighter). issuer must be in the authorized cabundle signer_cert = self.wapt.cabundle.certificate(action['signer']) if signer_cert: signer_cert_chain = [signer_cert] else: signer_cert_chain = [] chain = self.wapt.cabundle.check_certificates_chain(signer_cert_chain) if chain: required_attributes = ['uuid','action'] if name in ['trigger_install_packages','trigger_remove_packages','trigger_forget_packages']: required_attributes.append('packages') if name in ['trigger_change_description']: required_attributes.append('computer_description') if name in waptservice_remote_actions: required_attributes.extend(waptservice_remote_actions[name].required_attributes) verified_by = chain[0].verify_claim(action,max_age_secs=waptconfig.signature_clockskew, required_attributes=required_attributes) else: raise SSLVerifyException('Untrusted certificate %s for signed action %s, aborting' % (signer_cert_chain,action)) if not verified_by: raise SSLVerifyException('Bad signature for action %s, aborting' % action) if verified_by: verified_by = verified_by.get('verified_by',None) result = [] for action in actions: uuid = action['uuid'] if uuid != self.wapt.host_uuid: raise Exception('Task is not targeted to this host. task''s uuid does not match host''uuid') name = action['action'] if name in ['trigger_cancel_all_tasks']: data = [t.as_dict() for t in self.task_manager.cancel_all_tasks()] result.append(data) elif name in ['trigger_host_update','trigger_host_register']: if name == 'trigger_host_update': task = WaptUpdate() elif name == 'trigger_host_register': task = WaptRegisterComputer(computer_description = action.get('computer_description',None)) task.force = action.get('force',False) task.notify_user = action.get('notify_user',False) task.notify_server_on_finish = action.get('notify_server',False) task.created_by = verified_by data = self.task_manager.add_task(task).as_dict() result.append(data) elif name in ['trigger_change_description']: desc = action.get('computer_description',None) if desc is not None: setuphelpers.set_computer_description(desc) msg = u'Computer description of %s changed to %s' % (setuphelpers.get_hostname(),setuphelpers.get_computer_description()) if not setuphelpers.get_computer_description() == desc: raise Exception(u'Computer description has not been changed') result.append(dict(success=True, msg = msg, result = msg, )) if action.get('notify_server',False): task = WaptUpdate(created_by=verified_by) task.notify_server_on_finish = True self.task_manager.add_task(task) result.append(task.as_dict()) elif name == 'trigger_host_upgrade': notify_user = action.get('notify_user',False) notify_server_on_finish = action.get('notify_server',False) force = action.get('force',False) only_priorities = action.get('only_priorities',None) only_if_not_process_running = action.get('only_if_not_process_running',False) update_packages = action.get('update',True) if update_packages: result.append(self.task_manager.add_task(WaptUpdate(force=force,notify_user=notify_user, )).as_dict()) result.append(self.task_manager.add_task(WaptUpgrade(notify_user=notify_user, created_by=verified_by, only_priorities=only_priorities, only_if_not_process_running=only_if_not_process_running, force=force )).as_dict()) result.append(self.task_manager.add_task(WaptCleanup(notify_user=False,created_by=verified_by,priority=200)).as_dict()) elif name in ['trigger_install_packages','trigger_remove_packages','trigger_forget_packages']: packagenames = action['packages'] only_priorities = action.get('only_priorities',None) only_if_not_process_running = action.get('only_if_not_process_running',False) for packagename in packagenames: if name == 'trigger_install_packages': task = WaptPackageInstall(packagenames=packagename) elif name == 'trigger_remove_packages': task = WaptPackageRemove(packagenames=packagename) elif name == 'trigger_forget_packages': task = WaptPackageForget(packagenames=packagename) task.force = action.get('force',False) task.notify_user = action.get('notify_user',False) task.notify_server_on_finish = action.get('notify_server',False) task.created_by=verified_by task.only_priorities=only_priorities task.only_if_not_process_running=only_if_not_process_running result.append(self.task_manager.add_task(task).as_dict()) if name == 'trigger_install_packages': self.task_manager.add_task(WaptAuditPackage(packagenames=packagenames, force=task.force, notify_user=task.notify_user, notify_server_on_finish=task.notify_server_on_finish, priority=200)).as_dict() elif name == 'trigger_waptservicerestart': try: msg = setuphelpers.create_onetime_task('waptservicerestart','cmd.exe','/C net stop waptservice & net start waptservice') result.append(dict(success=True,msg = msg,result = msg)) except: # restart by nssm os._exit(10) elif name == 'trigger_longtask': task = WaptLongTask() task.force = args.get('force',False) task.notify_user = args.get('notify_user',False) task.notify_server_on_finish = args.get('notify_server',False) task.created_by=verified_by result.append(self.task_manager.add_task(task).as_dict()) elif name in waptservice_remote_actions: waptservice_remote_actions[name].trigger_action(self,action,verified_by) else: raise EWaptException('Unhandled remote action %s' % name) #self.emit('trigger_update_result',{'result':data}) if result_callback: result_callback(make_response(result,uuid=self.wapt.host_uuid,request_time=time.time()-start_time)) except BaseException as e: logger.info('Exception for actions %s: %s' % (repr(args),repr(e))) if result_callback: result_callback(make_response_from_exception(e,uuid=self.wapt.host_uuid,request_time=time.time()-start_time))
def main(): parser=OptionParser(usage=__doc__,prog = 'wapt-signpackage') parser.add_option("-c","--certificate", dest="public_key", default='', help="Path to the PEM RSA certificate to embed identitiy in control. (default: %default)") parser.add_option("-k","--private-key", dest="private_key", default='', help="Path to the PEM RSA private key to sign packages. (default: %default)") #parser.add_option("-w","--private-key-passwd", dest="private_key_passwd", default='', help="Path to the password of the private key. (default: %default)") parser.add_option("-l","--loglevel", dest="loglevel", default=None, type='choice', choices=['debug','warning','info','error','critical'], metavar='LOGLEVEL',help="Loglevel (default: warning)") parser.add_option("-m","--message-digest", dest="md", default='sha256', help="Message digest type for signatures. (default: %default)") parser.add_option("-s","--scan-packages", dest="doscan", default=False, action='store_true', help="Rescan packages and update local Packages index after signing. (default: %default)") parser.add_option("-r","--remove-setup", dest="removesetup", default=False, action='store_true', help="Remove setup.py. (default: %default)") parser.add_option("-i","--inc-release", dest="increlease", default=False, action='store_true', help="Increase release number when building package (default: %default)") parser.add_option("--maturity", dest="set_maturity", default=None, help="Set/change package maturity when signing package. (default: None)") parser.add_option( "--keep-signature-date", dest="keep_signature_date",default=False, action='store_true', help="Keep the current package signature date, and file changetime (default: %default)") parser.add_option( "--if-needed", dest="if_needed", default=False, action='store_true',help="Re-sign package only if needed (default: warning)") (options,args) = parser.parse_args() loglevel = options.loglevel if len(logger.handlers) < 1: hdlr = logging.StreamHandler(sys.stderr) hdlr.setFormatter(logging.Formatter( u'%(asctime)s %(levelname)s %(message)s')) logger.addHandler(hdlr) if loglevel: setloglevel(logger,loglevel) else: setloglevel(logger,'warning') if len(args) < 1: print(parser.usage) sys.exit(1) if not options.public_key and not options.private_key: print('ERROR: No certificate found or specified') sys.exit(1) if options.private_key and os.path.isfile(options.private_key): key = SSLPrivateKey(options.private_key) else: cert = SSLCertificate(options.public_key or options.private_key) key = cert.matching_key_in_dirs() if not key: print('ERROR: No private key found or specified') sys.exit(1) args = ensure_list(args) ca_bundle = SSLCABundle() signers_bundle = SSLCABundle() signers_bundle.add_certificates_from_pem(pem_filename=options.public_key) waptpackages = [] for arg in args: waptpackages.extend(glob.glob(arg)) errors = [] package_dirs = [] for waptpackage in waptpackages: package_dir = os.path.abspath(os.path.dirname(waptpackage)) if not package_dir in package_dirs: package_dirs.append(package_dir) print('Processing %s'%waptpackage) try: sign_needed=False pe = PackageEntry(waptfile = waptpackage) if options.removesetup: if pe.has_file('setup.py'): with pe.as_zipfile(mode='a') as waptfile: waptfile.remove('setup.py') sign_needed=True if not sign_needed and options.if_needed: try: pe.check_control_signature(trusted_bundle=signers_bundle,signers_bundle=signers_bundle) for md in ensure_list(options.md): if not pe.has_file(pe.get_signature_filename(md)): raise Exception('Missing signature for md %s' % md) logger.info('Skipping %s, already signed properly' % pe.asrequirement()) sign_needed = False except Exception as e: logger.info('Sign is needed for %s because %s' % (pe.asrequirement(),e)) sign_needed = True if options.increlease: pe.inc_build() sign_needed = True if options.set_maturity is not None and pe.maturity != options.set_maturity: pe.maturity = options.set_maturity sign_needed = True if not options.if_needed or sign_needed: pe.sign_package(private_key=key,certificate = signers_bundle.certificates(),mds = ensure_list(options.md),keep_signature_date=options.keep_signature_date) newfn = pe.make_package_filename() if newfn != pe.filename: newfn_path = os.path.join(package_dir,newfn) if not os.path.isfile(newfn_path): print(u"Renaming file from %s to %s to match new package's properties" % (pe.filename,newfn)) os.rename(os.path.join(package_dir,pe.filename),newfn_path) else: print('WARNING: unable to rename file from %s to %s because target already exists' % (pe.filename,newfn)) print('Done') except Exception as e: print(u'Error: %s'%ensure_unicode(e.message)) errors.append([waptpackage,repr(e)]) if options.doscan: for package_dir in package_dirs: if os.path.isfile(os.path.join(package_dir,'Packages')): print(u'Launching the update of Packages index in %s ...'% ensure_unicode(package_dir)) repo = WaptLocalRepo(package_dir) repo.update_packages_index() print('Done') else: print("Don't forget to rescan your repository with wapt-scanpackages %s" % os.path.dirname(waptpackages[0])) if errors: print('Package not processed properly: ') for fn,error in errors: print(u'%s : %s' % (fn,error)) sys.exit(1) else: sys.exit(0)
def add_ads_groups(waptconfigfile, hostdicts_list, sign_certs=None, sign_key=None, key_password=None, wapt_server_user=None,wapt_server_passwd=None, cabundle = None): if sign_certs is None: sign_bundle_fn = inifile_readstring(waptconfigfile,u'global',u'personal_certificate_path') sign_bundle = SSLCABundle(sign_bundle_fn) sign_certs = sign_bundle.certificates() # we assume a unique signer. if cabundle is None: cabundle = sign_bundle if not sign_certs: raise Exception(u'No personal signer certificate found in %s' % sign_bundle_fn) if sign_key is None: sign_key = sign_certs[0].matching_key_in_dirs(private_key_password=key_password) main_repo = WaptRemoteRepo(name='wapt',cabundle = cabundle) main_repo.load_config_from_file(waptconfigfile) host_repo = WaptHostRepo(name='wapt-host',host_id=[h['uuid'] for h in hostdicts_list],cabundle = cabundle) host_repo.load_config_from_file(waptconfigfile) total_hosts = len(host_repo.packages()) discarded_uuids = [p.package for p in host_repo.discarded] try: import waptconsole progress_hook = waptconsole.UpdateProgress except ImportError as e: def print_progress(show=False,n=0,max=100,msg=''): if show: print('%s %s/%s\r' % (msg,n,max),end='') else: if not msg: msg='Done' print("%s%s"%(msg,' '*(80-len(msg)))) progress_hook = print_progress packages = [] discarded = [] unchanged = [] try: progress_hook(True,0,len(hostdicts_list),'Editing %s hosts' % len(hostdicts_list)) i = 0 for h in hostdicts_list: try: host_package = None host_id = h['uuid'] hostname = h['computer_name'] groups = get_computer_groups(hostname) host_package = host_repo.get(host_id,PackageEntry(package=host_id,section='host')) if progress_hook(True,i,len(hostdicts_list),'Checking %s' % host_package.package): break wapt_groups = ensure_list(host_package['depends']) additional = [group for group in groups if not group in wapt_groups and (main_repo.get(group,None) is not None)] if additional: logger.info(u'Adding %s to %s' % (','.join(additional),host_package.package)) if progress_hook(True,i,len(hostdicts_list),'Editing %s' % host_package.package): break wapt_groups.extend(additional) host_package.depends = ','.join(wapt_groups) host_package.build_management_package() host_package.inc_build() host_file = host_package.build_management_package() host_package.sign_package(sign_certs,sign_key) packages.append(host_package) else: unchanged.append(host_package.package) except Exception as e: if host_package: discarded.append(host_package.package) logger.critical(u'Discarding because %s' % ensure_unicode(e)) # upload all in one step... progress_hook(True,3,3,'Upload %s host packages' % len(packages)) server = WaptServer().load_config_from_file(waptconfigfile) server.upload_packages(packages,auth=(wapt_server_user,wapt_server_passwd),progress_hook=progress_hook) return dict(updated = packages, discarded = discarded, unchanged = unchanged) finally: logger.debug('Cleanup') try: i = 0 for s in packages: i+=1 progress_hook(True,i,len(packages),'Cleanup') if os.path.isfile(s.localpath): os.remove(s.localpath) progress_hook(False) except WindowsError as e: logger.critical('Unable to remove temporary directory %s: %s'% (s,repr(e))) progress_hook(False)
def edit_hosts_depends(waptconfigfile,hosts_list, append_depends=[], remove_depends=[], append_conflicts=[], remove_conflicts=[], sign_certs=None, sign_key=None, key_password=None, wapt_server_user=None,wapt_server_passwd=None, cabundle = None, ): """Add or remove packages from host packages Args: Returns: dict: { updated: of uuid of machines actually updated unchanged : list of uuid skipped because of no change needed discarded : list of uuid discarded due to errors} >>> edit_hosts_depends('c:/wapt/wapt-get.ini','htlaptop.tranquilit.local','toto','tis-7zip','admin','password') """ if sign_certs is None: sign_bundle_fn = inifile_readstring(waptconfigfile,u'global',u'personal_certificate_path') sign_bundle = SSLCABundle(sign_bundle_fn) sign_certs = sign_bundle.certificates() # we assume a unique signer. if cabundle is None: cabundle = sign_bundle if not sign_certs: raise Exception(u'No personal signer certificate found in %s' % sign_bundle_fn) if sign_key is None: sign_key = sign_certs[0].matching_key_in_dirs(private_key_password=key_password) try: import waptconsole progress_hook = waptconsole.UpdateProgress except ImportError as e: def print_progress(show=False,n=0,max=100,msg=''): if show: print('%s %s/%s\r' % (msg,n,max),end='') else: if not msg: msg='Done' print("%s%s"%(msg,' '*(80-len(msg)))) progress_hook = print_progress hosts_list = ensure_list(hosts_list) progress_hook(True,0,len(hosts_list),'Loading %s hosts packages' % len(hosts_list)) host_repo = WaptHostRepo(name='wapt-host',host_id=hosts_list,cabundle = cabundle) host_repo.load_config_from_file(waptconfigfile) total_hosts = len(host_repo.packages()) discarded_uuids = [p.package for p in host_repo.discarded] hosts_list = ensure_list(hosts_list) append_depends = ensure_list(append_depends) remove_depends = ensure_list(remove_depends) append_conflicts = ensure_list(append_conflicts) remove_conflicts = ensure_list(remove_conflicts) packages = [] discarded = [] unchanged = [] progress_hook(True,0,len(hosts_list),'Editing %s hosts' % len(hosts_list)) i = 0 try: for host_id in hosts_list: i+=1 # don't change discarded packages. if host_id in discarded_uuids: discarded.append(host_id) else: host = host_repo.get(host_id) if host is None: host = PackageEntry(package=host_id,section='host') if progress_hook(True,i,len(hosts_list),'Editing %s' % host.package): break logger.debug(u'Edit host %s : +%s -%s'%( host.package, append_depends, remove_depends)) depends = host.depends conflicts = host.conflicts conflicts = add_to_csv_list(conflicts,append_conflicts) conflicts = remove_from_csv_list(conflicts,remove_conflicts) depends = remove_from_csv_list(depends,ensure_list(conflicts)) depends = add_to_csv_list(depends,append_depends) depends = remove_from_csv_list(depends,remove_depends) conflicts = remove_from_csv_list(conflicts,ensure_list(depends)) if depends != host.depends or conflicts != host.conflicts: host.depends = depends host.conflicts = conflicts host.inc_build() host_file = host.build_management_package() host.sign_package(sign_certs,sign_key) packages.append(host) else: unchanged.append(host.package) # upload all in one step... progress_hook(True,3,3,'Upload %s host packages' % len(packages)) server = WaptServer().load_config_from_file(waptconfigfile) server.upload_packages(packages,auth=(wapt_server_user,wapt_server_passwd),progress_hook=progress_hook) return dict(updated = [p.package for p in packages], discarded = discarded, unchanged = unchanged) finally: logger.debug('Cleanup') try: i = 0 for s in packages: i+=1 progress_hook(True,i,len(packages),'Cleanup') if os.path.isfile(s.localpath): os.remove(s.localpath) progress_hook(False) except WindowsError as e: logger.critical('Unable to remove temporary directory %s: %s'% (s,repr(e))) progress_hook(False)
def duplicate_from_file(package_filename,new_prefix='test',target_directory=None,authorized_certs=None,set_maturity=None): r"""Duplicate a downloaded package to match prefix defined in waptconfigfile renames all dependencies Returns: str: source directory >>> from common import Wapt >>> wapt = Wapt(config_filename = r'C:\Users\htouvet\AppData\Local\waptconsole\waptconsole.ini') >>> sources = duplicate_from_external_repo(wapt.config_filename,r'C:\tranquilit\wapt\tests\packages\tis-wapttest.wapt') >>> res = wapt.build_upload(sources,wapt_server_user='******',wapt_server_passwd='password') >>> res[0]['package'].depends u'test-wapttestsub,test-7zip' """ def rename_package(oldname,prefix): sp = oldname.split('-',1) if len(sp) == 2: return "%s-%s" % (prefix,sp[-1]) else: return oldname source_package = PackageEntry(waptfile = package_filename) # authorized_certs is a directoyr instead a list of certificates. if authorized_certs is not None and authorized_certs != '' and not isinstance(authorized_certs,list): bundle = SSLCABundle() bundle.add_pems(makepath(authorized_certs,'*.crt')) bundle.add_pems(makepath(authorized_certs,'*.cer')) bundle.add_pems(makepath(authorized_certs,'*.pem')) else: bundle = authorized_certs or None source_package.unzip_package(target_dir=target_directory,cabundle=bundle) source_package.invalidate_signature() package = PackageEntry(waptfile = source_package.sourcespath) oldname = source_package.package package.package = rename_package(oldname,new_prefix) package.inc_build() if set_maturity is not None: package.maturity = set_maturity result = package['sourcespath'] # renames dependencies if package.depends: newdepends = [] depends = ensure_list(package.depends) for dependname in depends: newname = rename_package(dependname,new_prefix) newdepends.append(newname) package.depends = ','.join(newdepends) # renames conflicts if package.conflicts: newconflicts = [] conflicts = ensure_list(package.conflicts) for dependname in conflicts: newname = rename_package(dependname,new_prefix) newconflicts.append(newname) package.conflicts = ','.join(newconflicts) package.save_control_to_wapt() return result