예제 #1
0
파일: jenkins.py 프로젝트: fakegit/eclogue
def add_jenkins():
    user = login_user
    body = request.get_json()
    if not body:
        return jsonify({
            'code': 114001,
            'message': 'invalid params',
        })
    base_url = body.get('base_url')
    username = body.get('username')
    password = body.get('password')
    artifacts = body.get('artifacts')
    if not base_url or not username or not password:
        return jsonify({
            'message': 'miss required params',
            'code': 114002
        }), 400

    vault_pass = config.jenkins.get('vault')
    options = {'vault_pss': vault_pass}
    encrypt = Vault(options).encrypt_string(password)
    record = {
        'add_by': user.username,
        'setting': {
            'username': username,
            'baseurl': base_url,
            'password': encrypt,
            'artifacts': artifacts,
        },
        'created_at': int(time.time())
    }
예제 #2
0
def encrypt_credential(text):
    secret = config.vault.get('secret')
    options = {
        'vault_pass': secret
    }
    vault = Vault(options=options)
    return vault.encrypt_string(text)
예제 #3
0
    def get_variables(self, ids, decode=False):
        records = self.find_by_ids(ids)
        variables = {}
        vault = Vault({'vault_pass': config.vault.get('secret')})
        for record in records:
            config_vars = record.get('variables')
            if not config_vars:
                continue

            for k, v in config_vars.items():
                key = '_'.join(
                    ['ECLOGUE', 'CONFIG',
                     record.get('name', ''), k])
                if not decode:
                    variables[key] = v
                    continue

                is_encrypt = Vault.is_encrypted(v)
                value = v
                if is_encrypt:
                    value = vault.decrypt_string(value)

                variables[key] = value

        return variables
예제 #4
0
def add_key():
    user = login_user
    payload = request.get_json()
    if not payload:
        return jsonify({
            'message': 'illegal params',
            'code': 104000,
        }), 400

    public_key = payload.get('public_key')
    name = payload.get('name')
    if not public_key:
        return jsonify({'message': 'invalid public key', 'code': 104000}), 400

    ssh = SSHKey(public_key)
    try:
        ssh.parse()
    except Exception as err:
        return jsonify({
            'message': 'invalid ssh key: {}'.format(str(err)),
            'code': 104001,
        }), 400

    fingerprint = ssh.hash_md5()
    existed = db.collection('public_keys').find_one(
        {'fingerprint': fingerprint})
    if existed:
        return jsonify({
            'message': 'ssh public key existed',
            'code': 104003
        }), 400

    options = {'vault_pass': config.vault.get('secret')}
    encode = Vault(options).encrypt_string(public_key)
    data = {
        'fingerprint': fingerprint,
        'user_id': user.get('user_id'),
        'content': encode,
        'name': name,
        'created_at': time.time()
    }

    result = db.collection('public_keys').insert_one(data)
    data['_id'] = result.inserted_id
    logger.info('add public_keys', extra={'record': data})

    return jsonify({
        'message': 'ok',
        'code': 0,
    })
예제 #5
0
        def parse_register(record):
            register = record.get('register')
            if not register:
                return record

            c_ids = map(lambda i: ObjectId(i), register)
            cfg_records = Configuration.find({'_id': {'$in': list(c_ids)}})
            if not cfg_records:
                return record

            try:
                variables = {}
                content = yaml.safe_load(record.get('content', ''))
                if not content:
                    return record

                vault = Vault({'vault_pass': config.vault.get('secret')})
                for cfg in cfg_records:
                    config_vars = cfg.get('variables')
                    if not config_vars:
                        continue

                    for k, v in config_vars.items():
                        key = '_'.join(
                            ['ECLOGUE', 'CONFIG',
                             cfg.get('name', ''), k])
                        is_encrypt = Vault.is_encrypted(v)
                        value = v
                        if is_encrypt:
                            value = vault.decrypt_string(value)

                        variables[key] = value

                content = dict(content)
                content.update(variables)
                record['content'] = yaml.safe_dump(content)
            except Exception as e:
                print(e)

            return record
