Skip to content

Commit a60836a

Browse files
tas50claude
andauthored
⭐ Expand Security Hub with standards controls, findings, and insights (#7156)
* ⭐ Expand Security Hub with standards controls, findings, automation rules, and insights Add typed resources for comprehensive Security Hub querying: - standardSubscription: enabled standards with status - standardControl: individual controls with pass/fail status, severity, remediation URLs - finding: ASFF findings with severity, compliance status, workflow state, affected resources - automationRule: rule metadata with status and execution order - insight + insightResult: saved filters with computed result aggregations This enables queries like: aws.securityhub.hubs { standardSubscriptions { controls.where(controlStatus == "ENABLED") { controlId severity title } } } Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 Fix error handling, perf, and logic issues in Security Hub resources Fix duplicate arn/productArn on findings (arn was incorrectly set to ProductArn), swallowed error in insight filters, by-value copy of large finding struct in hot loop, off-by-one in 1000-finding cap, and misleading standard name (was raw ARN). Replace custom strPtr/int32Ptr with sdk aws.String/aws.Int32. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🧹 Address review: migrate deprecated API, fix severityScore type - Replace deprecated DescribeStandardsControls with ListSecurityControlDefinitions + BatchGetStandardsControlAssociations - Rename severityScore float → severityNormalized int to match SDK type (*int32 range 0-100, not a decimal value) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 Fix standardNameFromArn to handle ruleset/ prefix CIS standards use "ruleset/" instead of "standards/" in their ARN (e.g., arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/...). Handle both prefixes so all standard names are human-readable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🟢 Add unit tests for Security Hub standardNameFromArn Tests all ARN formats: standards/, ruleset/, PCI-DSS, NIST, no-match fallback, empty string, and ARN without version suffix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🧹 Update permissions for new Security Hub APIs Replace deprecated DescribeStandardsControls with BatchGetStandardsControlAssociations and ListSecurityControlDefinitions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 📄 Document that permissions.json must always be committed It tracks IAM permissions required by each provider and changes to it are part of the PR, not throwaway build artifacts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 📄 Note that expect.txt removals are fine if CI passes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent bf0486f commit a60836a

File tree

7 files changed

+1818
-7
lines changed

7 files changed

+1818
-7
lines changed

CLAUDE.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ Think of it as: MQL (like SQL or even better GraphQL) → MQLC (compiler) → LL
346346
- Resource structs
347347
- Schema definitions
348348
- Data accessor methods
349-
- Generated files: `*.lr.go`, `*.lr.versions`, `*.resources.json`
349+
- Generated files: `*.lr.go`, `*.lr.versions`, `*.resources.json`, `*.permissions.json`
350350
351351
### Resource Caching & __id
352352
**How caching works:**
@@ -483,6 +483,7 @@ for {
483483
- Never manually edit generated `.lr.go` files - they get overwritten
484484
- Use `make providers/mqlr` for faster provider-specific regeneration
485485
- **Internal structs require a second generation pass.** If you add a new `mql*Internal` struct to a Go file, the first `./mqlr generate` won't embed it (the struct didn't exist when the generator ran). Run `./mqlr generate` again after adding Internal structs.
486+
- **Always commit `*.permissions.json`** when it changes. This file is regenerated by `make providers/build/<provider>` and tracks the IAM permissions each provider requires. Changes to it (e.g., new API calls added, deprecated calls removed) are part of the PR — they're not throwaway build artifacts.
486487
487488
### Testing & Verification
488489
- If you want to test simple changes, build and install the provider and use mql run ....
@@ -565,7 +566,7 @@ make test/integration
565566
566567
### Quick Pre-Commit Checklist
567568
- [ ] `gofmt -w` run on all changed `.go` files
568-
- [ ] Generated files are up-to-date (`.lr.go`, `.pb.go`)
569+
- [ ] Generated files are up-to-date (`.lr.go`, `.pb.go`, `.permissions.json`)
569570
- [ ] Linting passes (`make test/lint`)
570571
- [ ] Changes work interactively (`mql shell <provider>`)
571572
- [ ] `go.mod` is clean (`go mod tidy`)
@@ -585,6 +586,7 @@ CI runs [check-spelling/check-spelling](https://github.com/check-spelling/check-
585586
- If the word is a legitimate technical term: add it to `expect.txt` (keep sorted)
586587
- If the word appears in a pattern (ARN, hash, URL): add a regex to `patterns.txt`
587588
- If it's a genuine typo: fix the spelling
589+
- Removing words from `expect.txt` is fine as long as the spell check CI job passes
588590
589591
## 9. Commit Conventions
590592

providers/aws/resources/aws.lr

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,6 +3035,146 @@ private aws.securityhub.hub @defaults("arn region") {
30353035
region string
30363036
// List of enabled security standards (CIS, PCI-DSS, AWS Foundational, etc.)
30373037
enabledStandards() []dict
3038+
// Typed standard subscriptions with control details
3039+
standardSubscriptions() []aws.securityhub.standardSubscription
3040+
// Active findings (non-archived) in this hub
3041+
findings() []aws.securityhub.finding
3042+
// Automation rules configured in this hub
3043+
automationRules() []aws.securityhub.automationRule
3044+
// Custom and default insights
3045+
insights() []aws.securityhub.insight
3046+
}
3047+
3048+
// AWS Security Hub enabled standard subscription
3049+
private aws.securityhub.standardSubscription @defaults("name status") {
3050+
// ARN of the standard subscription
3051+
arn string
3052+
// ARN of the standard definition
3053+
standardArn string
3054+
// Name of the standard (e.g., CIS AWS Foundations Benchmark)
3055+
name string
3056+
// Region for this subscription
3057+
region string
3058+
// Subscription status: READY, INCOMPLETE, FAILED, DELETING, PENDING
3059+
status string
3060+
// Controls within this standard
3061+
controls() []aws.securityhub.standardControl
3062+
}
3063+
3064+
// AWS Security Hub standard control
3065+
private aws.securityhub.standardControl @defaults("controlId title controlStatus") {
3066+
// Control ARN
3067+
arn string
3068+
// Control identifier (e.g., CIS.1.1)
3069+
controlId string
3070+
// Control title
3071+
title string
3072+
// Description of what the control checks for
3073+
description string
3074+
// Control status: ENABLED, DISABLED
3075+
controlStatus string
3076+
// Severity: CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL
3077+
severity string
3078+
// Reason the control was disabled
3079+
disabledReason string
3080+
// Related compliance requirements
3081+
relatedRequirements []string
3082+
// URL to remediation documentation
3083+
remediationUrl string
3084+
}
3085+
3086+
// AWS Security Hub finding (ASFF format)
3087+
private aws.securityhub.finding @defaults("title severity workflowStatus") {
3088+
// Finding identifier
3089+
id string
3090+
// Finding title
3091+
title string
3092+
// Finding description
3093+
description string
3094+
// Normalized severity label: CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL
3095+
severity string
3096+
// Legacy normalized severity (0-100 integer, deprecated in favor of severity label)
3097+
severityNormalized int
3098+
// Record state: ACTIVE, ARCHIVED
3099+
recordState string
3100+
// Compliance status: PASSED, FAILED, WARNING, NOT_AVAILABLE
3101+
complianceStatus string
3102+
// Workflow status: NEW, NOTIFIED, RESOLVED, SUPPRESSED
3103+
workflowStatus string
3104+
// Finding type categories
3105+
types []string
3106+
// ARN of the product that generated the finding
3107+
productArn string
3108+
// Name of the product that generated the finding
3109+
productName string
3110+
// Identifier for the rule or check that generated the finding
3111+
generatorId string
3112+
// Type of the affected resource (e.g., AwsEc2Instance)
3113+
resourceType string
3114+
// ID of the affected resource
3115+
resourceId string
3116+
// Region of the affected resource
3117+
resourceRegion string
3118+
// When the finding was created
3119+
createdAt time
3120+
// When the finding was last updated
3121+
updatedAt time
3122+
// When the potential issue was first observed
3123+
firstObservedAt time
3124+
// When the potential issue was last observed
3125+
lastObservedAt time
3126+
// URL to remediation documentation
3127+
remediationUrl string
3128+
// Text description of the remediation
3129+
remediationText string
3130+
// AWS account ID where the finding was generated
3131+
accountId string
3132+
// Region where the finding was generated
3133+
region string
3134+
}
3135+
3136+
// AWS Security Hub automation rule
3137+
private aws.securityhub.automationRule @defaults("ruleName ruleStatus") {
3138+
// Rule ARN
3139+
arn string
3140+
// Rule name
3141+
ruleName string
3142+
// Rule execution order (1-1000, lower executes first)
3143+
ruleOrder int
3144+
// Rule status: ENABLED, DISABLED
3145+
ruleStatus string
3146+
// Rule description
3147+
description string
3148+
// Whether this rule stops further rule evaluation
3149+
isTerminal bool
3150+
// When the rule was created
3151+
createdAt time
3152+
// When the rule was last updated
3153+
updatedAt time
3154+
// Who created the rule
3155+
createdBy string
3156+
}
3157+
3158+
// AWS Security Hub insight (saved filter/aggregation)
3159+
private aws.securityhub.insight @defaults("name") {
3160+
// Insight ARN
3161+
arn string
3162+
// Insight name
3163+
name string
3164+
// Attribute that findings are grouped by
3165+
groupByAttribute string
3166+
// Filter criteria as dict
3167+
filters dict
3168+
// Computed insight results
3169+
results() []aws.securityhub.insightResult
3170+
}
3171+
3172+
// AWS Security Hub insight result entry
3173+
private aws.securityhub.insightResult @defaults("groupByAttributeValue count") {
3174+
// The value of the grouping attribute
3175+
groupByAttributeValue string
3176+
// Number of findings matching this value
3177+
count int
30383178
}
30393179

30403180
// AWS Shield Advanced

0 commit comments

Comments
 (0)