Last active
June 19, 2023 23:20
-
-
Save obijan42/a9ae4a7816b8a252f94ea2fb9359bd90 to your computer and use it in GitHub Desktop.
Example AWS findings remediation scripts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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...") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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: