Skip to content

Commit

Permalink
Merge pull request #643 from airbnb/ryandeivert-default-output
Browse files Browse the repository at this point in the history
[outputs] adding support for required alerting outputs
  • Loading branch information
ryandeivert authored Mar 20, 2018
2 parents a97fb60 + da8192a commit e6bd483
Show file tree
Hide file tree
Showing 35 changed files with 202 additions and 62 deletions.
4 changes: 1 addition & 3 deletions rules/community/binaryalert/binaryalert_yara_match.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
rule = StreamRules.rule


@rule(
logs=['binaryalert'],
outputs=['aws-firehose:alerts'])
@rule(logs=['binaryalert'])
def binaryalert_yara_match(rec):
"""
author: Austin Byers (Airbnb CSIRT)
Expand Down
4 changes: 1 addition & 3 deletions rules/community/cloudtrail/cloudtrail_critical_api_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
disable = StreamRules.disable()


@rule(
logs=['cloudtrail:events'],
outputs=['aws-firehose:alerts'])
@rule(logs=['cloudtrail:events'])
def cloudtrail_critical_api_calls(rec):
"""
author: airbnb_csirt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
disable = StreamRules.disable()


@rule(
logs=['cloudtrail:events'],
outputs=['aws-firehose:alerts'])
@rule(logs=['cloudtrail:events'])
def cloudtrail_mfa_policy_abuse_attempt(rec):
"""
author: Scott Piper of Summit Route in collaboration with Duo Security
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@rule(
logs=['cloudwatch:events'],
outputs=['aws-firehose:alerts'],
req_subkeys={
'detail': ['eventName', 'requestParameters']
})
Expand Down
1 change: 0 additions & 1 deletion rules/community/cloudtrail/cloudtrail_put_bucket_acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@rule(
logs=['cloudwatch:events'],
outputs=['aws-firehose:alerts'],
req_subkeys={
'detail': ['requestParameters', 'eventName']
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

@rule(
logs=['cloudwatch:events'],
outputs=['aws-firehose:alerts'],
req_subkeys={
'detail': ['requestParameters']
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@rule(
logs=['cloudwatch:events'],
outputs=['aws-firehose:alerts'],
req_subkeys={
'detail': ['userIdentity', 'eventType']
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

@rule(
logs=['cloudwatch:events'],
outputs=['aws-firehose:alerts'],
req_subkeys={
'detail': ['eventName', 'requestParameters']
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
rule = StreamRules.rule


@rule(logs=['duo:administrator'], outputs=['aws-firehose:alerts'])
@rule(logs=['duo:administrator'])
def duo_bypass_code_create_non_auto_generated(rec):
"""
author: @mimeframe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
rule = StreamRules.rule


@rule(logs=['duo:administrator'], outputs=['aws-firehose:alerts'])
@rule(logs=['duo:administrator'])
def duo_bypass_code_create_non_expiring(rec):
"""
author: @mimeframe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
rule = StreamRules.rule


@rule(logs=['duo:administrator'], outputs=['aws-firehose:alerts'])
@rule(logs=['duo:administrator'])
def duo_bypass_code_create_unlimited_use(rec):
"""
author: @mimeframe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['duo:authentication'], outputs=['aws-firehose:alerts'])
@rule(logs=['duo:authentication'])
def duo_anonymous_ip_failure(rec):
"""
author: airbnb_csirt
Expand Down
2 changes: 1 addition & 1 deletion rules/community/duo_authentication/duo_fraud.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['duo:authentication'], outputs=['aws-firehose:alerts'])
@rule(logs=['duo:authentication'])
def duo_fraud(rec):
"""
author: airbnb_csirt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['ghe:general'], outputs=['aws-firehose:alerts'])
@rule(logs=['ghe:general'])
def github_disable_dismiss_stale_pull_request_approvals(rec):
"""
author: @mimeframe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['ghe:general'], outputs=['aws-firehose:alerts'])
@rule(logs=['ghe:general'])
def github_disable_protect_this_branch(rec):
"""
author: @mimeframe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
rule = StreamRules.rule


@rule(logs=['ghe:general'], outputs=['aws-firehose:alerts'])
@rule(logs=['ghe:general'])
def github_disable_required_pull_request_reviews(rec):
"""
author: @mimeframe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['ghe:general'], outputs=['aws-firehose:alerts'])
@rule(logs=['ghe:general'])
def github_disable_required_status_checks(rec):
"""
author: @mimeframe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['ghe:general'], outputs=['aws-firehose:alerts'])
@rule(logs=['ghe:general'])
def github_disable_two_factor_requirement_org(rec):
"""
author: @mimeframe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['ghe:general'], outputs=['aws-firehose:alerts'])
@rule(logs=['ghe:general'])
def github_disable_two_factor_requirement_user(rec):
"""
author: @mimeframe
Expand Down
2 changes: 1 addition & 1 deletion rules/community/github/github_oauth_application_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['ghe:general'], outputs=['aws-firehose:alerts'])
@rule(logs=['ghe:general'])
def github_oauth_application_create(rec):
"""
author: @mimeframe
Expand Down
2 changes: 1 addition & 1 deletion rules/community/github/github_site_admin_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['ghe:general'], outputs=['aws-firehose:alerts'])
@rule(logs=['ghe:general'])
def github_site_admin_action(rec):
"""
author: @mimeframe
Expand Down
2 changes: 1 addition & 1 deletion rules/community/github/github_site_admin_user_promotion.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['ghe:general'], outputs=['aws-firehose:alerts'])
@rule(logs=['ghe:general'])
def github_site_admin_user_promotion(rec):
"""
author: @fusionrace, @mimeframe
Expand Down
2 changes: 1 addition & 1 deletion rules/community/guardduty/guard_duty_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
disable = StreamRules.disable()


@rule(logs=['cloudwatch:events'], matchers=['guard_duty'], outputs=['aws-firehose:alerts'])
@rule(logs=['cloudwatch:events'], matchers=['guard_duty'])
def guard_duty_all(*_):
"""
author: spiper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
rule = StreamRules.rule


