diff --git a/rules/aws/exfiltration_ec2_vm_export_failure.toml b/rules/aws/exfiltration_ec2_vm_export_failure.toml index bda445657..8f438957b 100644 --- a/rules/aws/exfiltration_ec2_vm_export_failure.toml +++ b/rules/aws/exfiltration_ec2_vm_export_failure.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2021/04/22" maturity = "production" -updated_date = "2021/04/22" +updated_date = "2021/06/24" [rule] author = ["Elastic", "Austin Songer"] @@ -22,6 +22,7 @@ language = "kuery" license = "Elastic License v2" name = "AWS EC2 VM Export Failure" note = """## Config + The AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.""" references = ["https://docs.aws.amazon.com/vm-import/latest/userguide/vmexport.html#export-instance"] risk_score = 21 diff --git a/tests/test_all_rules.py b/tests/test_all_rules.py index 382521779..8eef1fdc9 100644 --- a/tests/test_all_rules.py +++ b/tests/test_all_rules.py @@ -410,7 +410,7 @@ class TestRuleMetadata(BaseRuleTest): self.assertIn(rule_id, deprecated_rules, f'{rule_str} is logged in "deprecated_rules.json" but is missing') -class TestTuleTiming(BaseRuleTest): +class TestRuleTiming(BaseRuleTest): """Test rule timing and timestamps.""" def test_event_override(self): @@ -465,3 +465,32 @@ class TestLicense(BaseRuleTest): if 'elastic license' in rule_license.lower(): err_msg = f'{self.rule_str(rule)} If Elastic License is used, only v2 should be used' self.assertEqual(rule_license, 'Elastic License v2', err_msg) + + +class TestRuleInvestigationGuide(BaseRuleTest): + """Test the note field of a rule.""" + + def test_config(self): + """Test that rules which require a config note are using standard verbiage.""" + config = '## Config\n\n' + beats_integration_pattern = config + 'The {} Fleet integration, Filebeat module, or similarly ' \ + 'structured data is required to be compatible with this rule.' + required = { + 'aws': beats_integration_pattern.format('AWS'), + 'azure': beats_integration_pattern.format('Azure'), + 'gcp': beats_integration_pattern.format('GCP'), + 'google-workspace': beats_integration_pattern.format('Google Workspace'), + 'microsoft-365': beats_integration_pattern.format('Microsoft 365'), + 'okta': beats_integration_pattern.format('Okta'), + } + + for rule in self.all_rules: + rule_dir = rule.path.parts[-2] + note_str = required.get(rule_dir) + if note_str: + self.assert_(rule.contents.data.note, f'{self.rule_str(rule)} note required for config information') + + if note_str not in rule.contents.data.note: + self.fail(f'{self.rule_str(rule)} expected config missing\n\n' + f'Expected: {note_str}\n\n' + f'Actual: {rule.contents.data.note}')