trueno-aws-rules
v0.3.1
Published
Pure, dependency-free catalog of AWS cost, security & governance rules. Feed it discovered resources, get findings back.
Maintainers
Readme
trueno-aws-rules
A pure, dependency-free catalog of AWS cost, security, governance, performance, and reliability rules. Feed it AWS resources you've already discovered; get back structured findings.
No AWS SDK. No network calls. No I/O. The rules take already-fetched resource metadata as input and return findings — that boundary is the whole point. You own how resources are fetched (the AWS SDK, Steampipe, a CloudQuery dump, fixtures in a test); this library owns the judgement.
It powers the scanning engine at trueno and is published under MIT so you can audit, reuse, or extend the rules yourself.
Install
npm install trueno-aws-rulesQuick start
import { runRulesEngine, type AwsResource } from "trueno-aws-rules";
// You fetch these however you like — SDK, Steampipe, a JSON export.
const resources: AwsResource[] = [
{
accountId: "123456789012",
region: "us-east-1",
service: "ebs",
resourceType: "volume",
resourceId: "vol-0abc123",
tags: { Environment: "prod", Owner: "platform" },
metadata: { attached: false, sizeGiB: 500, volumeType: "gp3", createdAt: "2023-01-01T00:00:00Z" },
},
];
const { findings, riskByResourceId, costByResourceId } = runRulesEngine(resources);
for (const f of findings) {
console.log(`[${f.severity}] ${f.title} — ${f.recommendation}`);
// → [medium] Unattached EBS volume older than 30d — Snapshot and delete, …
}Each finding is a plain, serializable object:
type RuleFinding = {
moduleId: string; // "resource-inventory"
title: string;
description: string;
recommendation: string;
severity: "low" | "medium" | "high" | "critical";
category: "cost" | "security" | "governance" | "performance"
| "observability" | "compliance" | "reliability";
resourceType: string;
resourceId: string; // ARN if available, else the native id
region?: string | null;
estimatedMonthlySavings?: number | null; // for cost findings
evidence?: Record<string, unknown>;
metadata?: Record<string, unknown>;
};riskByResourceId / costByResourceId give you the peak risk (0–100) and cost
(0–100) score any rule assigned to each resource — handy for ranking.
Account-wide rules
Some checks are about the absence of something across the whole account
(no multi-region CloudTrail, no AWS Config recorder, no budgets, low Savings
Plans utilization). Those live in runAggregateRules:
import { runAggregateRules } from "trueno-aws-rules";
const findings = runAggregateRules({
resources, // the same resource list
regions: ["us-east-1", "eu-west-1"], // regions your scan actually covered
awsAccount12: "123456789012", // 12-digit account id (keys the synthetic finding)
});The AwsResource shape
Rules dispatch on service + resourceType and read service-specific keys off
metadata. For example the S3 rules read metadata.isPublic,
metadata.hasPublicAccessBlock, and metadata.hasLifecyclePolicy; the EBS rule
reads metadata.attached, metadata.sizeGiB, and metadata.createdAt. A
resource whose service/resourceType no rule recognizes simply yields no
findings, so it's safe to pass everything you discover.
The metadata keys each rule expects mirror the field names in the AWS API
responses — read src/engine.ts (it's flat, commented, and
each rule guards its own inputs) to see exactly what a given service rule looks
at.
CLI — gate CI on findings
The package ships a trueno-aws-rules binary that runs the same engine over a
resources JSON and exits non-zero when findings at or above a severity
threshold exist. Shift-left: catch a regression in the pull request, not in prod.
# from a file (the AwsResource[] you discovered), failing on high+ severity
npx trueno-aws-rules resources.json --fail-on high
# or pipe it in; emit machine-readable JSON
cat resources.json | npx trueno-aws-rules - --format jsonInput is either a bare AwsResource[] array, or an envelope that also enables
the account-wide rules:
{
"resources": [ /* AwsResource[] */ ],
"regions": ["us-east-1", "eu-west-1"],
"awsAccount12": "123456789012"
}| Flag | Values | Default | Meaning |
| ---------------- | ------------------------------- | ------- | ----------------------------------------- |
| --fail-on | low\|medium\|high\|critical | high | Min severity that exits non-zero |
| --from | resources\|terraform-plan | resources | Input format (see Terraform below) |
| --account | 12-digit id | — | Stamp account id (terraform-plan mode) |
| --region | region | — | Stamp region (terraform-plan mode) |
| --format | text\|json | text | Report format |
| --quiet, -q | — | off | Print only failing findings (text) |
Exit codes: 0 clean · 1 findings at/above --fail-on · 2 usage/input error.
Terraform (native, no inventory step)
Gate your IaC directly from terraform show -json — no need to build resources
JSON first:
# from a plan file
terraform plan -out tfplan.bin
terraform show -json tfplan.bin | npx trueno-aws-rules - --from terraform-plan --fail-on high
# or from current state
terraform show -json | npx trueno-aws-rules - --from terraform-planThe adapter converts Terraform's JSON (a plan file or state) into the
AwsResource contract and then runs the same rules. Supported resource types:
aws_s3_bucket (with its aws_s3_bucket_public_access_block /
_policy / _acl / _lifecycle_configuration companions correlated by bucket
name), aws_db_instance, aws_security_group (+ aws_vpc_security_group_ingress_rule),
aws_instance, and aws_lambda_function. Account-wide "absence" rules are
skipped for plan input — a plan is a partial slice of the account, so "no
CloudTrail here" isn't a real finding. Use --account / --region to stamp
those onto findings. Other input sources (live SDK inventory, Steampipe, a
CloudFormation/state export) still use the default AwsResource JSON contract.
GitHub Action
# .github/workflows/trueno.yml
name: trueno aws-rules
on: [pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# produce resources.json however fits your stack (a prior step), then:
- uses: hawa-dizeyi/trueno-aws-rules@main
with:
resources: resources.json
fail-on: highGate Terraform directly — no inventory step:
- uses: hashicorp/setup-terraform@v3
- run: terraform init && terraform plan -out tfplan.bin && terraform show -json tfplan.bin > tfplan.json
- uses: hawa-dizeyi/trueno-aws-rules@main
with:
resources: tfplan.json
from: terraform-plan
fail-on: highCoverage
58 service evaluators spanning ~140 distinct findings across:
api-gateway · athena · backup · budgets · cloudfront · cloudtrail · cloudwatch (alarms + logs) · config · cost-optimization-hub · docdb · dynamodb · ebs · ec2 · ecr · ecs · efs · eks · elasticache · emr · eventbridge · fsx · global-accelerator · glue · guardduty · iam · inspector · kinesis · kms · lambda · load-balancer · macie · marketplace · msk · neptune · network-firewall · opensearch · organizations · rds · redshift · reserved-instances · route53 · s3 · savings-plans · secrets-manager · security-group · security-hub · shield · sns · sqs · ssm-parameter · step-functions · vpc · waf — plus required-tag governance.
Purity guarantee
The published bundle has zero runtime dependencies. The rules are
deterministic: same input → same findings. That makes them trivially testable
and safe to run anywhere (a Lambda, a CI step, the browser). See
test/engine.test.ts.
How this package is maintained
The rule logic is generated from trueno's private engine by
scripts/extract.mjs, which strips the proprietary
scanner/persistence/account context and inlines the public types. The scanners,
assume-role/session handling, and persistence stay private by design — only the
rule catalog is open source.
License
MIT © Gigant Technology
