241 lines
7.0 KiB
Bash
Executable File
241 lines
7.0 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# AWS CDK Stack Validation Script
|
||
#
|
||
# This script performs meta-level validation of CDK stacks before deployment.
|
||
# Run this as part of pre-commit checks to ensure infrastructure quality.
|
||
#
|
||
# Focus areas:
|
||
# - CDK synthesis success validation
|
||
# - CloudFormation template size and resource count checks
|
||
# - Language detection and dependency verification
|
||
# - Integration with cdk-nag (recommended for comprehensive best practice checks)
|
||
#
|
||
# Supports CDK projects in multiple languages:
|
||
# - TypeScript/JavaScript (detects via package.json)
|
||
# - Python (detects via requirements.txt or setup.py)
|
||
# - Java (detects via pom.xml)
|
||
# - C# (detects via .csproj files)
|
||
# - Go (detects via go.mod)
|
||
#
|
||
# For comprehensive CDK best practice validation (IAM policies, security,
|
||
# naming conventions, etc.), use cdk-nag: https://github.com/cdklabs/cdk-nag
|
||
# cdk-nag provides suppression mechanisms and supports all CDK languages.
|
||
|
||
set -e
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
||
|
||
echo "🔍 AWS CDK Stack Validation"
|
||
echo "============================"
|
||
echo ""
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Track validation status
|
||
VALIDATION_PASSED=true
|
||
|
||
# Function to print success
|
||
success() {
|
||
echo -e "${GREEN}✓${NC} $1"
|
||
}
|
||
|
||
# Function to print error
|
||
error() {
|
||
echo -e "${RED}✗${NC} $1"
|
||
VALIDATION_PASSED=false
|
||
}
|
||
|
||
# Function to print warning
|
||
warning() {
|
||
echo -e "${YELLOW}⚠${NC} $1"
|
||
}
|
||
|
||
# Function to print info
|
||
info() {
|
||
echo "ℹ $1"
|
||
}
|
||
|
||
# Check if cdk is installed
|
||
if ! command -v cdk &> /dev/null; then
|
||
error "AWS CDK CLI not found. Install with: npm install -g aws-cdk"
|
||
exit 1
|
||
fi
|
||
|
||
success "AWS CDK CLI found"
|
||
|
||
# Detect CDK project language
|
||
detect_language() {
|
||
if [ -f "${PROJECT_ROOT}/package.json" ]; then
|
||
echo "typescript"
|
||
elif [ -f "${PROJECT_ROOT}/requirements.txt" ] || [ -f "${PROJECT_ROOT}/setup.py" ]; then
|
||
echo "python"
|
||
elif [ -f "${PROJECT_ROOT}/pom.xml" ]; then
|
||
echo "java"
|
||
elif [ -f "${PROJECT_ROOT}/cdk.csproj" ] || find "${PROJECT_ROOT}" -name "*.csproj" 2>/dev/null | grep -q .; then
|
||
echo "csharp"
|
||
elif [ -f "${PROJECT_ROOT}/go.mod" ]; then
|
||
echo "go"
|
||
else
|
||
echo "unknown"
|
||
fi
|
||
}
|
||
|
||
CDK_LANGUAGE=$(detect_language)
|
||
|
||
case "$CDK_LANGUAGE" in
|
||
typescript)
|
||
info "Detected TypeScript/JavaScript CDK project"
|
||
success "package.json found"
|
||
;;
|
||
python)
|
||
info "Detected Python CDK project"
|
||
success "requirements.txt or setup.py found"
|
||
;;
|
||
java)
|
||
info "Detected Java CDK project"
|
||
success "pom.xml found"
|
||
;;
|
||
csharp)
|
||
info "Detected C# CDK project"
|
||
success ".csproj file found"
|
||
;;
|
||
go)
|
||
info "Detected Go CDK project"
|
||
success "go.mod found"
|
||
;;
|
||
unknown)
|
||
warning "Could not detect CDK project language"
|
||
warning "Proceeding with generic validation only"
|
||
;;
|
||
esac
|
||
|
||
echo ""
|
||
info "Running CDK synthesis..."
|
||
|
||
# Synthesize stacks
|
||
if cdk synth --quiet > /dev/null 2>&1; then
|
||
success "CDK synthesis successful"
|
||
else
|
||
error "CDK synthesis failed"
|
||
echo ""
|
||
echo "Run 'cdk synth' for detailed error information"
|
||
exit 1
|
||
fi
|
||
|
||
echo ""
|
||
info "Checking for cdk-nag integration..."
|
||
|
||
# Check if cdk-nag is being used for comprehensive validation
|
||
case "$CDK_LANGUAGE" in
|
||
typescript)
|
||
if grep -r "cdk-nag" "${PROJECT_ROOT}/package.json" 2>/dev/null | grep -q "."; then
|
||
success "cdk-nag found in package.json"
|
||
else
|
||
warning "cdk-nag not found - recommended for comprehensive CDK validation"
|
||
warning "Install with: npm install --save-dev cdk-nag"
|
||
warning "See: https://github.com/cdklabs/cdk-nag"
|
||
fi
|
||
;;
|
||
python)
|
||
if grep -r "cdk-nag" "${PROJECT_ROOT}/requirements.txt" 2>/dev/null | grep -q "."; then
|
||
success "cdk-nag found in requirements.txt"
|
||
elif grep -r "cdk-nag" "${PROJECT_ROOT}/setup.py" 2>/dev/null | grep -q "."; then
|
||
success "cdk-nag found in setup.py"
|
||
else
|
||
warning "cdk-nag not found - recommended for comprehensive CDK validation"
|
||
warning "Install with: pip install cdk-nag"
|
||
warning "See: https://github.com/cdklabs/cdk-nag"
|
||
fi
|
||
;;
|
||
java)
|
||
if grep -r "cdk-nag" "${PROJECT_ROOT}/pom.xml" 2>/dev/null | grep -q "."; then
|
||
success "cdk-nag found in pom.xml"
|
||
else
|
||
warning "cdk-nag not found - recommended for comprehensive CDK validation"
|
||
warning "See: https://github.com/cdklabs/cdk-nag"
|
||
fi
|
||
;;
|
||
csharp)
|
||
if find "${PROJECT_ROOT}" -name "*.csproj" -exec grep -l "CdkNag" {} \; 2>/dev/null | grep -q "."; then
|
||
success "cdk-nag found in .csproj"
|
||
else
|
||
warning "cdk-nag not found - recommended for comprehensive CDK validation"
|
||
warning "See: https://github.com/cdklabs/cdk-nag"
|
||
fi
|
||
;;
|
||
go)
|
||
if grep -r "cdk-nag-go" "${PROJECT_ROOT}/go.mod" 2>/dev/null | grep -q "."; then
|
||
success "cdk-nag-go found in go.mod"
|
||
else
|
||
warning "cdk-nag-go not found - recommended for comprehensive CDK validation"
|
||
warning "See: https://github.com/cdklabs/cdk-nag-go"
|
||
fi
|
||
;;
|
||
esac
|
||
|
||
success "Integration checks completed"
|
||
|
||
echo ""
|
||
info "💡 Note: This script focuses on template and meta-level validation."
|
||
info "For comprehensive CDK best practice checks (IAM, security, naming, etc.),"
|
||
info "use cdk-nag: https://github.com/cdklabs/cdk-nag"
|
||
|
||
echo ""
|
||
info "Checking synthesized templates..."
|
||
|
||
# Get list of synthesized templates
|
||
TEMPLATES=$(find "${PROJECT_ROOT}/cdk.out" -name "*.template.json" 2>/dev/null || echo "")
|
||
|
||
if [ -z "$TEMPLATES" ]; then
|
||
error "No CloudFormation templates found in cdk.out/"
|
||
exit 1
|
||
fi
|
||
|
||
TEMPLATE_COUNT=$(echo "$TEMPLATES" | wc -l)
|
||
success "Found ${TEMPLATE_COUNT} CloudFormation template(s)"
|
||
|
||
# Validate each template
|
||
for template in $TEMPLATES; do
|
||
STACK_NAME=$(basename "$template" .template.json)
|
||
|
||
# Check template size
|
||
TEMPLATE_SIZE=$(wc -c < "$template")
|
||
MAX_SIZE=51200 # 50KB warning threshold
|
||
|
||
if [ "$TEMPLATE_SIZE" -gt "$MAX_SIZE" ]; then
|
||
warning "${STACK_NAME}: Template size (${TEMPLATE_SIZE} bytes) is large"
|
||
warning "Consider using nested stacks to reduce size"
|
||
fi
|
||
|
||
# Count resources
|
||
RESOURCE_COUNT=$(jq '.Resources | length' "$template" 2>/dev/null || echo 0)
|
||
|
||
if [ "$RESOURCE_COUNT" -gt 200 ]; then
|
||
warning "${STACK_NAME}: High resource count (${RESOURCE_COUNT})"
|
||
warning "Consider splitting into multiple stacks"
|
||
else
|
||
success "${STACK_NAME}: ${RESOURCE_COUNT} resources"
|
||
fi
|
||
done
|
||
|
||
echo ""
|
||
echo "============================"
|
||
|
||
if [ "$VALIDATION_PASSED" = true ]; then
|
||
echo -e "${GREEN}✓ Validation passed${NC}"
|
||
echo ""
|
||
info "Stack is ready for deployment"
|
||
exit 0
|
||
else
|
||
echo -e "${RED}✗ Validation failed${NC}"
|
||
echo ""
|
||
error "Please fix the errors above before deploying"
|
||
exit 1
|
||
fi
|