SQS Queues with Encryption Control

for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
    echo "Region: $region"
    queue_urls=($(aws sqs list-queues --region "$region" --query 'QueueUrls[*]' --output text))
    for queue_url in "${queue_urls[@]}"; do
        echo "  Queue URL: $queue_url"
        aws sqs get-queue-attributes --region "$region" --queue-url "$queue_url" --attribute-names "SqsManagedSseEnabled" "KmsMasterKeyId" --query 'Attributes'
    done
done  

EBS Volumes Encryption Control

aws ec2 describe-volumes --region eu-west1 --query 'Volumes[?Encrypted==`false`].[VolumeId,Encrypted,Tags[?Key==`Name`].Value | [0]]' 

This settings can check in EC2 > Elastic Block Store > Volumes > (Click the volumes check button) > control the Encryption section on the AWS console.

Remember to change the region on the command.

Root Account Hardware MFA Control

List the MFA devices along with their corresponding users.

aws iam list-mfa-devices --query 'MFADevices[*].[SerialNumber,User.Arn]' --output json            

List the virtual MFA devices along with their corresponding users.

aws iam list-virtual-mfa-devices --assignment-status Assigned --query 'VirtualMFADevices[*].[SerialNumber,User.Arn]' --output json | jq . 

This settings can check in the IAM > Users > MFA section on AWS console.

Private EBS Snapshot Encryption Control

aws ec2 describe-snapshots –-region eu-west-1 –-owner-ids <Owner ID>  

This settings can check in EC2 > Elastic Block Store > Snapshots > (Click the snapshots check button) > control the Encryption section on the AWS console.

Dropping Invalid Header Fields Control

for region in $(aws ec2 describe-regions --region eu-central-1 --query 'Regions[*].RegionName' --output text); do                                                                                                              
    echo "Load balancers in region $region:" 
    for arn in $(aws elbv2 describe-load-balancers --region $region --query 'LoadBalancers[].LoadBalancerArn' --output text); do
        drop_invalid_header_fields=$(aws elbv2 describe-load-balancer-attributes --region $region --load-balancer-arn $arn --query 'Attributes[?(Key == `routing.http.drop_invalid_header_fields.enabled`)].Value | [0]' --output text)
        if [ "$drop_invalid_header_fields" == "false" ]; then                                                                                                                                                                               
            echo "  Load Balancer ARN: $arn" 
            echo "    Drop Invalid Header Fields Enabled: $drop_invalid_header_fields"                                                                                                                                                      
        fi                                   
    done                                                                        
    echo ""                                  
done 

This settings can check in EC2 > Load Balancers > (Click the Load Balancer check button) > Attributes > control the ‘Drop invalid header fields’ section on the AWS console.

ELB Load Balancers Clear-Text (HTTP) Communication Control

for region in $(aws ec2 describe-regions --query 'Regions[*].RegionName' --output text); do
  echo "Load balancer listeners with HTTP protocol in region $region:"
  aws elb describe-load-balancers --region $region --query 'LoadBalancerDescriptions[?ListenerDescriptions[?Listener.Protocol==`HTTP`]].{LoadBalancerName: LoadBalancerName, Protocol: ListenerDescriptions[].Listener.Protocol}' --output table
done 

This settings can check in EC2 > Load Balancer > (Click the Load Balancer check button) > Listeners and rules > control the protocols on the AWS console.

ELB HTTPS Load Balancer SSL/TLS Policy Control

# Get all AWS regions
for region in $(aws ec2 describe-regions --query 'Regions[*].RegionName' --output text); do
    echo -e "\n================= Region: $region ================="

    # Get all Classic Load Balancer names in the region
    elbs=$(aws elb describe-load-balancers \
        --region "$region" \
        --query 'LoadBalancerDescriptions[].LoadBalancerName' \
        --output text 2>/dev/null)

    # Skip if no ELBs found
    if [[ -z "$elbs" ]]; then
        echo "No Classic Load Balancers found in region $region."
        continue
    fi

    # Loop over each ELB
    for name in $elbs; do
        echo -e "\n#---------- SSL/TLS Policies for Classic Load Balancer: $name ---------#"
        aws elb describe-load-balancer-policies \
            --region "$region" \
            --load-balancer-name "$name" \
            --query 'PolicyDescriptions[?PolicyTypeName==`SSLNegotiationPolicyType`].{PolicyName: PolicyName, PolicyTypeName: PolicyTypeName}' \
            --output table 2>/dev/null
    done