예제 #6
0
def upload_playbook(_id):
    files = request.files
    record = Book.find_by_id(_id)
    if not record:
        return jsonify({
            "message": "book not found",
            "code": 104004,
        }), 400

    if not files:
        return jsonify({
            'message': 'invalid files params',
            'code': 104001
        }), 400

    file = files['file']
    filename = file.filename.lstrip('/')
    path_list = filename.split('/')
    filename = '/'.join(path_list[1:])
    filename = '/' + filename
    home_path, basename = os.path.split(filename)
    file_list = set(_make_path(filename))
    for dirname in file_list:
        check = Playbook.find_one({
            'book_id': _id,
            'path': dirname,
        })
        if not check:
            parent_path, name = os.path.split(dirname)
            parent_path = parent_path if parent_path != '/' else None
            parent = {
                'path': dirname,
                'is_dir': True,
                'is_edit': False,
                'book_id': _id,
                'parent': parent_path,
                'name': name,
                'created_at': time.time(),
            }
            meta = get_meta(dirname)
            parent.update(meta)
            parent['additions'] = meta
            Playbook.insert_one(parent)

    data = {
        'path': filename,
        'is_dir': False,
        'parent': home_path or None,
        'book_id': _id
    }

    can_edit = is_edit(file)
    if not can_edit:
        file_id = db.save_file(filename=filename, fileobj=file)
        data['file_id'] = file_id
    else:
        content = file.stream.read()
        content = content.decode('utf-8')
        data['is_encrypt'] = Vault.is_encrypted(content)
        if data['is_encrypt']:
            # @todo vault password
            vault = Vault()
            data['content'] = vault.encrypt_string(content)
            data['md5'] = md5(content)
        else:
            data['content'] = content
            data['md5'] = md5(content)

    meta = get_meta(data['path'])
    data.update(meta)
    data['additions'] = meta
    data['is_edit'] = can_edit
    data['created_at'] = time.time()
    data['updated_at'] = time.time()
    Playbook.update_one({
        'path': filename,
        'book_id': _id
    }, {'$set': data},
                        upsert=True)

    return jsonify({
        "message": "ok",
        "code": 0,
    })
