mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 06:45:08 +00:00
feat(allowlist): Support regexes in Tags to allow "or"-like conditional matching (#2300)
Co-authored-by: Kevin Pullin <kevinp@nexttrucking.com> Co-authored-by: Sergio Garcia <sergargar1@gmail.com>
This commit is contained in:
@@ -7,9 +7,10 @@ You can use `-w`/`--allowlist-file` with the path of your allowlist yaml file, b
|
|||||||
|
|
||||||
## Allowlist Yaml File Syntax
|
## Allowlist Yaml File Syntax
|
||||||
|
|
||||||
### Account, Check and/or Region can be * to apply for all the cases
|
### Account, Check and/or Region can be * to apply for all the cases.
|
||||||
### Resources is a list that can have either Regex or Keywords
|
### Resources and tags are lists that can have either Regex or Keywords.
|
||||||
### Tags is an optional list containing tuples of 'key=value'
|
### Tags is an optional list that matches on tuples of 'key=value' and are "ANDed" together.
|
||||||
|
### Use an alternation Regex to match one of multiple tags with "ORed" logic.
|
||||||
########################### ALLOWLIST EXAMPLE ###########################
|
########################### ALLOWLIST EXAMPLE ###########################
|
||||||
Allowlist:
|
Allowlist:
|
||||||
Accounts:
|
Accounts:
|
||||||
@@ -25,10 +26,10 @@ You can use `-w`/`--allowlist-file` with the path of your allowlist yaml file, b
|
|||||||
Regions:
|
Regions:
|
||||||
- "*"
|
- "*"
|
||||||
Resources:
|
Resources:
|
||||||
- "test" # Will ignore every resource containing the string "test" and the tags 'test=test' and 'project=test' in account 123456789012 and every region
|
- "test"
|
||||||
Tags:
|
Tags:
|
||||||
- "test=test" # Will ignore every resource containing the string "test" and the tags 'test=test' and 'project=test' in account 123456789012 and every region
|
- "test=test" # Will ignore every resource containing the string "test" and the tags 'test=test' and
|
||||||
- "project=test"
|
- "project=test|project=stage" # either of ('project=test' OR project=stage) in account 123456789012 and every region
|
||||||
|
|
||||||
"*":
|
"*":
|
||||||
Checks:
|
Checks:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
### Account, Check and/or Region can be * to apply for all the cases
|
### Account, Check and/or Region can be * to apply for all the cases.
|
||||||
### Resources is a list that can have either Regex or Keywords
|
### Resources and tags are lists that can have either Regex or Keywords.
|
||||||
### Tags is an optional list containing tuples of 'key=value'
|
### Tags is an optional list that matches on tuples of 'key=value' and are "ANDed" together.
|
||||||
|
### Use an alternation Regex to match one of multiple tags with "ORed" logic.
|
||||||
########################### ALLOWLIST EXAMPLE ###########################
|
########################### ALLOWLIST EXAMPLE ###########################
|
||||||
Allowlist:
|
Allowlist:
|
||||||
Accounts:
|
Accounts:
|
||||||
@@ -16,10 +17,10 @@ Allowlist:
|
|||||||
Regions:
|
Regions:
|
||||||
- "*"
|
- "*"
|
||||||
Resources:
|
Resources:
|
||||||
- "test" # Will ignore every resource containing the string "test" and the tags 'test=test' and 'project=test' in account 123456789012 and every region
|
- "test"
|
||||||
Tags:
|
Tags:
|
||||||
- "test=test" # Will ignore every resource containing the string "test" and the tags 'test=test' and 'project=test' in account 123456789012 and every region
|
- "test=test" # Will ignore every resource containing the string "test" and the tags 'test=test' and
|
||||||
- "project=test"
|
- "project=test|project=stage" # either of ('project=test' OR project=stage) in account 123456789012 and every region
|
||||||
|
|
||||||
"*":
|
"*":
|
||||||
Checks:
|
Checks:
|
||||||
|
|||||||
@@ -192,13 +192,21 @@ def is_allowlisted_in_tags(check_allowlist, elem, resource, tags):
|
|||||||
# Check if there are allowlisted tags
|
# Check if there are allowlisted tags
|
||||||
if "Tags" in check_allowlist:
|
if "Tags" in check_allowlist:
|
||||||
# Check if there are resource tags
|
# Check if there are resource tags
|
||||||
if tags:
|
if not tags or not re.search(elem, resource):
|
||||||
tags_in_resource_tags = True
|
return False
|
||||||
for tag in check_allowlist["Tags"]:
|
|
||||||
if tag not in tags:
|
all_allowed_tags_in_resource_tags = True
|
||||||
tags_in_resource_tags = False
|
for allowed_tag in check_allowlist["Tags"]:
|
||||||
if tags_in_resource_tags and re.search(elem, resource):
|
found_allowed_tag = False
|
||||||
return True
|
for resource_tag in tags:
|
||||||
|
if re.search(allowed_tag, resource_tag):
|
||||||
|
found_allowed_tag = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not found_allowed_tag:
|
||||||
|
all_allowed_tags_in_resource_tags = False
|
||||||
|
|
||||||
|
return all_allowed_tags_in_resource_tags
|
||||||
else:
|
else:
|
||||||
if re.search(elem, resource):
|
if re.search(elem, resource):
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -165,15 +165,15 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
@@ -187,7 +187,7 @@ class Test_Allowlist:
|
|||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
is_allowlisted(
|
is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", []
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -207,20 +207,20 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
is_allowlisted(
|
is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", []
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -240,20 +240,20 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
is_allowlisted(
|
is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", []
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -273,20 +273,20 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted_in_region(
|
assert is_allowlisted_in_region(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted_in_region(
|
assert is_allowlisted_in_region(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted_in_region(
|
assert is_allowlisted_in_region(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
is_allowlisted_in_region(
|
is_allowlisted_in_region(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", []
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -306,20 +306,20 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", []
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
is_allowlisted_in_check(
|
is_allowlisted_in_check(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", ""
|
allowlist, AWS_ACCOUNT_NUMBER, "check_test", "us-east-2", "test", []
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -332,7 +332,7 @@ class Test_Allowlist:
|
|||||||
"check_test": {
|
"check_test": {
|
||||||
"Regions": ["us-east-1", "eu-west-1"],
|
"Regions": ["us-east-1", "eu-west-1"],
|
||||||
"Resources": ["*"],
|
"Resources": ["*"],
|
||||||
"Tags": ["environment=dev", "project=prowler"],
|
"Tags": ["environment=dev", "project=.*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,7 +345,7 @@ class Test_Allowlist:
|
|||||||
"check_test",
|
"check_test",
|
||||||
AWS_REGION,
|
AWS_REGION,
|
||||||
"prowler",
|
"prowler",
|
||||||
"environment=dev",
|
["environment=dev"],
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
@@ -354,7 +354,7 @@ class Test_Allowlist:
|
|||||||
"check_test",
|
"check_test",
|
||||||
AWS_REGION,
|
AWS_REGION,
|
||||||
"prowler-test",
|
"prowler-test",
|
||||||
"environment=dev project=prowler",
|
["environment=dev", "project=prowler"],
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
@@ -364,7 +364,7 @@ class Test_Allowlist:
|
|||||||
"check_test",
|
"check_test",
|
||||||
"us-east-2",
|
"us-east-2",
|
||||||
"test",
|
"test",
|
||||||
"environment=pro",
|
["environment=pro"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -380,14 +380,14 @@ class Test_Allowlist:
|
|||||||
check_allowlist,
|
check_allowlist,
|
||||||
check_allowlist["Resources"][0],
|
check_allowlist["Resources"][0],
|
||||||
"prowler",
|
"prowler",
|
||||||
"environment=dev",
|
["environment=dev"],
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted_in_tags(
|
assert is_allowlisted_in_tags(
|
||||||
check_allowlist,
|
check_allowlist,
|
||||||
check_allowlist["Resources"][0],
|
check_allowlist["Resources"][0],
|
||||||
"prowler-test",
|
"prowler-test",
|
||||||
"environment=dev project=prowler",
|
["environment=dev", "project=prowler"],
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
@@ -395,6 +395,35 @@ class Test_Allowlist:
|
|||||||
check_allowlist,
|
check_allowlist,
|
||||||
check_allowlist["Resources"][0],
|
check_allowlist["Resources"][0],
|
||||||
"test",
|
"test",
|
||||||
"environment=pro",
|
["environment=pro"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_is_allowlisted_in_tags_regex(self):
|
||||||
|
# Allowlist example
|
||||||
|
check_allowlist = {
|
||||||
|
"Regions": ["us-east-1", "eu-west-1"],
|
||||||
|
"Resources": ["*"],
|
||||||
|
"Tags": ["environment=(dev|test)", ".*=prowler"],
|
||||||
|
}
|
||||||
|
|
||||||
|
assert is_allowlisted_in_tags(
|
||||||
|
check_allowlist,
|
||||||
|
check_allowlist["Resources"][0],
|
||||||
|
"prowler-test",
|
||||||
|
["environment=test", "proj=prowler"],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not is_allowlisted_in_tags(
|
||||||
|
check_allowlist,
|
||||||
|
check_allowlist["Resources"][0],
|
||||||
|
"prowler-test",
|
||||||
|
["env=prod", "project=prowler"],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not is_allowlisted_in_tags(
|
||||||
|
check_allowlist,
|
||||||
|
check_allowlist["Resources"][0],
|
||||||
|
"prowler-test",
|
||||||
|
["environment=prod", "project=myproj"],
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user