done

This settings can check in EC2 > Load Balancer > (Click the Load Balancer check button) > Listeners and rules > control the protocols on the AWS console.

Inline role Policy Allows ‘iam:PassRole’ For All Resources or all IAM Role Resource Control

aws iam get-role-policy --role-name <RoleName>  --policy-name SsmOnboardingInlinePolicy  --query 'PolicyDocument'; aws iam get-role-policy --role-name <RoleName>  --policy-name STS_Assume_Role --query 'PolicyDocument' 

EC2 Instance Metadata Service Version 2 (IMDSv2) Control

aws ec2 describe-instances --region eu-west-1 --query 'Reservations[].Instances[].{InstanceId: InstanceId, MetadataOptions: MetadataOptions.HttpTokens}' --output table 

This settings can check in EC2 > Instances > (Click the Instance check button) > Description > Metadata section on the AWS console.

Non-Default Security Group Control for that Open All Ports to All Ingress Sources (TCP)

for region in `aws ec2 describe-regions --region eu-central-1 --query Regions[*].[RegionName] --output text`; do echo -e "\n #---------- Listing security groups in region: $region --------- #"; for secGroupIPPerm in $(aws ec2 describe-security-groups --region $region --output text --query 'SecurityGroups[*].GroupId');        do echo -e "\n------Listing IP Permissions in group: $secGroupIPPerm ..."; aws ec2 describe-security-groups --region $region --group-ids $secGroupIPPerm --query 'SecurityGroups[*].IpPermissions[]'; done; done;

Cross-Account AssumeRule Policy Lacks External ID and MFA Control

aws iam get-role --role-name Cloudreach_Automated_Patching --query 'Role.AssumeRolePolicyDocument'

Managed Policies Allow All Action or Uses Wildcard in Actions Control

aws iam get-policy-version --policy-arn "arn:aws:iam::aws:policy/AdministratorAccess" --version-id v1 --query 'PolicyVersion.Document' && aws iam get-policy-version --policy-arn "arn:aws:iam::723974773212:policy/RI-TransitGateway-Policy" --version-id v1 --query 'PolicyVersion.Document'

Bucket Access Logging Control

for bucket_name in $(aws s3api list-buckets --query "Buckets[*].Name" --output text); do   echo "Checking whether access logging is enabled for Bucket: $bucket_name" aws s3api get-bucket-logging --bucket "$bucket_name" --query 'LoggingEnabled'; done

Bucket Clear-text (HTTP) Communication Control

for bucket_name in $(aws s3api list-buckets --query "Buckets[*].Name" --output text); do
    echo "Checking whether secure transport enabled attribute is either present or enabled for Bucket: $bucket_name"
    policy_output=$(aws s3api get-bucket-policy --bucket "$bucket_name" --query 'Policy' 2>&1)

    if [[ $policy_output == *"NoSuchBucketPolicy"* ]]; then
        echo "No bucket policy found for $bucket_name"
    else
        echo "$policy_output" | jq --arg bucket "$bucket_name" -r 'try(if (.secure_transport_enabled == false) then "Secure transport is set to false for Bucket: \($bucket)" else "Secure transport is set to true for Bucket: \($bucket)" end) catch "Secure_transport_enabled attribute not found on bucket \($bucket)."'
    fi
    echo ""
done

Bucket Server-Side Encryption Control

for bucket_name in $(aws s3api list-buckets --query "Buckets[*].Name" --output text); do
    echo "Checking whether server-side encryption is enabled for Bucket: $bucket_name"
    policy_output=$(aws s3api get-bucket-policy --bucket "$bucket_name" --query 'Policy' 2>&1)
done;

Bucket Public Access Control

for s3Buckets in `aws s3api list-buckets --query 'Buckets[*].Name' --output text | tr '\t' '\n'`; do echo -e "\n #---------- Listing versioning status properties for S3 bucket: $s3Buckets --------- #"; aws s3api get-bucket-acl --bucket $s3Buckets --query 'Grants[?(Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`)]'; done;

Network ACLs with Allow All Engress Traffic Rule (Default) Control

