Security Guidelines¶
Security best practices for deploying and operating the SG Provisioner Tool.
Table of Contents¶
Credential Management¶
AWS Credentials¶
Never hardcode credentials. Use one of these methods:
IAM Roles (Recommended for EC2/ECS)
# No credentials needed — automatic from instance metadata docker run --rm \ -v $(pwd)/sg/configs:/app/configs:ro \ -v $(pwd)/sg/reports:/app/reports \ sg-provisioner:latest \ -con my-config.yaml \ -act create-security-groups --force
AWS Profiles (Recommended for Developers)
# Docker -v ~/.aws:/home/sguser/.aws:ro # Local export AWS_PROFILE=production
Environment Variables
-e AWS_ACCESS_KEY_ID=<access_key> -e AWS_SECRET_ACCESS_KEY=<secret_key> -e AWS_DEFAULT_REGION=us-west-2
Credential Rotation¶
Rotate access keys every 90 days
Use temporary credentials (STS AssumeRole) when possible
Monitor credential age with IAM Credential Report
Security Group Design Principles¶
1. Least Privilege¶
Only allow traffic that is explicitly required:
# ✅ Good — specific port, specific source
ingress:
- protocol: tcp
port: 5432
source_tier: app
description: PostgreSQL from app tier only
# ❌ Bad — all ports, all sources
ingress:
- protocol: tcp
port_range: 0-65535
source: 0.0.0.0/0
2. Defense in Depth¶
Layer security controls:
Security Groups (instance level)
Network ACLs (subnet level)
VPC design (network level)
IAM policies (API level)
3. Tier Isolation¶
Use cross-tier references instead of broad CIDRs:
# ✅ Good — only app tier can reach database
ingress:
- protocol: tcp
port: 5432
source_tier: app
# ❌ Bad — entire VPC can reach database
ingress:
- protocol: tcp
port: 5432
source: 10.0.0.0/16
4. Deny by Default¶
Security groups deny all inbound traffic by default. Only add rules for traffic you explicitly need. Keep egress rules minimal.
Rule Best Practices¶
Ingress Rules¶
Pattern |
Risk |
Recommendation |
|---|---|---|
|
HIGH |
Use bastion host or SSM Session Manager |
|
HIGH |
Use VPN or SSM Fleet Manager |
|
CRITICAL |
Never expose databases to internet |
|
LOW |
Acceptable for public web tier |
|
LOW |
Preferred — uses SG reference |
Egress Rules¶
Pattern |
Risk |
Recommendation |
|---|---|---|
All traffic to |
MEDIUM |
Restrict to needed ports |
Port 443 to |
LOW |
Acceptable for AWS API access |
DB port to |
LOW |
Preferred — uses SG reference |
No egress rules |
SAFE |
Database tier — fully isolated |
Port Ranges¶
Avoid broad port ranges:
# ❌ Bad — too broad
- protocol: tcp
port_range: 1024-65535
source: 0.0.0.0/0
# ✅ Good — specific port
- protocol: tcp
port: 8443
source_tier: web
CIDR Restrictions¶
Public Access (0.0.0.0/0)¶
Only acceptable for:
Web tier ingress on ports 80/443
Egress on port 443 (AWS APIs, package repos)
Never use for:
Database ports (3306, 5432, 1521, 1433, 5439, 27017)
SSH (22) or RDP (3389)
Application ports (8080, 8443, 9090)
IPv6 (::/0)¶
Same rules apply as IPv4. The scenario validator flags ::/0 on dangerous ports.
Internal CIDRs¶
When you must use CIDRs instead of tier references:
# ✅ Narrow — specific subnet
source: 10.0.11.0/24
# ⚠️ Broad — entire VPC
source: 10.0.0.0/16
# ❌ Never — entire internet
source: 0.0.0.0/0
CloudFormation Security¶
Stack Protection¶
Use
--forceflag only when intentionalReview templates before deployment (
validate-prov-template)Use
show-changesto preview modificationsRun
check-driftregularly to detect manual changes
Drift Remediation¶
If drift is detected:
Identify who made the change (CloudTrail)
Determine if the change is desired
Either update your config to match, or redeploy to revert
Test Deployments¶
Always test in isolation first:
docker run --rm \
-v ~/.aws:/home/sguser/.aws:ro \
-v $(pwd)/sg/configs:/app/configs:ro \
-v $(pwd)/sg/reports:/app/reports \
sg-provisioner:latest \
-con my-config.yaml \
-act test-deploy
This creates a separate stack with a random suffix — no impact on production.
Docker Security¶
Image Verification¶
# Scan image before use
trivy image sg-provisioner:latest
Runtime Security¶
# Read-only credentials
-v ~/.aws:/home/sguser/.aws:ro
# Read-only config
-v $(pwd)/sg/configs:/app/configs:ro
# No privileged mode
# No host networking
# No extra capabilities
Logging and Monitoring¶
Audit Logs¶
Every action generates a log file in reports/:
globalbank-prod-c001-us-west-2-sg-create-security-groups-20260505_101914_057.log
CloudTrail¶
Monitor for:
CreateSecurityGroup/DeleteSecurityGroupeventsAuthorizeSecurityGroupIngress/RevokeSecurityGroupIngresseventsCreateStack/DeleteStackeventsPutParameter/DeleteParameterevents
CloudWatch Alarms¶
Set alarms for:
Security group rule changes outside CloudFormation
Stack deletion events
Failed API calls (AccessDenied)
Compliance¶
Tagging for Governance¶
tags:
cost_center: Fraud Operations
project: Fraud Detection
owner: fraud-team
compliance: pci-dss
data_classification: confidential
Regular Audits¶
Review security group rules quarterly
Run
check-driftweeklyAudit IAM permissions monthly
Rotate credentials every 90 days
Documentation¶
Keep configs in version control
Document all overrides with descriptions
Maintain change log for production deployments
Security Checklist¶
Before production deployment:
IAM policy generated and scoped to company prefix
VPC exists and is verified
Scenario reviewed — no overly permissive rules
Overrides reviewed — descriptions provided
Template validated locally (
validate-prov-template)Review report generated and approved (
create-review-report)Test deployment successful (
test-deploy)No database ports open to
0.0.0.0/0No SSH/RDP open to the world
Egress rules are minimal
Tags applied for cost allocation and governance
CloudTrail enabled for audit
Credentials are temporary or recently rotated
Docker image scanned for vulnerabilities
References¶
IAM Permissions
Configuration Reference