srini-cybersec/cloudguardian

GitHub: srini-cybersec/cloudguardian

Stars: 0 | Forks: 0

# CloudGuardian [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/31264e869a023913.svg)](https://github.com/srini-cybersec/cloudguardian/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) ## Why CloudGuardian? Cloud breaches almost never look like zero-days — they look like **misconfiguration**. A public S3 bucket, an SSH port open to `0.0.0.0/0`, an IAM policy with `Action="*" Resource="*"`. Cloud-Security-Posture-Management (CSPM) tools catch these issues at runtime; **CloudGuardian shifts that left** into the pull request, before the resource is ever provisioned. It is: - **Air-gap safe** — pure-Python, zero network calls, no telemetry. Safe for regulated environments and offline CI runners. - **Multi-format** — one tool for Terraform HCL, CloudFormation (YAML + JSON), Kubernetes manifests, and standalone IAM policy documents. - **CI/CD-native** — emits SARIF 2.1.0 for GitHub Code Scanning, plus JSON / CSV / HTML / Rich-console formats. - **Opinionated but tunable** — every rule has a CWE, references, compliance mapping, and a remediation snippet. Disable any rule with one flag. ## Problem statement Modern teams ship 100s of IaC changes per week. Reviewing every one for cloud security best practice is impossible by hand. Existing scanners either: - run only at runtime (too late — the breach already happened), or - target one format (Terraform-only, Kubernetes-only), forcing teams to glue together a half-dozen pipelines. CloudGuardian is a single Python tool that ingests the four most common cloud config formats and applies a unified, well-cited rule pack with a single threshold and a single exit code. ## Architecture ┌──────────────────────────────────────────────────────────────────┐ │ CloudGuardian CLI │ │ (Click — scan / rules / stats subcommands) │ └─────────────┬───────────────────────────────────────┬────────────┘ │ │ ▼ ▼ ┌─────────────┐ ┌──────────────┐ │ File walker │ ──► classifier ──► │ Config │ │ (recursive) │ (TF / CFN / K8S / │ (.cloudguardian.yml + └─────┬───────┘ IAM JSON) │ env vars + CLI flags) │ └──────────────┘ ▼ ┌──────────────────────────────────────────────────────┐ │ Parsers │ │ ┌──────────┐ ┌──────────────┐ ┌──────┐ ┌─────────┐ │ │ │ HCL/TF │ │ CloudFormation│ │ K8s │ │ IAM JSON│ │ │ │ lexer + │ │ (YAML + JSON │ │ YAML │ │ │ │ │ │ parser │ │ intrinsics) │ │ │ │ │ │ │ └──────────┘ └──────────────┘ └──────┘ └─────────┘ │ │ ──► Resource (unified schema) │ └──────────────────────────┬───────────────────────────┘ ▼ ┌──────────────────────────────────────────────────────┐ │ Rule engine │ │ 25+ rules across AWS / Azure / GCP / Kubernetes │ │ Each rule: id, severity, CWE, compliance, fix │ └──────────────────────────┬───────────────────────────┘ ▼ ┌──────────────────────────────────────────────────────┐ │ Reporters │ │ console (Rich) │ json │ sarif │ html │ csv │ │ + risk score (0-100) + verdict │ └──────────────────────────────────────────────────────┘ ## Quick start ### Install git clone https://github.com/srini-cybersec/cloudguardian cd cloudguardian pip install -e . ### Scan a directory cloudguardian scan ./infra ╭───────────────────── CloudGuardian ─────────────────────╮ │ Tool version 1.0.0 │ │ Files scanned 4 │ │ Resources 12 │ │ Findings 9 │ │ Risk score 100 / 100 │ │ Verdict CRITICAL │ ╰─────────────────────────────────────────────────────────╯ Findings by severity ┏━━━━━━━━━━┳━━━━━━━┓ ┃ Severity ┃ Count ┃ ┡━━━━━━━━━━╇━━━━━━━┩ │ CRITICAL │ 4 │ │ HIGH │ 3 │ │ MEDIUM │ 2 │ │ LOW │ 0 │ │ INFO │ 0 │ └──────────┴───────┘ ### Emit SARIF for GitHub Code Scanning cloudguardian scan ./infra \ --format sarif \ --output cloudguardian.sarif \ --fail-on HIGH Wire it into Actions: - name: CloudGuardian run: | pip install cloudguardian cloudguardian scan . --format sarif --output cg.sarif --fail-on HIGH - uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: cg.sarif ### List rules and stats cloudguardian rules --cloud aws --severity HIGH cloudguardian stats ### Docker docker build -t cloudguardian:local . docker run --rm -v "$(pwd):/work:ro" cloudguardian:local scan /work --fail-on HIGH ## Built-in rules (excerpt) | ID | Cloud | Severity | Title | |----|-------|----------|-------| | CG-AWS-S3-001 | aws | CRITICAL | S3 bucket grants a public canned ACL | | CG-AWS-S3-002 | aws | HIGH | S3 bucket has no server-side encryption | | CG-AWS-S3-003 | aws | MEDIUM | S3 bucket versioning is disabled | | CG-AWS-SG-001 | aws | CRITICAL | SG exposes SSH/RDP/DB to 0.0.0.0/0 | | CG-AWS-SG-002 | aws | CRITICAL | SG allows ALL ports from public internet | | CG-AWS-EBS-001 | aws | HIGH | EBS volume created without encryption | | CG-AWS-RDS-001 | aws | HIGH | RDS instance is publicly accessible | | CG-AWS-RDS-002 | aws | HIGH | RDS storage is not encrypted | | CG-AWS-IAM-001 | aws | CRITICAL | IAM policy grants `*:*` admin | | CG-AWS-IAM-002 | aws | CRITICAL | Root account access key provisioned | | CG-AWS-EC2-001 | aws | HIGH | EC2 does not enforce IMDSv2 | | CG-AWS-LAMBDA-001 | aws | HIGH | Lambda permission has `Principal="*"` | | CG-AWS-CT-001 | aws | MEDIUM | CloudTrail is not multi-region | | CG-AWS-KMS-001 | aws | MEDIUM | KMS CMK rotation disabled | | CG-AZ-STG-001 | azure | CRITICAL | Azure storage allows public blob | | CG-AZ-NET-001 | azure | CRITICAL | NSG exposes SSH/RDP publicly | | CG-AZ-SQL-001 | azure | HIGH | Azure SQL allows obsolete TLS | | CG-GCP-STG-001 | gcp | CRITICAL | GCS bucket public (allUsers) | | CG-GCP-NET-001 | gcp | CRITICAL | GCP firewall exposes admin port | | CG-GCP-GCE-001 | gcp | HIGH | GCE uses full cloud-platform scope | | CG-K8S-001 | k8s | CRITICAL | Container runs privileged | | CG-K8S-002 | k8s | HIGH | runAsNonRoot not enforced | | CG-K8S-003 | k8s | HIGH | hostPID/hostIPC/hostNetwork enabled | | CG-K8S-004 | k8s | HIGH | Dangerous Linux capabilities added | | CG-K8S-005 | k8s | CRITICAL | RBAC wildcard verbs+resources | | CG-IAM-STMT-001 | aws | HIGH | IAM statement uses wildcard Action | | CG-IAM-STMT-002 | aws | HIGH | Allow + NotAction (deny-list trap) | | CG-IAM-STMT-003 | aws | CRITICAL | Public Principal without Condition | | CG-IAM-STMT-005 | aws | HIGH | Privilege-escalation primitive | Run `cloudguardian rules` for the full live list. ## Configuration `.cloudguardian.yml` (project-root, optional): fail_on: HIGH disabled_rules: - CG-AWS-S3-004 # logging is enforced elsewhere exclude_paths: - .terraform/ - modules/vendor/ output_format: sarif include_info: false Every option also accepts an env-var override: `CLOUDGUARDIAN_FAIL_ON`, `CLOUDGUARDIAN_DISABLED_RULES`, `CLOUDGUARDIAN_EXCLUDE_PATHS`, `CLOUDGUARDIAN_OUTPUT_FORMAT`. ## CI/CD recipes ### Block merges on CRITICAL findings only cloudguardian scan . --fail-on CRITICAL Exit code is `0` if no finding meets the threshold, `1` otherwise — perfect for `pre-commit`, `make check`, or any pipeline gate. ### Generate human-readable HTML for the PR artifacts tab cloudguardian scan . --format html --output report.html ### Combine with `pre-commit` repos: - repo: local hooks: - id: cloudguardian name: CloudGuardian (IaC posture) entry: cloudguardian scan . --fail-on HIGH language: system pass_filenames: false ## Security considerations CloudGuardian is **read-only** by design: If you discover a security issue, please open a private security advisory on GitHub rather than a public issue. ## Development pip install -r requirements-dev.txt pip install -e . black src tests ruff check src tests mypy src bandit -r src -ll pytest --cov=src/cloudguardian --cov-report=term-missing Layout: src/cloudguardian/ ├── cli.py # Click entry-point ├── config.py # YAML + env-var configuration ├── engine.py # discover → parse → evaluate → report ├── models.py # Severity, Resource, Finding, ScanReport ├── parsers/ # HCL, CloudFormation, K8s, IAM ├── rules/ # built-in rule pack (one module per cloud) └── reporters/ # console, json, sarif, html, csv Adding a rule is ~25 lines: see any module in `src/cloudguardian/rules/` for the pattern. ## License MIT — see [LICENSE](LICENSE).