From b71c3069e2070f1ea1f52ea1d4e93a11143f7cc8 Mon Sep 17 00:00:00 2001 From: content-bot <55035720+content-bot@users.noreply.github.com> Date: Tue, 3 Oct 2023 12:41:38 +0300 Subject: [PATCH] AWS EXPANDR-6233 (#29840) (#30002) * update script * update play * RN * fix RN * Apply suggestions from code review * docker update * clean README * add predefined regions --------- Co-authored-by: johnnywilkes <32227961+johnnywilkes@users.noreply.github.com> Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com> Co-authored-by: Michael Yochpaz <8832013+MichaelYochpaz@users.noreply.github.com> --- .../AWS_-_Security_Group_Remediation_v2.yml | 28 +++++++++------- ..._-_Security_Group_Remediation_v2_README.md | 3 +- .../ReleaseNotes/1_1_5.md | 13 ++++++++ .../Scripts/AWSRecreateSG/AWSRecreateSG.py | 32 ++++++++++++++----- .../Scripts/AWSRecreateSG/AWSRecreateSG.yml | 26 ++++++++++++++- .../AWSRecreateSG/AWSRecreateSG_test.py | 7 ++-- .../Scripts/AWSRecreateSG/README.md | 21 ++++++++---- .../pack_metadata.json | 2 +- 8 files changed, 101 insertions(+), 31 deletions(-) create mode 100644 Packs/AWS-Enrichment-Remediation/ReleaseNotes/1_1_5.md diff --git a/Packs/AWS-Enrichment-Remediation/Playbooks/AWS_-_Security_Group_Remediation_v2.yml b/Packs/AWS-Enrichment-Remediation/Playbooks/AWS_-_Security_Group_Remediation_v2.yml index d8c8a1515653..c63ad8d245a0 100644 --- a/Packs/AWS-Enrichment-Remediation/Playbooks/AWS_-_Security_Group_Remediation_v2.yml +++ b/Packs/AWS-Enrichment-Remediation/Playbooks/AWS_-_Security_Group_Remediation_v2.yml @@ -1,7 +1,5 @@ id: AWS - Security Group Remediation v2 version: -1 -contentitemexportablefields: - contentitemfields: {} name: AWS - Security Group Remediation v2 description: |- This playbook takes in some information about an EC2 instance (ID and public_ip) and with provided port and protocol, determines what security groups on the primary interface of an EC2 instance are over-permissive. It uses an automation to determine what interface on an EC2 instance has an over-permissive security group on, determine which security groups have over-permissive rules and to replace them with a copy of the security group that has only the over-permissive portion removed. Over-permissive is defined as sensitive ports (SSH, RDP, etc) being exposed to the internet via IPv4. @@ -9,10 +7,10 @@ starttaskid: "0" tasks: "0": id: "0" - taskid: 887ec5b3-a4d7-47fc-82b0-701e072c0deb + taskid: 7aeccd71-8a2e-47a8-8ba0-b91bac919bf4 type: start task: - id: 887ec5b3-a4d7-47fc-82b0-701e072c0deb + id: 7aeccd71-8a2e-47a8-8ba0-b91bac919bf4 version: -1 name: "" iscommand: false @@ -39,10 +37,10 @@ tasks: isautoswitchedtoquietmode: false "2": id: "2" - taskid: 978b630a-7e00-443b-83f3-5e683144863a + taskid: 57209409-3b96-48f9-865d-61de73bd6309 type: title task: - id: 978b630a-7e00-443b-83f3-5e683144863a + id: 57209409-3b96-48f9-865d-61de73bd6309 version: -1 name: Done type: title @@ -67,10 +65,10 @@ tasks: isautoswitchedtoquietmode: false "31": id: "31" - taskid: e71350f2-0f75-41e1-841d-ee3c938fc23f + taskid: fe8c7803-f99e-4ee6-8481-fa710b622cd7 type: condition task: - id: e71350f2-0f75-41e1-841d-ee3c938fc23f + id: fe8c7803-f99e-4ee6-8481-fa710b622cd7 version: -1 name: Is AWS - EC2 enabled and are input values defined? description: Determines if the AWS - EC2 integration instance is configured and input values are defined in order to continue with remediating security groups. @@ -152,10 +150,10 @@ tasks: isautoswitchedtoquietmode: false "32": id: "32" - taskid: 193a8c2a-b241-47af-8e26-16eb37674369 + taskid: d2488b84-78ba-4f31-8b35-c47e61425dd9 type: regular task: - id: 193a8c2a-b241-47af-8e26-16eb37674369 + id: d2488b84-78ba-4f31-8b35-c47e61425dd9 version: -1 name: Create Security Group automation description: Automation to determine what interface on an EC2 instance has an over-permissive security group on, determine which security groups have over-permissive rules and to replace them with a copy of the security group that has only the over-permissive portion removed. Over-permissive is defined as sensitive ports (SSH, RDP, etc) being exposed to the internet via IPv4. @@ -182,6 +180,9 @@ tasks: public_ip: complex: root: inputs.PublicIP + region: + complex: + root: inputs.Region separatecontext: false continueonerrortype: "" view: |- @@ -234,7 +235,7 @@ inputs: complex: root: alert accessor: remoteip - required: false + required: true description: Public IP address of the EC2 instance. playbookInputQuery: - key: AWSAssumeArn @@ -242,6 +243,11 @@ inputs: required: false description: Name of an AWS role to assume (should be the same for all organizations). playbookInputQuery: +- key: Region + value: {} + required: false + description: Region where EC2 instance is present. + playbookInputQuery: outputs: [] tests: - No tests (auto formatted) diff --git a/Packs/AWS-Enrichment-Remediation/Playbooks/AWS_-_Security_Group_Remediation_v2_README.md b/Packs/AWS-Enrichment-Remediation/Playbooks/AWS_-_Security_Group_Remediation_v2_README.md index d25da1ff41e8..1188957180f3 100644 --- a/Packs/AWS-Enrichment-Remediation/Playbooks/AWS_-_Security_Group_Remediation_v2_README.md +++ b/Packs/AWS-Enrichment-Remediation/Playbooks/AWS_-_Security_Group_Remediation_v2_README.md @@ -29,8 +29,9 @@ This playbook does not use any commands. | InstanceID | ID of the AWS EC2 instance. | | Required | | Port | TCP/UDP port to be restricted. | alert.remoteport | Required | | Protocol | Protocol of the port to be restricted. | | Required | -| PublicIP | Public IP address of the EC2 instance. | alert.remoteip | Optional | +| PublicIP | Public IP address of the EC2 instance. | alert.remoteip | Required | | AWSAssumeArn | Name of an AWS role to assume \(should be the same for all organizations\). | | Optional | +| Region | Region where EC2 instance is present. | | Optional | ## Playbook Outputs diff --git a/Packs/AWS-Enrichment-Remediation/ReleaseNotes/1_1_5.md b/Packs/AWS-Enrichment-Remediation/ReleaseNotes/1_1_5.md new file mode 100644 index 000000000000..7c06a0575acd --- /dev/null +++ b/Packs/AWS-Enrichment-Remediation/ReleaseNotes/1_1_5.md @@ -0,0 +1,13 @@ + +#### Playbooks + +##### AWS - Security Group Remediation v2 + +Updated the playbook to include the **Region** input in the **AWSRecreateSG** script. + +#### Scripts + +##### AWSRecreateSG + +- Added the **Region** input to specify the region to run AWS commands. +- Updated the Docker image to: *demisto/python3:3.10.13.75921*. diff --git a/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG.py b/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG.py index 268d569f89ca..45b4337e1439 100644 --- a/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG.py +++ b/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG.py @@ -57,7 +57,7 @@ def split_rule(rule: dict, port: int, protocol: str) -> list[dict]: return (res_list) -def sg_fix(sg_info: list, port: int, protocol: str, assume_role: str, instance_to_use: str) -> dict: +def sg_fix(sg_info: list, port: int, protocol: str, assume_role: str, instance_to_use: str, region: str) -> dict: """ For a SG determine what needs to be recreated. Calls split_rule() if there are rules with ranges of ports to be split up @@ -118,6 +118,8 @@ def sg_fix(sg_info: list, port: int, protocol: str, assume_role: str, instance_t cmd_args = {"groupName": new_name, "vpcId": info['VpcId'], "description": description, "using": instance_to_use} if assume_role: cmd_args.update({'roleArn': assume_role, 'roleSessionName': ROLE_SESSION_NAME}) + if region: + cmd_args.update({'region': region}) new_sg = demisto.executeCommand("aws-ec2-create-security-group", cmd_args) if isError(new_sg): raise ValueError('Error on creating new security group') @@ -126,6 +128,8 @@ def sg_fix(sg_info: list, port: int, protocol: str, assume_role: str, instance_t cmd_args = {"groupId": new_id, "IpPermissionsFull": item, "using": instance_to_use} if assume_role: cmd_args.update({'roleArn': assume_role, 'roleSessionName': ROLE_SESSION_NAME}) + if region: + cmd_args.update({'region': region}) res = demisto.executeCommand("aws-ec2-authorize-security-group-ingress-rule", cmd_args) if isError(res): @@ -144,6 +148,8 @@ def sg_fix(sg_info: list, port: int, protocol: str, assume_role: str, instance_t cmd_args = {"groupId": new_id, "IpPermissionsFull": e_format, "using": instance_to_use} if assume_role: cmd_args.update({'roleArn': assume_role, 'roleSessionName': ROLE_SESSION_NAME}) + if region: + cmd_args.update({'region': region}) res = demisto.executeCommand("aws-ec2-authorize-security-group-egress-rule", cmd_args) # Don't error if the message is that the rule already exists. @@ -159,6 +165,8 @@ def sg_fix(sg_info: list, port: int, protocol: str, assume_role: str, instance_t cmd_args = {"groupId": new_id, "IpPermissionsFull": all_traffic_rule, "using": instance_to_use} if assume_role: cmd_args.update({'roleArn': assume_role, 'roleSessionName': ROLE_SESSION_NAME}) + if region: + cmd_args.update({'region': region}) res = demisto.executeCommand("aws-ec2-revoke-security-group-egress-rule", cmd_args) if isError(res): @@ -166,7 +174,7 @@ def sg_fix(sg_info: list, port: int, protocol: str, assume_role: str, instance_t return {'new-sg': new_id} -def replace_sgs(replace_list: list, int_sg_mapping: dict, assume_role: str, instance_to_use: str): +def replace_sgs(replace_list: list, int_sg_mapping: dict, assume_role: str, instance_to_use: str, region: str): """ Replace the actual SGs on the interface @@ -185,13 +193,16 @@ def replace_sgs(replace_list: list, int_sg_mapping: dict, assume_role: str, inst cmd_args = {"networkInterfaceId": entry['int'], "groups": formatted_list, "using": instance_to_use} if assume_role: cmd_args.update({'roleArn': assume_role, 'roleSessionName': ROLE_SESSION_NAME}) + if region: + cmd_args.update({'region': region}) res = demisto.executeCommand("aws-ec2-modify-network-interface-attribute", cmd_args) if isError(res): raise ValueError('Error on replacing security group(s) on network interface') -def determine_excessive_access(int_sg_mapping: dict, port: int, protocol: str, assume_role: str, instance_to_use: str) -> list: +def determine_excessive_access(int_sg_mapping: dict, port: int, protocol: str, assume_role: str, instance_to_use: str, + region: str) -> list: """ Pulls info on each SG and then calls sg_fix() to actually create the new SGs @@ -208,13 +219,15 @@ def determine_excessive_access(int_sg_mapping: dict, port: int, protocol: str, a for mapping in int_sg_mapping: for sg in int_sg_mapping[mapping]: cmd_args = {"groupIds": sg, "using": instance_to_use} + if region: + cmd_args.update({'region': region}) if assume_role: cmd_args.update({'roleArn': assume_role, 'roleSessionName': ROLE_SESSION_NAME}) sg_info = demisto.executeCommand("aws-ec2-describe-security-groups", cmd_args) if isError(sg_info): raise ValueError('Error on describing security group') elif sg_info: - res = sg_fix(sg_info, port, protocol, assume_role, instance_to_use) + res = sg_fix(sg_info, port, protocol, assume_role, instance_to_use, region) # Need interface, old sg and new sg. if res.get('new-sg'): res['old-sg'] = sg @@ -223,7 +236,7 @@ def determine_excessive_access(int_sg_mapping: dict, port: int, protocol: str, a return replace_list -def instance_info(instance_id: str, public_ip: str, assume_role: str) -> tuple[dict, str]: +def instance_info(instance_id: str, public_ip: str, assume_role: str, region: str) -> tuple[dict, str]: """ Finds interface with public_ip and from this creates interface ID/SG mapping @@ -235,6 +248,8 @@ def instance_info(instance_id: str, public_ip: str, assume_role: str) -> tuple[d tuple[dict, str]: A dictionary mapping interfaces to security groups (dict), and an integration to use (str). """ cmd_args = {"instanceIds": instance_id} + if region: + cmd_args.update({'region': region}) if assume_role: cmd_args.update({'roleArn': assume_role, 'roleSessionName': ROLE_SESSION_NAME}) instance_info = demisto.executeCommand("aws-ec2-describe-instances", cmd_args) @@ -282,17 +297,18 @@ def aws_recreate_sg(args: dict[str, Any]) -> str: protocol = args.get('protocol', None) public_ip = args.get('public_ip', None) assume_role = args.get('assume_role', None) + region = args.get('region', None) if not instance_id or not port or not protocol or not public_ip: raise ValueError('instance_id, port, protocol and public_ip all need to be specified') # Determine interface with public IP and associated SGs. - int_sg_mapping, instance_to_use = instance_info(instance_id, public_ip, assume_role) + int_sg_mapping, instance_to_use = instance_info(instance_id, public_ip, assume_role, region) # Determine what SGs are overpermissive for particular port. - replace_list = determine_excessive_access(int_sg_mapping, port, protocol, assume_role, instance_to_use) + replace_list = determine_excessive_access(int_sg_mapping, port, protocol, assume_role, instance_to_use, region) if len(replace_list) == 0: raise ValueError('No security groups were found to need to be replaced') - replace_sgs(replace_list, int_sg_mapping, assume_role, instance_to_use) + replace_sgs(replace_list, int_sg_mapping, assume_role, instance_to_use, region) display_message = f"For interface {replace_list[0]['int']}: \r\n" for replace in replace_list: display_message += f"replaced SG {replace['old-sg']} with {replace['new-sg']} \r\n" diff --git a/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG.yml b/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG.yml index 1952cb16710b..d66b4f6adafa 100644 --- a/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG.yml +++ b/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG.yml @@ -17,6 +17,28 @@ args: required: true - description: Name of an AWS role to assume (should be the same for all organizations). name: assume_role +- description: Region where EC2 instance is present. + name: region + auto: PREDEFINED + predefined: + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + - ca-central-1 + - eu-west-1 + - eu-central-1 + - eu-west-2 + - ap-northeast-1 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-south-1 + - sa-east-1 + - eu-north-1 + - eu-west-3 + - us-gov-east-1 + - us-gov-west-1 comment: Automation to determine which interface on an EC2 instance has an over-permissive security group, determine which security groups have over-permissive rules, and replace them with a copy of the security group that has only the over-permissive portion removed. Over-permissive is defined as sensitive ports (SSH, RDP, etc) being exposed to the internet via IPv4. commonfields: id: AWSRecreateSG @@ -29,7 +51,7 @@ dependson: - AWS - EC2|||aws-ec2-authorize-security-group-egress-rule - AWS - EC2|||aws-ec2-revoke-security-group-ingress-rule - AWS - EC2|||aws-ec2-revoke-security-group-egress-rule -dockerimage: demisto/python3:3.10.13.73190 +dockerimage: demisto/python3:3.10.13.75921 enabled: true name: AWSRecreateSG runas: DBotWeakRole @@ -41,3 +63,5 @@ type: python fromversion: 6.5.0 tests: - No tests (auto formatted) +engineinfo: {} +runonce: false diff --git a/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG_test.py b/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG_test.py index 3ad25965cfa3..0dafcf37cb4c 100644 --- a/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG_test.py +++ b/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/AWSRecreateSG_test.py @@ -51,7 +51,7 @@ def test_instance_info(mocker): from AWSRecreateSG import instance_info from test_data.sample import INSTANCE_INFO mocker.patch.object(demisto, "executeCommand", return_value=INSTANCE_INFO) - args = {"instance_id": "fake-instance-id", "public_ip": "1.1.1.1", "assume_role": "test_role"} + args = {"instance_id": "fake-instance-id", "public_ip": "1.1.1.1", "assume_role": "test_role", "region": "us-east-1"} result = instance_info(**args) assert result == ({'eni-00000000000000000': ['sg-00000000000000000']}, 'AWS - EC2') @@ -70,7 +70,8 @@ def test_sg_fix(mocker): from test_data.sample import SG_INFO new_sg = [{'Type': 1, 'Contents': {'AWS.EC2.SecurityGroups': {'GroupId': 'sg-00000000000000001'}}}] mocker.patch.object(demisto, "executeCommand", return_value=new_sg) - args = {"sg_info": SG_INFO, "port": 22, "protocol": "tcp", "assume_role": "test_role", "instance_to_use": "AWS - EC2"} + args = {"sg_info": SG_INFO, "port": 22, "protocol": "tcp", "assume_role": "test_role", "instance_to_use": "AWS - EC2", + "region": "us-east-1"} result = sg_fix(**args) assert result == {'new-sg': 'sg-00000000000000001'} @@ -98,7 +99,7 @@ def executeCommand(name, args): mocker.patch.object(demisto, "executeCommand", side_effect=executeCommand) args = {"int_sg_mapping": {'eni-00000000000000000': ['sg-00000000000000000']}, "port": 22, - "protocol": "tcp", "assume_role": "test_role", "instance_to_use": "AWS - EC2"} + "protocol": "tcp", "assume_role": "test_role", "instance_to_use": "AWS - EC2", "region": "us-east-1"} result = determine_excessive_access(**args) assert result == [{'int': 'eni-00000000000000000', 'old-sg': 'sg-00000000000000000', 'new-sg': 'sg-00000000000000001'}] diff --git a/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/README.md b/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/README.md index c6b7203c5db3..49be913678f5 100644 --- a/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/README.md +++ b/Packs/AWS-Enrichment-Remediation/Scripts/AWSRecreateSG/README.md @@ -1,4 +1,4 @@ -Automation to determine what interface on an EC2 instance has an over-permissive security group on, determine which security groups have over-permissive rules and to replace them with a copy of the security group that has only the over-permissive portion removed. Over-permissive is defined as sensitive ports (SSH, RDP, etc) being exposed to the internet via IPv4. +Automation to determine which interface on an EC2 instance has an over-permissive security group, determine which security groups have over-permissive rules and replace them with a copy of the security group that has only the over-permissive portion removed. Over-permissive is defined as sensitive ports (SSH, RDP, etc.) being exposed to the internet via IPv4. ## Script Data @@ -7,18 +7,26 @@ Automation to determine what interface on an EC2 instance has an over-permissive | **Name** | **Description** | | --- | --- | | Script Type | python3 | +| Cortex XSOAR Version | 6.5.0 | ## Dependencies --- This script uses the following commands and scripts. -* aws-ec2-create-security-group -* aws-ec2-authorize-security-group-ingress-rule * aws-ec2-revoke-security-group-egress-rule +* aws-ec2-authorize-security-group-ingress-rule * aws-ec2-authorize-security-group-egress-rule -* aws-ec2-revoke-security-group-ingress-rule * aws-ec2-describe-instances +* aws-ec2-revoke-security-group-ingress-rule +* aws-ec2-create-security-group + +## Used In + +--- +This script is used in the following playbooks and scripts. + +* AWS - Security Group Remediation v2 ## Inputs @@ -27,10 +35,11 @@ This script uses the following commands and scripts. | **Argument Name** | **Description** | | --- | --- | | instance_id | EC2 Instance ID. | -| port | TCP/UDP Port to be restricted. | +| port | TCP/UDP port to be restricted. | | protocol | Protocol of the port to be restricted. | | public_ip | Public IP address of the EC2 instance. | -| assume_role | If assuming roles for AWS, this is the name of the role to assume (should be the same for all organizations). | +| assume_role | Name of an AWS role to assume \(should be the same for all organizations\). | +| region | Region where EC2 instance is present. | ## Outputs diff --git a/Packs/AWS-Enrichment-Remediation/pack_metadata.json b/Packs/AWS-Enrichment-Remediation/pack_metadata.json index 4b873348641a..7c5d5a2d759f 100644 --- a/Packs/AWS-Enrichment-Remediation/pack_metadata.json +++ b/Packs/AWS-Enrichment-Remediation/pack_metadata.json @@ -2,7 +2,7 @@ "name": "AWS Enrichment and Remediation", "description": "Playbooks using multiple AWS content packs for enrichment and remediation purposes", "support": "xsoar", - "currentVersion": "1.1.4", + "currentVersion": "1.1.5", "author": "Cortex XSOAR", "url": "https://www.paloaltonetworks.com/cortex", "email": "",