Skip to content

Commit 59ba8f2

Browse files
authored
feat: policy-as-code Implementation (#129)
1 parent a22ac9b commit 59ba8f2

59 files changed

Lines changed: 2845 additions & 1000 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Archive.zip

984 KB
Binary file not shown.

README.fr.md

Lines changed: 94 additions & 307 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 93 additions & 308 deletions
Large diffs are not rendered by default.

cleancloud/cleancloud.yaml

Lines changed: 117 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,123 @@
1-
# cleancloud.yaml
1+
# cleancloud.yaml — Policy-as-code configuration
2+
# Auto-detected in the current directory. Override with: cleancloud scan --config path/to/cleancloud.yaml
23
version: 1
34

5+
# ── Filtering precedence (strongest first) ────────────────────────────────────
6+
# 1. Exceptions — explicit human approvals, bypass all other filters
7+
# 2. Tag filtering — resource-scope exclusion by tag/label
8+
# 3. Rule enable/disable + params — pre-scan rule selection
9+
# 4. Defaults — global fallbacks for min_cost / confidence / override_risk_level
10+
# 5. Thresholds — CI/CD exit-code policy
11+
12+
# ── Defaults ─────────────────────────────────────────────────────────────────
13+
# Global fallbacks applied to all rules unless overridden at the rule level.
14+
# min_cost: per-finding, using estimated_monthly_cost_usd (not total across findings).
15+
defaults:
16+
min_cost: 10 # suppress findings below $10/month estimated cost
17+
confidence: MEDIUM # suppress LOW confidence findings globally
18+
19+
# ── Tag filtering ────────────────────────────────────────────────────────────
20+
# Suppress findings on resources that carry these tags/labels.
21+
# Applied AFTER exceptions — explicitly-excepted resources are never re-suppressed by a tag rule.
22+
# Useful for excluding intentional infrastructure (prod keep-warm, IaC-managed resources).
423
tag_filtering:
524
enabled: true
25+
mode: exclude # "exclude" suppresses findings on matched resources (only supported mode)
626
ignore:
727
- key: env
8-
value: production
9-
- key: team
10-
value: platform
11-
- key: team
28+
values: [production, staging] # suppress findings on prod and staging resources
29+
- key: cleancloud-ignore # key-only match (any value)
30+
31+
# ── Rule configuration ───────────────────────────────────────────────────────
32+
# Enable or disable rules, tune thresholds, or pass parameters to individual rules.
33+
# Rules not listed here are enabled by default (opt-out model).
34+
# Per-rule settings override defaults above.
35+
# Rule IDs must match exactly — a typo raises an error at scan start with a suggestion.
36+
# Run `cleancloud scan --help` or see docs/rules.md for the full list.
37+
rules:
38+
aws.resource.untagged:
39+
enabled: false # team manages tags separately
40+
41+
aws.ec2.ami.old:
42+
enabled: true
43+
min_cost: 5 # only flag AMIs with estimated cost >= $5/month (overrides default)
44+
45+
aws.rds.instance.idle:
46+
enabled: true
47+
min_cost: 100 # suppress RDS findings below $100/month estimated cost
48+
params:
49+
idle_days: 21 # require 21 days idle before flagging (default: 14)
50+
51+
gcp.sql.instance.idle:
52+
enabled: true
53+
params:
54+
idle_days: 21 # require 21 days idle before flagging (default: 14)
55+
56+
azure.compute.snapshot.old:
57+
enabled: true
58+
params:
59+
max_age_days: 60 # flag snapshots older than 60 days (default: 90)
60+
confidence: LOW # include LOW confidence findings for this rule (overrides global default)
61+
62+
aws.sagemaker.endpoint.idle:
63+
enabled: true
64+
# override_risk_level overrides the `risk` field on findings — affects display and reporting only.
65+
# It does NOT affect fail_on_confidence thresholds (which use signal strength, not risk).
66+
override_risk_level: HIGH
67+
68+
# ── Categories ───────────────────────────────────────────────────────────────
69+
# Override the default category without using the --category CLI flag.
70+
# Equivalent to: cleancloud scan --provider aws --category all
71+
# CLI --category flag takes precedence when explicitly set.
72+
# categories:
73+
# include: [hygiene, ai] # run both hygiene and AI/ML rules
74+
75+
# ── Exceptions ───────────────────────────────────────────────────────────────
76+
# Strongest filter — excepted resources bypass tag filtering and all other suppression.
77+
# Fields: rule_id (exact), resource_id (glob: *, ?, [seq]), account_id, region, reason.
78+
# account_id and region narrow the match — omit to match any account/region.
79+
# Document the reason for every exception — these are git-reviewable approvals.
80+
# Note: require_reason / require_ticket enforcement planned for a future release.
81+
exceptions:
82+
- rule_id: aws.ec2.instance.stopped
83+
resource_id: i-0abc1234567890def
84+
reason: "Bastion host — kept stopped intentionally, started on demand"
85+
expires_at: "2026-12-31" # exception reviewed quarterly; auto-expires if not renewed
86+
87+
- rule_id: aws.rds.instance.idle
88+
resource_id: db-prod-reporting
89+
reason: "Quarterly reporting DB — idle between cycles, do not terminate"
90+
91+
- rule_id: aws.rds.instance.idle
92+
resource_id: "db-test-*" # glob — suppress all test databases
93+
reason: "Test databases are ephemeral and frequently idle"
94+
95+
- rule_id: aws.ebs.unattached
96+
resource_id: "vol-*"
97+
account_id: "111111111111" # narrow to a specific AWS account
98+
region: us-west-2 # narrow to a specific region
99+
reason: "Archive volumes in legacy account, migration planned"
100+
101+
- rule_id: gcp.sql.instance.idle
102+
resource_id: my-project:us-central1:analytics-db
103+
reason: "Idle between quarterly runs"
104+
105+
# ── Thresholds ───────────────────────────────────────────────────────────────
106+
# Config-file equivalents of --fail-on-* CLI flags.
107+
# CLI flags take precedence if both are set.
108+
# fail_on_confidence uses signal strength (LOW/MEDIUM/HIGH), not the override_risk_level above.
109+
#
110+
# Exit codes:
111+
# 0 — No findings (or all filtered/suppressed)
112+
# 1 — Unexpected error (bug or infrastructure failure)
113+
# 2 — Policy violation — a threshold was breached (CI/CD should fail here)
114+
# 3 — Permission error — insufficient IAM/RBAC permissions to complete scan
115+
#
116+
# Threshold evaluation order (OR logic — first breach triggers exit 2):
117+
# 1. fail_on_findings: true → any remaining finding
118+
# 2. fail_on_confidence: X → any finding with confidence >= X
119+
# 3. fail_on_cost: X → total estimated_monthly_cost_usd across findings >= X
120+
thresholds:
121+
fail_on_confidence: HIGH # exit 2 if any HIGH confidence finding remains after filtering
122+
fail_on_cost: 500 # exit 2 if total estimated waste >= $500/month
123+
fail_on_findings: false # exit 2 on any finding (most strict — usually too noisy for CI)

0 commit comments

Comments
 (0)