def delete_role(self): try: self.logger.info("Deleting role.") self.load_auth_cookie() self.start_db_session() self.check_admin() data = tornado.escape.json_decode(self.request.body) self.logger.debug(data) if 'username' not in data or data['username'] == '': raise TemboardUIError(400, "Username field is missing.") delete_role(self.db_session, data['username']) self.db_session.commit() self.db_session.close() self.logger.info("Done.") return JSONAsyncResult(200, {'delete': True}) except (TemboardUIError, Exception) as e: self.logger.exception(str(e)) self.logger.info("Failed.") try: self.db_session.rollback() self.db_session.close() except Exception: pass if isinstance(e, TemboardUIError): return JSONAsyncResult(e.code, {'error': e.message}) else: return JSONAsyncResult(500, {'error': "Internal error."})
def get_group(self, group_kind, group_name): self.logger.info("Getting group by name.") self.setUp() self.check_admin() group = get_group(self.db_session, group_name, group_kind) self.logger.debug(group) if group_kind == 'role': self.tearDown(commit=False) self.logger.info("Done") return JSONAsyncResult( 200, { 'name': group.group_name, 'kind': group.group_kind, 'description': group.group_description }) else: user_groups = get_group_list(self.db_session) self.tearDown(commit=False) self.logger.info("Done.") return JSONAsyncResult( 200, { 'name': group.group_name, 'kind': group.group_kind, 'description': group.group_description, 'user_groups': [{ 'name': user_group.group_name, 'description': user_group.group_description } for user_group in user_groups], 'in_groups': [ari.role_group_name for ari in group.ari] })
def push_data(self, ): key = self.request.headers.get('X-Key') if not key: return JSONAsyncResult(http_code=401, data={'error': 'X-Key header missing'}) try: data = tornado.escape.json_decode(self.request.body) # Insert data in an other thread. except Exception as e: return JSONAsyncResult(http_code=500, data={'error': e.message}) try: # We need to use a scoped_session object here as far the # code below is executed in its own thread. session_factory = sessionmaker(bind=self.engine) Session = scoped_session(session_factory) thread_session = Session() # Check the key if data['instances'][0]['available']: check_agent_key(thread_session, data['hostinfo']['hostname'], data['instances'][0]['data_directory'], data['instances'][0]['port'], key) else: # Case when PostgreSQL instance is not started. check_host_key(thread_session, data['hostinfo']['hostname'], key) # Update the inventory host = merge_agent_info(thread_session, data['hostinfo'], data['instances']) # Send the write SQL commands to the database because the # metrics are inserted with queries not the orm. Tables must # be there. thread_session.flush() thread_session.commit() # Insert metrics data insert_metrics(thread_session, host, data['data'], self.logger, data['hostinfo']['hostname'], data['instances'][0]['port']) # Close the session thread_session.close() return JSONAsyncResult(http_code=200, data={'done': True}) except IntegrityError as e: self.logger.exception(str(e)) try: thread_session.rollback() thread_session.close() except Exception: pass return JSONAsyncResult(http_code=409, data={'error': e.message}) except Exception as e: self.logger.exception(str(e)) try: thread_session.rollback() thread_session.close() except Exception: pass return JSONAsyncResult(http_code=500, data={'error': e.message})
def get_group(self, group_kind, group_name): try: self.logger.info("Getting group by name.") self.load_auth_cookie() self.start_db_session() self.check_admin() group = get_group(self.db_session, group_name, group_kind) self.logger.debug(group) if group_kind == 'role': self.db_session.expunge_all() self.db_session.commit() self.db_session.close() self.logger.info("Done") return JSONAsyncResult( 200, { 'name': group.group_name, 'kind': group.group_kind, 'description': group.group_description }) else: user_groups = get_group_list(self.db_session) self.db_session.expunge_all() self.db_session.commit() self.db_session.close() self.logger.info("Done.") return JSONAsyncResult( 200, { 'name': group.group_name, 'kind': group.group_kind, 'description': group.group_description, 'user_groups': [{ 'name': user_group.group_name, 'description': user_group.group_description } for user_group in user_groups], 'in_groups': [ari.role_group_name for ari in group.ari] }) except (TemboardUIError, Exception) as e: self.logger.exception(str(e)) self.logger.info("Failed.") try: self.db_session.rollback() self.db_session.close() except Exception: pass if isinstance(e, TemboardUIError): return JSONAsyncResult(e.code, {'error': e.message}) else: return JSONAsyncResult(500, {'error': "Internal error."})
def handle_exceptions(self, e): try: self.db_session.rollback() self.db_session.close() except Exception: pass if (isinstance(e, TemboardUIError) or isinstance(e, TemboardError)): return JSONAsyncResult(http_code=e.code, data={'error': e.message}) else: return JSONAsyncResult(http_code=500, data={'error': e.message})
def get_activity_w_b(self, agent_address, agent_port, mode): try: self.logger.info("Getting waiting/blocking sessions (proxy).") role = None instance = None self.load_auth_cookie() self.start_db_session() role = self.current_user if not role: raise TemboardUIError(302, "Current role unknown.") instance = get_instance(self.db_session, agent_address, agent_port) if not instance: raise TemboardUIError(404, "Instance not found.") if __name__ not in [ plugin.plugin_name for plugin in instance.plugins ]: raise TemboardUIError(408, "Plugin not activated.") self.db_session.expunge_all() self.db_session.commit() self.db_session.close() xsession = self.request.headers.get('X-Session') if not xsession: raise TemboardUIError(401, 'X-Session header missing') # Load activity. if mode == 'waiting': data_activity = temboard_activity_waiting( self.ssl_ca_cert_file, instance.agent_address, instance.agent_port, xsession) elif mode == 'blocking': data_activity = temboard_activity_blocking( self.ssl_ca_cert_file, instance.agent_address, instance.agent_port, xsession) else: raise TemboardUIError(404, "Mode unknown.") self.logger.info("Done.") return JSONAsyncResult(http_code=200, data=data_activity) except (TemboardUIError, TemboardError, Exception) as e: self.logger.exception(str(e)) self.logger.info("Failed.") try: self.db_session.close() except Exception: pass if (isinstance(e, TemboardUIError) or isinstance(e, TemboardError)): return JSONAsyncResult(http_code=e.code, data={'error': e.message}) else: return JSONAsyncResult(http_code=500, data={'error': e.message})
def post_hba(self, agent_address, agent_port): try: self.logger.info("Posting HBA (proxy).") instance = None role = None self.load_auth_cookie() self.start_db_session() role = self.current_user if not role: raise TemboardUIError(302, "Current role unknown.") instance = get_instance(self.db_session, agent_address, agent_port) if not instance: raise TemboardUIError(404, "Instance not found.") if __name__ not in [ plugin.plugin_name for plugin in instance.plugins ]: raise TemboardUIError(408, "Plugin not active.") self.db_session.expunge_all() self.db_session.commit() self.db_session.close() xsession = self.get_secure_cookie( "temboard_%s_%s" % (instance.agent_address, instance.agent_port)) if not xsession: raise TemboardUIError(401, "Authentication cookie is missing.") data = temboard_post_conf_file( self.ssl_ca_cert_file, 'hba', instance.agent_address, instance.agent_port, xsession, tornado.escape.json_decode(self.request.body)) # And reload postgresql configuration. temboard_post_administration_control(self.ssl_ca_cert_file, instance.agent_address, instance.agent_port, xsession, {'action': 'reload'}) self.logger.info("Done.") return JSONAsyncResult(http_code=200, data=data) except (TemboardUIError, TemboardError, Exception) as e: self.logger.exception(str(e)) self.logger.info("Failed.") try: self.db_session.close() except Exception: pass if (isinstance(e, TemboardUIError) or isinstance(e, TemboardError)): return JSONAsyncResult(http_code=e.code, data={'error': e.message}) else: return JSONAsyncResult(http_code=500, data={'error': e.message})
def delete_hba(self, agent_address, agent_port): try: self.logger.info("Deleting HBA (proxy).") instance = None role = None self.load_auth_cookie() self.start_db_session() role = self.current_user if not role: raise TemboardUIError(302, "Current role unknown.") instance = get_instance(self.db_session, agent_address, agent_port) if not instance: raise TemboardUIError(404, "Instance not found.") if __name__ not in [ plugin.plugin_name for plugin in instance.plugins ]: raise TemboardUIError(408, "Plugin not active.") self.db_session.expunge_all() self.db_session.commit() self.db_session.close() xsession = self.get_secure_cookie( "temboard_%s_%s" % (instance.agent_address, instance.agent_port)) if not xsession: raise TemboardUIError(401, "Authentication cookie is missing.") res = temboard_delete_hba_version( self.ssl_ca_cert_file, instance.agent_address, instance.agent_port, xsession, self.get_argument('version', None)) self.logger.info("Done.") return JSONAsyncResult(http_code=200, data=res) except (TemboardUIError, TemboardError, Exception) as e: self.logger.exception(str(e)) self.logger.info("Failed.") try: self.db_session.close() except Exception: pass if (isinstance(e, TemboardUIError) or isinstance(e, TemboardError)): return JSONAsyncResult(http_code=e.code, data={'error': e.message}) else: return JSONAsyncResult(http_code=500, data={'error': e.message})
def post_kill(self, agent_address, agent_port): try: self.logger.info("Posting terminate backend.") role = None instance = None self.load_auth_cookie() self.start_db_session() role = self.current_user if not role: raise TemboardUIError(302, "Current role unknown.") instance = get_instance(self.db_session, agent_address, agent_port) if not instance: raise TemboardUIError(404, "Instance not found.") if __name__ not in [ plugin.plugin_name for plugin in instance.plugins ]: raise TemboardUIError(408, "Plugin not activated.") self.db_session.expunge_all() self.db_session.commit() self.db_session.close() xsession = self.request.headers.get('X-Session') if not xsession: raise TemboardUIError(401, 'X-Session header missing') self.logger.debug(tornado.escape.json_decode(self.request.body)) data_kill = temboard_activity_kill( self.ssl_ca_cert_file, instance.agent_address, instance.agent_port, xsession, tornado.escape.json_decode(self.request.body)) self.logger.info("Done.") return JSONAsyncResult(http_code=200, data=data_kill) except (TemboardUIError, TemboardError, Exception) as e: self.logger.exception(str(e)) self.logger.info("Failed.") try: self.db_session.close() except Exception: pass if (isinstance(e, TemboardUIError) or isinstance(e, TemboardError)): return JSONAsyncResult(http_code=e.code, data={'error': e.message}) else: return JSONAsyncResult(http_code=500, data={'error': e.message})
def get_alerts(self, address, port): self.setUp(address, port) data_buffer = cStringIO.StringIO() cur = self.db_session.connection().connection.cursor() cur.execute("SET search_path TO monitoring") query = """ COPY ( SELECT array_to_json(array_agg(x)) FROM ( SELECT json_build_object('description', c.description, 'name', c.name, 'key', sc.key, 'state', sc.state, 'datetime', sc.datetime, 'value', sc.value, 'warning', sc.warning, 'critical', sc.critical) as x FROM monitoring.state_changes sc JOIN monitoring.checks c ON (sc.check_id = c.check_id) WHERE c.host_id = %s AND c.instance_id = %s AND (sc.state = 'WARNING' OR sc.state = 'CRITICAL') ORDER BY sc.datetime desc LIMIT 20 ) as tab ) TO STDOUT """ # noqa # build the query query = cur.mogrify(query, (self.host_id, self.instance_id)) cur.copy_expert(query, data_buffer) cur.close() data = data_buffer.getvalue() data_buffer.close() try: data = json.loads(data) except Exception as e: logger.exception(str(e)) logger.debug(data) data = [] return JSONAsyncResult(http_code=200, data=data)
def get_activity(self, agent_address, agent_port, mode): self.logger.info("Getting activity (proxy).") self.setUp(agent_address, agent_port) self.check_active_plugin(__name__) xsession = self.request.headers.get('X-Session') if not xsession: raise TemboardUIError(401, 'X-Session header missing') # Load activity. if mode == 'waiting': data_activity = temboard_activity_waiting(self.ssl_ca_cert_file, agent_address, agent_port, xsession) elif mode == 'blocking': data_activity = temboard_activity_blocking(self.ssl_ca_cert_file, agent_address, agent_port, xsession) else: data_activity = temboard_activity(self.ssl_ca_cert_file, agent_address, agent_port, xsession) self.logger.info("Done.") return JSONAsyncResult(http_code=200, data=data_activity)
def get_checks(self, address, port): self.setUp(address, port) data = checks_info(self.db_session, self.host_id, self.instance_id) for datum in data: spec = check_specs[datum['name']] if 'value_type' in spec: datum['value_type'] = spec['value_type'] return JSONAsyncResult(http_code=200, data=data)
def get_detail(self, address, port, check_name): self.setUp(address, port) if check_name not in check_specs: raise TemboardUIError(404, "Unknown check '%s'" % check_name) detail = check_state_detail(self.db_session, self.host_id, self.instance_id, check_name) return JSONAsyncResult(http_code=200, data=detail)
def get_discover(self, agent_address, agent_port): self.logger.info("Getting discovery.") self.setUp() self.check_admin() res = temboard_discover(self.ssl_ca_cert_file, agent_address, agent_port) self.tearDown(commit=False) self.logger.info("Done.") return JSONAsyncResult(200, res)
def get_role(self, username): try: self.logger.info("Getting role by name.") self.load_auth_cookie() self.start_db_session() self.check_admin() role = get_role(self.db_session, username) groups = get_group_list(self.db_session) self.db_session.expunge_all() self.db_session.commit() self.db_session.close() self.logger.info("Done.") return JSONAsyncResult( 200, { 'role_name': role.role_name, 'role_email': role.role_email, 'is_active': role.is_active, 'is_admin': role.is_admin, 'in_groups': [group.group_name for group in role.groups], 'groups': [{ 'name': group.group_name, 'description': group.group_description } for group in groups] }) except (TemboardUIError, Exception) as e: self.logger.exception(str(e)) self.logger.info("Failed.") try: self.db_session.rollback() self.db_session.close() except Exception: pass if isinstance(e, TemboardUIError): return JSONAsyncResult(e.code, {'error': e.message}) else: return JSONAsyncResult(500, {'error': "Internal error."})
def handle_exception(self, e): # Exception handler aimed to return JSONAsyncResult self.logger.exception(str(e)) try: self.db_session.close() except Exception: pass # Return 200 with empty list when an error occurs no_error = int(self.get_argument('noerror', default=0)) if no_error == 1: return JSONAsyncResult(http_code=200, data=u'') else: if (isinstance(e, TemboardUIError)): http_code = e.code message = e.message else: http_code = 500 message = "Internal error" return JSONAsyncResult(http_code=http_code, data={'error': message})
def get_check_changes(self, address, port, check_name): self.setUp(address, port) # Arguments start = self.get_argument('start', default=None) end = self.get_argument('end', default=None) if check_name not in check_specs: raise TemboardUIError(404, "Unknown check '%s'" % check_name) start_time = None end_time = None if start: try: start_time = dt_parser.parse(start) except ValueError as e: raise TemboardUIError(406, 'Datetime not valid.') if end: try: end_time = dt_parser.parse(end) except ValueError as e: raise TemboardUIError(406, 'Datetime not valid.') data_buffer = cStringIO.StringIO() cur = self.db_session.connection().connection.cursor() cur.execute("SET search_path TO monitoring") query = """ COPY ( SELECT array_to_json(array_agg(json_build_object( 'datetime', f.datetime, 'enabled', f.enabled, 'warning', f.warning, 'critical', f.critical, 'description', f.description ))) FROM get_check_changes(%s, %s, %s, %s, %s) f ) TO STDOUT """ # noqa # build the query query = cur.mogrify( query, (self.host_id, self.instance_id, check_name, start_time, end_time)) cur.copy_expert(query, data_buffer) cur.close() data = data_buffer.getvalue() data_buffer.close() try: data = json.loads(data) except Exception as e: logger.exception(str(e)) logger.debug(data) data = [] return JSONAsyncResult(http_code=200, data=data)
def post_login(self): try: self.logger.info("Login (API).") post = tornado.escape.json_decode(self.request.body) p_role_name = post['username'] p_role_password = post['password'] role_hash_password = hash_password(p_role_name, p_role_password) self.start_db_session() role = get_role_by_auth(self.db_session, p_role_name, role_hash_password) self.logger.info("Role '%s' authentificated." % (role.role_name)) self.db_session.expunge_all() self.db_session.commit() self.db_session.close() sleep(1) self.logger.info("Done.") return JSONAsyncResult(http_code=200, data={"message": "OK"}, secure_cookie={ 'name': 'temboard', 'content': gen_cookie(role.role_name, role_hash_password) }) except (TemboardUIError, Exception) as e: try: self.db_session.rollback() self.db_session.close() except Exception: pass self.logger.exception(str(e)) self.logger.info("Failed.") sleep(1) return JSONAsyncResult(http_code=401, data={"error": "Wrong username/password."})
def delete_group(self, group_kind): self.logger.info("Deleting group.") self.setUp() self.check_admin() data = tornado.escape.json_decode(self.request.body) self.logger.debug(data) if 'group_name' not in data or data['group_name'] == '': raise TemboardUIError(400, "Group name field is missing.") delete_group(self.db_session, data['group_name'], group_kind) self.tearDown() self.logger.info("Done.") return JSONAsyncResult(200, {'delete': True})
def get_hba_options(self, agent_address, agent_port): self.logger.info("Getting HBA options (proxy).") self.setUp(agent_address, agent_port) self.check_active_plugin(__name__) xsession = self.request.headers.get('X-Session') if not xsession: raise TemboardUIError(401, 'X-Session header missing') hba_options = temboard_get_hba_options(self.ssl_ca_cert_file, agent_address, agent_port, xsession) self.logger.info("Done.") return JSONAsyncResult(http_code=200, data=hba_options)
def get_all(self, group_kind): try: self.logger.info("Getting group list.") self.load_auth_cookie() self.start_db_session() self.check_admin() groups = get_group_list(self.db_session, group_kind) self.logger.debug(groups) self.db_session.expunge_all() self.db_session.commit() self.db_session.close() self.logger.info("Done.") return JSONAsyncResult( 200, { 'groups': [{ 'name': group.group_name, 'kind': group.group_kind, 'description': group.group_description } for group in groups], 'loaded_plugins': self.application.loaded_plugins }) except (TemboardUIError, Exception) as e: self.logger.info("Failed.") self.logger.exception(str(e)) try: self.db_session.rollback() self.db_session.close() except Exception: pass if isinstance(e, TemboardUIError): return JSONAsyncResult(e.code, {'error': e.message}) else: return JSONAsyncResult(500, {'error': "Internal error."})
def post_configuration(self, agent_address, agent_port): self.logger.info("Posting configuration (proxy).") self.setUp(agent_address, agent_port) self.check_active_plugin(__name__) xsession = self.get_secure_cookie("temboard_%s_%s" % (agent_address, agent_port)) if not xsession: raise TemboardUIError(401, "Authentication cookie is missing.") data = temboard_post_configuration( self.ssl_ca_cert_file, agent_address, agent_port, xsession, tornado.escape.json_decode(self.request.body)) self.logger.info("Done.") return JSONAsyncResult(http_code=200, data=data)
def delete_hba(self, agent_address, agent_port): self.logger.info("Deleting HBA (proxy).") self.setUp(agent_address, agent_port) self.check_active_plugin(__name__) xsession = self.get_secure_cookie("temboard_%s_%s" % (agent_address, agent_port)) if not xsession: raise TemboardUIError(401, "Authentication cookie is missing.") res = temboard_delete_hba_version(self.ssl_ca_cert_file, agent_address, agent_port, xsession, self.get_argument('version', None)) self.logger.info("Done.") return JSONAsyncResult(http_code=200, data=res)
def post_kill(self, agent_address, agent_port): self.logger.info("Posting terminate backend.") self.setUp(agent_address, agent_port) self.check_active_plugin(__name__) xsession = self.request.headers.get('X-Session') if not xsession: raise TemboardUIError(401, 'X-Session header missing') self.logger.debug(tornado.escape.json_decode(self.request.body)) data_kill = temboard_activity_kill( self.ssl_ca_cert_file, agent_address, agent_port, xsession, tornado.escape.json_decode(self.request.body)) self.logger.info("Done.") return JSONAsyncResult(http_code=200, data=data_kill)
def delete_instance(self): self.logger.info("Deleting instance.") self.setUp() self.check_admin() data = tornado.escape.json_decode(self.request.body) self.logger.debug(data) if 'agent_address' not in data or data['agent_address'] == '': raise TemboardUIError(400, "Agent address field is missing.") if 'agent_port' not in data or data['agent_port'] == '': raise TemboardUIError(400, "Agent port field is missing.") delete_instance(self.db_session, data['agent_address'], data['agent_port']) self.tearDown() self.logger.info("Done.") return JSONAsyncResult(200, {'delete': True})
def post_group(self, group_kind, group_name): self.logger.info("Posting new group.") self.setUp() group = None self.check_admin() if group_name: # Update group case. group = get_group(self.db_session, group_name, group_kind) data = tornado.escape.json_decode(self.request.body) self.logger.debug(data) # Submited attributes checking. if 'new_group_name' not in data or data['new_group_name'] == '': raise TemboardUIError(400, "Group name is missing.") if 'description' not in data: raise TemboardUIError(400, "Group description field is missing.") check_group_name(data['new_group_name']) check_group_description(data['description']) # At this point we can proceed with DB operations. # Update group case. if group: if group_kind == 'instance': for ari in group.ari: delete_role_group_from_instance_group( self.db_session, ari.role_group_name, group.group_name) group = update_group(self.db_session, group.group_name, group_kind, data['new_group_name'], data['description']) # New group case. else: group = add_group(self.db_session, data['new_group_name'], data['description'], group_kind) if 'user_groups' in data and data['user_groups']: for group_name in data['user_groups']: add_role_group_in_instance_group(self.db_session, group_name, group.group_name) self.tearDown() self.logger.info("Done.") return JSONAsyncResult(200, {'ok': True})
def get_all(self, group_kind): self.logger.info("Getting group list.") self.setUp() self.check_admin() groups = get_group_list(self.db_session, group_kind) self.logger.debug(groups) self.logger.info("Done.") self.tearDown(commit=False) return JSONAsyncResult( 200, { 'groups': [{ 'name': group.group_name, 'kind': group.group_kind, 'description': group.group_description } for group in groups], 'loaded_plugins': self.application.loaded_plugins })
def post_checks(self, address, port): self.setUp(address, port) # POST data reading post = tornado.escape.json_decode(self.request.body) if 'checks' not in post or type(post.get('checks')) is not list: raise TemboardUIError(400, "Post data not valid.") for row in post['checks']: if row.get('name') not in check_specs: raise TemboardUIError(404, "Unknown check '%s'" % row.get('name')) for row in post['checks']: # Find the check from its name check = self.db_session.query(Check).filter( Check.name == unicode(row.get('name')), Check.host_id == self.host_id, Check.instance_id == self.instance_id).first() if u'enabled' in row: check.enabled = bool(row.get(u'enabled')) if u'warning' in row: warning = row.get(u'warning') if type(warning) not in (int, float): raise TemboardUIError(400, "Post data not valid.") check.warning = warning if u'critical' in row: critical = row.get(u'critical') if type(critical) not in (int, float): raise TemboardUIError(400, "Post data not valid.") check.critical = critical if u'description' in row: check.description = row.get(u'description') self.db_session.merge(check) self.db_session.commit() return JSONAsyncResult(http_code=200, data=dict())
def get_instance(self, agent_address, agent_port): self.logger.info("Getting instance.") self.setUp(agent_address, agent_port) self.check_admin() groups = get_group_list(self.db_session, 'instance') self.logger.info("Done.") self.tearDown(commit=False) return JSONAsyncResult( 200, { 'agent_address': self.instance.agent_address, 'agent_port': self.instance.agent_port, 'agent_key': self.instance.agent_key, 'hostname': self.instance.hostname, 'cpu': self.instance.cpu, 'memory_size': self.instance.memory_size, 'pg_port': self.instance.pg_port, 'pg_version': self.instance.pg_version, 'pg_data': self.instance.pg_data, 'in_groups': [group.group_name for group in self.instance.groups], 'enabled_plugins': [plugin.plugin_name for plugin in self.instance.plugins], 'groups': [{ 'name': group.group_name, 'description': group.group_description } for group in groups], 'loaded_plugins': self.application.loaded_plugins })
def get_checks(self, address, port): self.setUp(address, port) data = checks_info(self.db_session, self.host_id, self.instance_id) return JSONAsyncResult(http_code=200, data=data)