Skip to content

raajheshkannaa/green-stone

Repository files navigation

Green Stone

Continuous Security Group Rule Change Detection & Response at Scale

Get notified of Security Group changes across all AWS Accounts & Regions in an AWS Organization, with the ability to revert those changes with a single button click from Slack.

Built with AWS CDK (Python) — deploy the entire stack in one language, no Terraform or CSPM tools required. Designed for small-to-medium teams (0-200) running AWS at scale who need real-time network security controls without vendor lock-in.

MITRE ATT&CK: T1562.007 — Impair Defenses: Disable or Modify Cloud Firewall

Architecture

Green Stone Architecture

How It Works

  1. EventBridge triggers sg-detect Lambda every 10 minutes
  2. sg-detect assumes cloudtrail-lake-read-role in the Organization account and queries CloudTrail Lake for AuthorizeSecurityGroupIngress events in the last 20 minutes (overlapping window to avoid missing events)
  3. New security group changes are stored in DynamoDB and sent to Slack as interactive messages with Ignore and Deny buttons
  4. Security group changes are allowed by default — security doesn't add friction to operations
  5. If a user clicks Deny, Slack sends the callback to API Gatewaysg-respond Lambda
  6. sg-respond reads the event from DynamoDB, assumes spoke-001 role in the target account, and calls revoke_security_group_ingress to revert the change
  7. The Slack message is updated with who approved/denied the change

Components

Component Purpose
sg-detect (Lambda) Queries CloudTrail Lake, stores events, sends Slack alerts
sg-respond (Lambda) Handles Slack callbacks, reverts SG changes
API Gateway Receives Slack interactive message webhooks
DynamoDB secgrouprequests Stores SG change event details by CloudTrail requestId
EventBridge Rule Triggers sg-detect every 10 minutes
VPC (Private Subnet + NAT) Lambda runs in private subnet for outbound-only access

Prerequisites

  1. IAM Hub-Spoke Roles — deployed via FleetAccess:

    • hub-001 in Security Account (assumed by both Lambdas)
    • spoke-001 in all member accounts (assumed by sg-respond to revert changes)
    • cloudtrail-lake-read-role in Organization account (assumed by sg-detect to query)
  2. CloudTrail Lake — enabled in the Organization account with an Event Data Store aggregating across all accounts

  3. Slack App — with:

    • Incoming Webhooks enabled
    • Interactivity enabled (URL will be the API Gateway endpoint from CDK output)
    • Note the Signing Secret for request verification
  4. AWS CDKnpm install -g aws-cdk

Setup

git clone https://github.com/raajheshkannaa/green-stone
cd green-stone

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Configuration

Copy config.py.example to each of these 4 locations:

config.py
src/revertsg-1/config.py
src/revertsg-2/config.py
stacks/config.py

Fill in your values:

AUTOMATION_ACCOUNT = '123456789012'    # Where Lambdas run
ORG_ACCOUNT = '987654321098'           # Where CloudTrail Lake lives
CLOUDTRAIL_LAKE_READ_ROLE = 'cloudtrail-lake-read-role'
HOOK_URL = 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'
SIGNINGSECRET = 'your-slack-signing-secret'

Or set them as environment variables (recommended for production — the CDK stack passes them to Lambda automatically).

Deploy

# Verify stacks
cdk ls

# Synthesize CloudFormation
cdk synth

# Deploy with Security Account credentials
cdk deploy --profile security-account

CDK deploys a CodePipeline that creates a CodeCommit repo. Push your code to that repo and the pipeline handles the rest.

The CDK output will print the API Gateway URL — update your Slack App's Interactivity URL with this.

Design Decisions

  • Allow by default, deny explicitly — SG changes go through unless a security engineer clicks Deny. This prevents security from blocking operations while still maintaining oversight.
  • 20-minute lookback window — CloudTrail events can be delayed 2-3 minutes. The 10-minute trigger with 20-minute lookback ensures overlap so no events are missed.
  • DynamoDB dedupConditionExpression='attribute_not_exists(requestid)' ensures the same event isn't processed twice across overlapping windows.
  • VPC-bound Lambdas — run in private subnets with NAT for outbound-only access.
  • PAY_PER_REQUEST DynamoDB — no need to manage capacity for low-volume security events.

Cost Estimate

For a typical organization (~50 accounts, ~10 SG changes/day):

  • Lambda: ~$0.50/month (2 functions, 10-min intervals)
  • DynamoDB: ~$0.25/month (on-demand, low volume)
  • API Gateway: ~$0.01/month (Slack callbacks only)
  • NAT Gateway: ~$35/month (this is the main cost)
  • CloudTrail Lake: ~$2.50/GB ingested (shared across all detections)

Total: ~$38/month (dominated by NAT Gateway)

Related Projects

  • aws-cloudtrail-lake-detections — Additional CloudTrail Lake detections (compromised keys, public resources, CloudTrail tampering)
  • fleet-access — Hub-Spoke IAM role deployment (prerequisite for this project)

License

MIT

About

Real-time Security Group change detection & one-click revert across AWS Organizations — CDK + Python + CloudTrail Lake + Slack ChatOps

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages