Compare commits

...

9 Commits

Author SHA1 Message Date
Hugo P.Brito
7ab85c107b feat(cli): add --resource-group flag to filter checks by resource group
Extend the resource group filter to all providers via the CLI.
The --resource-group flag allows filtering checks by their ResourceGroup
metadata field, and --list-resource-groups lists all available groups.
2026-03-25 15:51:24 +00:00
Hugo P.Brito
f58e9cfb0f Merge remote-tracking branch 'origin/master' into fix/oraclecloud-idp-group-mapping-events-10411 2026-03-24 12:54:31 +00:00
Hugo P.Brito
814c2f59e6 fix(sdk): support renamed OCI IdP mapping events
- Accept current and legacy OCI IdP group mapping event names\n- Add regression coverage for both event name variants\n- Align check metadata and CIS 3.1 guidance with current names
2026-03-23 09:27:43 +00:00
Hugo P.Brito
d3ffb71a21 fix(sdk): move changelog entry to 5.21.2 unreleased section 2026-03-23 09:06:59 +00:00
Hugo P.Brito
3f43f59d10 fix(sdk): move changelog entry to 5.22.0 unreleased section 2026-03-23 09:00:25 +00:00
Hugo P.Brito
8e4c7c346f Merge remote-tracking branch 'origin/master' into fix/azure-vm-backup-case-insensitive-comparison 2026-03-23 08:59:44 +00:00
Hugo P.Brito
0aeb1eec15 fix(sdk): move changelog entry to 5.21.1 UNRELEASED section 2026-03-19 12:57:25 +00:00
Hugo P.Brito
2362ec0dc1 Merge remote-tracking branch 'origin/master' into fix/azure-vm-backup-case-insensitive-comparison 2026-03-19 12:56:27 +00:00
Hugo P.Brito
0ccc010e6d fix(sdk): use case-insensitive comparison for Azure VM backup checks
- Compare VM names with .lower() in vm_backup_enabled and vm_sufficient_daily_backup_retention_period
- Add tests to verify case-insensitive matching between VM names and backup item names
- Update SDK changelog
2026-03-19 12:51:20 +00:00
11 changed files with 314 additions and 13 deletions

View File