for region in `aws ec2 describe-regions --region us-east-1 --query Regions[*].[RegionName] --output text `; do echo -e "\n #---------- Listing ACLs in region: $region --------- #"; for acl in $(aws ec2 describe-network-acls --region $region --output text --query 'NetworkAcls[*].NetworkAclId' ); do echo -e "\n------Listing ACL details in ACL: $acl ..."; aws ec2 describe-network-acls --region $region --network-acl-ids $acl --query 'NetworkAcls[*].Entries[?(RuleAction==`allow`) && (Egress==`true`)] | []' ; done; done;

User with both password and keys control

aws iam generate-credential-report                                                        
aws iam get-credential-report --query 'Content' --output text | base64 -d | csvjson | jq 'map(select(.password_enabled == "true" and (.access_key_1_active == true or .access_key_2_active == true)) | {user, arn, password_enabled, access_key_1_active, access_key_2_active, mfa_active})'

This settings can check in IAM > Users > (Click the User check button) > Security credentials section on the AWS console.

Deletion Protection on Load Balancer Control

for region in $(aws ec2 describe-regions --query 'Regions[*].RegionName' --output text); do
    echo "Load balancer deletion protection status in region $region:"                   
    for arn in $(aws elbv2 describe-load-balancers --region $region --query 'LoadBalancers[?contains(Type, `application`) || contains(Type, `net`)].LoadBalancerArn' --output text); do
        echo -e "\n#---------- Deletion protection status for load balancer with the ARN: $arn --------- #"
        deletion_protection_enabled=$(aws elbv2 describe-load-balancer-attributes --region $region --load-balancer-arn $arn --query 'Attributes[?Key==`deletion_protection.enabled`].Value' --output text)
        echo "Deletion Protection Enabled: $deletion_protection_enabled"        
    done          
done

This settings can check in EC2 > Load Balancing > Load Balancer > (Click the volumes check button) > Attributes > control the ‘Protection’ section on the AWS console.

Bucket MFA Delete Control

for s3Buckets in `aws s3api list-buckets --query 'Buckets[*].Name' --output text | tr '\t' '\n'`; do echo -e "\n #---------- Listing bucket MFA properties for S3 bucket: $s3Buckets --------- #"; aws s3api get-bucket-versioning --bucket $s3Buckets --query 'MFADelete'; done;

This settings can control in S3 > Buckets > (Click the bucket check button) > Properties > control the ‘Multi-factor authentication (MFA) delete’ section on the AWS console.

Alarm without associated action control

aws cloudwatch describe-alarms --region eu-west-1 --query 'MetricAlarms[?length(AlarmActions) == `0`]'

RDP Port Check to All Ingress Sources

for region in $(aws ec2 describe-regions --region eu-central-1 --query 'Regions[].RegionName' --output text);do echo "Region: $region" && aws ec2 describe-security-groups --region "$region" --query "SecurityGroups[?IpPermissions[?ToPort==\`3389\` && IpProtocol==\`tcp\` && IpRanges[?CidrIp=='0.0.0.0/0']]].{Region: \`$region\`, GroupId: GroupId, GroupName: GroupName, Ingress: IpPermissions[?ToPort==\`3389\` && IpProtocol==\`tcp\` && IpRanges[?CidrIp=='0.0.0.0/0']]}"; done

SSH Port Check to All Ingress Sources

for region in $(aws ec2 describe-regions --region eu-central-1 --query 'Regions[].RegionName' --output text);do echo "Region: $region" && aws ec2 describe-security-groups --region $region --query "SecurityGroups[?IpPermissions[?ToPort==\`22\` && IpProtocol==\`tcp\` && IpRanges[?CidrIp=="

Data Events Logging Configuration Check for S3 Buckets

aws cloudtrail describe-trails --region eu-west-1 --trail-name-list riverisland-prod-cloudtrail --query 'trailList[0].{ARN: TrailARN, CloudWatchLogsLogGroupArn: CloudWatchLogsLogGroupArn, CloudWatchLogsRoleArn: CloudWatchLogsRoleArn, DataEventsEnabled: IsMultiRegionTrail}' --output json

### ELBv2 Access Log Control

