def add_agent(self, agent_name, agent_ip=None): # Thực hiện thêm agent trên manager thông qua API của manager log = logger("Add agent") if agent_ip: data_create = {'name': agent_name, 'ip': agent_ip} res = requests.post('{0}/{1}'.format(self.base_url, 'agents'), data=data_create, auth=self.auth) else: data_create = {'name': agent_name} res = requests.post('{0}/{1}'.format(self.base_url, 'agents'), data=data_create, auth=self.auth) if res.status_code == 200: agent_info = res.json() if agent_info['error'] == 0: agent_id = agent_info['data']['id'] agent_key = agent_info['data']['key'] return agent_id, agent_key else: log.error(agent_info['message']) exit() else: # msg = json.dumps(res, indent=4, sort_keys=True) code = "Status: {0} - {1}".format( res.status_code, requests.status_codes._codes[res.status_code]) log.error("ERROR - ADD AGENT:\n{0}\n".format(code)) exit()
def getToken(self, user_name): log = logger('Get token') url = self.manager['url'] try: api_auth = '{0}/api/auth/token/'.format(url) if user_name not in self.manager['manager']: log.error('Permission denied') exit() data_auth = { 'username': user_name, 'password': self.manager['manager'][user_name] } response = requests.post(api_auth, data=data_auth) if response.status_code == 400: content = response.json() if 'non_field_errors' in content: log.error(content['non_field_errors'][0]) log.warning('Username/password incorrect') if 'username' in content and 'required' in content['username'][0] \ or 'password' in content and 'required' in content['password'][0]: log.error('Missing username or password') return elif response.status_code == 404: log.error('{0} not found, please check again'.format(api_auth)) return elif response.status_code == 200: return response.json()['token'] except OSError as err: log.warning("Cannot access to web manager\n {0}".format(err)) return None
def _set_info_for_php(proj_name, host='127.0.0.1'): log = logger('set info') dir = os.getcwd() + '/' + proj_name if not isdir(dir): log.error('Can not find project') # while dir.split('/')[-1] != proj_name: # dir = dirname(dir) # if dir == '/' or dir == None: # log.error('Can not find project') # return dir += '/lib/db.php' with open(dir) as f: content = f.readlines() for i in range(len(content)): if '$host =' in content[i]: content[i] = '\t$host = \'{}\';\n'.format(host) if '$user ='******'\t$user = \'{}\';\n'.format(proj_name) if '$pass ='******'\t$pass = \'{}\';\n'.format(proj_name) if '$db =' in content[i]: content[i] = '\t$db = \'{}\';\n'.format(proj_name) with open(dir, "w") as f: f.writelines(content)
def deploy_cmd(server, instance, clone=False): log = logger('deploy') log.info("Deploying...") first_deploy = False if instance: inst_name = instance['name'] url_remote = instance['project']['url'] db_name = instance['db_name'] version = instance['project_ver']['version'] inst_type = instance['type'] dest_dir = '/opt/web/{}'.format(inst_name) if not server.check_remote_file(dest_dir): first_deploy = True if first_deploy: log.info("Clone project") server.git_clone(url_remote, dest_dir, version) if not clone: server.create_db(dest_dir, db_name, inst_name, inst_type) if inst_type != 'i': dir_input_db = '/opt/web/{0}/db/'.format(inst_name) log.info('Prepare database for importing') server.import_db(dir_input_db, db_name) else: server.git_pull(version, dest_dir)
def deploy(ctx, ip, port, instance_name, url, project_name, db_name, project_ver, type, clone, user_name): """Deploy new project or just update source code""" log = logger('Deploy log') user = UserConfig() token = user.getToken(user_name) instance = {} urlWebManager = user.manager['url'] if token: head = {'Authorization': 'JWT {}'.format(token)} resource = 'api/instances/{0}'.format(instance_name) res = requests.get('{0}/{1}'.format(urlWebManager, resource), headers=head) if res.status_code == 404: log.error( 'Instance {0} not found on WebManager'.format(instance_name)) return elif res.status_code == 200: instance = res.json() else: if ip and port and url and project_ver: instance = { 'name': instance_name, 'project': { 'name': project_name or instance_name.split('_')[0], 'url': url }, 'db_name': db_name or instance_name, 'project_ver': { "version": project_ver }, 'type': type or instance_name.split('_')[-1][0], } host = {'ip': ip, 'port': port} else: log.error('Not enough information to execute command') exit() try: srv = Server(instance['host'] if 'host' in instance else host) deploy_cmd(srv, instance, clone) if token: data_update = { 'usr_deployed': user_name, 'latest_deploy': datetime.now() } head = {'Authorization': 'JWT {}'.format(token)} resource = 'api/instances/{0}'.format(instance_name) res = requests.put('{0}/{1}'.format(urlWebManager, resource), headers=head, data=data_update) if res.status_code == 200: log.info('The deployment process has been completed') else: log.warning('Cannot update user deployed instance {0} ' 'or deployment time'.format(instance_name)) except OSError as err: log.error(err)
def create_user(self, user, host, passwd, follow=False): log = logger('create user') query = "CREATE USER \'{}\'@\'{}\' " \ "IDENTIFIED BY \'{}\';".format(user, host, passwd) log.debug("Create user database \n {}".format(query)) cmd = ['mysql', '--execute=\"%s\"' % query] self.execute(cmd, follow)
def git_pull(self, version='1.0', inst_path=None, follow=False): log = logger('git pull') if not self.check_remote_file(inst_path): log.ERROR("Don't found directory of project") return log.info("Pulling project...") cmd = ['git', '-C', inst_path, 'pull', 'origin', version] self.execute(cmd, follow)
def _grant_user(db_name, user): log = logger('grant user') log.info('Set grant all on database for user') query = "GRANT ALL ON {}.* TO '{}'@'{}'".format(db_name, user, '127.0.0.1') cmd = [ 'mysql', '--execute=\'%s\'' % query ] subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def restore(ctx, path, database): '''Restore database from file .sql''' log = logger('restore database') # Đợi khi có website sẽ thay thông tin project trên web if not path: os.mkdir('/opt/web/db_bk/{}'.format('project_name')) path = '/opt/web/db_bk/{}/{}.sql'.format('project_name', 'project_name') _restore(path, database)
def import_db(self, dir, db_name, follow=False): log = logger('Import database') if self.check_remote_file(dir): cmd = ['find', dir, '-name', '*.sql'] list_db = self.execute(cmd, follow) log.info('Restore data to database') for db in list_db.split('\n'): if db: cmd = ['mysql', '--database', db_name, '<', db] self.execute(cmd, follow)
def import_agent(self, agent_key): # Import agent key được remote thực hiện từ server manager đến server agent log = logger('Import agent') cmd = [ 'yes', '|', '/var/ossec/bin/manage_agents', '-i', '\'{0}\''.format(agent_key) ] i = self.server.execute(cmd) if 'Added' in i: log.info('Imported agent key')
def _restore(path, db_name): log = logger('Query restore') if not isfile(path): log.warning('Could not find backup file or not existed') return cmd = [ 'mysql', '--database', db_name, '<', [path] ] subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def _create_user(user, passwd): log = logger('create user') query = "CREATE USER \'{}\'@\'{}\' " \ "IDENTIFIED BY \'{}\';".format(user, '127.0.0.1', passwd) log.info("Creating user database") cmd = [ 'mysql', '--execute=\"%s\"' % query ] subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def get_status(self, agent_name): # Lấy các thông tin agent sau khi đăng ký log = logger('Get status agent') pending_count = 0 if agent_name: res = requests.get('{0}/{1}/{2}'.format(self.base_url, 'agents/name', agent_name), auth=self.auth) if res.status_code == 200: last_alive = None monitor = 'n' #Never Connected agent_info = res.json() if agent_info['error'] == 0: if 'Active' in agent_info['data']['status']: monitor = 'a' #Active elif 'Pending' in agent_info['data']['status']: # Thực hiện lại get_status sau 3 lần pending, # nếu sau 3 lần (mỗi lần 5s) agent vẫn ở trạng thái pending # thì update status trên wabmanager is_agents=False if pending_count < 3: time.sleep(5) pending_count += 1 return self.get_status(agent_name) monitor = 'p' #Pending last_alive = agent_info['data']['lastKeepAlive'] elif 'Disconnected' in agent_info['data']['status']: monitor = 'd' if monitor == 'a': return { 'id_agent': agent_info['data']['id'], 'monitor': monitor, 'date_add': agent_info['data']['dateAdd'], 'last_alive': agent_info['data']['lastKeepAlive'], 'os': agent_info['data']['os']['platform'] + ' ' +\ agent_info['data']['os']['version'], } else: return { 'id_agent': agent_info['data']['id'], 'monitor': monitor, 'date_add': agent_info['data']['dateAdd'], 'last_alive': last_alive, } else: log.error(agent_info['message']) else: # msg = json.dumps(res, indent=4, sort_keys=True) code = "Status: {0} - {1}".format( res.status_code, requests.status_codes._codes[res.status_code]) log.error("ERROR - ADD AGENT:\n{0}\n".format(code)) exit()
def create(ctx, name, password, user): '''Create empty database''' log = logger('Create database') if not isfile('/opt/web/.my.cnf'): log.error('Missing configuration file of mysql') return # Đợi khi có website sẽ thay thông tin project trên web if not user: user = '******' _create_user(user, password) if not name: name = 'project_name' _create_db(name, user)
def _create_db(name, user='******'): log = logger('create database') log.info('Creating database {}'.format(name)) cmd = ['/usr/bin/mysqladmin', 'create', name] ex = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = ex.communicate() if 'database exists' in error.decode('UTF-8'): log.warning('Database \"{}\" already exists'.format(name)) if click.confirm('Do you want drop and create one new?'): _drop_db(name) log.info('Creating new empty database') _create_db(name) _grant_user(name, user)
def __init__(self, host, userhost='web', timeout=60): log = logger("Server configuration ") # self.user = UserConfig() if host: log.info('Configurating host') host_ssh = '%s@%s' % (userhost, host['ip']) self.ssh = ssh.bake(host_ssh, '-p', host['port'] or '22', '-A', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no', '-o', 'BatchMode=yes', '-o', 'PasswordAuthentication=no', '-o', 'ConnectTimeout=%s' % timeout) else: log.error('No host to deploy') exit(0)
def __init__(self): log = logger("User log") config_name = '.{}'.format('manager') commandrc = join(expanduser('~'), config_name) if exists(commandrc): with open(commandrc, 'r') as commandrc_file: commandrc_file = commandrc_file.read().split('\n') data = '' for contennt in commandrc_file: data += '{}\n '.format( base64.b64decode(contennt).decode()) self.manager = yaml.load(data) or {} if not self.manager: log.error( "Missing file .manager, please authentication Who you are?") return
def start(ctx, url, version, name): """Build project on local""" log = logger("start") log.info("Checking url") try: sh.git('ls-remote', url) except ErrorReturnCode as e: if "not found" in str(e): log.error("Repository not found") return gc = sh.git.bake('clone', url, '-b', version) if name: gc(name, _bg=True) else: gc() _set_info_for_php(name or url.split("/")[1].replace(".git", ""))
def execute(self, cmd, follow=False, print_follow=False): """ Execute a command on the remote host follow allow to read stdout as an iterator """ log = logger('execute command sh') if print_follow: result = self.ssh(*cmd, _iter=True, _err_to_out=follow) for line in result: print(line.strip()) else: result = self.ssh(*cmd, _iter=False, _err_to_out=follow) # Pipe error output to stdout when following if not follow and result.stderr: ''' Don't do this with follow, or it will stop output until the command is fully executed. ''' log.debug(result.stderr) return result
def create_db(self, proj_dir, db_name, instance_name, inst_type='i', create_user=True, host='localhost', follow=False): config_php = proj_dir + "/lib/db.php" if not db_name: db_name = instance_name log = logger('create database') db_user = instance_name log.info('Generate password') if inst_type == 'i': passwd = 'abc123ABC!!!' elif inst_type == 's': passwd = 'abc123ABC!@#' else: passwd = self.generate_passwd() log.info('Update file config connect between PHP and MySQL') cmd = [ 'sed', '-i', "\"s/\$host =/\$host = \'{0}\'\;/g;" "s/\$user =/\$user = \'{1}\'\;/g;" "s/\$pass =/\$pass = \'{2}\'\;/g;" "s/\$db =/\$db = \'{3}\'\;/g\"".format(host, db_user, passwd, db_name), config_php ] self.execute(cmd, follow) if create_user: log.info('Create user database') self.create_user(db_user, host, passwd) log.info('Create database {}'.format(db_name)) cmd = ['mysqladmin', 'create', db_name] output = self.execute(cmd, follow) log.info('Set grant all on database for user') self.grant_user(db_user, host, db_name)
def createDB(ctx, name, type, ip, port, createuser, instance_name, user_name): """Create empty database for instance""" log = logger('Create empty database log') print(createDB) user = UserConfig() token = user.getToken(user_name) instance = {} if token: head = {'Authorization': 'JWT {}'.format(token)} urlWebManager = user.manager['url'] resource = 'api/instances/{0}'.format(instance_name) res = requests.get('{0}/{1}'.format(urlWebManager, resource), headers=head) if res.status_code == 404: log.error( 'Instance {0} not found on WebManager'.format(instance_name)) return elif res.status_code == 200: instance = res.json() else: if ip and port: instance = { 'name': instance_name, 'db_name': name or instance_name, 'type': type or instance_name.split('_')[-1][0], } host = {'ip': ip, 'port': port} else: log.error('Not enough information to execute command') exit() try: srv = Server(instance['host'] if 'host' in instance else host) dest_dir = '/opt/web/{}'.format(instance_name) srv.create_db(dest_dir, instance['db_name'], instance_name, instance['type'], createuser) log.info('Create new database has been completed') except OSError as err: log.error(err)
def git_clone(self, url, dest_dir, version='1.0', follow=False): log = logger('git clone') log.info("Clonning project from github") cmd = ['git clone', '--progress', url, dest_dir, '--branch', version] self.execute(cmd, follow)
def grant_user(self, user, host, db_name, follow=False): log = logger('grant user') query = "GRANT ALL ON {}.* TO '{}'@'{}'".format(db_name, user, host) log.debug('Set grant all on database for user \n{}'.format(query)) cmd = ['mysql', '--execute=\'%s\'' % query] self.execute(cmd, follow)
def register(ctx, ip, port, url, user_name, agent_name): """Create trust relationship between Wazuh manager and agents.""" log = logger('Register agents') user = UserConfig() token = user.getToken(user_name) urlWebManager = user.manager['url'] if token: head = {'Authorization': 'JWT {}'.format(token)} resource = 'api/hosts/{0}'.format(agent_name) res = requests.get('{0}/{1}'.format(urlWebManager, resource), headers=head) if res.status_code == 404: log.error( 'Hostname {0} not found on WebManager'.format(agent_name)) return elif res.status_code == 200: host = res.json() if not ip: ip = host['ip'] else: if host['ip'] != '': data_update = {'ip': ip} resource = 'api/hosts/{0}'.format(agent_name) res = requests.put('{0}/{1}'.format( urlWebManager, resource), headers=head, data=data_update) if res.status_code == 200: log.info('Update succeeded') else: log.error('Something wrong ' 'when you update host\'s ip address') else: if ip and port: host = {'ip': ip, 'port': port} else: log.error('Not enough information to execute command') exit() try: srv = Server(host, userhost="root") monitor = Monitor(manager_url=url, server=srv) log.info('Adding agent {0} to manager'.format(agent_name)) agent_id, agent_key = monitor.add_agent(agent_name, ip) log.info('Agent {0} had id {1}'.format(agent_name, agent_id)) log.info('Importing agent key') monitor.import_agent(agent_key) log.info('Restarting ossec') monitor.restart_ossec() time.sleep( 5 ) # Đợi 5s cho quá trình restart trình điều khiển của agent hoàn tất if token: head = {'Authorization': 'JWT {}'.format(token)} log.info('Update infomations') data_update = monitor.get_status(agent_name) resource = 'api/hosts/{0}'.format(agent_name) res = requests.put('{0}/{1}'.format(urlWebManager, resource), headers=head, data=data_update) if res.status_code == 200: log.info('The register agent process has been completed') else: log.warning( 'Cannot update information about {0} host \n {1}'.format( agent_name, res)) except OSError as err: log.error(err)
def restart_ossec(self): # Restart trình điều khiển của agent sau khi import key log = logger('Restart ossec') cmd = ["/var/ossec/bin/ossec-control", "restart"] self.server.execute(cmd)
def _drop_db(name): log = logger('drop database') cmd = ['/usr/bin/mysqladmin', 'drop', '-f', name] log.info('Dropping database \"{}\" '.format(name)) subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) log.info('Dropped database \"{}\"'.format(name))