Secure AWS infrastructure foundation built with Terraform, featuring AWS Config aggregator for organization-wide compliance monitoring and security testing lab environments.
This project establishes a production-grade foundation for AWS security infrastructure using Infrastructure as Code (IaC) principles. It implements comprehensive security monitoring with AWS Config, IAM security roles, and a hands-on security testing laboratory.
Key Features:
- AWS Config Aggregator: Organization-wide compliance monitoring across all AWS accounts and regions
- Security Testing Lab: Ubuntu target + attacker instances with Kali tools for offensive/defensive testing
- Multi-Account Management: IAM roles for cross-account access via IAM Identity Center
- Configuration Recording: Continuous tracking of all AWS resource configurations
- Security Monitoring: AWS Config recorder, Config aggregator, and Macie integration
- Local State Management: Simplified Terraform state management for rapid iteration
- Security First: IMDSv2 required, encrypted EBS, public access blocked on S3 buckets
Most AWS security IaC is reactive — controls added after the fact. This foundation starts from the security posture: Config aggregation for drift detection, credential-less CI/CD via OIDC (no long-lived keys in pipelines), and an integrated security lab for adversarial testing against the same infrastructure you're defending.
- Terraform - Infrastructure as Code for AWS resource provisioning
- AWS Config - Resource configuration recording and organization-wide aggregation
- AWS EC2 - Security lab instances (Ubuntu target + attacker with Kali tools)
- AWS S3 - Encrypted storage for AWS Config snapshots and Macie findings
- AWS IAM - Security analyst roles, Config recorder roles, cross-account access
- AWS SSM - Session Manager for secure instance access
- AWS Macie - Sensitive data discovery and classification
┌─────────────────┐
│ Your Admin │
│ Workstation │
└────────┬────────┘
│ SSH/RDP/SSM
▼
┌────────────────────────────────────────────────────────────┐
│ AWS VPC (172.31.0.0/16) │
│ ┌─────────────────────┐ ┌─────────────────────────┐ │
│ │ Attacker Box │ │ Ubuntu Target │ │
│ │ (Ubuntu + Kali) │────▶│ (t3.medium) │ │
│ │ │ │ │ │
│ │ - Metasploit │ ALL │ - Ubuntu Desktop │ │
│ │ - Nmap, Hydra │PORTS│ - Apache, MySQL │ │
│ │ - Impacket, CrackME │ │ - XRDP for remote │ │
│ │ - SecLists, PEASS │ │ - Vulnerable services │ │
│ └─────────────────────┘ └─────────────────────────┘ │
│ SG: kali-attacker SG: ubuntu-target │
└────────────────────────────────────────────────────────────┘
Security Features:
- IMDSv2 required (prevents SSRF credential theft)
- Encrypted EBS volumes
- SSM Session Manager enabled
- CloudWatch detailed monitoring
┌────────────────────────────────────────────────────────────────┐
│ AWS Organization │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Account │ │ Account │ │ Account │ │
│ │ (squinks) │ │ (sec-tools) │ │(log-archive) │ ... │
│ │ │ │ │ │ │ │
│ │ Config │ │ Config │ │ Config │ │
│ │ Recorder │ │ Recorder │ │ Recorder │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └─────────────────┼─────────────────┘ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ Config Aggregator │ │
│ │ (organization-wide) │ │
│ │ All Regions │ │
│ └────────┬───────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ S3 Bucket │ │
│ │ (Config Data) │ │
│ │ Encrypted │ │
│ └─────────────────┘ │
└────────────────────────────────────────────────────────────────┘
Config Features:
- Continuous Recording: Tracks all resource configuration changes
- Organization Aggregation: Centralized view across all AWS accounts
- All Regions: Monitors resources in every AWS region
- Compliance Monitoring: Enables compliance rules and auditing
- 7-Year Retention: Config snapshots retained for compliance requirements
- Encryption at Rest: S3 server-side encryption (AES256) for Config data
- Access Control: IAM service roles with least privilege permissions
- Public Access: Completely blocked via S3 bucket policies
- Audit Trail: S3 versioning and lifecycle policies for Config snapshots
- Compliance: Continuous monitoring of resource configurations
- Terraform >= 1.0
- AWS CLI v2 with SSO configured
- SSH Key for EC2 instance access
- AWS Organizations with multiple accounts (recommended)
- IAM permissions to create:
- EC2 instances and security groups
- IAM roles and policies
- AWS Config recorder and aggregator
- S3 buckets for Config and Macie
- AWS IAM Identity Center (SSO) access
git clone https://github.com/hmbldv/aws-sec.git
cd aws-secEdit the Terraform variables file:
cd terraform/infrastructure
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your valuesExample terraform.tfvars:
aws_account_id = "123456789012" # Your AWS account ID
aws_region = "us-west-1"
environment = "production"
ssh_public_key = "ssh-ed25519 AAAA..." # Your SSH public key
admin_cidr_blocks = ["YOUR_IP/32"] # Restrict to your IP# Authenticate to AWS
aws sso login --profile default
# Initialize Terraform
terraform init
# Review the plan
terraform plan
# Apply to create all resources
terraform applyThe .gitlab-ci.yml pipeline:
- Authenticates to AWS using OIDC (no stored credentials)
- Assumes the
devops-operatorIAM role - Runs Terraform commands with temporary credentials
Current Pipeline Stages:
test- Validates AWS authentication
Future Pipeline Stages (to be implemented):
validate- Terraform fmt and validateplan- Terraform plan on merge requestsapply- Terraform apply on main branchsecurity- tfsec security scanning
The devops-operator role requires this trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/gitlab.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"gitlab.com:aud": "https://gitlab.com"
},
"StringLike": {
"gitlab.com:sub": "project_path:<your-gitlab-username>/<project>:*"
}
}
}
]
}Security Note: The project_path condition restricts this role to only this GitLab project.
# Authenticate to AWS
aws sso login --profile <your-profile>
# Navigate to infrastructure directory
cd terraform/infrastructure
# Initialize with local backend
terraform init
# Plan changes
terraform plan
# Apply changes
terraform applyAutomatic Execution:
- Push to
mainbranch triggers the pipeline - OIDC authentication happens automatically
- No manual AWS credential management needed
Manual Pipeline Trigger:
- Go to GitLab project → CI/CD → Pipelines
- Click "Run Pipeline"
- Select branch and run
- ✅ AWS Config aggregator deployed (organization-wide)
- ✅ AWS Config recorder running (continuous monitoring)
- ✅ Security lab deployed (Ubuntu target + attacker with Kali tools)
- ✅ IAM roles created (SecurityAnalyst, OrganizationAdmin)
- ✅ S3 buckets managed (AWS Config, Macie)
- ✅ GitLab OIDC authentication working
- ⏳ Multi-account scanning (Log Archive access pending)
SSH Access:
# Attacker box (Ubuntu + Kali tools)
ssh -i ~/.ssh/id_ed25519 ubuntu@<attacker-public-ip>
# Target box
ssh -i ~/.ssh/id_ed25519 ubuntu@<target-public-ip>RDP Access (after user-data completes):
- Attacker:
<attacker-public-ip>:3389(user:pentester/ pass:KaliPentester123!) - Target:
<target-public-ip>:3389(user:labuser/ pass:LabPassword123!)
SSM Session Manager:
aws ssm start-session --target <instance-id>- Deploy Config recorders in other organization accounts
- Expand GitLab CI/CD pipeline with Terraform stages
- Implement security scanning (tfsec, checkov)
- Add GuardDuty, Security Hub, CloudTrail
- Encryption: All S3 buckets use AES256 server-side encryption
- Access Control: S3 buckets are private with explicit deny policies
- IMDSv2: Required on all EC2 instances to prevent SSRF attacks
- EBS Encryption: All volumes encrypted at rest
- Network Security: Security groups with principle of least privilege
- No Stored Credentials: OIDC federation eliminates long-lived access keys
- Temporary Credentials: STS provides short-lived credentials (1 hour)
- Least Privilege: IAM roles restricted to specific GitLab project path
- Audit Trail: CloudTrail logs all API calls made by roles
- Never commit credentials to Git (use
.gitignore) - Review Terraform plans before applying
- Enable MFA for AWS console access
- Monitor costs to detect unexpected resource creation
- Stop EC2 instances when not in use (biggest cost savings)
- Restrict CIDR blocks to your actual IP addresses
aws-sec/
├── terraform/
│ └── infrastructure/ # Main infrastructure code
│ ├── config-aggregator.tf # AWS Config aggregator
│ ├── config-recorder.tf # AWS Config recorder
│ ├── security-lab.tf # EC2 instances (target + attacker)
│ ├── iam-policies.tf # SecurityAnalyst, OrganizationAdmin roles
│ ├── s3-buckets.tf # AWS Config and Macie bucket management
│ ├── oidc.tf # GitLab OIDC provider and devops role
│ ├── variables.tf # Input variables
│ └── providers.tf # AWS provider configuration
│
├── docs/ # Additional documentation
│ └── config-aggregator-setup.md # Config aggregator deployment guide
│
├── scripts/ # Automation scripts
├── .gitlab-ci.yml # GitLab CI/CD pipeline
├── .gitignore # Excludes sensitive files
└── README.md # This file
Possible Causes:
- OIDC identity provider not configured in AWS
- IAM role trust policy incorrect
- Project path in trust policy doesn't match
Solution:
- Verify OIDC provider exists:
aws iam list-open-id-connect-providers - Check IAM role trust policy matches your GitLab project path
- Ensure role has necessary permissions
Solution:
# Check recorder status
aws configservice describe-configuration-recorder-status
# Check delivery channel
aws configservice describe-delivery-channels
# Verify S3 bucket permissions
aws s3api get-bucket-policy --bucket config-bucket-<account-id>Possible Causes:
- Security group doesn't allow your IP
- User data script still running
- SSH key mismatch
Solution:
- Update
admin_cidr_blocksin terraform.tfvars with your actual IP - Wait 5-10 minutes for user data to complete
- Verify SSH key matches the one configured in terraform.tfvars
- AWS Config aggregator (organization-wide)
- AWS Config recorder (continuous monitoring)
- Security testing lab (Ubuntu target + attacker)
- IAM roles for security analysts
- S3 bucket management (Config, Macie)
- GitLab OIDC integration
- IMDSv2 enforcement on EC2
- Deploy Config recorders in all organization accounts
- VPC with public/private subnets (dedicated security lab VPC)
- AWS GuardDuty for threat detection
- Security Hub for centralized findings
- CloudTrail for audit logging
- Config rules for compliance monitoring
- KMS keys for encryption
- Terraform plan on merge requests
- Automated security scanning (tfsec, checkov)
- Cost estimation (Infracost)
- Automated testing
- Slack/SNS notifications
- Customer-managed KMS keys for S3 encryption
- MFA delete for S3 buckets
- S3 bucket logging
- VPC endpoints for S3 access
- Secrets management with AWS Secrets Manager
Current Costs (estimated):
- EC2 (t3.medium x2): ~$60/month (if running 24/7) - stop when not in use!
- EBS Storage (90GB): ~$7/month
- AWS Config: ~$2/month per recorder + $0.003 per config item
- S3 Storage: ~$0.023/GB/month (Standard tier)
- S3 Requests: Minimal (Config writes)
- Data Transfer: Free within same region
Cost-Saving Tips:
- Stop EC2 instances when not actively testing (biggest savings!)
- Config data moved to STANDARD_IA after 90 days (~50% cheaper)
- Old Config data moved to Glacier after 365 days (~80% cheaper)
- No KMS charges (using AWS-managed keys)
- Use SSM Session Manager instead of SSH to avoid NAT gateway costs
Estimated Monthly Cost:
- With EC2 running: ~$75/month
- With EC2 stopped: ~$15/month (S3 + Config + EBS storage only)
MIT
Johnny Endrihs
- GitHub: hmbldv
- GitLab: Private GitLab for CI/CD deployment
Built as part of DevSecOps portfolio demonstrating:
- Infrastructure as Code (Terraform)
- AWS Security Best Practices
- AWS Config for Compliance Monitoring
- CI/CD Automation (GitLab)
- OIDC Federation
- Cost Optimization
- Security Testing Lab Environments
Preparing for AWS Certified Security - Specialty