Example #1
0
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
Example #2
0
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)))
Example #3
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)

    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)
Example #4
0
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)
Example #5
0
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
Example #6
0
    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)
Example #7
0
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)
Example #8
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))
Example #9
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]
            # 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))
Example #10
0
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)
Example #11
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)
Example #12
0
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)
Example #13
0
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