mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-04-14 00:19:46 +00:00
Compare commits
9 Commits
chore/bump
...
PROWLER-12
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ab85c107b | ||
|
|
f58e9cfb0f | ||
|
|
814c2f59e6 | ||
|
|
d3ffb71a21 | ||
|
|
3f43f59d10 | ||
|
|
8e4c7c346f | ||
|
|
0aeb1eec15 | ||
|
|
2362ec0dc1 | ||
|
|
0ccc010e6d |
@@ -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)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
@@ -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": ""
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user