예제 #7
0
def explore():
    payload = request.get_json()
    form = request.form
    payload = payload or form
    if not payload:
        return jsonify({
            'message': 'empty request payload',
            'code': 144000,
        }), 400

    explore_type = payload.get('type')
    credential = payload.get('credential')
    # if not credential:
    #     return jsonify({
    #         'message': 'param credential required',
    #         'code': 144000,
    #     }), 400

    private_key = ''
    if credential:
        credential = Credential.find_by_id(credential)
        if not credential or not credential.get('status'):
            return jsonify({
                'message': 'invalid credential',
                'code': 144040,
            }), 404

        vault = Vault({'vault_pass': config.vault.get('secret')})

        body = credential['body']
        private_key = vault.decrypt_string(body[credential['type']])

    maintainer = payload.get('maintainer')
    if not maintainer or type(maintainer) != list:
        maintainer = [login_user.get('username')]
    else:
        maintainer.extend(login_user.get('username'))

    if explore_type == 'manual':
        region = payload.get('region')
        group = payload.get('group')
        ssh_host = payload.get('ssh_host')
        ssh_user = payload.get('ssh_user')
        ssh_port = payload.get('ssh_port') or 22
        if not ssh_host or not ssh_user or not ssh_port:
            return jsonify({
                'message': 'illegal ssh connection params',
                'code': 144001,
            }), 400

        region_record = Region.find_one({'_id': ObjectId(region)})
        if not region_record:
            return jsonify({
                'message': 'invalid region',
                'code': 144002,
            }), 400

        group_record = Group.find_by_ids(group)
        if not group_record:
            return jsonify({
                'message': 'invalid group',
                'code': 144003,
            }), 400

        options = {
            'remote_user': ssh_user,
            'verbosity': 3,
        }
        hosts = ssh_host + ':' + str(ssh_port) + ','
        runner = setup(hosts, options, private_key)
        result = runner.get_result()
        data = process_ansible_setup(result)
        records = []
        if not data:
            return jsonify({
                'code': 144009,
                'message': 'fetch target host failed',
                'data': result
            }), 406

        for item in data:
            item['ansible_ssh_host'] = ssh_host
            item['ansible_ssh_user'] = ssh_user
            item['ansible_ssh_port'] = ssh_port
            item['maintainer'] = maintainer
            item['group'] = list(map(lambda i: str(i['_id']), group_record))
            item['add_by'] = login_user.get('username')
            item['state'] = 'active'
            where = {'ansible_ssh_host': item['ansible_ssh_host']}
            update = {'$set': item}
            result = db.collection('machines').update_one(where,
                                                          update,
                                                          upsert=True)
            extra = item.copy()
            extra['_id'] = result.upserted_id
            logger.info('add machines hostname: '.format({item['hostname']}),
                        extra={'record': data})
            records.append(item)
        # def func(item):
        #     item['ansible_ssh_host'] = ssh_host
        #     item['ansible_ssh_user'] = ssh_user
        #     item['ansible_ssh_port'] = ssh_port
        #     item['maintainer'] = maintainer
        #     item['group'] = list(map(lambda i: str(i['_id']), group_record))
        #     item['add_by'] = login_user.get('username')
        #     item['state'] = 'active'
        #
        #     return item
        #
        # data = list(map(func, data))
        # db.collection('machines').insert_many(data)

        return jsonify({
            'message': 'ok',
            'code': 0,
            'data': records,
            'records': data
        })

    files = request.files
    if not files:
        return jsonify({
            'message': 'illegal param',
            'code': 104000,
        }), 400

    file = files.get('inventory')
    if not files:
        return jsonify({
            'message': 'files required',
            'code': 104001,
        }), 400

    sources = file.read().decode('utf-8')
    # inventory is not only yaml
    with NamedTemporaryFile('w+t', delete=True) as fd:
        fd.write(sources)
        fd.seek(0)
        options = {
            'verbosity': 0,
        }
        runner = setup(fd.name, options, private_key)
        result = runner.get_result()
        data = process_ansible_setup(result)
        if not data:
            return jsonify({
                'code': 144009,
                'message': 'fetch target host failed',
                'data': result
            }), 400

        manager = runner.inventory
        hosts = parser_inventory(manager)
        records = []
        default_region = db.collection('regions').find_one({'name': 'default'})
        if not default_region:
            result = db.collection('regions').insert_one({
                'name':
                'default',
                'add_by':
                None,
                'description':
                'auto generate',
                'created_at':
                time.time(),
            })
            region_id = str(result.inserted_id)
        else:
            region_id = str(default_region.get('_id'))

        for node in data:
            hostname = node.get('ansible_hostname')
            for group, host in hosts.items():
                where = {'name': group}
                # insert_data = {'$set': insert_data}
                existed = db.collection('groups').find_one(where)
                if not existed:
                    insert_data = {
                        'name': group,
                        'region': region_id,
                        'description': 'auto generator',
                        'state': 'active',
                        'add_by': login_user.get('username'),
                        'maintainer': None,
                        'created_at': int(time.time())
                    }
                    insert_result = db.collection('groups').insert_one(
                        insert_data)
                    group = insert_result.inserted_id
                else:
                    group = existed['_id']

                if host.get('name') == hostname:
                    vars = host.get('vars')
                    node['ansible_ssh_host'] = vars.get('ansible_ssh_host')
                    node['ansible_ssh_user'] = vars.get(
                        'ansible_ssh_user', 'root')
                    node['ansible_ssh_port'] = vars.get(
                        'ansible_ssh_port', '22')
                    node['group'] = [group]
                    node['add_by'] = login_user.get('username')
                    node['state'] = 'active'

                    break

            records.append(node)

        for record in records:
            where = {'ansible_ssh_host': record['ansible_ssh_host']}
            update = {'$set': record}
            result = db.collection('machines').update_one(where,
                                                          update,
                                                          upsert=True)
            extra = record.copy()
            extra['_id'] = result.upserted_id
            logger.info('add machines hostname: '.format({record['hostname']}),
                        extra={'record': data})

        return jsonify({
            'message': 'ok',
            'code': 0,
            'data': data,
            'records': records,
        })