@rule(
datatypes=['command', 'filePath', 'processPath', 'fileName'],
outputs=['aws-firehose:alerts'])
@rule(datatypes=['command', 'filePath', 'processPath', 'fileName'])
def right_to_left_character(rec):
"""
author: @javutin
Expand Down
2 changes: 1 addition & 1 deletion rules/community/onelogin/onelogin_events_assumed_role.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rule = StreamRules.rule


@rule(logs=['onelogin:events'], outputs=['aws-firehose:alerts'])
@rule(logs=['onelogin:events'])
def onelogin_events_assumed_role(rec):
"""
author: @javutin
Expand Down
16 changes: 10 additions & 6 deletions stream_alert/alert_processor/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from stream_alert.alert_processor import LOGGER
from stream_alert.alert_processor.helpers import validate_alert
from stream_alert.alert_processor.outputs.output_base import StreamAlertOutput
from stream_alert.shared import NORMALIZATION_KEY
from stream_alert.shared import NORMALIZATION_KEY, resources


def handler(event, context):
Expand All @@ -41,14 +41,15 @@ def handler(event, context):
"""
# A failure to load the config will log the error in load_output_config
# and return here
config = _load_output_config()
if not config:
return

split_arn = context.invoked_function_arn.split(':')
region = split_arn[3]
account_id = split_arn[4]
function_name = context.function_name
prefix = function_name.split('_')[0]

config = _load_output_config(prefix)
if not config:
return

# Return the current list of statuses back to the caller
return list(run(event, region, account_id, function_name, config))
Expand Down Expand Up @@ -151,7 +152,7 @@ def _sort_dict(unordered_dict):
return result


def _load_output_config(config_path='conf/outputs.json'):
def _load_output_config(prefix, config_path='conf/outputs.json'):
"""Load the outputs configuration file from disk
Returns:
Expand All @@ -164,4 +165,7 @@ def _load_output_config(config_path='conf/outputs.json'):
LOGGER.error('The \'%s\' file could not be loaded into json', config_path)
return

# Merge in the default outputs info
config = resources.merge_required_outputs(config, prefix)

return config
20 changes: 10 additions & 10 deletions stream_alert/rule_processor/rules_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from stream_alert.rule_processor import LOGGER
from stream_alert.rule_processor.threat_intel import StreamThreatIntel
from stream_alert.shared import NORMALIZATION_KEY
from stream_alert.shared import NORMALIZATION_KEY, resources

DEFAULT_RULE_DESCRIPTION = 'No rule description provided'

Expand Down Expand Up @@ -53,6 +53,7 @@ class StreamRules(object):
def __init__(self, config):
"""Initialize a StreamRules instance to cache a StreamThreatIntel instance."""
self._threat_intel = StreamThreatIntel.load_from_config(config)
self._required_outputs_set = resources.get_required_outputs()

@classmethod
def get_rules(cls):
Expand Down Expand Up @@ -85,12 +86,6 @@ def decorator(rule):
rule_name)
return

if not outputs:
LOGGER.error(
'Invalid rule [%s] - rule must have \'outputs\' declared',
rule_name)
return

if rule_name in cls.__rules:
raise ValueError('rule [{}] already defined'.format(rule_name))
cls.__rules[rule_name] = RuleAttributes(rule_name,
Expand Down Expand Up @@ -397,6 +392,8 @@ def process(self, input_payload):

return alerts, normalized_records



def threat_intel_match(self, payload_with_normalized_records):
"""Apply Threat Intelligence on normalized records
Expand All @@ -421,8 +418,7 @@ def threat_intel_match(self, payload_with_normalized_records):
self.rule_analysis(ioc_record.pre_parsed_record, rule, ioc_record, alerts)
return alerts

@staticmethod
def rule_analysis(record, rule, payload, alerts):
def rule_analysis(self, record, rule, payload, alerts):
"""Class method to analyze rule against a record
Args:
Expand All @@ -443,14 +439,18 @@ def rule_analysis(record, rule, payload, alerts):
LOGGER.info('Rule [%s] triggered alert [%s] on log type [%s] from entity \'%s\' '
'in service \'%s\'', rule.rule_name, alert_id, payload.log_source,
payload.entity, payload.service())

# Combine the required alert outputs with the ones for this rule
all_outputs = self._required_outputs_set.union(set(rule.outputs or []))

alert = {
'id': alert_id,
'record': record,
'rule_name': rule.rule_name,
'rule_description': rule.rule_function.__doc__ or DEFAULT_RULE_DESCRIPTION,
'log_source': str(payload.log_source),
'log_type': payload.type,
'outputs': rule.outputs,
'outputs': list(all_outputs), # TODO: @austinbyers - change this to a set
'source_service': payload.service(),
'source_entity': payload.entity,
'context': rule.context}
Expand Down
Loading

0 comments on commit e6bd483

Please sign in to comment.