in ingest_suricata_rules/rules_processor.py [0:0]
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
# bucket = os.environ["SuricataRulesBucket"]
# key = "rules/emerging-imap.rules"
suricata_rules_filename = key.split('/')[-1].split('.')[0].replace('_','-')
s3.download_file(bucket, key, '/tmp/'+suricata_rules_filename)
content=parse_file('/tmp/'+suricata_rules_filename)
print("Processing Suricata Rules file : s3://"+bucket+"/"+key)
print("Initial Suricata Rules count including commented rules (excluding commented headers): ", len(content))
# Drop commented / disabled rules
initial_ruleset = [ rule for rule in content if rule.enabled == True ]
print("Initial Suricata Rules count (uncommented rule lines): ", len(initial_ruleset))
# When testing with 3000+ rules faced lamdba timeout issues
# If file contains more than 1000 active rules split into multiple files to avoid lamdba timeout issues
if len(initial_ruleset) > 1000:
print("Initial Rule Count > 1000. Spliting files by 1000 rules to process them individually")
split_files(initial_ruleset,1000,suricata_rules_filename,bucket)
exit()
valid_ruleset, dropped_ruleset = process_ruleset(initial_ruleset)
valid_ruleset, dropped_ruleset = replace_rule_vars_with_values(valid_ruleset,dropped_ruleset)
# Drop Rules with undefined RuleVariables
final_ruleset = [ rule for rule in valid_ruleset if rule.enabled == True ]
final_rule_count = len(final_ruleset)
print("Valid Rule count that can be applied to ANF: ", final_rule_count)
print("Dropped Rule count that cannot be applied to ANF: ", len(dropped_ruleset))
save_rulesets(final_ruleset,bucket,suricata_rules_filename,'FINALBEFOREAPPLY')
save_rulesets(dropped_ruleset,bucket,suricata_rules_filename,'DROPPED')
# Calculate required rule group capacity
if final_rule_count == 0 :
print("SKIPPING RULE FILE: No Valid Rules found that can be applied to ANF for file :", suricata_rules_filename)
save_rulesets(final_ruleset,bucket,suricata_rules_filename,'EMPTY')
exit()
# if 1 <= final_rule_count <= 80:
# RuleGroupCapacity = 100
# if 81 <= final_rule_count <= 400:
# RuleGroupCapacity = 500
# if final_rule_count > 401:
# RuleGroupCapacity = 1000
# Roundup to nearest hundred with 30% buffer
RuleGroupCapacity = int(math.ceil((final_rule_count * 1.3) / 100.0)) * 100
# Create/Update RuleGroup per each ruleset chunk
RuleGroupName="suricata-"+suricata_rules_filename
RulesString = "\n".join([ str(rule) for rule in final_ruleset ])
# To convert any IDS Rulegroup to IPS Rulegroup
# Lambda checks ssm param : ConvertRuleGroupIDStoIPS for list of suricata rulegroups to create/update respective ips rulegroups
ids_ips_convert_list = [x.strip() for x in get_rulegroups_to_convert(ConvertRuleGroupIDStoIPSSSMParam).split(",")]
if check_rule_group_exists(RuleGroupName):
RuleGroup=get_rule_group(RuleGroupName)
UpdateToken=RuleGroup["UpdateToken"]
print("Attempting Update RuleGroup: "+RuleGroupName+ " with " + str(len(final_ruleset)) + " rules" )
try:
response = anf.update_rule_group(
RuleGroupName=RuleGroupName,
Type=RuleGroupType,
Rules=RulesString,
UpdateToken=RuleGroup["UpdateToken"]
)
print(response)
save_rulesets(final_ruleset,bucket,RuleGroupName,'APPLIED')
if RuleGroupName in ids_ips_convert_list:
trigger_ids_to_ips(final_ruleset,bucket,RuleGroupName)
except Exception as err:
save_rulesets(final_ruleset,bucket,RuleGroupName,'ERROR')
raise err
else:
print("Attempting Create RuleGroup: "+RuleGroupName+ " with " + str(len(final_ruleset)) + " rules" )
try:
response = anf.create_rule_group(
RuleGroupName=RuleGroupName,
Type=RuleGroupType,
Rules=RulesString,
Capacity=RuleGroupCapacity
)
print(response)
save_rulesets(final_ruleset,bucket,RuleGroupName,'APPLIED')
if RuleGroupName in ids_ips_convert_list:
trigger_ids_to_ips(final_ruleset,bucket,RuleGroupName)
except Exception as err:
save_rulesets(final_ruleset,bucket,RuleGroupName,'ERROR')
raise err