예제 #8
0
파일: helper.py 프로젝트: eclogue/eclogue
def load_ansible_playbook(payload):
    template = payload.get('template')
    extra = payload.get('extra', {}) or {}
    if not template:
        return {
            'message': 'invalid params',
            'code': 104000,
        }
    name = template.get('name')
    if not name:
        return {
            'message': 'name required',
            'code': 104000,
        }
    entry = template.get('entry')
    if len(entry) < 2:
        return {
            'message': 'entry not found',
            'code': 104001,
        }
    book_id, entry_id = entry
    book_record = Book.find_by_id(book_id)
    if not book_record:
        return {
            'message': 'book not found',
            'code': 1040011,
        }
    entry_record = Playbook.find_by_id(entry_id)
    if not entry_record:
        return {
            'message': 'entry not found',
            'code': 104001,
        }
    inventory_type = template.get('inventory_type', 'file')
    inventory = template.get('inventory', None)
    if not inventory:
        return {'message': 'invalid param inventory', 'code': 104002}
    if inventory_type == 'file':
        inventory_record = parse_file_inventory(inventory)
    else:
        inventory_record = parse_cmdb_inventory(inventory)

    if not inventory_record:
        return {'message': 'illegal inventory', 'code': 104002}
    group_name = inventory_record.keys()
    if not inventory_record:
        return {'message': 'invalid param inventory', 'code': 104002}
    roles = template.get('roles')
    role_names = []
    if roles:
        roles = list(map(lambda i: ObjectId(i), roles))
        check = Playbook.find({
            'book_id': book_id,
            '_id': {
                '$in': roles,
            }
        })
        check = list(check)
        if not check:
            return {'message': 'invalid param role', 'code': 104003}

        role_names = list(map(lambda i: i.get('name'), check))

    extra_vars = {
        'node': list(group_name),
    }

    private_key = template.get('private_key')
    if private_key:
        key_record = Credential.find_one({
            '_id': ObjectId(private_key),
            'type': 'private_key'
        })
        if not key_record:
            return {'message': 'invalid private key', 'code': 104031}

    variables = extra.get('extraVars') or {}
    # variables.update({'node': inventory_record.get('limit')})
    if type(variables) in [dict, list]:
        variables = yaml.safe_dump(variables)

    app = template.get('app')
    if app:
        # @todo status=1
        app_record = Application.find_by_id(app)
        if not app_record:
            return {'message': 'invalid app', 'code': 104043}

        app_type = app_record.get('type')
        app_params = app_record.get('params')
        integration = Integration(app_type, app_params)
        check_app = integration.check_app_params()
        if not check_app:
            return {'message': 'invalid app', 'code': 104014}

        job_space = integration.get_job_space(name)
        if job_space and variables:
            tpl = Template(variables)
            variables = tpl.render(ECLOGUE_JOB_SPACE=job_space)

    if variables:
        variables = yaml.safe_load(variables)
        variables and extra_vars.update(variables)

    options = dict()
    extra_options = template.get('extraOptions')
    if extra_options and type(extra_options) == dict:
        options = extra_options.copy()
        # default_options = get_default_options('playbook')
        # for key, value in extra_options.items():
        #     if default_options.get(key):
        #         options[key] = value

    options['skip_tags'] = template.get('skip_tags', [])
    options['inventory'] = inventory_record
    # @todo limit
    # options['limit'] = inventory_record.get('limit', None)
    # options['credential'] = template.get('credential')
    options['limit'] = template.get('limit', 'all')
    options['forks'] = template.get('forks', 5)
    options['tags'] = template.get('tags', [])
    options['listtags'] = template.get('listtags', False)
    options['listtasks'] = template.get('listtasks', False)
    options['timeout'] = template.get('timeout', 10)
    options['verbosity'] = template.get('verbosity', 0)
    become_method = template.get('become_method')
    if become_method:
        options['become'] = 'yes'
        options['become_method'] = become_method
        if template.get('become_user'):
            options['become_user'] = template.get('become_user')

    vault_pass = template.get('vault_pass')
    if vault_pass:
        vault_record = Credential.find_one({'_id': ObjectId(vault_pass)})
        if not vault_record or not vault_record.get('body'):
            return {'message': 'invalid vault pass', 'code': 104004}

        vault_body = vault_record.get('body')
        vault = Vault({'vault_pass': config.vault.get('secret')})
        options['vault_pass'] = vault.decrypt_string(
            vault_body.get('vault_pass'))

    options['verbosity'] = template.get('verbosity', 0)
    options['diff'] = template.get('diff', False)
    # options['vault'] = template.get('vault')
    options['extra_vars'] = extra_vars
    status = int(extra.get('status', 0))

    return {
        'message': 'ok',
        'data': {
            'inventory': options['inventory'],
            'options': options,
            'name': name,
            'entry': entry_record['name'],
            'book_id': book_id,
            'book_name': book_record['name'],
            'roles': role_names,
            'inventory_type': inventory_type,
            'private_key': private_key,
            'template': template,
            'extra': extra,
            'status': status,
        }
    }