From 0d83349eb826f2711f0c3e01a3691026d34dbda7 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 10 Jan 2025 16:12:47 +0000
Subject: [PATCH 1/4] chore(deps): update actions/upload-artifact action to
 v4.6.0

---
 .github/workflows/scorecards.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index b7746599..069c2820 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -63,7 +63,7 @@ jobs:
       # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
       # format to the repository Actions tab.
       - name: "Upload artifact"
-        uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
+        uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
         with:
           name: SARIF file
           path: results.sarif

From 77ef96ab6d118d022b454acb4939210c149b521b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D2=89=CE=B1k=CE=B1=20x=E2=A0=A0=E2=A0=B5?=
 <32862241+4k4xs4pH1r3@users.noreply.github.com>
Date: Mon, 13 Jan 2025 21:30:54 -0500
Subject: [PATCH 2/4] Create aws_sg_ec2_add_new_entries.py
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: ҉αkα x⠠⠵ <32862241+4k4xs4pH1r3@users.noreply.github.com>
---
 AWS/aws_sg_ec2_add_new_entries.py | 385 ++++++++++++++++++++++++++++++
 1 file changed, 385 insertions(+)
 create mode 100644 AWS/aws_sg_ec2_add_new_entries.py

diff --git a/AWS/aws_sg_ec2_add_new_entries.py b/AWS/aws_sg_ec2_add_new_entries.py
new file mode 100644
index 00000000..4ffe85c7
--- /dev/null
+++ b/AWS/aws_sg_ec2_add_new_entries.py
@@ -0,0 +1,385 @@
+import boto3
+import ipaddress
+import socket
+import threading
+from ports import ports_to_open
+
+# --- Global Variables and Aliases ---
+ec2 = None  # Initialize ec2 client globally
+dry_run = False  # Set dry_run globally
+
+# Global dictionary to store reachability test results
+port_reachability_results = {}
+
+
+# def test_port_reachability(instance_ip, port, protocol, results):
+#     """Tests if a specific port is reachable from the internet."""
+#     try:
+#         if protocol == 'tcp':
+#             with socket.create_connection((instance_ip, port), timeout=5) as sock:
+#                 results[(port, protocol)] = True
+#         elif protocol == 'udp':
+#             with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
+#                 sock.settimeout(5)
+#                 sock.sendto(b'', (instance_ip, port))
+#                 try:
+#                     sock.recvfrom(1024)
+#                     results[(port, protocol)] = True
+#                 except socket.timeout:
+#                     results[(port, protocol)] = False
+#         else:
+#             results[(port, protocol)] = False
+#     except Exception as e:
+#         print(f"Error testing reachability for {instance_ip}:{port}/{protocol}: {e}")
+#         results[(port, protocol)] = False
+
+
+def add_inbound_rules_to_security_groups(region_name, instance_ids, allowed_cidrs):
+    """
+    Adds inbound rules to the security groups of specified EC2 instances.
+    Handles RulesPerSecurityGroupLimitExceeded by consolidating rules or
+    creating a new security group.
+    Adds exception handling for creating duplicate security groups.
+    Identifies and removes rules that allow traffic from an Internet Gateway on specific TCP ports.
+
+    Args:
+        region_name: The AWS region where the instances are located.
+        instance_ids: A list of EC2 instance IDs.
+        allowed_cidrs: A list of allowed source CIDR ranges.
+    """
+
+    global ec2
+    ec2 = boto3.client('ec2', region_name=region_name)
+
+    try:
+        # Get information about the instances
+        response = ec2.describe_instances(InstanceIds=instance_ids)
+
+        for reservation in response['Reservations']:
+            for instance in reservation['Instances']:
+                instance_id = instance['InstanceId']
+                instance_ip = instance.get('PublicIpAddress')  # Get the public IP if available
+                print(f"Processing instance: {instance_id} (Public IP: {instance_ip})")
+
+                # Get the security groups associated with the instance
+                security_groups = instance['SecurityGroups']
+
+                for sg in security_groups:
+                    sg_id = sg['GroupId']
+                    sg_name = sg['GroupName']
+                    print(f"  Processing security group: {sg_name} ({sg_id})")
+
+                    # Describe existing inbound rules for the security group
+                    sg_response = ec2.describe_security_group_rules(
+                        Filters=[
+                            {'Name': 'group-id', 'Values': [sg_id]}
+                        ]
+                    )
+
+                    existing_rules = sg_response['SecurityGroupRules']
+
+                    # Test port reachability before modifying rules
+                    # if instance_ip:
+                    #     threads = []
+                    #     for port_info in ports_to_open:
+                    #         port = port_info['Port']
+                    #         protocol = port_info['Protocol']
+                    #         if isinstance(port, list):
+                    #             for p in range(port[0], port[1] + 1):
+                    #                 thread = threading.Thread(target=test_port_reachability,
+                    #                                           args=(instance_ip, p, protocol, port_reachability_results))
+                    #                 threads.append(thread)
+                    #                 thread.start()
+                    #         else:
+                    #             thread = threading.Thread(target=test_port_reachability,
+                    #                                       args=(instance_ip, port, protocol, port_reachability_results))
+                    #             threads.append(thread)
+                    #             thread.start()
+
+                    #     for thread in threads:
+                    #         thread.join()
+
+                    # Identify and remove rules allowing traffic from an Internet Gateway on specific TCP ports
+                    # rules_to_remove = []
+                    # for rule in existing_rules:
+                    #     if rule['IpProtocol'] == 'tcp' or rule['IpProtocol'] == 'udp':
+                    #         port_range = list(range(rule['FromPort'], rule['ToPort'] + 1)) if rule.get('FromPort') and rule.get('ToPort') and rule['FromPort'] != rule['ToPort'] else [rule.get('FromPort',0)]
+                    #         for port in port_range:
+                    #             # if (port, rule['IpProtocol']) in port_reachability_results and port_reachability_results[(port, rule['IpProtocol'])]: # Commented out reachability check
+                    #             if 'CidrIpv4' in rule and rule['CidrIpv4'] == '0.0.0.0/0':
+                    #                     rules_to_remove.append(rule['SecurityGroupRuleId'])
+
+                    # if rules_to_remove:
+                    #     try:
+                    #         ec2.revoke_security_group_ingress(
+                    #             GroupId=sg_id,
+                    #             SecurityGroupRuleIds=rules_to_remove,
+                    #             DryRun=dry_run
+                    #         )
+                    #         for rule_id in rules_to_remove:
+                    #             print(
+                    #                 f"   Removed rule allowing traffic from 0.0.0.0/0 on a previously open port in security group {sg_name} ({sg_id})") # Modified message to indicate it might have been previously open
+                    #     except Exception as e:
+                    #         print(f"   Error removing rule: {e}")
+
+                    # Track the rules that need to be added
+                    rules_to_add = []
+
+                    # Add inbound rules for each port and CIDR range
+                    for port_info in ports_to_open:
+                        port = port_info['Port']
+                        protocol = port_info['Protocol']
+
+                        for cidr in allowed_cidrs:
+                            # Check if a rule already exists
+                            rule_exists = False
+                            if isinstance(port, list):  # Handle port ranges
+                                rule_exists = any(
+                                    rule.get('IpProtocol') == protocol and
+                                    rule.get('FromPort') <= port[0] and
+                                    rule.get('ToPort') >= port[1] and
+                                    any(ip_range.get('CidrIp') == cidr for ip_range in rule.get('IpRanges', []))
+                                    for rule in existing_rules
+                                )
+                            else:  # Handle single ports
+                                rule_exists = any(
+                                    rule.get('IpProtocol') == protocol and
+                                    rule.get('FromPort') == port and
+                                    rule.get('ToPort') == port and
+                                    any(ip_range.get('CidrIp') == cidr for ip_range in rule.get('IpRanges', []))
+                                    for rule in existing_rules
+                                )
+
+                            if not rule_exists:
+                                if isinstance(port, list):  # Handle port ranges
+                                    rules_to_add.append(
+                                        {
+                                            'IpProtocol': protocol,
+                                            'FromPort': port[0],
+                                            'ToPort': port[1],
+                                            'IpRanges': [{'CidrIp': cidr}]
+                                        }
+                                    )
+                                else:  # Handle single ports
+                                    rules_to_add.append(
+                                        {
+                                            'IpProtocol': protocol,
+                                            'FromPort': port,
+                                            'ToPort': port,
+                                            'IpRanges': [{'CidrIp': cidr}]
+                                        }
+                                    )
+
+                    # Try to add the rules in a single batch
+                    if rules_to_add:
+                        try:
+                            ec2.authorize_security_group_ingress(
+                                GroupId=sg_id,
+                                IpPermissions=rules_to_add,
+                                DryRun=dry_run
+                            )
+                            for rule in rules_to_add:
+                                if isinstance(rule['FromPort'], int) and rule['FromPort'] == rule['ToPort']:
+                                    print(
+                                        f"   Added rule: {rule['IpProtocol']}/{rule['FromPort']} from {rule['IpRanges'][0]['CidrIp']} to {sg_name} ({sg_id})")
+                                else:
+                                    print(
+                                        f"   Added rule: {rule['IpProtocol']}/{rule['FromPort']}-{rule['ToPort']} from {rule['IpRanges'][0]['CidrIp']} to {sg_name} ({sg_id})")
+
+                        except ec2.exceptions.ClientError as e:
+                            if e.response['Error']['Code'] == 'RulesPerSecurityGroupLimitExceeded':
+                                print(f"   Error: RulesPerSecurityGroupLimitExceeded for {sg_name} ({sg_id}).")
+
+                                # Consolidate rules for the specified ports
+                                consolidated_rules = consolidate_rules(rules_to_add, ports_to_open)
+
+                                # Attempt to add consolidated rules
+                                try:
+                                    ec2.authorize_security_group_ingress(
+                                        GroupId=sg_id,
+                                        IpPermissions=consolidated_rules,
+                                        DryRun=dry_run
+                                    )
+                                    for rule in consolidated_rules:
+                                        if isinstance(rule['FromPort'], int) and rule['FromPort'] == rule['ToPort']:
+                                            print(
+                                                f"   Added consolidated rule: {rule['IpProtocol']}/{rule['FromPort']} to {sg_name} ({sg_id})")
+                                        else:
+                                            print(
+                                                f"   Added consolidated rule: {rule['IpProtocol']}/{rule['FromPort']}-{rule['ToPort']} to {sg_name} ({sg_id})")
+
+                                except ec2.exceptions.ClientError as e:
+                                    if e.response['Error']['Code'] == 'RulesPerSecurityGroupLimitExceeded':
+                                        print(
+                                            f"   Error: RulesPerSecurityGroupLimitExceeded even after consolidation for {sg_name} ({sg_id}).")
+                                        # Create a new security group
+                                        new_sg_id = create_new_security_group(ec2, sg_name, instance['VpcId'],
+                                                                              consolidated_rules, allowed_cidrs, sg_id)
+
+                                        if new_sg_id:
+                                            print(f"   Created new security group: {new_sg_id}")
+
+                                            # Attach the new security group to the instance
+                                            current_group_ids = [sg['GroupId'] for sg in security_groups]
+                                            if new_sg_id not in current_group_ids:
+                                                ec2.modify_instance_attribute(InstanceId=instance_id,
+                                                                              Groups=(current_group_ids + [new_sg_id]),
+                                                                              DryRun=dry_run)
+                                                print(f"   Attached new security group {new_sg_id} to instance {instance_id}")
+                                            else:
+                                                print(
+                                                    f"   Security group {new_sg_id} is already attached to instance {instance_id}")
+
+                                        else:
+                                            print(f"   An unexpected error occurred: {e}")
+                                    else:
+                                        print(f"   An unexpected error occurred: {e}")
+
+    except Exception as e:
+        print(f"An error occurred: {e}")
+
+
+def consolidate_rules(rules, ports_to_open):
+    """Consolidates rules for the same port into a single rule with multiple CIDR ranges."""
+    consolidated_rules = []
+    for port_info in ports_to_open:
+        port = port_info['Port']
+        protocol = port_info['Protocol']
+
+        # Collect CIDR ranges for the current port and protocol
+        cidr_ranges = {}
+        for rule in rules:
+            if isinstance(port, list):  # Handle port ranges
+                if rule['FromPort'] == port[0] and rule['ToPort'] == port[1] and rule['IpProtocol'] == protocol:
+                    sg_id = rule.get('SecurityGroupId', 'default')
+                    if sg_id not in cidr_ranges:
+                        cidr_ranges[sg_id] = set()
+                    cidr_ranges[sg_id].update([r['CidrIp'] for r in rule['IpRanges']])
+            else:  # Handle single ports
+                if rule['FromPort'] == port and rule['IpProtocol'] == protocol:
+                    sg_id = rule.get('SecurityGroupId', 'default')
+                    if sg_id not in cidr_ranges:
+                        cidr_ranges[sg_id] = set()
+                    cidr_ranges[sg_id].update([r['CidrIp'] for r in rule['IpRanges']])
+
+        # Create consolidated rules for each security group
+        for sg_id, cidrs in cidr_ranges.items():
+            if isinstance(port, list):  # Handle port ranges
+                consolidated_rules.append(
+                    {
+                        'IpProtocol': protocol,
+                        'FromPort': port[0],
+                        'ToPort': port[1],
+                        'IpRanges': [{'CidrIp': cidr} for cidr in cidrs]
+                    }
+                )
+            else:  # Handle single ports
+                consolidated_rules.append(
+                    {
+                        'IpProtocol': protocol,
+                        'FromPort': port,
+                        'ToPort': port,
+                        'IpRanges': [{'CidrIp': cidr} for cidr in cidrs]
+                    }
+                )
+
+    return consolidated_rules
+
+
+def create_new_security_group(ec2, original_sg_name, vpc_id, rules, allowed_cidrs, original_sg_id):
+    """Creates a new security group and adds the specified rules. Handles duplicate group name error."""
+    new_sg_name = f"{original_sg_name}-extended"
+
+    # Check for existing security groups with the '-extended' suffix
+    existing_sgs = ec2.describe_security_groups(Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])['SecurityGroups']
+    count = 1
+    while any(sg['GroupName'] == new_sg_name for sg in existing_sgs):
+        new_sg_name = f"{original_sg_name}-extended-{count}"
+        count += 1
+
+    try:
+        # Create the new security group with the updated name
+        response = ec2.create_security_group(
+            GroupName=new_sg_name,
+            Description=f"Extended rules for {original_sg_name}",
+            VpcId=vpc_id,
+            DryRun=dry_run
+        )
+        new_sg_id = response['GroupId']
+        print(f"   Created new security group: {new_sg_id} ({new_sg_name})")
+
+        # Add the rules to the new security group
+        ec2.authorize_security_group_ingress(
+            GroupId=new_sg_id,
+            IpPermissions=rules,
+            DryRun=dry_run
+        )
+        print(f"   Added consolidated rules to the new security group: {new_sg_id} ({new_sg_name})")
+
+        return new_sg_id
+
+    except ec2.exceptions.ClientError as e:
+        if e.response['Error']['Code'] == 'InvalidGroup.Duplicate':
+            print(f"   Error creating new security group: Security group '{new_sg_name}' already exists.")
+
+            # Find the existing security group with the updated name
+            sg_response = ec2.describe_security_groups(
+                Filters=[
+                    {'Name': 'group-name', 'Values': [new_sg_name]},
+                    {'Name': 'vpc-id', 'Values': [vpc_id]}
+                ]
+            )
+
+            if sg_response['SecurityGroups']:
+                existing_sg = sg_response['SecurityGroups'][0]
+                print(f"   Existing security group with name '{new_sg_name}' found: {existing_sg['GroupId']}")
+                return existing_sg['GroupId']
+
+        else:
+            print(f"   Error creating new security group: {e}")
+            return None
+
+
+# --- Configuration ---
+region_name = 'us-west-2'  # Replace with your AWS region
+instance_ids = [
+    'i-asdsadasdsasadasd',  # dc1
+    'i-asdsadasdsadasdas',  # dc2
+    # Add more instance IDs if needed
+}
+allowed_cidrs = [
+    '10.1.65.0/24',
+    '10.100.20.0/24',
+    '10.100.200.0/24',
+    '10.100.30.0/24',
+    '10.20.0.0/24',
+    '10.20.11.0/24',
+    '10.20.31.0/24',
+    '10.20.33.0/24',
+    '10.20.38.0/24',    
+    '10.20.48.0/24',
+    '10.20.49.0/24',
+    '10.20.51.0/24',    
+    '10.50.0.0/24',
+    '10.50.3.0/24',
+    '10.50.4.0/24',
+    '10.50.5.0/24',
+    '10.50.6.0/24',    
+    '172.16.113.0/24',
+    '172.16.129.0/24',
+    '172.16.34.0/24',
+    '172.16.64.0/24',
+    '172.16.65.0/24',
+    '172.16.66.0/24',
+    '172.16.67.0/24',
+    '172.16.68.0/24',
+    '172.16.69.0/24',
+    '172.16.89.0/24',    
+    '172.30.0.0/24',
+    '172.30.15.0/24',
+    '172.30.42.0/24'
+    # Add more CIDR ranges if needed
+]
+
+# --- Run the function ---
+add_inbound_rules_to_security_groups(region_name, instance_ids, allowed_cidrs)