for region in $(aws ec2 describe-regions --query 'Regions[*].RegionName' --output text); do
    echo "Checking access logs enabled status for ELBv2 load balancers in region $region:"
        for arn in $(aws elbv2 describe-load-balancers --region $region --query 'LoadBalancers[?contains(Type, `application`) || contains(Type, `net`)].LoadBalancerArn' --output text); do
        echo -e "\n#---------- Load Balancer ARN: $arn --------- #"
        logs_enabled=$(aws elbv2 describe-load-balancer-attributes --region "$region" --load-balancer-arn "$arn" --query 'Attributes[?Key==`access_logs.s3.enabled`].Value | [0]')
        echo "Access Logs to S3: $logs_enabled" 
    done
done 

Active Access Key Rotation Control

for user in $(aws iam list-users --query 'Users[*].UserName' --output text); do
    # Get all access keys for the user
    keys=$(aws iam list-access-keys --user-name $user --query 'AccessKeyMetadata[?Status==`Active`].{AccessKeyId: AccessKeyId, CreateDate: CreateDate}' --output json)

    # Loop through each access key and check if it's active and older than 90 days
    for key in $(echo "$keys" | jq -r '.[] | @base64'); do
        _jq() {
            echo "${key}" | base64 --decode | jq -r "${1}"
        }

        access_key_id=$(_jq '.AccessKeyId')
        create_date=$(_jq '.CreateDate')

        create_date_unix=$(date -d "$create_date" +%s)
        ninety_days_ago=$(date -d 'now - 90 days' +%s)

        if [ $create_date_unix -lt $ninety_days_ago ]; then
		echo "User: $user - Active Keys:"
            echo "  Access Key: $access_key_id - Created: $create_date"
            echo "  Access Key older than 90 days from today."
		echo ""
        fi
    done
done

KSM Customer Master Keys (CMKs) with Rotation Disable Control

for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
    echo "Region: $region"
    key_ids=($(aws kms list-keys --region "$region" --query 'Keys[*].KeyId' --output text))

    for key_id in "${key_ids[@]}"; do
        rotation_status=$(aws kms get-key-rotation-status --region "$region" --key-id "$key_id" --query 'KeyRotationEnabled' --output text)

        echo "  Key ID: $key_id (Rotation Enabled: $rotation_status)"
    done
done

Security Group Open UDP Port Control

for region in $(aws ec2 describe-regions --region eu-central-1 --query 'Regions[*].[RegionName]' --output text); do
  echo -e "\n #---------- Listing security groups in region: $region --------- #";
  for secGroupIPPerm in $(aws ec2 describe-security-groups --region $region --output text --query 'SecurityGroups[*].GroupId'); do
    echo -e "\n------Listing IP Permissions in group: $secGroupIPPerm ...";
    aws ec2 describe-security-groups --region $region --group-ids $secGroupIPPerm --query 'SecurityGroups[*].IpPermissions[?IpProtocol==`udp`]';
  done;
done;

Flow Log Control

for region in $(aws ec2 describe-regions --region eu-central-1 --query 'Regions[].RegionName' --output text); do
        echo "Region: $region"
    for subnetName in $(aws ec2 describe-subnets --query 'Subnets[*].SubnetId' --region eu-central-1 --output text); do
        echo "Subnet: $subnetName"
        aws ec2 describe-flow-logs --filter Name=resource-id,Values=$subnetName --region $region --output json
    done
done

Unused Security Group Control

EC2 Control

comm -23  <(aws ec2 describe-security-groups --region eu-west-1 --query 'SecurityGroups[*].GroupId' --output text | tr '\t' '\n'| sort) <(aws ec2 describe-instances --region eu-west-1 --query 'Reservations[*].Instances[*].SecurityGroups[*].GroupId' --output text | tr '\t' '\n' | sort | uniq)

ELB Control

aws elb describe-load-balancers --region eu-west-1 --query 'LoadBalancerDescriptions[*].SecurityGroups[*]' --output text | tr '\t' '\n' | sort | uniq

RDS Control

aws rds describe-db-security-groups --region eu-west-1 --query 'DBSecurityGroups[*].EC2SecurityGroups[*].EC2SecurityGroupId' --output text | tr '\t' '\n' | sort | uniq

Password Policy Control

This settings can check in IAM > Account Management > Account Settings section on the AWS console.