Skip to content

Commit

Permalink
Bug fixes - Cleanroom recovery action (demisto#36068) (demisto#36147)
Browse files Browse the repository at this point in the history
* Adding new action details in readme

* Bug fixes cleanroom action

* Bug Fixes - Cleanroom recovery action

* Readme changes for cleanroom recovery changes

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Update pack_metadata.json

* Update Packs/CommvaultSecurityIQ/README.md

---------

Co-authored-by: Cv-securityIQ <[email protected]>
Co-authored-by: barryyosi-panw <[email protected]>
  • Loading branch information
3 people authored Sep 5, 2024
1 parent efcc7e3 commit 2f64d93
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ class Constants:
source_webhook: str = "webhook"
source_fetch_incidents: str = "fetch"
description: str = "description"
max_vm_fetch: int = 1000
default_recovery_group_name: str = "APIRecoveryGroup"


def field_mapper(field_name: str, source: str = Constants.source_syslog) -> str:
Expand Down Expand Up @@ -441,10 +443,8 @@ def validate_session_or_generate_token(self, api_token: str) -> bool:
else:
current_epoch = int(datetime.now().timestamp())
token_expiry_from_last_generation = int(

self.access_token_last_generation
+ str(self.access_token_expiry_in_days * 7 * 24 * 60 * 60)

)
if current_epoch > token_expiry_from_last_generation:
demisto.debug("Token is expired, re-generating")
Expand Down Expand Up @@ -787,7 +787,7 @@ def get_incident_details(self, message: str) -> dict | None:
"originating_client": extract_from_regex(
message,
"",
fr"{field_mapper(Constants.originating_client)} \[(.*?)\]",
rf"{field_mapper(Constants.originating_client)} \[(.*?)\]",
),
"affected_files_count": if_zero_set_none(
extract_from_regex(
Expand Down Expand Up @@ -1132,7 +1132,12 @@ def list_recovery_target(self):
recovery_target_id = None
response = self.http_request("GET", "/V4/recoverytargets", None)
if response is not None and "recoveryTargets" in response:
recovery_target_id = response["recoveryTargets"][0]["id"]
targets = response["recoveryTargets"]
for current_target in targets:
# Always selecting first recovery target with application type CLEAN_ROOM
if current_target.get("applicationType") == "CLEAN_ROOM":
recovery_target_id = current_target["id"]
break
return recovery_target_id

def search_recovery_group(self, recovery_group_name):
Expand Down Expand Up @@ -1220,7 +1225,7 @@ def add_vm_to_recovery(
"client": {"id": vm_info["hypervisorId"]},
"recoveryPointDetails": {
"entityRecoveryPoint": recovery_point_timestamp,
"inheritedFrom": "RECOVERY_GROUP",
"inheritedFrom": "RECOVERY_ENTITY",
"entityRecoveryPointCategory": "POINT_IN_TIME",
},
"workload": 8,
Expand Down Expand Up @@ -1261,14 +1266,16 @@ def fetch_vm_details(self, vm_name):
and backupSetId. If the VM is not found, an empty dictionary is returned.
"""
vm_info = {}
response = self.http_request("GET", "/v4/virtualmachines")
headers = self.headers
headers["pagingInfo"] = f"0,{Constants.max_vm_fetch}"
response = self.http_request("GET", "/v4/virtualmachines", headers=headers)
if response is not None and "virtualMachines" in response:
vms = response["virtualMachines"]
for vm in vms:
current_vm_name = vm["name"].lower()
if current_vm_name == vm_name.lower():
demisto.info(f"Found VM [{current_vm_name}] ")
vm_info["vmName"] = current_vm_name
vm_info["vmName"] = vm_name
vm_info["vmGroupId"] = vm["vmGroup"]["id"]
vm_info["hypervisorId"] = vm["hypervisor"]["id"]
vm_info["vmGuid"] = vm["UUID"]
Expand All @@ -1292,13 +1299,15 @@ def get_point_in_time_timestamp(self, input_date):
dt = dt.replace(tzinfo=None)
epoch_time = int(dt.timestamp())
except Exception:
demisto.error("Invalid recovery point format. Use format dd:mm:yyyy hh:mm:ss")
demisto.error(
"Invalid recovery point format. Use format dd:mm:yyyy hh:mm:ss"
)
return epoch_time

def add_vm_to_recovery_group(self, vm_name, inpute_date):
point_in_time_ts = self.get_point_in_time_timestamp(inpute_date)
demisto.error(f"Point in time reference {point_in_time_ts}")
recovery_group_name = "APIRecoveryGroup"
recovery_group_name = Constants.default_recovery_group_name
target_id = self.list_recovery_target()
demisto.debug(f"Target Id {target_id}")
if target_id is not None:
Expand All @@ -1314,9 +1323,7 @@ def add_vm_to_recovery_group(self, vm_name, inpute_date):
):
return True
else:
raise Exception(
f"Add VM [{vm_name}] to recovery group failed."
)
raise Exception(f"Add VM [{vm_name}] to recovery group failed.")
else:
raise Exception("Recovery group is not available.")
else:
Expand Down Expand Up @@ -1691,7 +1698,9 @@ def main() -> None:
elif command == "commvault-security-set-cleanroom-add-vm-to-recovery-group":
vm_name = demisto.args().get("vm_name")
clean_recovery_point_time = demisto.args().get("clean_recovery_point")
return_results(add_vm_to_cleanroom(client, vm_name, clean_recovery_point_time))
return_results(
add_vm_to_cleanroom(client, vm_name, clean_recovery_point_time)
)
else:
raise NotImplementedError(f"Command '{command}' is not implemented.")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def http_request(
elif endpoint == "/Subclient/11351":
return {"subClientProperties": [{"content": []}]}
elif endpoint == "/V4/recoverytargets":
return {"recoveryTargets": [{"id": "123"}]}
return {"recoveryTargets": [{"id": "123", "applicationType": "CLEAN_ROOM"}]}
elif endpoint == "/recoverygroup/recid/entity":
return {"errorCode": 0, "errorMessage": ""}
elif endpoint == "/v4/virtualmachines":
Expand Down
15 changes: 8 additions & 7 deletions Packs/CommvaultSecurityIQ/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@


Introducing Commvault Security IQ integration pack for Commvault products. It enables security analysts swiftly respond to threats using pre-built integrations, playbooks to secure and audit backups and backup software ecosystem.
Introducing Commvault Cloud integration pack for Commvault products. It enables security analysts swiftly respond to threats using pre-built integrations, playbooks to secure and audit backups and backup software ecosystem.

With today's evolving threat landscape, data is under constant risk of data destruction and exfiltration. Organizations are challenged with responding to security events as quickly as they can to limit the impact of cyber threats on their production as well as backup data. This content pack allows organizations to monitor anomaly alerts from Commvault and Metallic data protection platforms, so they can respond with orchestrated actions to help fortify the data protection platform.
With today's evolving threat landscape, data is under constant risk of data destruction and exfiltration. Organizations are challenged with responding to security events as quickly as they can to limit the impact of cyber threats on their production as well as backup data. This content pack allows organizations to monitor anomaly alerts from Commvault Cloud data protection platforms, so they can respond with orchestrated actions to help fortify the data protection platform.

## Key features :

- Support for Commvault and Metallic
- Support for Commvault Cloud
- Suspicious file anomaly monitoring to indicate file encryption.
- Fetch Commvault and Metallic file anomaly alerts over API, Commvault Webhook, or Syslog
- Fetch Commvault Cloud file anomaly alerts over API, Commvault Webhook, or Syslog
- Native API token storage or Azure Key Vault token storage
- Ability to export and view list of infected files for investigation

## Automation Use cases:

- Disable data aging within Commvault/Metallic when server compromise is detected to protect backup data
- Interactive runbook to disable Commvault/Metallic user account if suspicious user behavior is detected to avoid exfiltration attempts.
- Interactive runbook to disable IDP provider configured for Commvault/Metallic user authentication to restrict access to backups in the event of a cyber incident to avoid exfiltration attempts.
- Disable data aging within Commvault Cloud when server compromise is detected to protect backup data.
- Interactive runbook to disable Commvault Cloud user account if suspicious user behavior is detected to avoid exfiltration attempts.
- Interactive runbook to disable IDP provider configured for Commvault Cloud user authentication to restrict access to backups in the event of a cyber incident to avoid exfiltration attempts.
- Add a VM to the Cleanroom using the nearest clean recovery point, identified based on the incident time, after a compromise is detected.
9 changes: 9 additions & 0 deletions Packs/CommvaultSecurityIQ/ReleaseNotes/1_1_1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

#### Integrations

##### Commvault Cloud

- Virtual Machines API not returning all the VMs.
- Use clean room-specific recovery group.
- Inherit entity rather than group to set point-in-time recovery epoch.
- Preserve VM name case while adding it to the clean room.
2 changes: 1 addition & 1 deletion Packs/CommvaultSecurityIQ/pack_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Commvault Cloud",
"description": "Commvault Cloud provides pre-built integrations, automation workflows, and playbooks to streamline operations, enhance threat intelligence integration, and gain actionable insights through advanced reporting and analytics.",
"support": "partner",
"currentVersion": "1.1.0",
"currentVersion": "1.1.1",
"author": "Commvault Systems",
"url": "https://www.commvault.com/support",
"email": "[email protected]",
Expand Down

0 comments on commit 2f64d93

Please sign in to comment.