From ee6b5818c828f416a8f1c62e2d35b32547ce677c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D2=89=CE=B1k=CE=B1=20x=E2=A0=A0=E2=A0=B5?=
 <32862241+4k4xs4pH1r3@users.noreply.github.com>
Date: Mon, 13 Jan 2025 21:32:08 -0500
Subject: [PATCH 3/4] Create ports.py
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: ҉αkα x⠠⠵ <32862241+4k4xs4pH1r3@users.noreply.github.com>
---
 AWS/ports.py | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 AWS/ports.py

diff --git a/AWS/ports.py b/AWS/ports.py
new file mode 100644
index 00000000..1e5dca8a
--- /dev/null
+++ b/AWS/ports.py
@@ -0,0 +1,69 @@
+# ports.py
+
+ports_to_open = [
+    # Remote Access and Management
+    {'Port': 3389, 'Protocol': 'tcp', 'Purpose': 'RDP (Remote Desktop Protocol)'},
+    {'Port': 3389, 'Protocol': 'udp', 'Purpose': 'RDP (Remote Desktop Protocol)'},
+    {'Port': 5985, 'Protocol': 'tcp', 'Purpose': 'WinRM-HTTP (WS-Management)'},
+    {'Port': 5986, 'Protocol': 'tcp', 'Purpose': 'WinRM-HTTPS (WS-Management)'},
+    {'Port': 9389, 'Protocol': 'tcp', 'Purpose': 'AD DS Web Services'},
+
+    # File and Printer Sharing
+    {'Port': 137, 'Protocol': 'udp', 'Purpose': 'NetBIOS Name Service'},
+    {'Port': 138, 'Protocol': 'udp', 'Purpose': 'NetBIOS Datagram Service'},
+    {'Port': 139, 'Protocol': 'tcp', 'Purpose': 'NetBIOS Session Service'},
+    {'Port': 445, 'Protocol': 'tcp', 'Purpose': 'SMB over TCP (CIFS)'},
+
+    # Directory Services (Active Directory, LDAP)
+    {'Port': 88, 'Protocol': 'tcp', 'Purpose': 'Kerberos'},
+    {'Port': 88, 'Protocol': 'udp', 'Purpose': 'Kerberos'},
+    {'Port': 389, 'Protocol': 'tcp', 'Purpose': 'LDAP'},
+    {'Port': 389, 'Protocol': 'udp', 'Purpose': 'LDAP'},
+    {'Port': 464, 'Protocol': 'tcp', 'Purpose': 'Kerberos Change/Set Password'},
+    {'Port': 464, 'Protocol': 'udp', 'Purpose': 'Kerberos Change/Set Password'},
+    {'Port': 636, 'Protocol': 'tcp', 'Purpose': 'LDAPS (LDAP over SSL/TLS)'},
+    {'Port': 3268, 'Protocol': 'tcp', 'Purpose': 'Global Catalog'},
+    {'Port': 3269, 'Protocol': 'tcp', 'Purpose': 'Global Catalog over SSL/TLS'},
+
+    # Domain Name System (DNS)
+    {'Port': 53, 'Protocol': 'tcp', 'Purpose': 'DNS'},
+    {'Port': 53, 'Protocol': 'udp', 'Purpose': 'DNS'},
+
+    # Dynamic Host Configuration Protocol (DHCP)
+    {'Port': 68, 'Protocol': 'udp', 'Purpose': 'DHCP Client'},
+    {'Port': 546, 'Protocol': 'udp', 'Purpose': 'DHCPv6 Client'},
+
+    # Time Synchronization
+    {'Port': 123, 'Protocol': 'udp', 'Purpose': 'NTP (Network Time Protocol)'},
+
+    # Remote Procedure Call (RPC)
+    {'Port': 135, 'Protocol': 'tcp', 'Purpose': 'RPC Endpoint Mapper'},
+    {'Port': 135, 'Protocol': 'udp', 'Purpose': 'RPC Endpoint Mapper'},
+    {'Port': [49152, 65535], 'Protocol': 'tcp', 'Purpose': 'Dynamic RPC Ports'},
+
+    # Network Discovery and Service Location
+    {'Port': 1900, 'Protocol': 'udp', 'Purpose': 'SSDP (Simple Service Discovery Protocol)'},
+    {'Port': 2869, 'Protocol': 'tcp', 'Purpose': 'ICSLAP'},
+    {'Port': 3702, 'Protocol': 'udp', 'Purpose': 'WS-Discovery'},
+    {'Port': 5353, 'Protocol': 'udp', 'Purpose': 'mDNS (Multicast DNS)'},
+    {'Port': 5355, 'Protocol': 'udp', 'Purpose': 'LLMNR (Link-Local Multicast Name Resolution)'},
+    {'Port': 5357, 'Protocol': 'tcp', 'Purpose': 'WSDAPI (Web Services for Devices)'},
+    {'Port': 5357, 'Protocol': 'udp', 'Purpose': 'WSDAPI (Web Services for Devices)'},
+    {'Port': 5358, 'Protocol': 'tcp', 'Purpose': 'WSDAPI (Web Services for Devices)'},
+
+    # Other Ports
+    {'Port': 554, 'Protocol': 'tcp', 'Purpose': 'RTSP (Real Time Streaming Protocol)'},
+    {'Port': 554, 'Protocol': 'udp', 'Purpose': 'RTSP (Real Time Streaming Protocol)'},
+    {'Port': [8554, 8558], 'Protocol': 'tcp', 'Purpose': 'RTSP (Real Time Streaming Protocol)'},
+    {'Port': [8554, 8558], 'Protocol': 'udp', 'Purpose': 'RTSP (Real Time Streaming Protocol)'},
+    {'Port': [5000, 5020], 'Protocol': 'tcp', 'Purpose': 'UPnP or other applications'},
+    {'Port': 7680, 'Protocol': 'tcp', 'Purpose': 'Delivery Optimization (Windows Update P2P)'},
+    {'Port': 10246, 'Protocol': 'tcp', 'Purpose': 'Registered port (application specific)'},
+    {'Port': 10247, 'Protocol': 'tcp', 'Purpose': 'Registered port (application specific)'},
+    {'Port': 17472, 'Protocol': 'tcp', 'Purpose': 'Registered port (application specific)'},
+    {'Port': 9955, 'Protocol': 'tcp', 'Purpose': 'Specific service port'},
+    {'Port': 23554, 'Protocol': 'tcp', 'Purpose': 'Specific service port'},
+    {'Port': 23555, 'Protocol': 'tcp', 'Purpose': 'Specific service port'},
+    {'Port': 23556, 'Protocol': 'tcp', 'Purpose': 'Specific service port'},
+    {'Port': 443, 'Protocol': 'tcp', 'Purpose': 'IPHTTPS'}
+]

From 002f1606d6e4dd79b1d1625b689bdffdc64b6404 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D2=89=CE=B1k=CE=B1=20x=E2=A0=A0=E2=A0=B5?=
 <32862241+4k4xs4pH1r3@users.noreply.github.com>
Date: Mon, 13 Jan 2025 21:33:14 -0500
Subject: [PATCH 4/4] .

---
 AWS/{ => ec2/security_groups}/aws_sg_ec2_add_new_entries.py | 0
 AWS/{ => ec2/security_groups}/ports.py                      | 0
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename AWS/{ => ec2/security_groups}/aws_sg_ec2_add_new_entries.py (100%)
 rename AWS/{ => ec2/security_groups}/ports.py (100%)

diff --git a/AWS/aws_sg_ec2_add_new_entries.py b/AWS/ec2/security_groups/aws_sg_ec2_add_new_entries.py
similarity index 100%
rename from AWS/aws_sg_ec2_add_new_entries.py
rename to AWS/ec2/security_groups/aws_sg_ec2_add_new_entries.py
diff --git a/AWS/ports.py b/AWS/ec2/security_groups/ports.py
similarity index 100%
rename from AWS/ports.py
rename to AWS/ec2/security_groups/ports.py