CloudGuard is a serverless Cloud Security Posture Management (CSPM) app. It connects to an AWS account through a read-only IAM role (assumed via STS AssumeRole — no access keys are ever shared), scans for common misconfigurations, and presents findings, a security score, and remediation guidance in a dashboard.
It is a real, working application: the backend is deployed on AWS and scans live accounts. In a test run against a real account it flagged genuinely public S3 buckets, internet-exposed SSH ports, and unencrypted volumes.
Same diagram as Mermaid (renders inline on GitHub)
flowchart TB
User([User]) --> FE["React + TypeScript SPA<br/>(Tailwind + shadcn/ui)"]
FE -->|"sign up / sign in"| Cognito["Amazon Cognito<br/>User Pool"]
Cognito -->|"JWT id token"| FE
FE -->|"REST calls + JWT"| APIGW["API Gateway<br/>(Cognito Authorizer)"]
APIGW --> L1["Lambda<br/>start-scan"]
APIGW --> L2["Lambdas<br/>scans · findings · dashboard"]
L1 -->|"sts:AssumeRole + ExternalId"| Role["CloudGuardScannerRole<br/>(read-only IAM role)"]
Role --> Scan["Scanners:<br/>S3 · Security Groups · IAM MFA<br/>Access Keys · EBS · Unused"]
Scan --> Acct[("Customer AWS Account")]
L1 -->|"persist"| DDB[("DynamoDB<br/>Scans + Findings")]
L2 -->|"read"| DDB
Request flow: the user signs in with Cognito and gets a JWT. Every API call
carries that JWT, which API Gateway's Cognito authorizer validates. The
start-scan Lambda assumes the customer's read-only role via STS, runs the
scanners in the target account, computes a security score, and writes results to
DynamoDB. The dashboard reads them back.
| Scanner | Service | Example finding | Severity |
|---|---|---|---|
| Public buckets | S3 | Block Public Access off / public ACL / public policy | High |
| Open security groups | EC2 | 0.0.0.0/0 on ports 22, 3389, 3306, 5432, 80, 443 |
Critical–Low |
| IAM MFA | IAM | Console user without MFA | High |
| Old access keys | IAM | Active key older than 90 days | Medium |
| EBS encryption | EBS | Unencrypted volume | High |
| Unused resources | EC2/EBS | Unattached volumes, unused EIPs, stopped instances, old snapshots | Low |
Security score starts at 100; each finding subtracts by severity (Critical −15, High −10, Medium −5, Low −2), floored at 0. The same weights are used on the frontend (src/lib/score.ts) and backend (backend/src/cloudguard/scoring.py).
- Frontend: React 19, TypeScript, Vite, Tailwind CSS v4, shadcn/ui, Recharts,
React Router,
amazon-cognito-identity-js - Backend: Python 3.13, boto3, AWS Lambda
- Infrastructure (AWS SAM / CloudFormation): API Gateway, Lambda, DynamoDB, Amazon Cognito, IAM, STS
- Testing: pytest + moto (mocked AWS) — 29 tests
CloudGuard never asks for AWS access keys. The user deploys
public/cloudguard-role.yaml, which creates a
read-only IAM role trusting CloudGuard's account with an External ID
condition (guards against the confused-deputy problem). The backend obtains
short-lived credentials via sts:AssumeRole — nothing long-lived is stored. The
user identity for every request is taken from the verified Cognito JWT, not
from client input.
.
├── src/ # React frontend
│ ├── pages/ # Login, Dashboard, ConnectAccount, ScanResults, …
│ ├── components/ # UI (shadcn/ui) + app components
│ ├── context/ # AuthContext (Cognito), AccountContext
│ └── lib/ # api.ts (API client), score.ts
├── public/cloudguard-role.yaml # read-only scanner role (CloudFormation)
├── backend/ # Python scanners + SAM infrastructure
│ ├── src/cloudguard/ # scanners, orchestrator, handlers, sts, storage
│ ├── tests/ # pytest + moto
│ ├── template.yaml # AWS SAM template
│ └── DEPLOYMENT.md # deploy runbook
└── README.md
npm install
cp .env.example .env # fill in your deployed API + Cognito values
npm run dev # http://localhost:5173cd backend
python -m venv .venv && .venv\Scripts\Activate.ps1 # Windows
pip install -e ".[dev]"
pytest -q # 29 passedSee backend/DEPLOYMENT.md. In short:
cd backend
sam build
sam deploy --guided # creates Cognito, API Gateway, Lambdas, DynamoDBThen put the stack Outputs (ApiUrl, UserPoolId, UserPoolClientId) into the
frontend .env.
Built and deployed
- ✅ React dashboard (auth, connect account, scan, findings, reports, settings)
- ✅ Six Python/boto3 scanners + security scoring (29 tests)
- ✅ STS AssumeRole cross-account read-only access
- ✅ API Gateway + Lambda + DynamoDB (AWS SAM)
- ✅ Amazon Cognito auth + API authorizer (JWT-protected API)
Planned
- ⬜ Step Functions (async, parallel scanners — removes the API timeout limit)
- ⬜ SNS email alerts + EventBridge scheduled scans
- ⬜ Public hosting (S3 + CloudFront)
- ⬜ AWS Config / Security Hub integration