mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
fix(mutelist): Fix tags match (#4606)
This commit is contained in:
@@ -8,6 +8,26 @@ from prowler.lib.mutelist.models import mutelist_schema
|
||||
|
||||
|
||||
class Mutelist(ABC):
|
||||
"""
|
||||
Abstract base class for managing a mutelist.
|
||||
|
||||
Attributes:
|
||||
_mutelist (dict): Dictionary containing information about muted checks for different accounts.
|
||||
_mutelist_file_path (str): Path to the mutelist file.
|
||||
MUTELIST_KEY (str): Key used to access the mutelist in the mutelist file.
|
||||
|
||||
Methods:
|
||||
__init__: Initializes a Mutelist object.
|
||||
mutelist: Property that returns the mutelist dictionary.
|
||||
mutelist_file_path: Property that returns the mutelist file path.
|
||||
is_finding_muted: Abstract method to check if a finding is muted.
|
||||
get_mutelist_file_from_local_file: Retrieves the mutelist file from a local file.
|
||||
validate_mutelist: Validates the mutelist against a schema.
|
||||
is_muted: Checks if a finding is muted for the audited account, check, region, resource, and tags.
|
||||
is_muted_in_check: Checks if a check is muted.
|
||||
is_excepted: Checks if the account, region, resource, and tags are excepted based on the exceptions.
|
||||
"""
|
||||
|
||||
_mutelist: dict = {}
|
||||
_mutelist_file_path: str = None
|
||||
|
||||
@@ -68,6 +88,25 @@ class Mutelist(ABC):
|
||||
"""
|
||||
Check if the provided finding is muted for the audited account, check, region, resource and tags.
|
||||
|
||||
The Mutelist works in a way that each field is ANDed, so if a check is muted for an account, region, resource and tags, it will be muted.
|
||||
The exceptions are ORed, so if a check is excepted for an account, region, resource or tags, it will not be muted.
|
||||
The only particularity is the tags, which are ORed.
|
||||
|
||||
So, for the following Mutelist:
|
||||
```
|
||||
Mutelist:
|
||||
Accounts:
|
||||
'*':
|
||||
Checks:
|
||||
ec2_instance_detailed_monitoring_enabled:
|
||||
Regions: ['*']
|
||||
Resources:
|
||||
- 'i-123456789'
|
||||
Tags:
|
||||
- 'Name=AdminInstance | Environment=Prod'
|
||||
```
|
||||
The check `ec2_instance_detailed_monitoring_enabled` will be muted for all accounts and regions and for the resource_id 'i-123456789' with at least one of the tags 'Name=AdminInstance' or 'Environment=Prod'.
|
||||
|
||||
Args:
|
||||
mutelist (dict): Dictionary containing information about muted checks for different accounts.
|
||||
audited_account (str): The account being audited.
|
||||
@@ -172,7 +211,9 @@ class Mutelist(ABC):
|
||||
muted_in_resource = self.is_item_matched(
|
||||
muted_resources, finding_resource
|
||||
)
|
||||
muted_in_tags = self.is_item_matched(muted_tags, finding_tags)
|
||||
muted_in_tags = self.is_item_matched(
|
||||
muted_tags, finding_tags, tag=True
|
||||
)
|
||||
|
||||
# For a finding to be muted requires the following set to True:
|
||||
# - muted_in_check -> True
|
||||
@@ -240,7 +281,9 @@ class Mutelist(ABC):
|
||||
)
|
||||
|
||||
excepted_tags = exceptions.get("Tags", [])
|
||||
is_tag_excepted = self.is_item_matched(excepted_tags, finding_tags)
|
||||
is_tag_excepted = self.is_item_matched(
|
||||
excepted_tags, finding_tags, tag=True
|
||||
)
|
||||
|
||||
if (
|
||||
not is_account_excepted
|
||||
@@ -264,7 +307,7 @@ class Mutelist(ABC):
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def is_item_matched(matched_items, finding_items):
|
||||
def is_item_matched(matched_items, finding_items, tag=False):
|
||||
"""
|
||||
Check if any of the items in matched_items are present in finding_items.
|
||||
|
||||
@@ -278,10 +321,15 @@ class Mutelist(ABC):
|
||||
try:
|
||||
is_item_matched = False
|
||||
if matched_items and (finding_items or finding_items == ""):
|
||||
# If we use tags, we need to use re.search instead of re.match because we need to match the tags in the format key1=value1 | key2=value2
|
||||
if tag:
|
||||
operation = re.search
|
||||
else:
|
||||
operation = re.match
|
||||
for item in matched_items:
|
||||
if item.startswith("*"):
|
||||
item = ".*" + item[1:]
|
||||
if re.match(item, finding_items):
|
||||
if operation(item, finding_items):
|
||||
is_item_matched = True
|
||||
break
|
||||
return is_item_matched
|
||||
|
||||
@@ -1223,35 +1223,49 @@ class TestAWSMutelist:
|
||||
def test_is_muted_in_tags(self):
|
||||
mutelist_tags = ["environment=dev", "project=prowler"]
|
||||
|
||||
assert AWSMutelist.is_item_matched(mutelist_tags, "environment=dev")
|
||||
assert AWSMutelist.is_item_matched(mutelist_tags, "environment=dev", tag=True)
|
||||
|
||||
assert AWSMutelist.is_item_matched(
|
||||
mutelist_tags,
|
||||
"environment=dev | project=prowler",
|
||||
mutelist_tags, "environment=dev | project=prowler", tag=True
|
||||
)
|
||||
|
||||
assert AWSMutelist.is_item_matched(
|
||||
mutelist_tags, "environment=pro | project=prowler", tag=True
|
||||
)
|
||||
|
||||
assert not (
|
||||
AWSMutelist.is_item_matched(
|
||||
mutelist_tags,
|
||||
"environment=pro",
|
||||
)
|
||||
AWSMutelist.is_item_matched(mutelist_tags, "environment=pro", tag=True)
|
||||
)
|
||||
|
||||
def test_is_muted_in_tags_with_piped_tags(self):
|
||||
mutelist_tags = ["environment=dev|project=prowler"]
|
||||
|
||||
assert AWSMutelist.is_item_matched(mutelist_tags, "environment=dev", tag=True)
|
||||
|
||||
assert AWSMutelist.is_item_matched(
|
||||
mutelist_tags, "environment=dev | project=prowler", tag=True
|
||||
)
|
||||
|
||||
assert AWSMutelist.is_item_matched(
|
||||
mutelist_tags, "environment=pro | project=prowler", tag=True
|
||||
)
|
||||
|
||||
assert not (
|
||||
AWSMutelist.is_item_matched(mutelist_tags, "environment=pro", tag=True)
|
||||
)
|
||||
|
||||
def test_is_muted_in_tags_regex(self):
|
||||
mutelist_tags = ["environment=(dev|test)", ".*=prowler"]
|
||||
assert AWSMutelist.is_item_matched(
|
||||
mutelist_tags,
|
||||
"environment=test | proj=prowler",
|
||||
mutelist_tags, "environment=test | proj=prowler", tag=True
|
||||
)
|
||||
|
||||
assert AWSMutelist.is_item_matched(
|
||||
mutelist_tags,
|
||||
"env=prod | project=prowler",
|
||||
mutelist_tags, "env=prod | project=prowler", tag=True
|
||||
)
|
||||
|
||||
assert not AWSMutelist.is_item_matched(
|
||||
mutelist_tags,
|
||||
"environment=prod | project=myproj",
|
||||
mutelist_tags, "environment=prod | project=myproj", tag=True
|
||||
)
|
||||
|
||||
def test_is_muted_in_tags_with_no_tags_in_finding(self):
|
||||
|
||||
Reference in New Issue
Block a user