Skip to content

Instantly share code, notes, and snippets.

@obijan42
Last active June 19, 2023 23:20
Show Gist options
  • Select an option

  • Save obijan42/a9ae4a7816b8a252f94ea2fb9359bd90 to your computer and use it in GitHub Desktop.

Select an option

Save obijan42/a9ae4a7816b8a252f94ea2fb9359bd90 to your computer and use it in GitHub Desktop.
Example AWS findings remediation scripts
#!/bin/bash
# Finding: CodeBuild.5 CodeBuild project environments should not have privileged mode enabled
# This script reviews CodeBuild project environments and ensures privileged mode is disabled.
# Get list of CodeBuild projects
projects=$(aws codebuild list-projects --query 'projects' --output text)
# Loop through each project
for project in $projects; do
echo "Checking CodeBuild project $project..."
# Get project environment details
environment=$(aws codebuild batch-get-projects --names "$project" --query 'projects[0].environment' --output json)
# Check if privileged mode is enabled
privileged_mode=$(echo "$environment" | jq -r '.privilegedMode')
if [ "$privileged_mode" == "true" ]; then
# Privileged mode is enabled, disable it
echo "Privileged mode is enabled for CodeBuild project $project, disabling it..."
aws codebuild update-project --name "$project" --environment-variables "name=PRIVILEGED_MODE,value=false,type=PLAINTEXT" --source-version "$LATEST" --buildspec-override '{"version":0,"phases":{"install":{"runtime-versions":{"docker":"18"}}},"artifacts":{"files":["**/*"],"name":"artifacts","discard-paths":"yes"}}'
else
echo "Privileged mode is disabled for CodeBuild project $project."
fi
done
#!/bin/bash
# This script sets the S3 lifecycle policy for each bucket in the account to delete everything, including object versions and partial uploads, after 1 day.
# WARNING: This DELETES ALL FILES after 24h
# Get a list of S3 buckets in the account
buckets=$(aws s3api list-buckets --query 'Buckets[*].Name' --output text)
# Loop through each bucket
for bucket in $buckets; do
echo "Setting S3 lifecycle policy for bucket $bucket..."
# Set the S3 lifecycle policy for the bucket to delete everything after 1 day, including object versions and partial uploads
aws s3api put-bucket-lifecycle-configuration --bucket "$bucket" --lifecycle-configuration '{"Rules":[{"Status":"Enabled","Prefix":"","ID":"Delete objects after 1 day","Expiration":{"Days":1},"NoncurrentVersionExpiration":{"NoncurrentDays":1},"AbortIncompleteMultipartUpload":{"DaysAfterInitiation":1}}]}'
done
#!/bin/bash
# Finding: EC2.22 Unused EC2 security groups should be removed
# Read security group IDs from file
while read -r sg_id; do
# Check if security group is in use
in_use=$(aws ec2 describe-network-interfaces --filters Name=group-id,Values="$sg_id" --query 'NetworkInterfaces[*]' --output json)
if [ -z "$in_use" ]; then
# Delete security group if not in use
echo "Deleting security group $sg_id..."
aws ec2 delete-security-group --group-id "$sg_id"
else
echo "Security group $sg_id is in use and cannot be deleted."
fi
done < sg_ids.txt
#!/bin/bash
import boto3
# Create an EC2 client
ec2 = boto3.client('ec2')
# Get a list of all regions in the AWS account
try:
regions = [region['RegionName'] for region in ec2.describe_regions()['Regions']]
except Exception as e:
print(f"Error getting regions: {e}")
exit(1)
# Loop through each region
for region in regions:
print(f"Checking region {region}...")
# Create a client for the current region
try:
ec2 = boto3.client('ec2', region_name=region)
except Exception as e:
print(f"Error creating client for region {region}: {e}")
continue
# Get a list of all VPCs in the region
try:
vpcs = ec2.describe_vpcs()['Vpcs']
except Exception as e:
print(f"Error getting VPCs in region {region}: {e}")
continue
# Loop through each VPC
for vpc in vpcs:
vpc_id = vpc['VpcId']
# Check if the VPC is the default VPC
if vpc['IsDefault']:
# Get a list of all instances in the VPC
try:
instances = ec2.describe_instances(Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])['Reservations']
except Exception as e:
print(f"Error getting instances in VPC {vpc_id} in region {region}: {e}")
continue
# Check if there are any instances in the VPC
if len(instances) == 0:
# Delete the empty VPC
print(f"Deleting empty VPC {vpc_id} in region {region}...")
try:
ec2.delete_vpc(VpcId=vpc_id)
except Exception as e:
print(f"Error deleting VPC {vpc_id} in region {region}: {e}")
continue
else:
print(f"Default VPC {vpc_id} in region {region} has {len(instances)} instances, skipping deletion...")
else:
print(f"VPC {vpc_id} in region {region} is not the default VPC, skipping...")
#!/bin/bash
# This script reviews all launch configurations in an AWS account and deletes ones that are not in use.
# Get a list of launch configurations
launch_configs=$(aws autoscaling describe-launch-configurations --query 'LaunchConfigurations[*].LaunchConfigurationName' --output text)
# Loop through each launch configuration
for launch_config in $launch_configs; do
echo "Checking launch configuration $launch_config..."
# Get a list of auto scaling groups that use the launch configuration
auto_scaling_groups=$(aws autoscaling describe-auto-scaling-groups --query 'AutoScalingGroups[?LaunchConfigurationName==`'"$launch_config"'`].AutoScalingGroupName' --output text)
if [ -z "$auto_scaling_groups" ]; then
# Launch configuration is not being used, delete it
echo "Launch configuration $launch_config is not being used, deleting it..."
aws autoscaling delete-launch-configuration --launch-configuration-name "$launch_config"
else
# Launch configuration is being used, list the auto scaling groups that use it
echo "Launch configuration $launch_config is being used by the following auto scaling groups:"
echo "$auto_scaling_groups"
fi
done
#!/bin/bash
# Filename: disable-vpc-default-sg-rules.sh
# Finding: EC2.2 The VPC default security group should not allow inbound and outbound traffic
# Get the default security group ID
DEFAULT_SG_ID=$(aws ec2 describe-security-groups --query 'SecurityGroups[?GroupName==`default`].GroupId' --output text)
# Check if the security group ID was found
if [ -z "$DEFAULT_SG_ID" ]; then
echo "Default security group not found."
exit 1
fi
# Display the instances associated with the security group
echo "Instances associated with the default security group ($DEFAULT_SG_ID):"
aws ec2 describe-instances --filters "Name=instance.group-id,Values=$DEFAULT_SG_ID" --query 'Reservations[].Instances[].InstanceId'
# Display the security group rules
echo "Ingress rules for default security group ($DEFAULT_SG_ID):"
aws ec2 describe-security-groups --group-ids $DEFAULT_SG_ID --query 'SecurityGroups[].IpPermissions[]'
echo "Egress rules for default security group ($DEFAULT_SG_ID):"
aws ec2 describe-security-groups --group-ids $DEFAULT_SG_ID --query 'SecurityGroups[].IpPermissionsEgress[]'
# Ask for confirmation before deleting the rules
read -p "Are you sure you want to delete all ingress and egress rules for the default security group? (y/n): " confirm
if [ "$confirm" != "y" ]; then
echo "Aborting."
exit 0
fi
# Delete all ingress rules
aws ec2 revoke-security-group-ingress --group-id $DEFAULT_SG_ID --protocol all --port all
# Delete all egress rules
aws ec2 revoke-security-group-egress --group-id $DEFAULT_SG_ID --protocol all --port all
echo "All ingress and egress rules for the default security group ($DEFAULT_SG_ID) have been deleted."
#!/bin/bash
# Finding: ElasticBeanstalk.2 Elastic Beanstalk managed platform updates should be enabled
# This script ensures that every Elastic Beanstalk environment has managed platform updates enabled.
# Get list of Elastic Beanstalk environments
environments=$(aws elasticbeanstalk describe-environments --query 'Environments[*].EnvironmentId' --output text)
# Loop through each environment
for environment in $environments; do
echo "Checking Elastic Beanstalk environment $environment..."
# Check if managed platform updates are enabled
managed_updates=$(aws elasticbeanstalk describe-configuration-settings --environment-id "$environment" --query 'ConfigurationSettings[?OptionName==`ManagedActionsEnabled`].OptionValue' --output text)
if [ "$managed_updates" != "true" ]; then
# Managed platform updates are not enabled, enable them
echo "Managed platform updates are not enabled for Elastic Beanstalk environment $environment, enabling them..."
aws elasticbeanstalk update-environment --environment-id "$environment" --option-settings Namespace=aws:elasticbeanstalk:managedactions,OptionName=ManagedActionsEnabled,Value=true
else
echo "Managed platform updates are enabled for Elastic Beanstalk environment $environment."
fi
done
#!/bin/bash
# Finding: ECS.5 ECS containers should be limited to read-only access to root filesystems
# This script reviews ECS containers and ensures the root file system is read-only.
# Get list of ECS clusters
clusters=$(aws ecs list-clusters --query 'clusterArns' --output text)
# Loop through each cluster
for cluster_arn in $clusters; do
cluster_name=$(basename "$cluster_arn")
echo "Checking ECS cluster $cluster_name..."
# Get list of running tasks in the cluster
task_list=$(aws ecs list-tasks --cluster "$cluster_name" --desired-status RUNNING --query 'taskArns' --output text)
# Loop through each task
for task_arn in $task_list; do
task_definition=$(aws ecs describe-tasks --cluster "$cluster_name" --tasks "$task_arn" --query 'tasks[0].taskDefinitionArn' --output text)
container_list=$(aws ecs describe-task-definition --task-definition "$task_definition" --query 'taskDefinition.containerDefinitions[*]' --output json)
# Loop through each container in the task
for container in $container_list; do
# Check if root file system is read-only
read_only=$(echo "$container" | jq -r '.readonlyRootFilesystem')
if [ "$read_only" != "true" ]; then
# Root file system is not read-only, set it to read-only
container_name=$(echo "$container" | jq -r '.name')
echo "Root file system is not read-only for container $container_name in task $task_arn, setting it to read-only..."
aws ecs register-task-definition --family "$(echo "$task_definition" | cut -d':' -f 6)" --revision "$(echo "$task_definition" | cut -d':' -f 7)" --container-definitions "[$(echo "$container_list" | jq "map(if .name==\"$container_name\" then .readonlyRootFilesystem=true else . end)")]" --query 'taskDefinition.taskDefinitionArn' --output text
else
echo "Root file system is read-only for container $container_name in task $task_arn."
fi
done
done
done
#!/bin/bash
# Finding: Other
# This script reviews EKS containers and ensures the root file system is read-only.
# Get list of EKS clusters
clusters=$(aws eks list-clusters --query 'clusters' --output text)
# Loop through each cluster
for cluster in $clusters; do
echo "Checking EKS cluster $cluster..."
# Get list of running pods in the cluster
pod_list=$(kubectl get pods --all-namespaces --field-selector=status.phase=Running --output=jsonpath='{range .items[*]}{.metadata.namespace} {.metadata.name}{"\n"}{end}' --kubeconfig ~/.kube/config --context "$cluster" 2>/dev/null)
# Loop through each pod
while read -r pod; do
namespace=$(echo "$pod" | awk '{print $1}')
pod_name=$(echo "$pod" | awk '{print $2}')
# Get pod spec
pod_spec=$(kubectl get pod "$pod_name" -n "$namespace" --output json --kubeconfig ~/.kube/config --context "$cluster" 2>/dev/null)
# Check if root file system is read-only
read_only=$(echo "$pod_spec" | jq -r '.spec.containers[].securityContext?.readOnlyRootFilesystem')
if [ "$read_only" != "true" ]; then
# Root file system is not read-only, set it to read-only
echo "Root file system is not read-only for pod $pod_name in namespace $namespace, setting it to read-only..."
kubectl patch pod "$pod_name" -n "$namespace" --type=json -p='[{"op": "add", "path": "/spec/containers/0/securityContext", "value": {"readOnlyRootFilesystem": true}}]' --kubeconfig ~/.kube/config --context "$cluster" 2>/dev/null
else
echo "Root file system is read-only for pod $pod_name in namespace $namespace."
fi
done <<< "$pod_list"
done
#!/bin/bash
# Finding: EKS.2 EKS clusters should run on a supported Kubernetes version
# This script reviews EKS clusters and ensures that their version is at least at the configured version number, and updates it otherwise.
# Set the minimum version number to compare against
minimum_version="1.21"
# Get list of EKS clusters
clusters=$(aws eks list-clusters --query 'clusters' --output text)
# Loop through each cluster
for cluster in $clusters; do
echo "Checking EKS cluster $cluster..."
# Get current version of the cluster
current_version=$(aws eks describe-cluster --name "$cluster" --query 'cluster.version' --output text)
if (( $(echo "$current_version >= $minimum_version" | bc -l) )); then
echo "EKS cluster $cluster is at least at version $minimum_version."
else
# Update the cluster version
echo "EKS cluster $cluster is at version $current_version, updating to at least version $minimum_version..."
aws eks update-cluster-version --name "$cluster" --version "$minimum_version"
fi
done
#!/bin/bash
# Finding: ElastiCache.1 ElastiCache Redis clusters should have automatic backup enabled
# This script reviews ElastiCache Redis clusters and ensures automatic backup is enabled.
# Get list of Redis clusters
redis_clusters=$(aws elasticache describe-cache-clusters --query 'CacheClusters[?Engine==`redis`].CacheClusterId' --output text)
# Loop through each Redis cluster
for cluster_id in $redis_clusters; do
echo "Checking Redis cluster $cluster_id..."
# Check if automatic backup is enabled
backup_enabled=$(aws elasticache describe-cache-cluster --cache-cluster-id "$cluster_id" --query 'CacheClusters[0].AutomaticBackupRetentionDays' --output text)
if [ "$backup_enabled" == "0" ]; then
# Automatic backup is not enabled, enable it
echo "Automatic backup is not enabled for Redis cluster $cluster_id, enabling it..."
aws elasticache modify-cache-cluster --cache-cluster-id "$cluster_id" --automatic-backup-retention-period 7
else
echo "Automatic backup is enabled for Redis cluster $cluster_id."
fi
done
#!/bin/bash
# Finding: Config.1 AWS Config should be enabled
# This script looks at every region, verifies that AWS Config is enabled, and activates it otherwise.
# Get list of AWS regions
regions=$(aws ec2 describe-regions --query 'Regions[*].RegionName' --output text)
# Loop through each region
for region in $regions; do
echo "Checking AWS Config status in region $region..."
# Check if AWS Config is enabled in the region
config_enabled=$(aws configservice describe-configuration-recorders --query 'ConfigurationRecorders[*].name' --output text --region "$region" 2>/dev/null)
if [ -z "$config_enabled" ]; then
# AWS Config is not enabled in the region, activate it
echo "AWS Config is not enabled in region $region, activating it..."
aws configservice put-configuration-recorder --configuration-recorder name=MyRecorder --recording-group allSupported --region "$region"
aws configservice start-configuration-recorder --configuration-recorder-name MyRecorder --region "$region"
else
echo "AWS Config is enabled in region $region."
fi
done
#!/usr/bin/env python3
import boto3
# Create a session using your AWS credentials
session = boto3.Session()
# Create an AWS client for organizations
client = session.client("organizations")
# Get the current AWS organization ID
org_id = client.describe_organization()["Organization"]["Id"]
# List all SCPs in the organization
scps = client.list_policies(Filter="SERVICE_CONTROL_POLICY")["Policies"]
# For each SCP, list the OUs it is attached to and the policy content
for scp in scps:
scp_id = scp["Id"]
print(f"SCP ID: {scp_id}")
# Get and print the policy content and description
policy = client.describe_policy(PolicyId=scp_id)["Policy"]
policy_content = policy["Content"]
policy_description = policy["PolicySummary"]["Description"]
print(f"Policy Name: {policy['PolicySummary']['Name']}")
print(f"Policy Content: {policy_content}")
print(f"Policy Description: {policy_description}")
print("Attached OUs:")
# List all roots in the organization
roots = client.list_roots()["Roots"]
# For each root, list the OUs
for root in roots:
root_id = root["Id"]
ous = client.list_organizational_units_for_parent(ParentId=root_id)[
"OrganizationalUnits"
]
# For each OU, check if the SCP is attached and print the OU description
for ou in ous:
ou_id = ou["Id"]
attached_scps = client.list_policies_for_target(
TargetId=ou_id, Filter="SERVICE_CONTROL_POLICY"
)["Policies"]
for attached_scp in attached_scps:
if attached_scp["Id"] == scp_id:
ou_description = ou["Name"]
print(f"OU ID: {ou_id} Description: {ou_description} ")
print("------\n")
#!/bin/bash
# Get the current AWS organization ID
ORG_ID=$(aws organizations describe-organization --query 'Organization.Id' --output text)
# List all SCPs in the organization
SCPS=$(aws organizations list-policies --filter SERVICE_CONTROL_POLICY --query 'Policies[].Id' --output text)
# For each SCP, list the OUs it is attached to, the policy content, and the descriptions
for SCP_ID in $SCPS
do
echo "SCP ID: $SCP_ID"
# Get and print the policy content and description
POLICY=$(aws organizations describe-policy --policy-id $SCP_ID)
POLICY_CONTENT=$(echo $POLICY | jq -r '.Policy.Content')
POLICY_DESCRIPTION=$(echo $POLICY | jq -r '.Policy.PolicySummary.Description')
echo "Policy Content: $POLICY_CONTENT"
echo "Policy Description: $POLICY_DESCRIPTION"
echo "Attached OUs:"
# List all roots in the organization
ROOTS=$(aws organizations list-roots --query 'Roots[].Id' --output text)
# For each root, list the OUs
for ROOT_ID in $ROOTS
do
OUS=$(aws organizations list-organizational-units-for-parent --parent-id $ROOT_ID --query 'OrganizationalUnits[].Id' --output text)
# For each OU, check if the SCP is attached and print the OU description
for OU_ID in $OUS
do
ATTACHED_SCPS=$(aws organizations list-policies-for-target --target-id $OU_ID --filter SERVICE_CONTROL_POLICY --query 'Policies[].Id' --output text)
if [[ $ATTACHED_SCPS =~ $SCP_ID ]]
then
OU_DESCRIPTION=$(aws organizations describe-organizational-unit --organizational-unit-id $OU_ID --query 'OrganizationalUnit.Name' --output text)
echo "OU ID: $OU_ID"
echo "OU Description: $OU_DESCRIPTION"
fi
done
done
echo ""
done
#!/bin/bash
# Finding: [AutoScaling.3] Auto Scaling group launch configurations should configure EC2 instances to require Instance Metadata Service Version 2 (IMDSv2)
# This script ensures that every Auto Scaling group launch configuration specifies EC2 instances to require IMDSv2.
# Get list of Auto Scaling group names
asg_names=$(aws autoscaling describe-auto-scaling-groups --query 'AutoScalingGroups[*].AutoScalingGroupName' --output text)
# Loop through each Auto Scaling group
for asg_name in $asg_names; do
echo "Checking launch configuration for Auto Scaling group $asg_name..."
# Get launch configuration name
lc_name=$(aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names "$asg_name" --query 'AutoScalingGroups[*].LaunchConfigurationName' --output text)
# Check if launch configuration requires IMDSv2
lc_metadata=$(aws autoscaling describe-launch-configurations --launch-configuration-names "$lc_name" --query 'LaunchConfigurations[*].MetadataOptions' --output json)
lc_imdsv2=$(echo "$lc_metadata" | jq -r '.[] | select(.HttpTokens == "required" and .HttpEndpoint == "enabled")')
if [ -z "$lc_imdsv2" ]; then
# Launch configuration does not require IMDSv2, update it
echo "Updating launch configuration $lc_name to require IMDSv2..."
aws autoscaling update-launch-configuration --launch-configuration-name "$lc_name" --metadata-options HttpEndpoint=enabled,HttpTokens=required
else
echo "Launch configuration $lc_name already requires IMDSv2."
fi
done
#!/bin/bash
# This script finds and deletes unused security groups in every VPC in a region,
# and lists what uses them if they are being used.
# Get a list of VPC IDs in the region
vpc_ids=$(aws ec2 describe-vpcs --query 'Vpcs[*].VpcId' --output text)
# Loop through each VPC
for vpc_id in $vpc_ids; do
echo "Checking VPC $vpc_id..."
# Get a list of security groups in the VPC that match the prefix "launch-wizard"
security_groups=$(aws ec2 describe-security-groups --filters "Name=vpc-id,Values=$vpc_id" "Name=group-name,Values=launch-wizard*" --query 'SecurityGroups[*].GroupId' --output text)
# Loop through each security group
for sg in $security_groups; do
echo "Checking security group $sg..."
# Get a list of instances that use the security group
instances=$(aws ec2 describe-instances --filters "Name=vpc-id,Values=$vpc_id" "Name=instance.group-id,Values=$sg" --query 'Reservations[*].Instances[*].InstanceId' --output text )
if [ -z "$instances" ]; then
# Security group is not being used, delete it
echo "Security group $sg is not being used, deleting it..."
aws ec2 delete-security-group --group-id "$sg"
else
# Security group is being used, list the instances that use it
echo "Security group $sg is being used by the following instances:"
echo "$instances"
fi
done
done
#!/bin/bash
# Finding: RDS.13 RDS automatic minor version upgrades should be enabled
# This script reviews RDS instances and ensures minor version upgrades are enabled.
# Get list of RDS instance identifiers
instance_ids=$(aws rds describe-db-instances --query 'DBInstances[*].DBInstanceIdentifier' --output text)
# Loop through each instance
for instance_id in $instance_ids; do
echo "Checking RDS instance $instance_id..."
# Check if minor version upgrades are enabled
minor_upgrades_enabled=$(aws rds describe-db-instances --db-instance-identifier "$instance_id" --query 'DBInstances[0].AutoMinorVersionUpgrade' --output text)
if [ "$minor_upgrades_enabled" == "false" ]; then
# Minor version upgrades are not enabled, enable them
echo "Minor version upgrades are not enabled for RDS instance $instance_id, enabling them..."
aws rds modify-db-instance --db-instance-identifier "$instance_id" --auto-minor-version-upgrade
else
echo "Minor version upgrades are enabled for RDS instance $instance_id."
fi
done
#!/bin/bash
# Finding: EC2.19 Security groups should not allow unrestricted access to ports with high risk
# This script finds security groups that have a "high risk" port open to 0.0.0.0/0
# and changes the range to the IP range of the VPC they are in.
# Get list of VPCs in the region
vpcs=$(aws ec2 describe-vpcs --query 'Vpcs[*].VpcId' --output text)
# List of high-risk ports to check
high_risk_ports=(3389 20 21 22 23 110 143 3306 8080 1433 1434 9200 9300 5601 25 445 135 4333 5432 5500)
# Loop through each VPC
for vpc_id in $vpcs; do
echo "Checking security groups in VPC $vpc_id..."
# Get VPC CIDR
vpc_cidr=$(aws ec2 describe-vpcs --vpc-ids "$vpc_id" --query 'Vpcs[*].CidrBlock' --output text)
# Find security groups with high-risk ports open to 0.0.0.0/0
high_risk_sgs=$(aws ec2 describe-security-groups --filters Name=ip-permission.to-port,Values="${high_risk_ports[*]}" Name=ip-permission.cidr,Values="0.0.0.0/0" --query 'SecurityGroups[*].GroupId' --output text)
# Update security group rules
for sg_id in $high_risk_sgs; do
# Get current inbound rules for high-risk ports
for port in "${high_risk_ports[@]}"; do
rule=$(aws ec2 describe-security-groups --group-id "$sg_id" --query "SecurityGroups[*].IpPermissions[?ToPort==\`${port}\` && CidrIp==\`0.0.0.0/0\`] | [0]" --output json)
if [ -z "$rule" ]; then
# Rule not found, skip to next port
continue
fi
# Update inbound rule to use VPC CIDR range
aws ec2 revoke-security-group-ingress --group-id "$sg_id" --ip-permissions "$rule"
aws ec2 authorize-security-group-ingress --group-id "$sg_id" --protocol tcp --port "$port" --cidr "$vpc_cidr"
echo "Updated security group $sg_id to use VPC CIDR range for port $port."
done
done
done
#!/bin/bash
# Finding: EC2.19 Security groups should not allow unrestricted access to ports with high risk
# This script finds security groups that have a "high risk" port open to 0.0.0.0/0
# and changes the range to the IP range of the VPC they are in.
# Get list of security group IDs from file
sg_ids_file="sg_ids.txt"
sg_ids=$(cat "$sg_ids_file")
# List of high-risk ports to check
high_risk_ports=(3389 20 21 22 23 110 143 3306 8080 1433 1434 9200 9300 5601 25 445 135 4333 5432 5500)
# Loop through each security group
for sg_id in $sg_ids; do
echo "Checking security group $sg_id..."
# Get VPC CIDR
vpc_cidr=$(aws ec2 describe-security-groups --group-id "$sg_id" --query 'SecurityGroups[*].VpcId' --output text | xargs -I {} aws ec2 describe-vpcs --vpc-ids {} --query 'Vpcs[*].CidrBlock' --output text)
# Find inbound rules with high-risk ports open to 0.0.0.0/0
for port in "${high_risk_ports[@]}"; do
rule=$(aws ec2 describe-security-groups --group-id "$sg_id" --query "SecurityGroups[*].IpPermissions[?ToPort==\`${port}\` && CidrIp==\`0.0.0.0/0\`] | [0]" --output json)
if [ -z "$rule" ]; then
# Rule not found, skip to next port
continue
fi
# Update inbound rule to use VPC CIDR range
aws ec2 revoke-security-group-ingress --group-id "$sg_id" --ip-permissions "$rule"
aws ec2 authorize-security-group-ingress --group-id "$sg_id" --protocol tcp --port "$port" --cidr "$vpc_cidr"
echo "Updated security group $sg_id to use VPC CIDR range for port $port."
done
done
#!/bin/bash
# Finding: EC2.8 EC2 instances should use Instance Metadata Service Version 2 (IMDSv2)
# This script enables IMDSv2 on a list of EC2 instances specified in a file.
# Set the instance ID file
instance_file="instance_ids.txt"
# Loop through each line in the file
while read -r instance; do
# Check if instance is an ARN or an ID
if [[ "$instance" == *"arn:aws:ec2"* ]]; then
# Extract instance ID from instance ARN
instance_id=${instance##*/}
else
# Use instance ID as-is
instance_id="$instance"
fi
echo "Enabling IMDSv2 on instance $instance_id..."
aws ec2 modify-instance-metadata-options --instance-id "$instance_id" --http-endpoint enabled --http-tokens required
done < "$instances_file"
#!/bin/bash
# Finding: EC2.23 EC2 Transit Gateways should not automatically accept VPC attachment requests
# This script ensures that every transit gateway does not have AutoAcceptSharedAttachments enabled.
# Get list of transit gateway IDs
tgw_ids=$(aws ec2 describe-transit-gateways --query 'TransitGateways[*].TransitGatewayId' --output text)
# Loop through each transit gateway
for tgw_id in $tgw_ids; do
echo "Checking transit gateway $tgw_id..."
# Check if AutoAcceptSharedAttachments is enabled
auto_accept=$(aws ec2 describe-transit-gateway --transit-gateway-id "$tgw_id" --query 'TransitGateway.AutoAcceptSharedAttachments' --output text)
if [ "$auto_accept" == "enabled" ]; then
# AutoAcceptSharedAttachments is enabled, disable it
echo "AutoAcceptSharedAttachments is enabled for transit gateway $tgw_id, disabling it..."
aws ec2 modify-transit-gateway --transit-gateway-id "$tgw_id" --options '{"AutoAcceptSharedAttachments":"disable"}'
else
echo "AutoAcceptSharedAttachments is disabled for transit gateway $tgw_id."
fi
done
@obijan42
Copy link
Author

obijan42 commented Apr 21, 2023

These scripts will change your environments! Please review in advance and use with care. There is no "Undo".
They can be run from your local terminal or from the console in AWS Cloudshell.
Requirements:

  • Bash
  • AWS CLI
  • JQ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment