def profile(self): profile_path = self.rules.get('profile') if profile_path is None: return {} now = time.time() try: if not (self._update_ts <= now < self._update_ts + UPDATE_INTERVAL): # Check if updated ts = os.path.getmtime(profile_path) self._update_ts = now else: # Skip ts = self._profile_ts if ts > self._profile_ts or ts > now or now > self._profile_ts + FORCE_UPDATE_INTERVAL: elastalert_logger.info('Reloading profile %s', profile_path) with open(profile_path, 'r') as profile_file: profile = json.load(profile_file) self._profile = { k: timedelta(seconds=profile[k]) for k in profile } self._profile_ts = now except (OSError, IOError, ValueError) as e: elastalert_logger.error('Cannot load profile %s: %s', profile_path, e) return self._profile
def garbage_collect(self, timestamp): if self.garbage_time == 0: self.garbage_time = timestamp diff = timestamp - self.garbage_time self.garbage_time = timestamp elastalert_logger.info( "From garbage collect - time diff since last exec: %f" % diff.total_seconds()) if not diff.total_seconds() > 0: return self.exec_num += 1 elastalert_logger.info("Timeperiod: %d/%d" % (self.exec_num, self.runs_per_timeperiod)) # end of timeperiod if self.exec_num >= self.runs_per_timeperiod: self.exec_num = 0 self.timeperiods_index += 1 # end of all timeperiods (self.no_of_timeperiods) if self.timeperiods_index >= self.no_of_timeperiods: elastalert_logger.info("All timeperiods passed") elastalert_logger.info("Sets for all timeperiods: %s" % str(self.values)) self.timeperiods_index = 0 result = self.values[0] for i in range(0, self.no_of_timeperiods): result = result & self.values[i] self.values[i].clear() if result != set(): result_str = " ".join(result) elastalert_logger.info("Alert triggered, final result: %s" % result_str) extra = {self.field: result_str} self.add_match(extra)
def alert(self, matches): body = '' for match in matches: body += str(BasicMatchString(self.rule, match)) if len(matches) > 1: body += '\n----------------------------------------\n' if len(body) > 2047: body = body[ 0: 1950] + '\n *message was cropped according to chatwork embed description limits!*' headers = {'X-ChatWorkToken': self.chatwork_apikey} # set https proxy, if it was provided proxies = { 'https': self.chatwork_proxy } if self.chatwork_proxy else None auth = HTTPProxyAuth( self.chatwork_proxy_login, self.chatwork_proxy_pass) if self.chatwork_proxy_login else None params = {'body': body} try: response = requests.post(self.url, params=params, headers=headers, proxies=proxies, auth=auth) response.raise_for_status() except RequestException as e: raise EAException( "Error posting to Chattwork: %s. Details: %s" % (e, "" if e.response is None else e.response.text)) elastalert_logger.info("Alert sent to Chatwork room %s" % self.chatwork_room_id)
def alert(self, matches): """ Each match will trigger a POST to the specified endpoint(s). """ for match in matches: payload = match if self.post_all_values else {} payload.update(self.post_static_payload) for post_key, es_key in list(self.post_payload.items()): payload[post_key] = lookup_es_key(match, es_key) headers = { "Content-Type": "application/json", "Accept": "application/json;charset=utf-8" } if self.post_ca_certs: verify = self.post_ca_certs else: verify = not self.post_ignore_ssl_errors if self.post_ignore_ssl_errors: requests.packages.urllib3.disable_warnings() headers.update(self.post_http_headers) proxies = {'https': self.post_proxy} if self.post_proxy else None for url in self.post_url: try: response = requests.post(url, data=json.dumps( payload, cls=DateTimeEncoder), headers=headers, proxies=proxies, timeout=self.timeout, verify=verify) response.raise_for_status() except RequestException as e: raise EAException("Error posting HTTP Post alert: %s" % e) elastalert_logger.info("HTTP Post alert sent.")
def alert(self, matches): body = '⚠ *%s* ⚠ ```\n' % (self.create_title(matches)) for match in matches: body += str(BasicMatchString(self.rule, match)) # Separate text of aggregated alerts with dashes if len(matches) > 1: body += '\n----------------------------------------\n' if len(body) > 4095: body = body[0:4000] + "\n⚠ *message was cropped according to telegram limits!* ⚠" body += ' ```' headers = {'content-type': 'application/json'} # set https proxy, if it was provided proxies = {'https': self.telegram_proxy} if self.telegram_proxy else None auth = HTTPProxyAuth(self.telegram_proxy_login, self.telegram_proxy_password) if self.telegram_proxy_login else None payload = { 'chat_id': self.telegram_room_id, 'text': body, 'parse_mode': 'markdown', 'disable_web_page_preview': True } try: response = requests.post(self.url, data=json.dumps(payload, cls=DateTimeEncoder), headers=headers, proxies=proxies, auth=auth) warnings.resetwarnings() response.raise_for_status() except RequestException as e: raise EAException("Error posting to Telegram: %s. Details: %s" % (e, "" if e.response is None else e.response.text)) elastalert_logger.info( "Alert sent to Telegram room %s" % self.telegram_room_id)
def configure_logging(args, conf): # configure logging from config file if provided if 'logging' in conf: # load new logging config logging.config.dictConfig(conf['logging']) if args.verbose and args.debug: elastalert_logger.info( "Note: --debug and --verbose flags are set. --debug takes precedent." ) # re-enable INFO log level on elastalert_logger in verbose/debug mode # (but don't touch it if it is already set to INFO or below by config) if args.verbose or args.debug: if elastalert_logger.level > logging.INFO or elastalert_logger.level == logging.NOTSET: elastalert_logger.setLevel(logging.INFO) if args.debug: elastalert_logger.info( """Note: In debug mode, alerts will be logged to console but NOT actually sent. To send them but remain verbose, use --verbose instead.""") if not args.es_debug and 'logging' not in conf: logging.getLogger('elasticsearch').setLevel(logging.WARNING) if args.es_debug_trace: tracer = logging.getLogger('elasticsearch.trace') tracer.setLevel(logging.INFO) tracer.addHandler(logging.FileHandler(args.es_debug_trace))
def senddata(self, content): config_file = os.environ.get('ALERTA_CONF_FILE') or OPTIONS['config_file'] config = configparser.RawConfigParser(defaults=OPTIONS) try: config.read(os.path.expanduser(config_file)) except Exception: sys.exit("Problem reading configuration file %s - is this an ini file?" % config_file) want_profile = os.environ.get('ALERTA_DEFAULT_PROFILE') or config.defaults().get('profile') if want_profile and config.has_section('profile %s' % want_profile): for opt in OPTIONS: try: OPTIONS[opt] = config.getboolean('profile %s' % want_profile, opt) except (ValueError, AttributeError): OPTIONS[opt] = config.get('profile %s' % want_profile, opt) else: for opt in OPTIONS: try: OPTIONS[opt] = config.getboolean('DEFAULT', opt) except (ValueError, AttributeError): OPTIONS[opt] = config.get('DEFAULT', opt) try: LOG.debug("[alerta] sendto=%s ", OPTIONS.get("endpoint")) api = Client(endpoint=OPTIONS.get("endpoint"), key=OPTIONS.get("key"), ssl_verify=OPTIONS.get("sslverify")) api.send_alert(**content) except RequestException as e: raise EAException("send message has error: %s" % e) elastalert_logger.info("send msg success" )
def alert(self, matches): body = self.create_alert_body(matches) # post to victorops headers = {'content-type': 'application/json'} # set https proxy, if it was provided proxies = { 'https': self.victorops_proxy } if self.victorops_proxy else None payload = { "message_type": self.victorops_message_type, "entity_display_name": self.victorops_entity_display_name, "monitoring_tool": "ElastAlert", "state_message": body } if self.victorops_entity_id: payload["entity_id"] = self.victorops_entity_id try: response = requests.post(self.url, data=json.dumps(payload, cls=DateTimeEncoder), headers=headers, proxies=proxies) response.raise_for_status() except RequestException as e: raise EAException("Error posting to VictorOps: %s" % e) elastalert_logger.info("Trigger sent to VictorOps")
def __init__(self, *args): super(UniqueLongTermRule, self).__init__(*args) self.values = [] self.garbage_time = 0 self.exec_num = 0 self.field = self.rules['compare_key'] self.timeperiods_index = 0 self.no_of_timeperiods = int(self.rules['no_of_timeperiods']) for i in range(0, self.no_of_timeperiods): self.values.append(set()) timeperiod_sec = int(self.rules['timeframe'].total_seconds()) run_every_sec = int(self.rules['run_every'].total_seconds()) if run_every_sec > timeperiod_sec: raise EAException( "Run Every option cannot be greater than Timeperiod option") if timeperiod_sec % run_every_sec != 0: raise EAException( "Run Every must fit integer number of times in Timeperiod") self.runs_per_timeperiod = int(timeperiod_sec / run_every_sec) elastalert_logger.info( "Timeperiod sec: %d, Number of executions per timeperiod: %d, Number of timeperiods: %d" % (timeperiod_sec, self.runs_per_timeperiod, self.no_of_timeperiods))
def alert(self, matches): body = self.create_alert_body(matches) body = self.format_body(body) # post to Teams headers = {'content-type': 'application/json'} # set https proxy, if it was provided proxies = { 'https': self.ms_teams_proxy } if self.ms_teams_proxy else None payload = { '@type': 'MessageCard', '@context': 'http://schema.org/extensions', 'summary': self.ms_teams_alert_summary, 'title': self.create_title(matches), 'text': body } if self.ms_teams_theme_color != '': payload['themeColor'] = self.ms_teams_theme_color for url in self.ms_teams_webhook_url: try: response = requests.post(url, data=json.dumps(payload, cls=DateTimeEncoder), headers=headers, proxies=proxies) response.raise_for_status() except RequestException as e: raise EAException("Error posting to ms teams: %s" % e) elastalert_logger.info("Alert sent to MS Teams")
def alert(self, matches): # Format the command and arguments command = [ resolve_string(command_arg, matches[0]) for command_arg in self.rule['command'] ] self.last_command = command # Run command and pipe data try: subp = subprocess.Popen(command, stdin=subprocess.PIPE, shell=self.shell) if self.rule.get('pipe_match_json'): match_json = json.dumps(matches, cls=DateTimeEncoder) + '\n' stdout, stderr = subp.communicate(input=match_json.encode()) elif self.rule.get('pipe_alert_text'): alert_text = self.create_alert_body(matches) stdout, stderr = subp.communicate(input=alert_text.encode()) if self.rule.get("fail_on_non_zero_exit", False) and subp.wait(): raise EAException( "Non-zero exit code while running command %s" % (' '.join(command))) except OSError as e: raise EAException("Error while running command %s: %s" % (' '.join(command), e)) elastalert_logger.info("Alert sent to Command")
def garbage_collect(self, timestamp): key_del = set() for key, value in self.start_time_per_qk.items(): if total_seconds(timestamp - value) > self.time_seconds: # delete start entry if end event not found within specified timeframe if not self.invert: elastalert_logger.info( "Match not found for query_key: %s within specified timeframe" % key) key_del.add(key) # alert when end event not found after specified time has elapsed else: elastalert_logger.info( "Alert triggered! End event with query_key: %s not found" % key) extra = { self.compare_key: 'end event not found', 'start_event': self.start_value, 'end_event': self.end_value, self.query_key: key, } self.add_match(extra) key_del.add(key) for key in key_del: del self.start_time_per_qk[key]
def senddata(self, content): # 微信企业号有字符长度限制,超长自动截断 if len(content) > 2000: content = content[:1997] + "..." send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + self.access_token headers = {'content-type': 'application/json'} payload = { "touser": self.user_id, "toparty": self.party_id, "totag": self.tag_id, 'msgtype': "text", "agentid": self.agent_id, "text":{ "content": content.encode('UTF-8') #避免中文字符发送失败 }, "safe":"0" } # set https proxy, if it was provided # proxies = {'https': self.pagerduty_proxy} if self.pagerduty_proxy else None try: response = requests.post(send_url, data=json.dumps(payload, ensure_ascii=False), headers=headers) response.raise_for_status() except RequestException as e: raise EAException("推送消息异常: %s" % e) elastalert_logger.info("推送消息") print response.text
def alert(self, matches): client = TwilioClient(self.twilio_account_sid, self.twilio_auth_token) try: if self.twilio_use_copilot: if self.twilio_message_service_sid is None: raise EAException( "Twilio Copilot requires the 'twilio_message_service_sid' option" ) client.messages.create( body=self.rule['name'], to=self.twilio_to_number, messaging_service_sid=self.twilio_message_service_sid) else: if self.twilio_from_number is None: raise EAException( "Twilio SMS requires the 'twilio_from_number' option") client.messages.create(body=self.rule['name'], to=self.twilio_to_number, from_=self.twilio_from_number) except TwilioRestException as e: raise EAException("Error posting to twilio: %s" % e) elastalert_logger.info("Trigger sent to Twilio")
def alert(self, matches): # 参考elastalert的写法 # https://github.com/Yelp/elastalert/blob/master/elastalert/alerts.py#L236-L243 # body = self.create_alert_body(matches) # LOG.error(body) ''' resource={HOST} event={subject} environment=Production severity=warning status=Open ack={EVENT.ACK.STATUS} service={Service_NAME} value={Num_hits} text={NAME + Message} tags={} attributes.name={Name} attributes.ip={HOST.IP1} type=elastAlert dateTime={@timestamp} attributes.models=["dingding"] attributes.app={project_name} ''' body = self.create_alert_body(matches) if len(body) >= 1000: body = body[:1000] payload = { # "resource":matches[0]["fields"].get("ip",""), "resource": self.rule["name"], "event":self.create_custom_title(matches), "environment":"Production", "severity":"warning", "status": "open", "service":[self.rule["app"]], "value": matches[0]["num_hits"], # "text": self.rule["name"] + "\t" + matches[0]["message"], "text": body, "type": "elastAlert", "tags":"", "dateTime":matches[0]["@timestamp"] } attributes = {} attributes["name"] = self.rule["name"] fields = matches[0].get("fields",{}) attributes["ip"] = fields.get("ip","") attributes["models"] = "dingding" attributes["app"] = self.rule["app"] payload["attributes"] = attributes #matches 是json格式 #self.create_alert_body(matches)是String格式,详见 [create_alert_body 函数](https://github.com/Yelp/elastalert/blob/master/elastalert/alerts.py) LOG.debug(payload) elastalert_logger.info("send message to alerta") self.senddata(payload)
def alert(self, matches): body = self.create_alert_body(matches) body = self.format_body(body) headers = {'content-type': 'application/json'} proxies = { 'https': self.rocket_chat_proxy } if self.rocket_chat_proxy else None payload = { 'username': self.rocket_chat_username_override, 'text': self.rocket_chat_text_string, 'attachments': [{ 'color': self.rocket_chat_msg_color, 'title': self.create_title(matches), 'text': body, 'fields': [] }] } # if we have defined fields, populate noteable fields for the alert if self.rocket_chat_alert_fields != '': payload['attachments'][0]['fields'] = self.populate_fields(matches) if self.rocket_chat_emoji_override != '': payload['emoji'] = self.rocket_chat_emoji_override if self.rocket_chat_attach_kibana_discover_url: kibana_discover_url = lookup_es_key(matches[0], 'kibana_discover_url') if kibana_discover_url: payload['attachments'].append({ 'color': self.rocket_chat_kibana_discover_color, 'title': self.rocket_chat_kibana_discover_title, 'title_link': kibana_discover_url }) for url in self.rocket_chat_webhook_url: for channel_override in self.rocket_chat_channel_override: try: if self.rocket_chat_ca_certs: verify = self.rocket_chat_ca_certs else: verify = not self.rocket_chat_ignore_ssl_errors if self.rocket_chat_ignore_ssl_errors: requests.packages.urllib3.disable_warnings() payload['channel'] = channel_override response = requests.post(url, data=json.dumps( payload, cls=DateTimeEncoder), headers=headers, verify=verify, proxies=proxies, timeout=self.rocket_chat_timeout) warnings.resetwarnings() response.raise_for_status() except RequestException as e: raise EAException("Error posting to Rocket.Chat: %s" % e) elastalert_logger.info("Alert sent to Rocket.Chat")
def alert(self, matches): # 获取或者更新access_token self.get_token() self.send_template_data(matches) elastalert_logger.info("send message to %s" % (self.openid))
def add_value(self, qkey, value): try: self.arr[qkey].append(float(value)) except ValueError: elastalert_logger.info("Ignoring value since it is not a number") return False while len(self.arr[qkey]) > self.count: self.arr[qkey].pop(0) return True
def alert(self, matches): # Build TheHive alert object, starting with some defaults, updating with any # user-specified config alert_config = { 'artifacts': [], 'customFields': {}, 'date': int(time.time()) * 1000, 'description': self.create_alert_body(matches), 'sourceRef': str(uuid.uuid4()), 'tags': [], 'title': self.create_title(matches), } alert_config.update(self.rule.get('hive_alert_config', {})) # Iterate through each match found, populating the alert tags and observables as required tags = set() artifacts = [] for match in matches: artifacts = artifacts + self.load_observable_artifacts(match) tags.update(self.load_tags(alert_config['tags'], match)) alert_config['artifacts'] = artifacts alert_config['tags'] = list(tags) # Populate the customFields alert_config['customFields'] = self.load_custom_fields( alert_config['customFields'], matches[0]) # POST the alert to TheHive connection_details = self.rule['hive_connection'] api_key = connection_details.get('hive_apikey', '') hive_host = connection_details.get('hive_host', 'http://localhost') hive_port = connection_details.get('hive_port', 9000) proxies = connection_details.get('hive_proxies', { 'http': '', 'https': '' }) verify = connection_details.get('hive_verify', False) alert_body = json.dumps(alert_config, indent=4, sort_keys=True) req = f'{hive_host}:{hive_port}/api/alert' headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {api_key}' } try: response = requests.post(req, headers=headers, data=alert_body, proxies=proxies, verify=verify) response.raise_for_status() except RequestException as e: raise EAException(f"Error posting to TheHive: {e}") elastalert_logger.info("Alert sent to TheHive")
def alert(self, matches): body = self.create_alert_body(matches) to_addr = self.email if 'ses_email_from_field' in self.rule: recipient = lookup_es_key(matches[0], self.rule['ses_email_from_field']) if isinstance(recipient, str): if '@' in recipient: to_addr = [recipient] elif 'ses_email_add_domain' in self.rule: to_addr = [recipient + self.rule['ses_email_add_domain']] elif isinstance(recipient, list): to_addr = recipient if 'ses_email_add_domain' in self.rule: to_addr = [ name + self.rule['ses_email_add_domain'] for name in to_addr ] try: if self.aws_profile != '': session = boto3.Session(profile_name=self.aws_profile) else: session = boto3.Session( aws_access_key_id=self.aws_access_key_id, aws_secret_access_key=self.aws_secret_access_key, region_name=self.aws_region) client = session.client('ses') client.send_email(Source=self.from_addr, Destination={ 'ToAddresses': to_addr, 'CcAddresses': self.rule.get('ses_cc', []), 'BccAddresses': self.rule.get('ses_bcc', []) }, Message={ 'Subject': { 'Charset': 'UTF-8', 'Data': self.create_title(matches), }, 'Body': { 'Text': { 'Charset': 'UTF-8', 'Data': body, } } }, ReplyToAddresses=self.rule.get( 'ses_email_reply_to', [])) except Exception as e: raise EAException("Error sending Amazon SES: %s" % e) elastalert_logger.info("Sent Amazon SES to %s" % (to_addr, ))
def alert(self, matches): body = self.create_alert_body(matches) body = self.format_body(body) # post to Teams headers = {'content-type': 'application/json'} if self.ms_teams_ca_certs: verify = self.ms_teams_ca_certs else: verify = not self.ms_teams_ignore_ssl_errors if self.ms_teams_ignore_ssl_errors: requests.packages.urllib3.disable_warnings() # set https proxy, if it was provided proxies = {'https': self.ms_teams_proxy} if self.ms_teams_proxy else None payload = { '@type': 'MessageCard', '@context': 'http://schema.org/extensions', 'summary': self.ms_teams_alert_summary, 'title': self.create_title(matches), 'sections': [{'text': body}], } if self.ms_teams_alert_facts != '': payload['sections'][0]['facts'] = self.populate_facts(matches) if self.ms_teams_theme_color != '': payload['themeColor'] = self.ms_teams_theme_color if self.ms_teams_attach_kibana_discover_url: kibana_discover_url = lookup_es_key(matches[0], 'kibana_discover_url') if kibana_discover_url: payload['potentialAction'] = [ { '@type': 'OpenUri', 'name': self.ms_teams_kibana_discover_title, 'targets': [ { 'os': 'default', 'uri': kibana_discover_url, } ], } ] for url in self.ms_teams_webhook_url: try: response = requests.post(url, data=json.dumps(payload, cls=DateTimeEncoder), headers=headers, proxies=proxies, verify=verify) response.raise_for_status() except RequestException as e: raise EAException("Error posting to MS Teams: %s" % e) elastalert_logger.info("Alert sent to MS Teams")
def alert(self, matches): client = Exotel(self.exotel_account_sid, self.exotel_auth_token) try: message_body = self.rule['name'] + self.sms_body response = client.sms(self.rule['exotel_from_number'], self.rule['exotel_to_number'], message_body) if response != 200: raise EAException("Error posting to Exotel, response code is %s" % response) except RequestException: raise EAException("Error posting to Exotel").with_traceback(sys.exc_info()[2]) elastalert_logger.info("Trigger sent to Exotel")
def alert(self, matches): body = '' title = u'%s' % (self.create_title(matches)) for match in matches: body += str(BasicMatchString(self.rule, match)) if len(matches) > 1: body += '\n----------------------------------------\n' if len(body) > 2047: body = body[ 0: 1950] + '\n *message was cropped according to discord embed description limits!*' proxies = {'https': self.discord_proxy} if self.discord_proxy else None auth = HTTPProxyAuth( self.discord_proxy_login, self.discord_proxy_password) if self.discord_proxy_login else None headers = {"Content-Type": "application/json"} data = {} data["content"] = "%s %s %s" % (self.discord_emoji_title, title, self.discord_emoji_title) data["embeds"] = [] embed = {} embed["description"] = "%s" % (body) embed["color"] = (self.discord_embed_color) if self.discord_embed_footer: embed["footer"] = {} embed["footer"]["text"] = (self.discord_embed_footer ) if self.discord_embed_footer else None embed["footer"]["icon_url"] = ( self.discord_embed_icon_url ) if self.discord_embed_icon_url else None else: None data["embeds"].append(embed) try: response = requests.post(self.discord_webhook_url, data=json.dumps(data), headers=headers, proxies=proxies, auth=auth) warnings.resetwarnings() response.raise_for_status() except RequestException as e: raise EAException( "Error posting to Discord: %s. Details: %s" % (e, "" if e.response is None else e.response.text)) elastalert_logger.info("Alert sent to the webhook %s" % self.discord_webhook_url)
def compare(self, event): changed = False qkey = lookup_es_key(event, self.rules['query_key']) value = lookup_es_key(event, self.rules['compare_key']) if qkey not in self.arr: self.arr[qkey] = [] if self.add_value(qkey, value): changed = self.set_off_alarm(qkey) elastalert_logger.info("%s: %s" % (str(qkey), str(self.arr[qkey]))) return changed
def alert(self, matches): # https://github.com/Yelp/elastalert/blob/master/elastalert/alerts.py#L236-L243 body = self.create_alert_body(matches) # http://qydev.weixin.qq.com/wiki/index.php?title=AccessToken self.get_token() #print self.access_token #print self.expires_in self.senddata(body) elastalert_logger.info("发送消息给 %s" % (self.corp_id))
def senddata(self, content): #如果需要原始json,需要传入matches # http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F # 微信企业号有字符长度限制(2048),超长自动截断 # 参考 http://blog.csdn.net/handsomekang/article/details/9397025 #len utf8 3字节,gbk2 字节,ascii 1字节 if len(content) > 2048: content = content[:2045] + "..." # 微信发送消息文档 # http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s' % ( self.access_token) headers = {'content-type': 'application/json'} #最新微信企业号调整校验规则,tagid必须是string类型,如果是数字类型会报错,故而使用str()函数进行转换 payload = { "touser": self.user_id and str(self.user_id) or '', #用户账户,建议使用tag "toparty": self.party_id and str(self.party_id) or '', #部门id,建议使用tag "totag": self.tag_id and str(self.tag_id) or '', #tag可以很灵活的控制发送群体细粒度。比较理想的推送应该是,在heartbeat或者其他elastic工具自定义字段,添加标签id。这边根据自定义的标签id,进行推送 'msgtype': "text", "agentid": self.agent_id, "text": { "content": content.encode('UTF-8').decode("latin1") #避免中文字符发送失败 }, "safe": "0" } # set https proxy, if it was provided # 如果需要设置代理,可修改此参数并传入requests # proxies = {'https': self.pagerduty_proxy} if self.pagerduty_proxy else None try: #response = requests.post(send_url, data=json.dumps(payload, ensure_ascii=False), headers=headers) response = requests.post(send_url, data=json.dumps(payload, cls=MyEncoder, indent=4, ensure_ascii=False), headers=headers) response.raise_for_status() except RequestException as e: raise EAException("send message has error: %s" % e) elastalert_logger.info("send msg and response: %s" % response.text)
def alert(self, matches): headers = {'content-type': 'application/json'} proxies = { 'https': self.ms_teams_proxy } if self.ms_teams_proxy else None payload = { '@type': 'MessageCard', '@context': 'http://schema.org/extensions', 'themeColor': self.ms_teams_theme_color, 'summary': self.ms_teams_alert_summary, 'sections': [{ 'activityTitle': self.create_title(matches), 'facts': [], 'markdown': True }], 'potentialAction': [] } if self.ms_teams_alert_title != '': payload['sections'][0]['activityTitle'] = self.populate_title( matches) if self.ms_teams_alert_fields != '': payload['sections'][0]['facts'] = self.populate_fields(matches) if self.ms_teams_alert_links != '' or self.ms_teams_index_pattern_url != '': payload['potentialAction'] = self.populate_links(matches) with open('/opt/elastalert/elastalert_modules/alerter_test_output.log', 'a') as outfile: json.dump(payload, outfile) for url in self.ms_teams_webhook_url: try: response = requests.post(url, data=json.dumps(payload, cls=DateTimeEncoder), headers=headers, proxies=proxies) response.raise_for_status() except RequestException as e: raise EAException("Error posting to ms teams: %s" % e) elastalert_logger.info("Alert sent to MS Teams")
def alert(self, matches): headers = { 'content-type': 'application/json', 'Accept': 'application/json;charset=utf-8', } body = self.create_alert_body(matches) content = {'title': self.create_title(matches), 'text': body} webhook_url = 'https://' try: response = requests.post(webhook_url, data=json.dumps(content), headers=headers) response.raise_for_status() except RequestException as e: raise EAException("send message has error: %s" % e) elastalert_logger.info("send msg and response: %s")
def alert(self, matches): if not self.party_id and not self.user_id and not self.tag_id: elastalert_logger.warn("All touser & toparty & totag invalid") # 参考elastalert的写法 # https://github.com/Yelp/elastalert/blob/master/elastalert/alerts.py#L236-L243 body = self.create_alert_body(matches) # 微信企业号获取Token文档 # http://qydev.weixin.qq.com/wiki/index.php?title=AccessToken self.get_token() self.senddata(body) elastalert_logger.info("send message to %s" % (self.corp_id))
def alert(self, matches): # Override the resource if requested if self.use_qk_as_resource and 'query_key' in self.rule and lookup_es_key(matches[0], self.rule['query_key']): self.resource = lookup_es_key(matches[0], self.rule['query_key']) headers = {'content-type': 'application/json'} if self.api_key is not None: headers['Authorization'] = 'Key %s' % (self.rule['alerta_api_key']) alerta_payload = self.get_json_payload(matches[0]) try: response = requests.post(self.url, data=alerta_payload, headers=headers, verify=self.verify_ssl) response.raise_for_status() except RequestException as e: raise EAException("Error posting to Alerta: %s" % e) elastalert_logger.info("Alert sent to Alerta")
def alert(self, matches): if not self.party_id and not self.user_id and not self.tag_id: elastalert_logger.warn("All touser & toparty & totag invalid") # 参考elastalert的写法 # https://github.com/Yelp/elastalert/blob/master/elastalert/alerts.py#L236-L243 body = self.create_alert_body(matches) #matches 是json格式 #self.create_alert_body(matches)是String格式,详见 [create_alert_body 函数](https://github.com/Yelp/elastalert/blob/master/elastalert/alerts.py) # 微信企业号获取Token文档 # http://qydev.weixin.qq.com/wiki/index.php?title=AccessToken self.get_token() self.senddata(body) elastalert_logger.info("send message to %s" % (self.corp_id))
def senddata(self, content): #如果需要原始json,需要传入matches # http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F # 微信企业号有字符长度限制(2048),超长自动截断 # 参考 http://blog.csdn.net/handsomekang/article/details/9397025 #len utf8 3字节,gbk2 字节,ascii 1字节 if len(content) > 2048: content = content[:2045] + "..." # 微信发送消息文档 # http://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s' %( self.access_token) headers = {'content-type': 'application/json'} #最新微信企业号调整校验规则,tagid必须是string类型,如果是数字类型会报错,故而使用str()函数进行转换 payload = { "touser": self.user_id and str(self.user_id) or '', #用户账户,建议使用tag "toparty": self.party_id and str(self.party_id) or '', #部门id,建议使用tag "totag": self.tag_id and str(self.tag_id) or '', #tag可以很灵活的控制发送群体细粒度。比较理想的推送应该是,在heartbeat或者其他elastic工具自定义字段,添加标签id。这边根据自定义的标签id,进行推送 'msgtype': "text", "agentid": self.agent_id, "text":{ "content": content.encode('UTF-8') #避免中文字符发送失败 }, "safe":"0" } # set https proxy, if it was provided # 如果需要设置代理,可修改此参数并传入requests # proxies = {'https': self.pagerduty_proxy} if self.pagerduty_proxy else None try: response = requests.post(send_url, data=json.dumps(payload, ensure_ascii=False), headers=headers) response.raise_for_status() except RequestException as e: raise EAException("send message has error: %s" % e) elastalert_logger.info("send msg and response: %s" % response.text)