Skip to content

Commit b59a9f3

Browse files
authored
feat(rules): add NAT gateway and SageMaker discovery checks (#53)
* feat(rules): add NAT gateway and SageMaker discovery checks * fix(sdk): tolerate deleted SageMaker notebooks
1 parent 8cd3b28 commit b59a9f3

25 files changed

+1347
-100
lines changed

.changeset/cold-wasps-tan.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@cloudburn/sdk": patch
3+
---
4+
5+
Add AWS discovery dataset support for idle NAT gateways and running SageMaker notebook instances.

.changeset/gentle-pandas-smoke.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@cloudburn/rules": patch
3+
---
4+
5+
Add built-in AWS discovery rules for idle NAT gateways and running SageMaker notebook instances.

docs/architecture/rules.md

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -91,33 +91,38 @@ Rule evaluators consume static and live datasets through `context.resources.get(
9191

9292
## Current Rules
9393

94-
| ID | Name | Service | Supports | Status |
95-
| --------------------- | ----------------------------------------- | ------- | -------------- | ----------- |
96-
| `CLDBRN-AWS-CLOUDTRAIL-1` | CloudTrail Redundant Global Trails | cloudtrail | discovery | Implemented |
97-
| `CLDBRN-AWS-CLOUDTRAIL-2` | CloudTrail Redundant Regional Trails | cloudtrail | discovery | Implemented |
98-
| `CLDBRN-AWS-CLOUDWATCH-1` | CloudWatch Log Group Missing Retention | cloudwatch | discovery | Implemented |
99-
| `CLDBRN-AWS-CLOUDWATCH-2` | CloudWatch Unused Log Streams | cloudwatch | discovery | Implemented |
100-
| `CLDBRN-AWS-EC2-1` | EC2 Instance Type Not Preferred | ec2 | iac, discovery | Implemented |
101-
| `CLDBRN-AWS-EC2-2` | S3 Interface VPC Endpoint Used | ec2 | iac | Implemented |
102-
| `CLDBRN-AWS-EC2-3` | Elastic IP Address Unassociated | ec2 | discovery | Implemented |
103-
| `CLDBRN-AWS-EC2-4` | VPC Interface Endpoint Inactive | ec2 | discovery | Implemented |
104-
| `CLDBRN-AWS-EC2-5` | EC2 Instance Low Utilization | ec2 | discovery | Implemented |
105-
| `CLDBRN-AWS-EBS-1` | EBS Volume Type Not Current Generation | ebs | discovery, iac | Implemented |
106-
| `CLDBRN-AWS-EBS-2` | EBS Volume Unattached | ebs | discovery | Implemented |
107-
| `CLDBRN-AWS-EBS-3` | EBS Volume Attached To Stopped Instances | ebs | discovery | Implemented |
108-
| `CLDBRN-AWS-EBS-4` | EBS Volume Large Size | ebs | discovery | Implemented |
109-
| `CLDBRN-AWS-EBS-5` | EBS Volume High Provisioned IOPS | ebs | discovery | Implemented |
110-
| `CLDBRN-AWS-EBS-6` | EBS Volume Low Provisioned IOPS On io1/io2 | ebs | discovery | Implemented |
111-
| `CLDBRN-AWS-EBS-7` | EBS Snapshot Max Age Exceeded | ebs | discovery | Implemented |
112-
| `CLDBRN-AWS-ECR-1` | ECR Repository Missing Lifecycle Policy | ecr | iac, discovery | Implemented |
113-
| `CLDBRN-AWS-RDS-1` | RDS Instance Class Not Preferred | rds | iac, discovery | Implemented |
114-
| `CLDBRN-AWS-RDS-2` | RDS DB Instance Idle | rds | discovery | Implemented |
115-
| `CLDBRN-AWS-S3-1` | S3 Missing Lifecycle Configuration | s3 | iac, discovery | Implemented |
116-
| `CLDBRN-AWS-S3-2` | S3 Bucket Storage Class Not Optimized | s3 | iac, discovery | Implemented |
117-
| `CLDBRN-AWS-LAMBDA-1` | Lambda Cost Optimal Architecture | lambda | iac, discovery | Implemented |
94+
| ID | Name | Service | Supports | Status |
95+
| ------------------------- | ------------------------------------------ | ---------- | -------------- | ----------- |
96+
| `CLDBRN-AWS-CLOUDTRAIL-1` | CloudTrail Redundant Global Trails | cloudtrail | discovery | Implemented |
97+
| `CLDBRN-AWS-CLOUDTRAIL-2` | CloudTrail Redundant Regional Trails | cloudtrail | discovery | Implemented |
98+
| `CLDBRN-AWS-CLOUDWATCH-1` | CloudWatch Log Group Missing Retention | cloudwatch | discovery | Implemented |
99+
| `CLDBRN-AWS-CLOUDWATCH-2` | CloudWatch Unused Log Streams | cloudwatch | discovery | Implemented |
100+
| `CLDBRN-AWS-EC2-1` | EC2 Instance Type Not Preferred | ec2 | iac, discovery | Implemented |
101+
| `CLDBRN-AWS-EC2-2` | S3 Interface VPC Endpoint Used | ec2 | iac | Implemented |
102+
| `CLDBRN-AWS-EC2-3` | Elastic IP Address Unassociated | ec2 | discovery | Implemented |
103+
| `CLDBRN-AWS-EC2-4` | VPC Interface Endpoint Inactive | ec2 | discovery | Implemented |
104+
| `CLDBRN-AWS-EC2-5` | EC2 Instance Low Utilization | ec2 | discovery | Implemented |
105+
| `CLDBRN-AWS-EC2-10` | EC2 Instance Detailed Monitoring Enabled | ec2 | iac | Implemented |
106+
| `CLDBRN-AWS-EC2-11` | NAT Gateway Idle | ec2 | discovery | Implemented |
107+
| `CLDBRN-AWS-EBS-1` | EBS Volume Type Not Current Generation | ebs | discovery, iac | Implemented |
108+
| `CLDBRN-AWS-EBS-2` | EBS Volume Unattached | ebs | discovery | Implemented |
109+
| `CLDBRN-AWS-EBS-3` | EBS Volume Attached To Stopped Instances | ebs | discovery | Implemented |
110+
| `CLDBRN-AWS-EBS-4` | EBS Volume Large Size | ebs | discovery | Implemented |
111+
| `CLDBRN-AWS-EBS-5` | EBS Volume High Provisioned IOPS | ebs | discovery | Implemented |
112+
| `CLDBRN-AWS-EBS-6` | EBS Volume Low Provisioned IOPS On io1/io2 | ebs | discovery | Implemented |
113+
| `CLDBRN-AWS-EBS-7` | EBS Snapshot Max Age Exceeded | ebs | discovery | Implemented |
114+
| `CLDBRN-AWS-ECR-1` | ECR Repository Missing Lifecycle Policy | ecr | iac, discovery | Implemented |
115+
| `CLDBRN-AWS-RDS-1` | RDS Instance Class Not Preferred | rds | iac, discovery | Implemented |
116+
| `CLDBRN-AWS-RDS-2` | RDS DB Instance Idle | rds | discovery | Implemented |
117+
| `CLDBRN-AWS-S3-1` | S3 Missing Lifecycle Configuration | s3 | iac, discovery | Implemented |
118+
| `CLDBRN-AWS-S3-2` | S3 Bucket Storage Class Not Optimized | s3 | iac, discovery | Implemented |
119+
| `CLDBRN-AWS-SAGEMAKER-1` | SageMaker Notebook Instance Running | sagemaker | discovery | Implemented |
120+
| `CLDBRN-AWS-LAMBDA-1` | Lambda Cost Optimal Architecture | lambda | iac, discovery | Implemented |
118121

119122
`CLDBRN-AWS-LAMBDA-1` is an advisory rule. It recommends `arm64` only when compatibility is known or explicitly declared, and the static evaluator skips computed or otherwise unknown architecture values instead of treating them as definite `x86_64`.
120123

121124
CloudTrail and CloudWatch discovery rules now rely on dedicated live datasets. CloudBurn seeds both CloudWatch datasets from Resource Explorer `logs:log-group` catalog results, then uses narrow CloudWatch Logs APIs to hydrate group retention metadata and enumerate log streams.
122125

123126
EBS discovery rules now reuse the shared `aws-ebs-volumes` dataset for storage type, attachment, size, and IOPS checks, and use a dedicated `aws-ebs-snapshots` dataset seeded from Resource Explorer `ec2:snapshot` resources for snapshot-age review.
127+
128+
NAT gateway and SageMaker notebook discovery follow the same catalog-first model: CloudBurn seeds NAT review from `ec2:natgateway` resources and hydrates 7-day traffic totals with `DescribeNatGateways` plus CloudWatch metrics, while SageMaker notebook review is seeded from `sagemaker:notebook-instance` resources and hydrated through `DescribeNotebookInstance`.

docs/architecture/sdk.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ Current live-discovery behavior:
8181
- Resource Explorer inventory failures and dataset loader failures are fatal. The SDK does not degrade to partial live results.
8282
- Missing Lambda `Architectures` values from AWS are normalized to `['x86_64']`, matching the AWS default architecture.
8383
- Lambda hydrators limit in-flight `GetFunctionConfiguration` calls per region to avoid API throttling in large accounts.
84-
- Live scans require Resource Explorer access plus narrow hydrator permissions such as `apigateway:GetStage`, `application-autoscaling:DescribeScalableTargets`, `application-autoscaling:DescribeScalingPolicies`, `ce:GetCostAndUsage`, `cloudfront:GetDistribution`, `cloudfront:ListDistributions`, `cloudtrail:DescribeTrails`, `cloudwatch:GetMetricData`, `dynamodb:DescribeTable`, `ecs:DescribeContainerInstances`, `ecs:DescribeServices`, `ec2:DescribeVolumes`, `ec2:DescribeInstances`, `eks:ListNodegroups`, `eks:DescribeNodegroup`, `lambda:GetFunctionConfiguration`, `rds:DescribeDBInstances`, `route53:ListHealthChecks`, `route53:ListHostedZones`, `route53:ListResourceRecordSets`, `s3:GetLifecycleConfiguration`, `s3:GetIntelligentTieringConfiguration`, and `secretsmanager:DescribeSecret`.
84+
- Live scans require Resource Explorer access plus narrow hydrator permissions such as `apigateway:GetStage`, `application-autoscaling:DescribeScalableTargets`, `application-autoscaling:DescribeScalingPolicies`, `ce:GetCostAndUsage`, `cloudfront:GetDistribution`, `cloudfront:ListDistributions`, `cloudtrail:DescribeTrails`, `cloudwatch:GetMetricData`, `dynamodb:DescribeTable`, `ecs:DescribeContainerInstances`, `ecs:DescribeServices`, `ec2:DescribeInstances`, `ec2:DescribeNatGateways`, `ec2:DescribeVolumes`, `eks:ListNodegroups`, `eks:DescribeNodegroup`, `lambda:GetFunctionConfiguration`, `rds:DescribeDBInstances`, `route53:ListHealthChecks`, `route53:ListHostedZones`, `route53:ListResourceRecordSets`, `s3:GetLifecycleConfiguration`, `s3:GetIntelligentTieringConfiguration`, `sagemaker:DescribeNotebookInstance`, and `secretsmanager:DescribeSecret`.
8585

8686
## Public Result Shape
8787

0 commit comments

Comments
 (0)