AWSIdentifySGPublicExposure
Automation to determine which interface on an EC2 instance has a given public IP and identify associated security groups.
- Type
- python
- Pack
- CloudSecurityPolicyManagement
Source
import demistomock as demisto # noqa: F401
from CommonServerPython import * # noqa: F401
import traceback
def ec2_instance_info(
account_id: str, instance_id: str, public_ip: str, region: str, integration_instance: str
) -> tuple[str, list, str]:
"""
Finds interface with public_ip and from this creates interface ID/SG mapping
Args:
account_id (str): AWS Account ID
instance_id (str): EC2 Instance ID
public_ip (str): Public IP address of the EC2 instance
region (str): AWS Region where the instance is located
integration_instance (str): The AWS Integration Instance to use
Returns:
tuple: A tuple containing:
- The identified network interface
- List of its security groups
- The AWS integration instance used to retrieve the information
"""
cmd_args: dict[str, str] = {
"instance_ids": instance_id,
"region": region,
"account_id": account_id,
"using": integration_instance,
}
remove_nulls_from_dictionary(cmd_args)
result = demisto.executeCommand("aws-ec2-instances-describe", cmd_args)
instance_info = []
if result and len(result) > 1:
# If multiple entries were returned, such as when multiple AWS integration instances are configured,
# Identify the first entry with valid results.
for entry in result:
if not isError(entry):
instance_info = [entry]
break
else:
# If all entries are errors, use the first entry
instance_info = [result[0]]
else:
instance_info = result
if not instance_info:
raise DemistoException(
"Error retrieving instance network interface details with command 'aws-ec2-instances-describe'.\n"
"Error: No results returned."
)
if isError(instance_info):
raise DemistoException(
f"Error retrieving instance network interface details with command 'aws-ec2-instances-describe'.\n"
f"Error: {json.dumps(instance_info[0].get('Contents', ''))}"
)
interfaces = dict_safe_get(instance_info, (0, "Contents", "Reservations", 0, "Instances", 0, "NetworkInterfaces"))
instance_to_use = dict_safe_get(instance_info, (0, "Metadata", "instance"))
if interfaces:
for interface in interfaces:
if interface.get("Association") and interface.get("Association").get("PublicIp") == public_ip:
group_list = []
for sg in interface.get("Groups", []):
group_list.append(sg.get("GroupId", ""))
return interface.get("NetworkInterfaceId", ""), group_list, instance_to_use
# Raise an error if no interface was found with the given public IP
raise ValueError("Unable to find interface associated with the given public IP address.")
def identify_sgs(args: dict[str, str]) -> CommandResults:
"""
Main command that determines what EC2 network interface has a given public IP address and lists its security groups.
Args:
args (Dict[str, Any]): Demisto.args() object
Returns:
CommandResults: Demisto CommandResults object containing:
- EC2InstanceID: The original EC2 instance ID
- NetworkInterfaceID: The network interface ID
- PublicIP: The public IP address
- SecurityGroups: List of associated security group IDs
"""
account_id = args["account_id"]
instance_id = args["instance_id"]
public_ip = args["public_ip"]
region = args["region"]
integration_instance = args.get("integration_instance", "")
ec2_interface, sg_list, instance_to_use = ec2_instance_info(account_id, instance_id, public_ip, region, integration_instance)
outputs = {
"EC2InstanceID": instance_id,
"NetworkInterfaceID": ec2_interface,
"PublicIP": public_ip,
"SecurityGroups": sg_list,
"IntegrationInstance": instance_to_use,
}
readable_output = (
f"EC2 instance {instance_id} has public IP {public_ip} on ENI {ec2_interface}:\n"
f"Associated Security Groups: {', '.join(sg_list)}."
)
return CommandResults(
readable_output=readable_output,
outputs_key_field="EC2InstanceID",
outputs=outputs,
outputs_prefix="AWSPublicExposure.SGAssociations",
raw_response=outputs,
)
def main():
try:
return_results(identify_sgs(demisto.args()))
except Exception as ex:
demisto.error(traceback.format_exc()) # print the traceback
return_error(f"Failed to execute AWSIdentifySGPublicExposure. Error: {str(ex)}")
if __name__ in ("__main__", "__builtin__", "builtins"):
main()
README
Automation to determine which interface on an EC2 instance has a given public IP and identify associated security groups.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Cortex XSOAR Version | 6.10.0 |
Dependencies
This script uses the following commands and scripts.
- AWS
- aws-ec2-instances-describe
Inputs
| Argument Name | Description |
|---|---|
| account_id | The AWS Account ID. |
| instance_id | EC2 Instance ID. |
| public_ip | Public IP address whose network interface to identify. |
| region | Region where EC2 instance resides. |
| integration_instance | The AWS Integration Instance to use. |
Outputs
| Path | Description | Type |
|---|---|---|
| AWSPublicExposure.SGAssociations.EC2InstanceID | ID of the EC2 instance with public exposure. | String |
| AWSPublicExposure.SGAssociations.NetworkInterfaceID | ID of the Elastic Network Interface with public exposure. | String |
| AWSPublicExposure.SGAssociations.SecurityGroups | Security Group IDs associated with this interface. | Unknown |
| AWSPublicExposure.SGAssociations.PublicIP | Public IP address exposed. | String |
| AWSPublicExposure.SGAssociations.IntegrationInstance | The AWS Integration Instance used for identification. | String |