Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
This commit is contained in:
Executable
+595
@@ -0,0 +1,595 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#########################################################################################
|
||||
#### vpc-audit.sh — Audit AWS VPC configuration, security groups, and networking ####
|
||||
#### Reports on open security groups, missing flow logs, peering, subnet utilization ####
|
||||
#### Requires: bash 4+, aws-cli v2, jq ####
|
||||
#### ####
|
||||
#### Author: Phil Connor ####
|
||||
#### Contact: contact@mylinux.work ####
|
||||
#### License: MIT ####
|
||||
#### Version 1.01 ####
|
||||
#### ####
|
||||
#### Usage: ####
|
||||
#### export AWS_PROFILE="production" ####
|
||||
#### ./vpc-audit.sh --full ####
|
||||
#### ####
|
||||
#### See --help for all options. ####
|
||||
#########################################################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── Defaults ──────────────────────────────────────────────────────────
|
||||
AWS_REGION="${AWS_REGION:-}"
|
||||
VPC_ID="${VPC_ID:-}"
|
||||
OUTPUT_FORMAT="${OUTPUT_FORMAT:-text}"
|
||||
VERBOSE="${VERBOSE:-false}"
|
||||
COLOR="${COLOR:-auto}"
|
||||
|
||||
# Section flags
|
||||
RUN_FULL="false"
|
||||
RUN_SGS="false"
|
||||
RUN_FLOW="false"
|
||||
RUN_PEER="false"
|
||||
RUN_SUBNETS="false"
|
||||
RUN_ENDPOINTS="false"
|
||||
RUN_NACLS="false"
|
||||
|
||||
# ── State ─────────────────────────────────────────────────────────────
|
||||
SCRIPT_NAME="$(basename "$0")"
|
||||
readonly SCRIPT_NAME
|
||||
START_TIME=""
|
||||
PASS_COUNT=0
|
||||
WARN_COUNT=0
|
||||
CRIT_COUNT=0
|
||||
|
||||
readonly DANGEROUS_PORTS="22 3389 3306 5432 6379 27017 9200 9300 11211"
|
||||
|
||||
# ── Colors ────────────────────────────────────────────────────────────
|
||||
setup_colors() {
|
||||
if [[ "$COLOR" == "never" ]]; then
|
||||
RED="" GREEN="" YELLOW="" BLUE="" BOLD="" DIM="" RESET=""
|
||||
return
|
||||
fi
|
||||
if [[ "$COLOR" == "always" ]] || [[ -t 1 ]]; then
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
BLUE='\033[0;34m'
|
||||
BOLD='\033[1m'
|
||||
DIM='\033[2m'
|
||||
RESET='\033[0m'
|
||||
else
|
||||
RED="" GREEN="" YELLOW="" BLUE="" BOLD="" DIM="" RESET=""
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Logging ───────────────────────────────────────────────────────────
|
||||
log() { echo -e "${BLUE}[INFO]${RESET} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${RESET} $*" >&2; ((WARN_COUNT++)) || true; }
|
||||
err() { echo -e "${RED}[ERROR]${RESET} $*" >&2; }
|
||||
verbose() { if [[ "$VERBOSE" == "true" ]]; then echo -e "${DIM}[DEBUG]${RESET} $*"; fi; }
|
||||
|
||||
die() { err "$*"; exit 1; }
|
||||
|
||||
# ── AWS CLI wrapper ───────────────────────────────────────────────────
|
||||
aws_cmd() {
|
||||
local args=("$@")
|
||||
[[ -n "$AWS_REGION" ]] && args+=(--region "$AWS_REGION")
|
||||
verbose "aws ${args[*]}"
|
||||
aws "${args[@]}"
|
||||
}
|
||||
|
||||
# ── Dependency check ──────────────────────────────────────────────────
|
||||
check_deps() {
|
||||
for cmd in aws jq; do
|
||||
if ! command -v "$cmd" &>/dev/null; then
|
||||
die "${cmd} is required but not installed"
|
||||
fi
|
||||
done
|
||||
|
||||
if ! aws sts get-caller-identity &>/dev/null; then
|
||||
die "AWS credentials not configured or expired"
|
||||
fi
|
||||
|
||||
if [[ -z "$AWS_REGION" ]]; then
|
||||
AWS_REGION=$(aws configure get region 2>/dev/null || echo "")
|
||||
if [[ -z "$AWS_REGION" ]]; then
|
||||
die "AWS_REGION is required"
|
||||
fi
|
||||
fi
|
||||
verbose "Using region: ${AWS_REGION}"
|
||||
}
|
||||
|
||||
should_show() {
|
||||
[[ "$RUN_FULL" == "true" ]] && return 0
|
||||
case "$1" in
|
||||
sgs) [[ "$RUN_SGS" == "true" ]] ;;
|
||||
flow) [[ "$RUN_FLOW" == "true" ]] ;;
|
||||
peer) [[ "$RUN_PEER" == "true" ]] ;;
|
||||
subnets) [[ "$RUN_SUBNETS" == "true" ]] ;;
|
||||
endpoints) [[ "$RUN_ENDPOINTS" == "true" ]] ;;
|
||||
nacls) [[ "$RUN_NACLS" == "true" ]] ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ── Get VPC list ──────────────────────────────────────────────────────
|
||||
get_vpcs() {
|
||||
if [[ -n "$VPC_ID" ]]; then
|
||||
echo "$VPC_ID"
|
||||
else
|
||||
aws_cmd ec2 describe-vpcs \
|
||||
--query 'Vpcs[*].VpcId' \
|
||||
--output text 2>/dev/null | tr '\t' '\n'
|
||||
fi
|
||||
}
|
||||
|
||||
get_vpc_name() {
|
||||
local vid="$1"
|
||||
# shellcheck disable=SC2016
|
||||
aws_cmd ec2 describe-vpcs \
|
||||
--vpc-ids "$vid" \
|
||||
--query 'Vpcs[0].Tags[?Key==`Name`].Value | [0]' \
|
||||
--output text 2>/dev/null || echo "N/A"
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# SECURITY GROUPS
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
audit_security_groups() {
|
||||
log "Auditing security groups..."
|
||||
|
||||
local sg_filter=()
|
||||
[[ -n "$VPC_ID" ]] && sg_filter=(--filters "Name=vpc-id,Values=${VPC_ID}")
|
||||
|
||||
local sgs_json
|
||||
sgs_json=$(aws_cmd ec2 describe-security-groups \
|
||||
"${sg_filter[@]}" \
|
||||
--query 'SecurityGroups[*].{Id:GroupId,Name:GroupName,VpcId:VpcId,Ingress:IpPermissions}' \
|
||||
--output json 2>/dev/null)
|
||||
|
||||
local total_sgs
|
||||
total_sgs=$(echo "$sgs_json" | jq 'length')
|
||||
log "Found ${total_sgs} security group(s)"
|
||||
|
||||
# Check for 0.0.0.0/0 ingress
|
||||
echo ""
|
||||
echo -e " ${BOLD}Open Ingress Rules (0.0.0.0/0)${RESET}"
|
||||
printf " ${BOLD}%-14s %-24s %-10s %-8s %s${RESET}\n" "SG ID" "NAME" "PORT" "PROTO" "SEVERITY"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..70})"
|
||||
|
||||
local open_count=0
|
||||
echo "$sgs_json" | jq -c '.[]' | while IFS= read -r sg; do
|
||||
local sg_id sg_name
|
||||
sg_id=$(echo "$sg" | jq -r '.Id')
|
||||
sg_name=$(echo "$sg" | jq -r '.Name')
|
||||
|
||||
echo "$sg" | jq -c '.Ingress[]?' | while IFS= read -r rule; do
|
||||
local has_open
|
||||
has_open=$(echo "$rule" | jq '[.IpRanges[]? | select(.CidrIp == "0.0.0.0/0")] | length')
|
||||
|
||||
if [[ "$has_open" -gt 0 ]]; then
|
||||
local proto from_port to_port
|
||||
proto=$(echo "$rule" | jq -r '.IpProtocol')
|
||||
from_port=$(echo "$rule" | jq -r '.FromPort // "all"')
|
||||
to_port=$(echo "$rule" | jq -r '.ToPort // "all"')
|
||||
|
||||
local port_display="$from_port"
|
||||
[[ "$from_port" != "$to_port" ]] && port_display="${from_port}-${to_port}"
|
||||
[[ "$proto" == "-1" ]] && { proto="all"; port_display="all"; }
|
||||
|
||||
local severity="WARN"
|
||||
local sev_color="$YELLOW"
|
||||
for dp in $DANGEROUS_PORTS; do
|
||||
if [[ "$from_port" == "$dp" || "$port_display" == "all" ]]; then
|
||||
severity="CRITICAL"
|
||||
sev_color="$RED"
|
||||
((CRIT_COUNT++)) || true
|
||||
break
|
||||
fi
|
||||
done
|
||||
[[ "$severity" == "WARN" ]] && { ((WARN_COUNT++)) || true; }
|
||||
|
||||
printf " %-14s %-24s %-10s %-8s ${sev_color}%s${RESET}\n" \
|
||||
"$sg_id" "${sg_name:0:24}" "$port_display" "$proto" "$severity"
|
||||
((open_count++)) || true
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [[ "$open_count" -eq 0 ]]; then
|
||||
echo -e " ${GREEN}No open ingress rules found ✓${RESET}"
|
||||
((PASS_COUNT++)) || true
|
||||
fi
|
||||
|
||||
# Unused security groups
|
||||
echo ""
|
||||
echo -e " ${BOLD}Unused Security Groups${RESET}"
|
||||
local unused=0
|
||||
echo "$sgs_json" | jq -r '.[].Id' | while IFS= read -r sg_id; do
|
||||
local eni_count
|
||||
eni_count=$(aws_cmd ec2 describe-network-interfaces \
|
||||
--filters "Name=group-id,Values=${sg_id}" \
|
||||
--query 'NetworkInterfaces | length(@)' \
|
||||
--output text 2>/dev/null) || continue
|
||||
|
||||
if [[ "$eni_count" -eq 0 ]]; then
|
||||
local sg_name
|
||||
sg_name=$(echo "$sgs_json" | jq -r ".[] | select(.Id == \"${sg_id}\") | .Name")
|
||||
[[ "$sg_name" == "default" ]] && continue
|
||||
echo -e " ${YELLOW}⊘${RESET} ${sg_id} (${sg_name}) — not attached to any ENI"
|
||||
((unused++)) || true
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$unused" -eq 0 ]]; then
|
||||
echo -e " ${GREEN}No unused security groups ✓${RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# FLOW LOGS
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
audit_flow_logs() {
|
||||
log "Checking VPC flow logs..."
|
||||
|
||||
echo ""
|
||||
echo -e " ${BOLD}VPC Flow Log Status${RESET}"
|
||||
printf " ${BOLD}%-22s %-24s %s${RESET}\n" "VPC ID" "NAME" "FLOW LOGS"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..60})"
|
||||
|
||||
local vpcs
|
||||
vpcs=$(get_vpcs)
|
||||
|
||||
while IFS= read -r vpc_id; do
|
||||
[[ -z "$vpc_id" ]] && continue
|
||||
local vpc_name
|
||||
vpc_name=$(get_vpc_name "$vpc_id")
|
||||
[[ "$vpc_name" == "None" ]] && vpc_name="N/A"
|
||||
|
||||
local flow_count
|
||||
flow_count=$(aws_cmd ec2 describe-flow-logs \
|
||||
--filter "Name=resource-id,Values=${vpc_id}" \
|
||||
--query 'FlowLogs | length(@)' \
|
||||
--output text 2>/dev/null) || flow_count=0
|
||||
|
||||
if [[ "$flow_count" -gt 0 ]]; then
|
||||
printf " %-22s %-24s ${GREEN}enabled (%s)${RESET}\n" "$vpc_id" "${vpc_name:0:24}" "$flow_count"
|
||||
((PASS_COUNT++)) || true
|
||||
else
|
||||
printf " %-22s %-24s ${RED}NONE${RESET}\n" "$vpc_id" "${vpc_name:0:24}"
|
||||
((CRIT_COUNT++)) || true
|
||||
fi
|
||||
done <<< "$vpcs"
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# VPC PEERING
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
audit_peering() {
|
||||
log "Checking VPC peering connections..."
|
||||
|
||||
local peering_json
|
||||
peering_json=$(aws_cmd ec2 describe-vpc-peering-connections \
|
||||
--query 'VpcPeeringConnections[*].{Id:VpcPeeringConnectionId,Status:Status.Code,Requester:RequesterVpcInfo.VpcId,Accepter:AccepterVpcInfo.VpcId,RequesterCIDR:RequesterVpcInfo.CidrBlock,AccepterCIDR:AccepterVpcInfo.CidrBlock}' \
|
||||
--output json 2>/dev/null)
|
||||
|
||||
local total
|
||||
total=$(echo "$peering_json" | jq 'length')
|
||||
|
||||
echo ""
|
||||
echo -e " ${BOLD}VPC Peering Connections${RESET}"
|
||||
|
||||
if [[ "$total" -eq 0 ]]; then
|
||||
echo " No peering connections found"
|
||||
return
|
||||
fi
|
||||
|
||||
printf " ${BOLD}%-26s %-14s %-14s %s${RESET}\n" "PEERING ID" "REQUESTER" "ACCEPTER" "STATUS"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..65})"
|
||||
|
||||
echo "$peering_json" | jq -c '.[]' | while IFS= read -r peer; do
|
||||
local peer_id status requester accepter
|
||||
peer_id=$(echo "$peer" | jq -r '.Id')
|
||||
status=$(echo "$peer" | jq -r '.Status')
|
||||
requester=$(echo "$peer" | jq -r '.Requester')
|
||||
accepter=$(echo "$peer" | jq -r '.Accepter')
|
||||
|
||||
local color="$GREEN"
|
||||
[[ "$status" != "active" ]] && color="$YELLOW"
|
||||
|
||||
printf " %-26s %-14s %-14s ${color}%s${RESET}\n" "$peer_id" "$requester" "$accepter" "$status"
|
||||
done
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# SUBNET UTILIZATION
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
audit_subnets() {
|
||||
log "Checking subnet utilization..."
|
||||
|
||||
local subnet_filter=()
|
||||
[[ -n "$VPC_ID" ]] && subnet_filter=(--filters "Name=vpc-id,Values=${VPC_ID}")
|
||||
|
||||
local subnets_json
|
||||
subnets_json=$(aws_cmd ec2 describe-subnets \
|
||||
"${subnet_filter[@]}" \
|
||||
--query 'Subnets[*].{Id:SubnetId,VpcId:VpcId,AZ:AvailabilityZone,CIDR:CidrBlock,Available:AvailableIpAddressCount}' \
|
||||
--output json 2>/dev/null)
|
||||
|
||||
echo ""
|
||||
echo -e " ${BOLD}Subnet IP Utilization${RESET}"
|
||||
printf " ${BOLD}%-18s %-14s %-16s %-20s %8s %s${RESET}\n" "SUBNET" "VPC" "AZ" "CIDR" "AVAIL" "STATUS"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..90})"
|
||||
|
||||
echo "$subnets_json" | jq -c '.[]' | while IFS= read -r subnet; do
|
||||
local sid vpc_id az cidr avail
|
||||
sid=$(echo "$subnet" | jq -r '.Id')
|
||||
vpc_id=$(echo "$subnet" | jq -r '.VpcId')
|
||||
az=$(echo "$subnet" | jq -r '.AZ')
|
||||
cidr=$(echo "$subnet" | jq -r '.CIDR')
|
||||
avail=$(echo "$subnet" | jq -r '.Available')
|
||||
|
||||
# Calculate total IPs from CIDR
|
||||
local prefix
|
||||
prefix=$(echo "$cidr" | cut -d/ -f2)
|
||||
local total_ips=$(( (1 << (32 - prefix)) - 5 ))
|
||||
[[ "$total_ips" -lt 0 ]] && total_ips=0
|
||||
|
||||
local pct_free=100
|
||||
if [[ "$total_ips" -gt 0 ]]; then
|
||||
pct_free=$(( avail * 100 / total_ips ))
|
||||
fi
|
||||
|
||||
local status="OK"
|
||||
local color="$GREEN"
|
||||
if [[ "$pct_free" -lt 10 ]]; then
|
||||
status="CRITICAL"
|
||||
color="$RED"
|
||||
((CRIT_COUNT++)) || true
|
||||
elif [[ "$pct_free" -lt 20 ]]; then
|
||||
status="LOW"
|
||||
color="$YELLOW"
|
||||
((WARN_COUNT++)) || true
|
||||
else
|
||||
((PASS_COUNT++)) || true
|
||||
fi
|
||||
|
||||
printf " %-18s %-14s %-16s %-20s %8s ${color}%s${RESET}\n" \
|
||||
"$sid" "${vpc_id:0:14}" "$az" "$cidr" "$avail" "$status"
|
||||
done
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# VPC ENDPOINTS
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
audit_endpoints() {
|
||||
log "Listing VPC endpoints..."
|
||||
|
||||
local ep_filter=()
|
||||
[[ -n "$VPC_ID" ]] && ep_filter=(--filters "Name=vpc-id,Values=${VPC_ID}")
|
||||
|
||||
local ep_json
|
||||
ep_json=$(aws_cmd ec2 describe-vpc-endpoints \
|
||||
"${ep_filter[@]}" \
|
||||
--query 'VpcEndpoints[*].{Id:VpcEndpointId,Service:ServiceName,Type:VpcEndpointType,VpcId:VpcId,State:State}' \
|
||||
--output json 2>/dev/null)
|
||||
|
||||
local total
|
||||
total=$(echo "$ep_json" | jq 'length')
|
||||
|
||||
echo ""
|
||||
echo -e " ${BOLD}VPC Endpoints${RESET}"
|
||||
|
||||
if [[ "$total" -eq 0 ]]; then
|
||||
echo " No VPC endpoints found"
|
||||
return
|
||||
fi
|
||||
|
||||
printf " ${BOLD}%-26s %-40s %-12s %s${RESET}\n" "ENDPOINT ID" "SERVICE" "TYPE" "STATE"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..85})"
|
||||
|
||||
echo "$ep_json" | jq -c '.[]' | while IFS= read -r ep; do
|
||||
local ep_id service ep_type state
|
||||
ep_id=$(echo "$ep" | jq -r '.Id')
|
||||
service=$(echo "$ep" | jq -r '.Service')
|
||||
ep_type=$(echo "$ep" | jq -r '.Type')
|
||||
state=$(echo "$ep" | jq -r '.State')
|
||||
|
||||
local color="$GREEN"
|
||||
[[ "$state" != "available" ]] && color="$YELLOW"
|
||||
|
||||
printf " %-26s %-40s %-12s ${color}%s${RESET}\n" "$ep_id" "${service:0:40}" "$ep_type" "$state"
|
||||
done
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# NETWORK ACLS
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
audit_nacls() {
|
||||
log "Auditing network ACLs..."
|
||||
|
||||
local nacl_filter=()
|
||||
[[ -n "$VPC_ID" ]] && nacl_filter=(--filters "Name=vpc-id,Values=${VPC_ID}")
|
||||
|
||||
local nacls_json
|
||||
nacls_json=$(aws_cmd ec2 describe-network-acls \
|
||||
"${nacl_filter[@]}" \
|
||||
--output json 2>/dev/null)
|
||||
|
||||
echo ""
|
||||
echo -e " ${BOLD}Overly Permissive Network ACL Rules${RESET}"
|
||||
|
||||
local found=0
|
||||
echo "$nacls_json" | jq -c '.NetworkAcls[]' | while IFS= read -r nacl; do
|
||||
local nacl_id
|
||||
nacl_id=$(echo "$nacl" | jq -r '.NetworkAclId')
|
||||
|
||||
echo "$nacl" | jq -c '.Entries[]' | while IFS= read -r entry; do
|
||||
local cidr rule_action egress protocol rule_num
|
||||
cidr=$(echo "$entry" | jq -r '.CidrBlock // ""')
|
||||
rule_action=$(echo "$entry" | jq -r '.RuleAction')
|
||||
egress=$(echo "$entry" | jq -r '.Egress')
|
||||
protocol=$(echo "$entry" | jq -r '.Protocol')
|
||||
rule_num=$(echo "$entry" | jq -r '.RuleNumber')
|
||||
|
||||
# Skip default deny-all rules (rule 32767)
|
||||
[[ "$rule_num" == "32767" ]] && continue
|
||||
|
||||
if [[ "$cidr" == "0.0.0.0/0" && "$rule_action" == "allow" && "$protocol" == "-1" ]]; then
|
||||
local direction="ingress"
|
||||
[[ "$egress" == "true" ]] && direction="egress"
|
||||
|
||||
echo -e " ${YELLOW}!${RESET} ${nacl_id} — rule ${rule_num}: allow all ${direction} from 0.0.0.0/0"
|
||||
found=1
|
||||
((WARN_COUNT++)) || true
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [[ "$found" -eq 0 ]]; then
|
||||
echo -e " ${GREEN}No overly permissive NACL rules found ✓${RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# SUMMARY
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
print_summary() {
|
||||
echo ""
|
||||
echo -e " ${BOLD}═══════════════════════════════════════${RESET}"
|
||||
echo -e " ${BOLD}VPC Audit Summary${RESET}"
|
||||
echo -e " ${BOLD}═══════════════════════════════════════${RESET}"
|
||||
echo -e " ${GREEN}PASS:${RESET} ${PASS_COUNT}"
|
||||
echo -e " ${YELLOW}WARN:${RESET} ${WARN_COUNT}"
|
||||
echo -e " ${RED}CRITICAL:${RESET} ${CRIT_COUNT}"
|
||||
echo " ───────────────────────────────────────"
|
||||
|
||||
local end_time
|
||||
end_time=$(date +%s)
|
||||
echo " Completed in $(( end_time - START_TIME ))s"
|
||||
|
||||
if [[ "$CRIT_COUNT" -gt 0 ]]; then
|
||||
echo ""
|
||||
echo -e " ${RED}Action required: ${CRIT_COUNT} critical finding(s)${RESET}"
|
||||
exit 2
|
||||
elif [[ "$WARN_COUNT" -gt 0 ]]; then
|
||||
echo ""
|
||||
echo -e " ${YELLOW}Review recommended: ${WARN_COUNT} warning(s)${RESET}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# HELP
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
Usage: $SCRIPT_NAME [MODE] [OPTIONS]
|
||||
|
||||
Audit AWS VPC configuration and security.
|
||||
|
||||
MODES:
|
||||
--full Run all audit checks
|
||||
--security-groups Audit security group rules
|
||||
--flow-logs Check VPC flow log status
|
||||
--peering List VPC peering connections
|
||||
--subnets Check subnet IP utilization
|
||||
--endpoints List VPC endpoints
|
||||
--nacls Audit network ACL rules
|
||||
|
||||
OPTIONS:
|
||||
--vpc-id VPC_ID Scope audit to a specific VPC
|
||||
--format FORMAT Output: text (default), json, csv
|
||||
--verbose Debug output
|
||||
--no-color Disable colored output
|
||||
--help, -h Show this help
|
||||
|
||||
EXIT CODES:
|
||||
0 All checks passed
|
||||
1 Warnings found
|
||||
2 Critical findings
|
||||
|
||||
ENVIRONMENT VARIABLES:
|
||||
AWS_PROFILE AWS CLI profile
|
||||
AWS_REGION AWS region
|
||||
VPC_ID Target VPC ID
|
||||
OUTPUT_FORMAT Output format (default: text)
|
||||
VERBOSE Debug output (default: false)
|
||||
COLOR Color mode: auto, always, never
|
||||
|
||||
EXAMPLES:
|
||||
# Full VPC audit
|
||||
./$SCRIPT_NAME --full
|
||||
|
||||
# Audit specific VPC
|
||||
./$SCRIPT_NAME --full --vpc-id vpc-0abc123
|
||||
|
||||
# Security groups only
|
||||
./$SCRIPT_NAME --security-groups
|
||||
|
||||
# Subnet utilization
|
||||
./$SCRIPT_NAME --subnets
|
||||
EOF
|
||||
}
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# MAIN
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
main() {
|
||||
local mode_set="false"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--full) RUN_FULL="true"; mode_set="true"; shift ;;
|
||||
--security-groups) RUN_SGS="true"; mode_set="true"; shift ;;
|
||||
--flow-logs) RUN_FLOW="true"; mode_set="true"; shift ;;
|
||||
--peering) RUN_PEER="true"; mode_set="true"; shift ;;
|
||||
--subnets) RUN_SUBNETS="true"; mode_set="true"; shift ;;
|
||||
--endpoints) RUN_ENDPOINTS="true"; mode_set="true"; shift ;;
|
||||
--nacls) RUN_NACLS="true"; mode_set="true"; shift ;;
|
||||
--vpc-id) VPC_ID="$2"; shift 2 ;;
|
||||
--format) OUTPUT_FORMAT="$2"; shift 2 ;;
|
||||
--verbose) VERBOSE="true"; shift ;;
|
||||
--no-color) COLOR="never"; shift ;;
|
||||
--help|-h) show_help; exit 0 ;;
|
||||
*) die "Unknown option: $1 (see --help)" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
setup_colors
|
||||
|
||||
if [[ "$mode_set" == "false" ]]; then err "No mode specified"; echo ""; show_help; exit 1; fi
|
||||
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}VPC Audit${RESET}"
|
||||
echo "Region: ${AWS_REGION:-$(aws configure get region 2>/dev/null || echo 'default')}"
|
||||
[[ -n "$VPC_ID" ]] && echo "VPC: ${VPC_ID}"
|
||||
echo "Time: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
echo ""
|
||||
|
||||
check_deps
|
||||
|
||||
should_show "sgs" && audit_security_groups
|
||||
should_show "flow" && audit_flow_logs
|
||||
should_show "peer" && audit_peering
|
||||
should_show "subnets" && audit_subnets
|
||||
should_show "endpoints" && audit_endpoints
|
||||
should_show "nacls" && audit_nacls
|
||||
|
||||
print_summary
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user