@@ -2,6 +2,15 @@
All notable changes to the **Prowler SDK** are documented in this file.
## [Unreleased] (Prowler UNRELEASED)
### 🚀 Added
- `--resource-group` CLI flag to filter checks by resource group across all providers
- `--list-resource-groups` CLI flag to list available resource groups
---
## [5.22.0] (Prowler v5.22.0)
### 🐞 Fixed
@@ -9,6 +18,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
- Azure MySQL flexible server checks now compare configuration values case-insensitively to avoid false negatives when Azure returns lowercase values [(#10396)](https://github.com/prowler-cloud/prowler/pull/10396)
- Azure `vm_backup_enabled` and `vm_sufficient_daily_backup_retention_period` checks now compare VM names case-insensitively to avoid false negatives when Azure stores backup item names in a different case [(#10395)](https://github.com/prowler-cloud/prowler/pull/10395)
- `entra_non_privileged_user_has_mfa` skips disabled users to avoid false positives [(#10426)](https://github.com/prowler-cloud/prowler/pull/10426)
- Oracle Cloud `events_rule_idp_group_mapping_changes` now recognizes the CIS 3.1 `add/remove` event names to avoid false positives [(#10411)](https://github.com/prowler-cloud/prowler/issues/10411)
---

View File

@@ -27,6 +27,7 @@ from prowler.lib.check.check import (
list_categories,
list_checks_json,
list_fixers,
list_resource_groups,
list_services,
load_custom_checks_metadata,
parse_checks_from_file,
@@ -36,6 +37,7 @@ from prowler.lib.check.check import (
print_compliance_frameworks,
print_compliance_requirements,
print_fixers,
print_resource_groups,
print_services,
remove_custom_checks_module,
run_fixer,
@@ -161,6 +163,7 @@ def prowler():
excluded_services = args.excluded_service
services = args.service
categories = args.category
resource_groups = args.resource_group
checks_file = args.checks_file
checks_folder = args.checks_folder
severities = args.severity
@@ -170,6 +173,7 @@ def prowler():
not checks
and not services
and not categories
and not resource_groups
and not excluded_checks
and not excluded_services
and not severities
@@ -215,6 +219,10 @@ def prowler():
print_categories(list_categories(bulk_checks_metadata))
sys.exit()
if args.list_resource_groups:
print_resource_groups(list_resource_groups(bulk_checks_metadata))
sys.exit()
bulk_compliance_frameworks = {}
# Load compliance frameworks
logger.debug("Loading compliance frameworks from .json files")
@@ -256,6 +264,7 @@ def prowler():
severities=severities,
compliance_frameworks=compliance_framework,
categories=categories,
resource_groups=resource_groups,
provider=provider,
)

View File

@@ -662,8 +662,8 @@
"Description": "It is recommended to setup an Event Rule and Notification that gets triggered when Identity Provider Group Mappings are created, updated or deleted. Event Rules are compartment scoped and will detect events in child compartments. It is recommended to create the Event rule at the root compartment level.",
"RationaleStatement": "IAM Policies govern access to all resources within an OCI Tenancy. IAM Policies use OCI Groups for assigning the privileges. Identity Provider Groups could be mapped to OCI Groups to assign privileges to federated users in OCI. Monitoring and alerting on changes to Identity Provider Group mappings will help in identifying changes to the security posture.",
"ImpactStatement": "There is no performance impact when enabling the above described features but depending on the amount of notifications sent per month there may be a cost associated.",
"RemediationProcedure": "**From Console:**1. Go to the `Events Service` page: [https://cloud.oracle.com/events/rules](https://cloud.oracle.com/events/rules)2. Select the `compartment` that should host the rule3. Click `Create Rule`4. Provide a `Display Name` and `Description`5. Create a Rule Condition by selecting `Identity` in the Service Name Drop-down and selecting `Idp Group Mapping Create`, `Idp Group Mapping Delete` and `Idp Group Mapping Update`6. In the `Actions` section select `Notifications` as Action Type7. Select the `Compartment` that hosts the Topic to be used.8. Select the `Topic` to be used9. Optionally add Tags to the Rule10. Click `Create Rule`**From CLI:**1. Find the `topic-id` of the topic the Event Rule should use for sending notifications by using the topic `name` and `Compartment OCID````oci ons topic list --compartment-id <compartment-ocid> --all --query data [?name=='<topic-name>'].{name:name,topic_id:\\topic-id\\} --output table```2. Create a JSON file to be used when creating the Event Rule. Replace topic id, display name, description and compartment OCID.```{ actions: { actions: [ { actionType: ONS, isEnabled: true, topicId: <topic-id> }] }, condition:{\\eventType\\:[\\com.oraclecloud.identitycontrolplane.addidpgroupmapping\\,\\com.oraclecloud.identitycontrolplane.removeidpgroupmapping\\,\\com.oraclecloud.identitycontrolplane.updateidpgroupmapping\\],\\data\\:{}}, displayName: <display-name>, description: <description>, isEnabled: true, compartmentId: <compartment-ocid>}```3. Create the actual event rule```oci events rule create --from-json file://event_rule.json```4. Note in the JSON returned that it lists the parameters specified in the JSON file provided and that there is an OCID provided for the Event Rule",
"AuditProcedure": "**From Console:**1. Go to the Events Service page: [https://cloud.oracle.com/events/rules](https://cloud.oracle.com/events/rules)2. Select the `Compartment` that hosts the rules3. Find and click the `Rule` that handles `Idp Group Mapping` Changes (if any)4. Ensure the `Rule` is `ACTIVE`5. Click the `Edit Rule` button and verify that the `RuleConditions` section contains a condition for the Service `Identity` and Event Types: `Idp Group Mapping Create`, `Idp Group Mapping Delete` and `Idp Group Mapping Update`6. Verify that in the `Actions` section the Action Type contains: `Notifications` and that a valid `Topic` is referenced.**From CLI:** 1. Find the OCID of the specific Event Rule based on Display Name and Compartment OCID```oci events rule list --compartment-id <compartment-ocid> --query data [?\\display-name\\=='<displa-name>'].{id:id} --output table```2. List the details of a specific Event Rule based on the OCID of the rule.```oci events rule get --rule-id <rule-id>```3. In the JSON output locate the Conditions key value pair and verify that the following Conditions are present:```com.oraclecloud.identitycontrolplane.addidpgroupmappingcom.oraclecloud.identitycontrolplane.removeidpgroupmappingcom.oraclecloud.identitycontrolplane.updateidpgroupmapping```4. Verify the value of the `is-enabled` attribute is `true`5. In the JSON output verify that `actionType` is `ONS` and locate the `topic-id`6. Verify the correct topic is used by checking the topic name```oci ons topic get --topic-id <topic-id> --query data.{name:name} --output table```",
"RemediationProcedure": "**From Console:**1. Go to the `Events Service` page: [https://cloud.oracle.com/events/rules](https://cloud.oracle.com/events/rules)2. Select the `compartment` that should host the rule3. Click `Create Rule`4. Provide a `Display Name` and `Description`5. Create a Rule Condition by selecting `Identity` in the Service Name Drop-down and selecting `Idp Group Mapping Add`, `Idp Group Mapping Remove` and `Idp Group Mapping Update`6. In the `Actions` section select `Notifications` as Action Type7. Select the `Compartment` that hosts the Topic to be used.8. Select the `Topic` to be used9. Optionally add Tags to the Rule10. Click `Create Rule`**From CLI:**1. Find the `topic-id` of the topic the Event Rule should use for sending notifications by using the topic `name` and `Compartment OCID````oci ons topic list --compartment-id <compartment-ocid> --all --query data [?name=='<topic-name>'].{name:name,topic_id:\\topic-id\\} --output table```2. Create a JSON file to be used when creating the Event Rule. Replace topic id, display name, description and compartment OCID.```{ actions: { actions: [ { actionType: ONS, isEnabled: true, topicId: <topic-id> }] }, condition:{\\eventType\\:[\\com.oraclecloud.identitycontrolplane.addidpgroupmapping\\,\\com.oraclecloud.identitycontrolplane.removeidpgroupmapping\\,\\com.oraclecloud.identitycontrolplane.updateidpgroupmapping\\],\\data\\:{}}, displayName: <display-name>, description: <description>, isEnabled: true, compartmentId: <compartment-ocid>}```3. Create the actual event rule```oci events rule create --from-json file://event_rule.json```4. Note in the JSON returned that it lists the parameters specified in the JSON file provided and that there is an OCID provided for the Event Rule",
"AuditProcedure": "**From Console:**1. Go to the Events Service page: [https://cloud.oracle.com/events/rules](https://cloud.oracle.com/events/rules)2. Select the `Compartment` that hosts the rules3. Find and click the `Rule` that handles `Idp Group Mapping` Changes (if any)4. Ensure the `Rule` is `ACTIVE`5. Click the `Edit Rule` button and verify that the `RuleConditions` section contains a condition for the Service `Identity` and Event Types: `Idp Group Mapping Add`, `Idp Group Mapping Remove` and `Idp Group Mapping Update`6. Verify that in the `Actions` section the Action Type contains: `Notifications` and that a valid `Topic` is referenced.**From CLI:** 1. Find the OCID of the specific Event Rule based on Display Name and Compartment OCID```oci events rule list --compartment-id <compartment-ocid> --query data [?\\display-name\\=='<displa-name>'].{id:id} --output table```2. List the details of a specific Event Rule based on the OCID of the rule.```oci events rule get --rule-id <rule-id>```3. In the JSON output locate the Conditions key value pair and verify that the following Conditions are present:```com.oraclecloud.identitycontrolplane.addidpgroupmappingcom.oraclecloud.identitycontrolplane.removeidpgroupmappingcom.oraclecloud.identitycontrolplane.updateidpgroupmapping```4. Verify the value of the `is-enabled` attribute is `true`5. In the JSON output verify that `actionType` is `ONS` and locate the `topic-id`6. Verify the correct topic is used by checking the topic name```oci ons topic get --topic-id <topic-id> --query data.{name:name} --output table```",
"AdditionalInformation": "'- The same Notification topic can be reused by many Event Rules.- The generated notification will include an eventID that can be used when querying the Audit Logs in case further investigation is required.",
"References": ""
}

View File

@@ -228,6 +228,28 @@ def print_categories(categories: set):
print(message)
def list_resource_groups(bulk_checks_metadata: dict) -> set:
available_resource_groups = set()
for check in bulk_checks_metadata.values():
if check.ResourceGroup:
available_resource_groups.add(check.ResourceGroup)
return available_resource_groups
def print_resource_groups(resource_groups: set):
rg_num = len(resource_groups)
plural_string = f"\nThere are {Fore.YELLOW}{rg_num}{Style.RESET_ALL} available resource groups.\n"
singular_string = (
f"\nThere is {Fore.YELLOW}{rg_num}{Style.RESET_ALL} available resource group.\n"
)
message = plural_string if rg_num > 1 else singular_string
for rg in sorted(resource_groups):
print(f"- {rg}")
print(message)
def print_services(service_list: set):
services_num = len(service_list)
plural_string = f"\nThere are {Fore.YELLOW}{services_num}{Style.RESET_ALL} available services.\n"

View File

@@ -19,6 +19,7 @@ def load_checks_to_execute(
severities: list = None,
compliance_frameworks: list = None,
categories: set = None,
resource_groups: set = None,
) -> set:
"""Generate the list of checks to execute based on the cloud provider and the input arguments given"""
try:
@@ -30,6 +31,7 @@ def load_checks_to_execute(
checks_to_execute = set()
check_aliases = {}
check_categories = {}
check_resource_groups = {}
check_severities = {severity.value: [] for severity in Severity}
if not bulk_checks_metadata:
@@ -52,6 +54,12 @@ def load_checks_to_execute(
if category not in check_categories:
check_categories[category] = []
check_categories[category].append(check)
# Resource Groups
if metadata.ResourceGroup:
if metadata.ResourceGroup not in check_resource_groups:
check_resource_groups[metadata.ResourceGroup] = []
check_resource_groups[metadata.ResourceGroup].append(check)
except Exception as error:
logger.error(
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
@@ -170,6 +178,25 @@ def load_checks_to_execute(
for category in categories:
checks_to_execute.update(check_categories[category])
# Handle if there are resource groups passed using --resource-group
elif resource_groups:
# Validate that all resource groups exist
available_resource_groups = set(check_resource_groups.keys())
invalid_resource_groups = [
rg for rg in resource_groups if rg not in available_resource_groups
]
if invalid_resource_groups:
logger.critical(
f"Invalid resource group(s) specified: {', '.join(invalid_resource_groups)}"
)
logger.critical(
f"Please provide valid resource group names. Use 'prowler {provider} --list-resource-groups' to see available resource groups."
)
sys.exit(1)
for resource_group in resource_groups:
checks_to_execute.update(check_resource_groups[resource_group])
# If there are no checks passed as argument
else:
# get all checks

View File

@@ -322,6 +322,12 @@ Detailed documentation at https://docs.prowler.com
default=[],
# TODO: Pending validate choices
)
group.add_argument(
"--resource-group",
nargs="+",
help="List of resource groups to be executed.",
default=[],
)
common_checks_parser.add_argument(
"--checks-folder",
"-x",
@@ -332,7 +338,7 @@ Detailed documentation at https://docs.prowler.com
def __init_list_checks_parser__(self):
# List checks options
list_checks_parser = self.common_providers_parser.add_argument_group(
"List checks/services/categories/compliance-framework checks"
"List checks/services/categories/resource-groups/compliance-framework checks"
)
list_group = list_checks_parser.add_mutually_exclusive_group()
list_group.add_argument(
@@ -365,6 +371,11 @@ Detailed documentation at https://docs.prowler.com
action="store_true",
help="List the available check's categories",
)
list_group.add_argument(
"--list-resource-groups",
action="store_true",
help="List the available check's resource groups",
)
list_group.add_argument(
"--list-fixer",
"--list-fixers",

View File

@@ -9,7 +9,7 @@
"Severity": "high",
"ResourceType": "EventRule",
"ResourceGroup": "messaging",
"Description": "**OCI Events rules** monitor **IdP group mapping changes** with **notification actions** for `com.oraclecloud.identitycontrolplane.createidpgroupmapping`, `com.oraclecloud.identitycontrolplane.deleteidpgroupmapping`, and `com.oraclecloud.identitycontrolplane.updateidpgroupmapping`.",
"Description": "**OCI Events rules** monitor **IdP group mapping changes** with **notification actions** for `com.oraclecloud.identitycontrolplane.addidpgroupmapping`, `com.oraclecloud.identitycontrolplane.removeidpgroupmapping`, and `com.oraclecloud.identitycontrolplane.updateidpgroupmapping`.",
"Risk": "Without **alerts** on IdP group mapping changes, federated users can gain unauthorized group memberships unnoticed, enabling **privilege escalation** and broader access to OCI resources. This undermines **confidentiality** and **integrity**, and may affect **availability** through misuse of elevated permissions.",
"RelatedUrl": "",
"AdditionalURLs": [
@@ -18,13 +18,13 @@
],
"Remediation": {
"Code": {
"CLI": "oci events rule create --compartment-id <COMPARTMENT_OCID> --display-name <example_resource_name> --is-enabled true --condition '{\"eventType\":[\"com.oraclecloud.identitycontrolplane.createidpgroupmapping\",\"com.oraclecloud.identitycontrolplane.deleteidpgroupmapping\",\"com.oraclecloud.identitycontrolplane.updateidpgroupmapping\"]}' --actions '{\"actions\":[{\"actionType\":\"ONS\",\"isEnabled\":true,\"topicId\":\"<TOPIC_OCID>\"}]}'",
"CLI": "oci events rule create --compartment-id <COMPARTMENT_OCID> --display-name <example_resource_name> --is-enabled true --condition '{\"eventType\":[\"com.oraclecloud.identitycontrolplane.addidpgroupmapping\",\"com.oraclecloud.identitycontrolplane.removeidpgroupmapping\",\"com.oraclecloud.identitycontrolplane.updateidpgroupmapping\"]}' --actions '{\"actions\":[{\"actionType\":\"ONS\",\"isEnabled\":true,\"topicId\":\"<TOPIC_OCID>\"}]}'",
"NativeIaC": "",
"Other": "1. In OCI Console, go to Observability & Management > Events Service > Rules\n2. Click Create rule\n3. Condition: add Event types:\n - com.oraclecloud.identitycontrolplane.createidpgroupmapping\n - com.oraclecloud.identitycontrolplane.deleteidpgroupmapping\n - com.oraclecloud.identitycontrolplane.updateidpgroupmapping\n4. Actions: Add action > Notifications (ONS) and select the target Topic\n5. Ensure Rule is Enabled and click Create",
"Terraform": "```hcl\nresource \"oci_events_rule\" \"<example_resource_name>\" {\n compartment_id = \"<example_resource_id>\"\n display_name = \"<example_resource_name>\"\n is_enabled = true\n\n condition = jsonencode({\n eventType = [\n \"com.oraclecloud.identitycontrolplane.createidpgroupmapping\", # critical: monitor IdP group mapping create\n \"com.oraclecloud.identitycontrolplane.deleteidpgroupmapping\", # critical: monitor IdP group mapping delete\n \"com.oraclecloud.identitycontrolplane.updateidpgroupmapping\" # critical: monitor IdP group mapping update\n ]\n })\n\n actions {\n actions {\n action_type = \"ONS\" # critical: adds notification action\n topic_id = \"<example_resource_id>\" # critical: ONS topic to notify\n is_enabled = true\n }\n }\n}\n```"
"Other": "1. In OCI Console, go to Observability & Management > Events Service > Rules\n2. Click Create rule\n3. Condition: add Event types:\n - com.oraclecloud.identitycontrolplane.addidpgroupmapping\n - com.oraclecloud.identitycontrolplane.removeidpgroupmapping\n - com.oraclecloud.identitycontrolplane.updateidpgroupmapping\n4. Actions: Add action > Notifications (ONS) and select the target Topic\n5. Ensure Rule is Enabled and click Create",
"Terraform": "```hcl\nresource \"oci_events_rule\" \"<example_resource_name>\" {\n compartment_id = \"<example_resource_id>\"\n display_name = \"<example_resource_name>\"\n is_enabled = true\n\n condition = jsonencode({\n eventType = [\n \"com.oraclecloud.identitycontrolplane.addidpgroupmapping\", # critical: monitor IdP group mapping add\n \"com.oraclecloud.identitycontrolplane.removeidpgroupmapping\", # critical: monitor IdP group mapping remove\n \"com.oraclecloud.identitycontrolplane.updateidpgroupmapping\" # critical: monitor IdP group mapping update\n ]\n })\n\n actions {\n actions {\n action_type = \"ONS\" # critical: adds notification action\n topic_id = \"<example_resource_id>\" # critical: ONS topic to notify\n is_enabled = true\n }\n }\n}\n```"
},
"Recommendation": {
"Text": "Define **Events rules** for IdP group mapping changes (`com.oraclecloud.identitycontrolplane.createidpgroupmapping`, `...deleteidpgroupmapping`, `...updateidpgroupmapping`) and route notifications to monitored channels via **OCI Notifications**. Apply **least privilege** and **separation of duties**, and integrate alerts with a SIEM for **defense in depth**.",
"Text": "Define **Events rules** for IdP group mapping changes (`com.oraclecloud.identitycontrolplane.addidpgroupmapping`, `...removeidpgroupmapping`, `...updateidpgroupmapping`) and route notifications to monitored channels via **OCI Notifications**. Apply **least privilege** and **separation of duties**, and integrate alerts with a SIEM for **defense in depth**.",
"Url": "https://hub.prowler.com/check/events_rule_idp_group_mapping_changes"
}
},

View File

@@ -15,17 +15,33 @@ class events_rule_idp_group_mapping_changes(Check):
"""Execute the events_rule_idp_group_mapping_changes check."""
findings = []
# Required event types for IdP group mapping changes
required_event_types = [
# OCI CIS 3.1 renamed create/delete to add/remove. Accept both to keep
# compatibility with rules that still use the legacy event names.
current_required_event_types = [
"com.oraclecloud.identitycontrolplane.addidpgroupmapping",
"com.oraclecloud.identitycontrolplane.removeidpgroupmapping",
"com.oraclecloud.identitycontrolplane.updateidpgroupmapping",
]
legacy_required_event_types = [
"com.oraclecloud.identitycontrolplane.createidpgroupmapping",
"com.oraclecloud.identitycontrolplane.deleteidpgroupmapping",
"com.oraclecloud.identitycontrolplane.updateidpgroupmapping",
]
# Filter rules that monitor IdP group mapping changes
matching_rules = filter_rules_by_event_types(
events_client.rules, required_event_types
)
matching_rules = []
seen_rule_ids = set()
for required_event_types in (
current_required_event_types,
legacy_required_event_types,
):
for rule, condition in filter_rules_by_event_types(
events_client.rules, required_event_types
):
rule_id = getattr(rule, "id", None) or id(rule)
if rule_id not in seen_rule_ids:
matching_rules.append((rule, condition))
seen_rule_ids.add(rule_id)
# Create findings for each matching rule
for rule, _ in matching_rules:

View File

@@ -40,6 +40,7 @@ class TestCheckLoader:
ResourceIdTemplate="arn:partition:s3:::bucket_name",
Severity=S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_SEVERITY,
ResourceType="AwsS3Bucket",
ResourceGroup="storage",
Description="Check S3 Bucket Level Public Access Block.",
Risk="Public access policies may be applied to sensitive data buckets.",
RelatedUrl="",
@@ -76,6 +77,7 @@ class TestCheckLoader:
ResourceIdTemplate="arn:partition:iam::account-id:user/user_name",
Severity=IAM_USER_NO_MFA_SEVERITY,
ResourceType="AwsIamUser",
ResourceGroup="IAM",
Description="Check IAM User No MFA.",
Risk="IAM users should have Multi-Factor Authentication (MFA) enabled.",
RelatedUrl="",
@@ -533,3 +535,79 @@ class TestCheckLoader:
provider=self.provider,
)
assert exc_info.value.code == 1
def test_load_checks_to_execute_with_resource_groups(self):
"""Test that checks are filtered by resource group"""
bulk_checks_metadata = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata(),
IAM_USER_NO_MFA_NAME: self.get_custom_check_iam_metadata(),
}
resource_groups = {"storage"}
assert {S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME} == load_checks_to_execute(
bulk_checks_metadata=bulk_checks_metadata,
resource_groups=resource_groups,
provider=self.provider,
)
def test_load_checks_to_execute_with_multiple_resource_groups(self):
"""Test that checks are filtered by multiple resource groups"""
bulk_checks_metadata = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata(),
IAM_USER_NO_MFA_NAME: self.get_custom_check_iam_metadata(),
}
resource_groups = {"storage", "IAM"}
assert {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME,
IAM_USER_NO_MFA_NAME,
} == load_checks_to_execute(
bulk_checks_metadata=bulk_checks_metadata,
resource_groups=resource_groups,
provider=self.provider,
)
def test_load_checks_to_execute_with_invalid_resource_group(self):
"""Test that invalid resource group names cause sys.exit(1)"""
bulk_checks_metadata = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
resource_groups = {"invalid_resource_group"}
with pytest.raises(SystemExit) as exc_info:
load_checks_to_execute(
bulk_checks_metadata=bulk_checks_metadata,
resource_groups=resource_groups,
provider=self.provider,
)
assert exc_info.value.code == 1
def test_load_checks_to_execute_with_multiple_invalid_resource_groups(self):
"""Test that multiple invalid resource group names cause sys.exit(1)"""
bulk_checks_metadata = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
resource_groups = {"invalid_rg_1", "invalid_rg_2"}
with pytest.raises(SystemExit) as exc_info:
load_checks_to_execute(
bulk_checks_metadata=bulk_checks_metadata,
resource_groups=resource_groups,
provider=self.provider,
)
assert exc_info.value.code == 1
def test_load_checks_to_execute_with_mixed_valid_invalid_resource_groups(self):
"""Test that mix of valid and invalid resource groups cause sys.exit(1)"""
bulk_checks_metadata = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
resource_groups = {"storage", "invalid_resource_group"}
with pytest.raises(SystemExit) as exc_info:
load_checks_to_execute(
bulk_checks_metadata=bulk_checks_metadata,
resource_groups=resource_groups,
provider=self.provider,
)
assert exc_info.value.code == 1

View File

@@ -81,6 +81,7 @@ class Test_Parser:
assert not parsed.severity
assert not parsed.compliance
assert len(parsed.category) == 0
assert len(parsed.resource_group) == 0
assert not parsed.excluded_check
assert not parsed.excluded_service
assert not parsed.excluded_checks_file
@@ -89,6 +90,7 @@ class Test_Parser:
assert not parsed.list_compliance
assert not parsed.list_compliance_requirements
assert not parsed.list_categories
assert not parsed.list_resource_groups
assert not parsed.profile
assert not parsed.role
assert parsed.session_duration == 3600
@@ -131,6 +133,7 @@ class Test_Parser:
assert not parsed.severity
assert not parsed.compliance
assert len(parsed.category) == 0
assert len(parsed.resource_group) == 0
assert not parsed.excluded_check
assert not parsed.excluded_service
assert not parsed.excluded_checks_file
@@ -139,6 +142,7 @@ class Test_Parser:
assert not parsed.list_compliance
assert not parsed.list_compliance_requirements
assert not parsed.list_categories
assert not parsed.list_resource_groups
assert len(parsed.subscription_id) == 0
assert not parsed.az_cli_auth
assert parsed.sp_env_auth
@@ -173,6 +177,7 @@ class Test_Parser:
assert not parsed.severity
assert not parsed.compliance
assert len(parsed.category) == 0
assert len(parsed.resource_group) == 0
assert not parsed.excluded_check
assert not parsed.excluded_service
assert not parsed.excluded_checks_file
@@ -181,6 +186,7 @@ class Test_Parser:
assert not parsed.list_compliance
assert not parsed.list_compliance_requirements
assert not parsed.list_categories
assert not parsed.list_resource_groups
assert not parsed.credentials_file
def test_default_parser_no_arguments_kubernetes(self):
@@ -210,6 +216,7 @@ class Test_Parser:
assert not parsed.severity
assert not parsed.compliance
assert len(parsed.category) == 0
assert len(parsed.resource_group) == 0
assert not parsed.excluded_check
assert not parsed.excluded_service
assert not parsed.excluded_checks_file
@@ -218,6 +225,7 @@ class Test_Parser:
assert not parsed.list_compliance
assert not parsed.list_compliance_requirements
assert not parsed.list_categories
assert not parsed.list_resource_groups
assert parsed.kubeconfig_file == "~/.kube/config"
assert not parsed.context
assert not parsed.namespace
@@ -723,6 +731,24 @@ class Test_Parser:
assert category_1 in parsed.category
assert category_2 in parsed.category
def test_checks_parser_resource_groups(self):
argument = "--resource-groups"
resource_group = "storage"
command = [prowler_command, argument, resource_group]
parsed = self.parser.parse(command)
assert len(parsed.resource_group) == 1
assert resource_group in parsed.resource_group
def test_checks_parser_resource_groups_two(self):
argument = "--resource-groups"
resource_group_1 = "storage"
resource_group_2 = "compute"
command = [prowler_command, argument, resource_group_1, resource_group_2]
parsed = self.parser.parse(command)
assert len(parsed.resource_group) == 2
assert resource_group_1 in parsed.resource_group
assert resource_group_2 in parsed.resource_group
def test_list_checks_parser_list_checks_short(self):
argument = "-l"
command = [prowler_command, argument]
@@ -759,6 +785,12 @@ class Test_Parser:
parsed = self.parser.parse(command)
assert parsed.list_categories
def test_list_checks_parser_list_resource_groups(self):
argument = "--list-resource-groups"
command = [prowler_command, argument]
parsed = self.parser.parse(command)
assert parsed.list_resource_groups
def test_list_checks_parser_list_fixers(self):
argument = "--list-fixers"
command = [prowler_command, argument]

View File

@@ -9,6 +9,102 @@ from tests.providers.oraclecloud.oci_fixtures import (
class Test_events_rule_idp_group_mapping_changes:
def test_current_cis_3_1_event_types_pass(self):
"""events_rule_idp_group_mapping_changes: current CIS 3.1 event types should pass."""
events_client = mock.MagicMock()
events_client.audited_compartments = {OCI_COMPARTMENT_ID: mock.MagicMock()}
events_client.audited_tenancy = OCI_TENANCY_ID
rule = mock.MagicMock()
rule.id = "ocid1.eventrule.oc1.iad.aaaaaaaexample"
rule.name = "idp-group-mapping-events"
rule.region = OCI_REGION
rule.compartment_id = OCI_COMPARTMENT_ID
rule.lifecycle_state = "ACTIVE"
rule.is_enabled = True
rule.condition = """
{
"eventType": [
"com.oraclecloud.identitycontrolplane.addidpgroupmapping",
"com.oraclecloud.identitycontrolplane.removeidpgroupmapping",
"com.oraclecloud.identitycontrolplane.updateidpgroupmapping"
]
}
"""
rule.actions = [{"action_type": "ONS", "is_enabled": True}]
events_client.rules = [rule]
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_oraclecloud_provider(),
),
mock.patch(
"prowler.providers.oraclecloud.services.events.events_rule_idp_group_mapping_changes.events_rule_idp_group_mapping_changes.events_client",
new=events_client,
),
):
from prowler.providers.oraclecloud.services.events.events_rule_idp_group_mapping_changes.events_rule_idp_group_mapping_changes import (
events_rule_idp_group_mapping_changes,
)
check = events_rule_idp_group_mapping_changes()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert result[0].resource_id == rule.id
assert result[0].resource_name == rule.name
def test_legacy_event_types_still_pass(self):
"""events_rule_idp_group_mapping_changes: legacy event types remain supported."""
events_client = mock.MagicMock()
events_client.audited_compartments = {OCI_COMPARTMENT_ID: mock.MagicMock()}
events_client.audited_tenancy = OCI_TENANCY_ID
rule = mock.MagicMock()
rule.id = "ocid1.eventrule.oc1.iad.bbbbbbbexample"
rule.name = "legacy-idp-group-mapping-events"
rule.region = OCI_REGION
rule.compartment_id = OCI_COMPARTMENT_ID
rule.lifecycle_state = "ACTIVE"
rule.is_enabled = True
rule.condition = """
{
"eventType": [
"com.oraclecloud.identitycontrolplane.createidpgroupmapping",
"com.oraclecloud.identitycontrolplane.deleteidpgroupmapping",
"com.oraclecloud.identitycontrolplane.updateidpgroupmapping"
]
}
"""
rule.actions = [{"action_type": "ONS", "is_enabled": True}]
events_client.rules = [rule]
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_oraclecloud_provider(),
),
mock.patch(
"prowler.providers.oraclecloud.services.events.events_rule_idp_group_mapping_changes.events_rule_idp_group_mapping_changes.events_client",
new=events_client,
),
):
from prowler.providers.oraclecloud.services.events.events_rule_idp_group_mapping_changes.events_rule_idp_group_mapping_changes import (
events_rule_idp_group_mapping_changes,
)
check = events_rule_idp_group_mapping_changes()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert result[0].resource_id == rule.id
assert result[0].resource_name == rule.name
def test_no_resources(self):
"""events_rule_idp_group_mapping_changes: No resources to check"""
events_client = mock.MagicMock()