def compare(self, event): key = hashable(lookup_es_key(event, self.rules['query_key'])) values = [] elastalert_logger.debug(" Previous Values of compare keys " + str(self.occurrences)) for val in self.rules['compound_compare_key']: lookup_value = lookup_es_key(event, val) values.append(lookup_value) elastalert_logger.debug(" Current Values of compare keys " + str(values)) changed = False for val in values: if not isinstance(val, bool) and not val and self.rules['ignore_null']: return False # If we have seen this key before, compare it to the new value if key in self.occurrences: for idx, previous_values in enumerate(self.occurrences[key]): elastalert_logger.debug(" " + str(previous_values) + " " + str(values[idx])) changed = previous_values != values[idx] if changed: break if changed: self.change_map[key] = (self.occurrences[key], values) # If using timeframe, only return true if the time delta is < timeframe if key in self.occurrence_time: changed = event[self.rules['timestamp_field']] - self.occurrence_time[key] <= self.rules['timeframe'] # Update the current value and time elastalert_logger.debug(" Setting current value of compare keys values " + str(values)) self.occurrences[key] = values if 'timeframe' in self.rules: self.occurrence_time[key] = event[self.rules['timestamp_field']] elastalert_logger.debug("Final result of comparision between previous and current values " + str(changed)) return changed
def add_data(self, data): for document in data: for field in self.fields: value = () lookup_field = field if type(field) == list: # For composite keys, make the lookup based on all fields # Make it a tuple since it can be hashed and used in dictionary lookups lookup_field = tuple(field) for sub_field in field: lookup_result = lookup_es_key(document, sub_field) if not lookup_result: value = None break value += (lookup_result,) else: value = lookup_es_key(document, field) if not value and self.rules.get('alert_on_missing_field'): document['missing_field'] = lookup_field self.add_match(copy.deepcopy(document)) elif value: if value not in self.seen_values[lookup_field]: document['new_field'] = lookup_field self.add_match(copy.deepcopy(document)) self.seen_values[lookup_field].append(value)
def compare(self, event): key = hashable(lookup_es_key(event, self.rules["query_key"])) val = lookup_es_key(event, self.rules["compare_key"]) if not val and self.rules["ignore_null"]: return False changed = False # If we have seen this key before, compare it to the new value if key in self.occurrences: changed = self.occurrences[key] != val if changed: self.change_map[key] = (self.occurrences[key], val) # If using timeframe, only return true if the time delta is < timeframe if key in self.occurrence_time: changed = ( event[self.rules["timestamp_field"]] - self.occurrence_time[key] <= self.rules["timeframe"] ) # Update the current value and time self.occurrences[key] = val if "timeframe" in self.rules: self.occurrence_time[key] = event[self.rules["timestamp_field"]] return changed
def _add_custom_alert_text(self): missing = '<MISSING VALUE>' alert_text = unicode(self.rule.get('alert_text', '')) if 'alert_text_args' in self.rule: alert_text_args = self.rule.get('alert_text_args') alert_text_values = [lookup_es_key(self.match, arg) for arg in alert_text_args] # Support referencing other top-level rule properties # This technically may not work if there is a top-level rule property with the same name # as an es result key, since it would have been matched in the lookup_es_key call above for i in xrange(len(alert_text_values)): if alert_text_values[i] is None: alert_value = self.rule.get(alert_text_args[i]) if alert_value: alert_text_values[i] = alert_value alert_text_values = [missing if val is None else val for val in alert_text_values] alert_text = alert_text.format(*alert_text_values) elif 'alert_text_kw' in self.rule: kw = {} for name, kw_name in self.rule.get('alert_text_kw').items(): val = lookup_es_key(self.match, name) # Support referencing other top-level rule properties # This technically may not work if there is a top-level rule property with the same name # as an es result key, since it would have been matched in the lookup_es_key call above if val is None: val = self.rule.get(name) kw[kw_name] = missing if val is None else val alert_text = alert_text.format(**kw) self.text += alert_text
def alert(self, matches): qk = self.rule.get('query_key', None) for match in matches: if qk in match: elastalert_logger.info( 'Alert for %s, %s at %s:' % (self.rule['name'], match[qk], lookup_es_key(match, self.rule['timestamp_field']))) else: elastalert_logger.info('Alert for %s at %s:' % (self.rule['name'], lookup_es_key(match, self.rule['timestamp_field']))) elastalert_logger.info(unicode(BasicMatchString(self.rule, match)))
def add_data(self, data): qk = self.rules.get('query_key') for event in data: if qk: key = hashable(lookup_es_key(event, qk)) else: # If no query_key, we use the key 'all' for all events key = 'all' self.cardinality_cache.setdefault(key, {}) self.first_event.setdefault(key, event[self.ts_field]) value = hashable(lookup_es_key(event, self.cardinality_field)) if value is not None: # Store this timestamp as most recent occurence of the term self.cardinality_cache[key][value] = event[self.ts_field] self.check_for_match(key, event)
def get_aggregation_summary_text(self, matches): text = '' if 'aggregation' in self.rule and 'summary_table_fields' in self.rule: summary_table_fields = self.rule['summary_table_fields'] if not isinstance(summary_table_fields, list): summary_table_fields = [summary_table_fields] # Include a count aggregation so that we can see at a glance how many of each aggregation_key were encountered summary_table_fields_with_count = summary_table_fields + ['count'] text += "Aggregation resulted in the following data for summary_table_fields ==> {0}:\n\n".format(summary_table_fields_with_count) text_table = Texttable() text_table.header(summary_table_fields_with_count) match_aggregation = {} # Maintain an aggregate count for each unique key encountered in the aggregation period for match in matches: key_tuple = tuple([unicode(lookup_es_key(match, key)) for key in summary_table_fields]) if key_tuple not in match_aggregation: match_aggregation[key_tuple] = 1 else: match_aggregation[key_tuple] = match_aggregation[key_tuple] + 1 for keys, count in match_aggregation.iteritems(): text_table.add_row([key for key in keys] + [count]) text += text_table.draw() + '\n\n' return unicode(text)
def compare(self, event): term = lookup_es_key(event, self.rules["compare_key"]) if term is None: return not self.rules["ignore_null"] if term not in self.rules["whitelist"]: return True return False
def compare(self, event): term = lookup_es_key(event, self.rules['compare_key']) if term is None: return not self.rules['ignore_null'] if term not in self.rules['whitelist']: return True return False
def garbage_collect(self, timestamp): """ Remove all occurrence data that is beyond the timeframe away """ stale_keys = [] for key, window in self.occurrences.iteritems(): if timestamp - lookup_es_key(window.data[-1][0], self.ts_field) > self.rules['timeframe']: stale_keys.append(key) map(self.occurrences.pop, stale_keys)
def _add_custom_alert_text(self): missing = '<MISSING VALUE>' alert_text = unicode(self.rule.get('alert_text', '')) if 'alert_text_args' in self.rule: alert_text_args = self.rule.get('alert_text_args') alert_text_values = [lookup_es_key(self.match, arg) for arg in alert_text_args] alert_text_values = [missing if val is None else val for val in alert_text_values] alert_text = alert_text.format(*alert_text_values) elif 'alert_text_kw' in self.rule: kw = {} for name, kw_name in self.rule.get('alert_text_kw').items(): val = lookup_es_key(self.match, name) kw[kw_name] = missing if val is None else val alert_text = alert_text.format(**kw) self.text += alert_text
def add_data(self, data): for event in data: qk = self.rules.get("query_key", "all") if qk != "all": qk = hashable(lookup_es_key(event, qk)) if qk is None: qk = "other" self.handle_event(event, 1, qk)
def add_data(self, data): for event in data: qk = self.rules.get('query_key', 'all') if qk != 'all': qk = hashable(lookup_es_key(event, qk)) if qk is None: qk = 'other' self.handle_event(event, 1, qk)
def _add_custom_alert_text(self): alert_text = unicode(self.rule.get('alert_text', '')) if 'alert_text_args' in self.rule: alert_text_args = self.rule.get('alert_text_args') alert_text_values = [lookup_es_key(self.match, arg) for arg in alert_text_args] alert_text_values = ['<MISSING VALUE>' if val is None else val for val in alert_text_values] alert_text = alert_text.format(*alert_text_values) self.text += alert_text
def _add_custom_alert_text(self): alert_text = unicode(self.rule.get("alert_text", "")) if "alert_text_args" in self.rule: alert_text_args = self.rule.get("alert_text_args") alert_text_values = [lookup_es_key(self.match, arg) for arg in alert_text_args] alert_text_values = ["<MISSING VALUE>" if val is None else val for val in alert_text_values] alert_text = alert_text.format(*alert_text_values) self.text += alert_text
def get_match_str(self, match): lt = self.rules.get('use_local_time') match_ts = lookup_es_key(match, self.ts_field) starttime = pretty_ts(dt_to_ts(ts_to_dt(match_ts) - self.rules['timeframe']), lt) message = 'At least %d(%d) events occurred between %s and %s\n\n' % (self.rules['num_events'], match['count'], starttime, endtime) return message
def garbage_collect(self, timestamp): """ Remove all occurrence data that is beyond the timeframe away """ stale_keys = [] for key, window in self.occurrences.iteritems(): if timestamp - lookup_es_key( window.data[-1][0], self.ts_field) > self.rules['timeframe']: stale_keys.append(key) map(self.occurrences.pop, stale_keys)
def get_match_str(self, match): lt = self.rules.get('use_local_time') match_ts = lookup_es_key(match, self.ts_field) starttime = pretty_ts( dt_to_ts(ts_to_dt(match_ts) - self.rules['timeframe']), lt) endtime = pretty_ts(match_ts, lt) message = 'At least %d events occurred between %s and %s\n\n' % ( self.rules['num_events'], starttime, endtime) return message
def add_match(self, match): # TODO this is not technically correct # if the term changes multiple times before an alert is sent # this data will be overwritten with the most recent change change = self.change_map.get(hashable(lookup_es_key(match, self.rules["query_key"]))) extra = {} if change: extra = {"old_value": change[0], "new_value": change[1]} super(ChangeRule, self).add_match(dict(match.items() + extra.items()))
def create_custom_title(self, matches): alert_subject = self.rule['alert_subject'] if 'alert_subject_args' in self.rule: alert_subject_args = self.rule['alert_subject_args'] alert_subject_values = [lookup_es_key(matches[0], arg) for arg in alert_subject_args] alert_subject_values = ['<MISSING VALUE>' if val is None else val for val in alert_subject_values] return alert_subject.format(*alert_subject_values) return alert_subject
def add_match(self, match): # TODO this is not technically correct # if the term changes multiple times before an alert is sent # this data will be overwritten with the most recent change change = self.change_map.get(hashable(lookup_es_key(match, self.rules['query_key']))) extra = {} if change: extra = {'old_value': change[0], 'new_value': change[1]} super(ChangeRule, self).add_match(dict(match.items() + extra.items()))
def compare(self, event): key = hashable(lookup_es_key(event, self.rules['query_key'])) values = [] elastalert_logger.debug(" Previous Values of compare keys " + str(self.occurrences)) for val in self.rules['compound_compare_key']: lookup_value = lookup_es_key(event, val) values.append(lookup_value) elastalert_logger.debug(" Current Values of compare keys " + str(values)) changed = False for val in values: if not isinstance(val, bool) and not val and self.rules['ignore_null']: return False # If we have seen this key before, compare it to the new value if key in self.occurrences: for idx, previous_values in enumerate(self.occurrences[key]): elastalert_logger.debug(" " + str(previous_values) + " " + str(values[idx])) changed = previous_values != values[idx] if changed: break if changed: self.change_map[key] = (self.occurrences[key], values) # If using timeframe, only return true if the time delta is < timeframe if key in self.occurrence_time: changed = event[ self.rules['timestamp_field']] - self.occurrence_time[ key] <= self.rules['timeframe'] # Update the current value and time elastalert_logger.debug( " Setting current value of compare keys values " + str(values)) self.occurrences[key] = values if 'timeframe' in self.rules: self.occurrence_time[key] = event[self.rules['timestamp_field']] elastalert_logger.debug( "Final result of comparision between previous and current values " + str(changed)) return changed
def _add_custom_alert_text(self): missing = '<MISSING VALUE>' alert_text = unicode(self.rule.get('alert_text', '')) if 'alert_text_args' in self.rule: alert_text_args = self.rule.get('alert_text_args') alert_text_values = [ lookup_es_key(self.match, arg) for arg in alert_text_args ] alert_text_values = [ missing if val is None else val for val in alert_text_values ] alert_text = alert_text.format(*alert_text_values) elif 'alert_text_kw' in self.rule: kw = {} for name, kw_name in self.rule.get('alert_text_kw').items(): val = lookup_es_key(self.match, name) kw[kw_name] = missing if val is None else val alert_text = alert_text.format(**kw) self.text += alert_text
def add_match(self, match): # TODO this is not technically correct # if the term changes multiple times before an alert is sent # this data will be overwritten with the most recent change change = self.change_map.get(hashable(lookup_es_key(match, self.rules['query_key']))) extra = {} if change: extra = {'old_value': change[0], 'new_value': change[1]} elastalert_logger.debug("Description of the changed records " + str(dict(match.items() + extra.items()))) super(ChangeRule, self).add_match(dict(match.items() + extra.items()))
def add_data(self, data): for document in data: for field in self.fields: value = lookup_es_key(document, field) if not value and self.rules.get('alert_on_missing_field'): document['missing_field'] = field self.add_match(document) elif value: if value not in self.seen_values[field]: document['new_field'] = field self.add_match(document) self.seen_values[field].append(value)
def _add_custom_alert_text(self): alert_text = unicode(self.rule.get('alert_text', '')) if 'alert_text_args' in self.rule: alert_text_args = self.rule.get('alert_text_args') alert_text_values = [ lookup_es_key(self.match, arg) for arg in alert_text_args ] alert_text_values = [ '<MISSING VALUE>' if val is None else val for val in alert_text_values ] alert_text = alert_text.format(*alert_text_values) self.text += alert_text
def compare(self, event): key = hashable(lookup_es_key(event, self.rules['query_key'])) val = lookup_es_key(event, self.rules['compare_key']) if not val and self.rules['ignore_null']: return False changed = False # If we have seen this key before, compare it to the new value if key in self.occurrences: changed = self.occurrences[key] != val if changed: self.change_map[key] = (self.occurrences[key], val) # If using timeframe, only return true if the time delta is < timeframe if key in self.occurrence_time: changed = event[self.rules['timestamp_field']] - self.occurrence_time[key] <= self.rules['timeframe'] # Update the current value and time self.occurrences[key] = val if 'timeframe' in self.rules: self.occurrence_time[key] = event[self.rules['timestamp_field']] return changed
def add_data(self, data): qk = self.rules.get('query_key') for event in data: if qk: key = hashable(lookup_es_key(event, qk)) else: # If no query_key, we use the key 'all' for all events key = 'all' self.cardinality_cache.setdefault(key, {}) self.first_event.setdefault(key, event[self.ts_field]) if self.cardinality_field in event: # Store this timestamp as most recent occurence of the term self.cardinality_cache[key][event[self.cardinality_field]] = event[self.ts_field] self.check_for_match(key, event)
def _add_custom_alert_text(self): missing = '<MISSING VALUE>' alert_text = unicode(self.rule.get('alert_text', '')) if 'alert_text_args' in self.rule: alert_text_args = self.rule.get('alert_text_args') alert_text_values = [ lookup_es_key(self.match, arg) for arg in alert_text_args ] # Support referencing other top-level rule properties # This technically may not work if there is a top-level rule property with the same name # as an es result key, since it would have been matched in the lookup_es_key call above for i in xrange(len(alert_text_values)): if alert_text_values[i] is None: alert_value = self.rule.get(alert_text_args[i]) if alert_value: alert_text_values[i] = alert_value alert_text_values = [ missing if val is None else val for val in alert_text_values ] alert_text = alert_text.format(*alert_text_values) elif 'alert_text_kw' in self.rule: kw = {} for name, kw_name in self.rule.get('alert_text_kw').items(): val = lookup_es_key(self.match, name) # Support referencing other top-level rule properties # This technically may not work if there is a top-level rule property with the same name # as an es result key, since it would have been matched in the lookup_es_key call above if val is None: val = self.rule.get(name) kw[kw_name] = missing if val is None else val alert_text = alert_text.format(**kw) self.text += alert_text
def add_data(self, data): if 'query_key' in self.rules: qk = self.rules['query_key'] else: qk = None for event in data: if qk: key = hashable(lookup_es_key(event, qk)) else: # If no query_key, we use the key 'all' for all events key = 'all' # Store the timestamps of recent occurrences, per key self.occurrences.setdefault(key, EventWindow(self.rules['timeframe'], getTimestamp=self.get_ts)).append((event, 1)) self.check_for_match(key)
def create_custom_title(self, matches): opsgenie_subject = unicode(self.rule['opsgenie_subject']) if self.opsgenie_subject_args: opsgenie_subject_values = [lookup_es_key(matches[0], arg) for arg in self.opsgenie_subject_args] for i in xrange(len(opsgenie_subject_values)): if opsgenie_subject_values[i] is None: alert_value = self.rule.get(self.opsgenie_subject_args[i]) if alert_value: opsgenie_subject_values[i] = alert_value opsgenie_subject_values = ['<MISSING VALUE>' if val is None else val for val in opsgenie_subject_values] return opsgenie_subject.format(*opsgenie_subject_values) return opsgenie_subject
def create_custom_title(self, matches): opsgenie_subject = unicode(self.rule['opsgenie_subject']) if self.opsgenie_subject_args: opsgenie_subject_values = [lookup_es_key(matches[0], arg) for arg in self.opsgenie_subject_args] for i, subject_value in enumerate(opsgenie_subject_values): if subject_value is None: alert_value = self.rule.get(self.opsgenie_subject_args[i]) if alert_value: opsgenie_subject_values[i] = alert_value opsgenie_subject_values = ['<MISSING VALUE>' if val is None else val for val in opsgenie_subject_values] return opsgenie_subject.format(*opsgenie_subject_values) return opsgenie_subject
def add_data(self, data): if 'query_key' in self.rules: qk = self.rules['query_key'] else: qk = None for event in data: if qk: key = hashable(lookup_es_key(event, qk)) else: # If no query_key, we use the key 'all' for all events key = 'all' # Store the timestamps of recent occurrences, per key self.occurrences.setdefault(key, EventWindow(self.rules['timeframe'], getTimestamp=self.get_ts)).append((event, 1)) # Only check for match _once_ after adding all the events discovered in this run # If the current running count is 1, and the threshold is 10, and we go to add 8 entries # it should only count as a single match, and not 8 consecutive ones. self.check_for_match(key)
def create_custom_title(self, matches): alert_subject = unicode(self.rule['alert_subject']) if 'alert_subject_args' in self.rule: alert_subject_args = self.rule['alert_subject_args'] alert_subject_values = [lookup_es_key(matches[0], arg) for arg in alert_subject_args] # Support referencing other top-level rule properties # This technically may not work if there is a top-level rule property with the same name # as an es result key, since it would have been matched in the lookup_es_key call above for i in xrange(len(alert_subject_values)): if alert_subject_values[i] is None: alert_value = self.rule.get(alert_subject_args[i]) if alert_value: alert_subject_values[i] = alert_value alert_subject_values = ['<MISSING VALUE>' if val is None else val for val in alert_subject_values] return alert_subject.format(*alert_subject_values) return alert_subject
def add_data(self, data): if 'query_key' in self.rules: qk = self.rules['query_key'] else: qk = None for event in data: if qk: key = hashable(lookup_es_key(event, qk)) else: # If no query_key, we use the key 'all' for all events key = 'all' # Store the timestamps of recent occurrences, per key self.occurrences.setdefault(key, EventWindow(self.rules['timeframe'], getTimestamp=self.get_ts)).append((event, 1)) self.check_for_match(key, end=False) # We call this multiple times with the 'end' parameter because subclasses # may or may not want to check while only partial data has been added if key in self.occurrences: # could have been emptied by previous check self.check_for_match(key, end=True)
def _parse_responders(self, responders, responder_args, matches, default_responders): if responder_args: formated_responders = list() responders_values = dict((k, lookup_es_key(matches[0], v)) for k, v in responder_args.iteritems()) responders_values = dict((k, v) for k, v in responders_values.iteritems() if v) for responder in responders: responder = unicode(responder) try: formated_responders.append(responder.format(**responders_values)) except KeyError as error: logging.warn("OpsGenieAlerter: Cannot create responder for OpsGenie Alert. Key not foud: %s. " % (error)) if not formated_responders: logging.warn("OpsGenieAlerter: no responders can be formed. Trying the default responder ") if not default_responders: logging.warn("OpsGenieAlerter: default responder not set. Falling back") formated_responders = responders else: formated_responders = default_responders responders = formated_responders return responders
def add_data(self, data): if 'query_key' in self.rules: qk = self.rules['query_key'] else: qk = None for event in data: if qk: key = hashable(lookup_es_key(event, qk)) else: # If no query_key, we use the key 'all' for all events key = 'all' # Store the timestamps of recent occurrences, per key self.occurrences.setdefault( key, EventWindow(self.rules['timeframe'], getTimestamp=self.get_ts)).append((event, 1)) # Only check for match _once_ after adding all the events discovered in this run # If the current running count is 1, and the threshold is 10, and we go to add 8 entries # it should only count as a single match, and not 8 consecutive ones. self.check_for_match(key)
def compare(self, data): if self.rule.get('condition').get('script'): if self.rule.get('condition').get('script').get('inline'): script = self.rule.get('condition').get('script').get('inline') ret = ruby_alert_determine(['ruby', 'elasticwatcher/script_inline_alert_check.rb', '--query_result', json.dumps(data), '--script', script]) if ret[1] == 'true': return True else: return False else: ruby_script_name = self.rule.get('condition').get('script').get('name') determine_result = ruby_alert_determine(['ruby', 'rules/'+ruby_script_name, '--query_result', json.dumps(data)]) if determine_result[1] == "true": return True else: return False else: term = lookup_es_key(data, self.rule.get('condition').get('compare_key')) if term is None: return not self.rule.get('condition').get('ignore_null') if OPS_DICT.get(self.rule.get('condition').get('operator'))(term, self.rule.get('condition').get('expected')): return True return False
def comment_on_ticket(self, ticket, match): text = unicode(JiraFormattedMatchString(self.rule, match)) timestamp = pretty_ts(lookup_es_key(match, self.rule['timestamp_field'])) comment = "This alert was triggered again at %s\n%s" % (timestamp, text) self.client.add_comment(ticket, comment)
def compare(self, event): term = lookup_es_key(event, self.rules["compare_key"]) if term in self.rules["blacklist"]: return True return False
def alert(self, matches): if False: print "*********** STACK ***********" import traceback traceback.print_stack() print "*********** MATCHES ***********" print matches print "*********** RULES ************" print self.rule if 'template_text_content' in self.rule: text = self.rule['template_text_content'] elif 'template_text_file' in self.rule: with open(self.rule['template_text_file'], 'r') as f: text = f.read() else: text = '{{ matches|length }} items found' if 'template_html_content' in self.rule: html = self.rule['template_html_content'] elif 'template_html_file' in self.rule: with open(self.rule['template_html_file'], 'r') as f: html = f.read() else: html = '{{ matches|length }} items found' if 'email_from_field' in self.rule: recipient = lookup_es_key(matches[0], self.rule['email_from_field']) if isinstance(recipient, basestring): if '@' in recipient: to_addr = [recipient] elif 'email_add_domain' in self.rule: to_addr = [recipient + self.rule['email_add_domain']] elif isinstance(recipient, list): to_addr = recipient if 'email_add_domain' in self.rule: to_addr = [ name + self.rule['email_add_domain'] for name in to_addr ] es_conn_conf = util.build_es_conn_config(self.rule) env = { 'rule': self.rule, 'matches': matches, 'pipeline': self.pipeline, 'jira_server': self.pipeline['jira_server'] if (self.pipeline and 'jira_server' in self.pipeline) else None, 'jira_ticket': self.pipeline['jira_ticket'] if (self.pipeline and 'jira_ticket' in self.pipeline) else None, 'es': util.elasticsearch_client(es_conn_conf), 'json': json, 'util': util, 'datetime': datetime, 'kibana_context_args': kibana4_context_args, } text = Environment().from_string(text).render(**env) html = Environment().from_string(html).render(**env) messageRoot = MIMEMultipart('related') messageRoot['Subject'] = _encode_str(self.create_title(matches)) messageRoot['From'] = _encode_str(self.from_addr) if 'email_from_field' in self.rule: messageRoot['To'] = _convert_to_strings(to_addr) else: messageRoot['To'] = _convert_to_strings(self.rule['email']) if self.rule.get('email_reply_to'): messageRoot['Reply-To'] = _convert_to_strings( self.rule.get('email_reply_to')) messageRoot.preamble = 'This is a multi-part message in MIME format.' # Encapsulate the plain and HTML versions of the message body in an # 'alternative' part, so message agents can decide which they want to display. msgAlternative = MIMEMultipart('alternative') msgAlternative.attach(MIMEText(_encode_str(text), 'plain')) msgAlternative.attach(MIMEText(_encode_str(html), 'html')) messageRoot.attach(msgAlternative) try: if self.smtp_ssl: if self.smtp_port: self.smtp = SMTP_SSL(self.smtp_host, self.smtp_port) else: self.smtp = SMTP_SSL(self.smtp_host) else: if self.smtp_port: self.smtp = SMTP(self.smtp_host, self.smtp_port) else: self.smtp = SMTP(self.smtp_host) self.smtp.ehlo() if self.smtp.has_extn('STARTTLS'): self.smtp.starttls() if 'smtp_auth_file' in self.rule: self.smtp.login(self.user, self.password) except (SMTPException, error) as e: raise EAException("Error connecting to SMTP host: %s" % (e)) except SMTPAuthenticationError as e: raise EAException("SMTP username/password rejected: %s" % (e)) self.smtp.sendmail(messageRoot['From'], self.rule['email'], messageRoot.as_string()) self.smtp.close() elastalert_logger.info("Sent email to %s for rule: %s" % (self.rule['email'], self.rule['name']))
def lookup_value_source(d, key): hit = d.get('hits').get('hits')[0]['_source'] return lookup_es_key(hit, key)
def compare(self, event): term = lookup_es_key(event, self.rules['compare_key']) if term in self.rules['blacklist']: return True return False