Documentation
StackSage runs AWS audits in your environment (typically GitHub Actions) using a customer-controlled read-only role. It produces local artifacts you can share internally: a one-page summary, an HTML report, and machine-readable findings.
What StackSage does
- Finds cost waste and concrete savings opportunities.
- Flags security posture signals(IAM hygiene, exposure basics, audit logging baselines).
- Makes findings explainable via evidence/provenance (e.g. measured vs heuristic vs skipped due to permissions).
Trial mode (self-serve)
StackSage Trial is designed to run without dependency on us: you can set it up in your own repo, run it on demand, and download artifacts. Trial uses a public GHCR image and does not require a license.
Trial is intentionally limited: it caps findings and does not compute exact savings.
What you need
- A GitHub repo with Actions enabled
- AWS credentials (owned by you) stored as GitHub secrets
- A read-only IAM role ARN that the workflow can assume
Step 1 — Create the IAM role (AWS)
Create an IAM role in your AWS account and allow the GitHub runner to assume it (STS AssumeRole). Attach this minimal trial policy to that role:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "StackSageTrialReadOnly",
"Effect": "Allow",
"Action": [
"sts:GetCallerIdentity",
"ec2:DescribeRegions",
"ec2:DescribeSecurityGroups",
"ec2:DescribeAddresses",
"ec2:DescribeVolumes",
"iam:GetAccountSummary",
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"s3control:GetPublicAccessBlock"
],
"Resource": "*"
}
]
}Step 2 — Add GitHub secrets
In your repo: Settings → Secrets and variables → Actions
- Required: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
- Recommended: AWS_DEFAULT_REGION (example: us-east-1)
- Required (unless you always provide it as a workflow input): CUSTOMER_ROLE_ARN
- Optional: AWS_SESSION_TOKEN, CUSTOMER_EXTERNAL_ID
Step 3 — Add the workflow file
Create .github/workflows/stacksage_trial.yml with the workflow below. Run it from GitHub → Actions → “StackSage Audit (Trial)”.
name: StackSage Audit (Trial)
on:
workflow_dispatch:
inputs:
customer_role_arn:
description: "Customer role ARN to assume"
required: false
type: string
regions:
description: "Comma-separated AWS regions (optional; default: 1 region for trial)"
required: false
type: string
log_level:
description: "Log level (INFO/DEBUG)"
required: false
default: "INFO"
type: choice
options: ["INFO", "DEBUG"]
jobs:
audit:
runs-on: ubuntu-latest
env:
STACKSAGE_TRIAL_IMAGE: ghcr.io/amitdubey428/stacksage-trial:latest
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
CUSTOMER_EXTERNAL_ID: ${{ secrets.CUSTOMER_EXTERNAL_ID }}
steps:
- name: Pull StackSage trial image
run: docker pull "${STACKSAGE_TRIAL_IMAGE}"
- name: Run audit (trial mode)
shell: bash
run: |
set -euo pipefail
: "${AWS_ACCESS_KEY_ID:?Missing secret AWS_ACCESS_KEY_ID}"
: "${AWS_SECRET_ACCESS_KEY:?Missing secret AWS_SECRET_ACCESS_KEY}"
if [[ -z "${AWS_DEFAULT_REGION:-}" ]]; then
export AWS_DEFAULT_REGION="us-east-1"
fi
ROLE_ARN="${{ inputs.customer_role_arn || secrets.CUSTOMER_ROLE_ARN }}"
: "${ROLE_ARN:?Missing role ARN. Set input customer_role_arn or repo secret CUSTOMER_ROLE_ARN}"
REGIONS_ARG=""
if [[ -n "${{ inputs.regions }}" ]]; then
REGIONS_ARG="--regions ${{ inputs.regions }}"
fi
EXT_ID_ARG=""
if [[ -n "${CUSTOMER_EXTERNAL_ID:-}" ]]; then
EXT_ID_ARG="--external-id ${CUSTOMER_EXTERNAL_ID}"
fi
mkdir -p reports
docker run --rm -e AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}" -e AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}" -e AWS_SESSION_TOKEN="${AWS_SESSION_TOKEN:-}" -e AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-}" -v "$PWD":/work -w /app "${STACKSAGE_TRIAL_IMAGE}" bash -lc "python -m stacksage_trial.cli audit --role-arn ${ROLE_ARN} ${EXT_ID_ARG} ${REGIONS_ARG} --out /work/reports --log-level ${{ inputs.log_level }}"
- name: Upload reports artifact
uses: actions/upload-artifact@v4
with:
name: stacksage-reports
path: reports/
if-no-files-found: error
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
CUSTOMER_EXTERNAL_ID: ${{ secrets.CUSTOMER_EXTERNAL_ID }}
Outputs
The workflow uploads an artifact named stacksage-reports containing:
- audit_report.html — includes Security Findings + a limited Cost/Waste Preview
- summary.md
- findings.json / findings.csv
- run_provenance.json
Troubleshooting
- AccessDenied: ensure the trial policy is attached to the assumed role and the trust policy allows your GitHub principal.
- No regions: set AWS_DEFAULT_REGIONor provide regions input.
- Missing artifact: confirm the workflow step writes to reports/ before upload.
How it works (high level)
- Run StackSage on a schedule (GitHub Actions) or locally.
- Assume a customer-controlled read-only role (STS AssumeRole).
- Read resource metadata and (optional) aggregate utilization/spend totals.
- Generate local artifacts as workflow outputs under your control.
Outputs
- summary.md — one-page account brief (top savings, security posture, skipped checks, next actions)
- audit_report.html — full interactive report (financial findings vs security posture findings, plus complete appendix)
- findings.json / findings.csv — machine-readable exports
- remediation_plan.md / remediation_plan.json — prioritized fix plan with safe verification steps (paid runs)
See a real example at /demo-report.
Paid GitHub workflow ($99/mo)
The paid workflow is the “full” StackSage experience: deeper coverage, richer evidence, and a license secret. Trial is the fastest way to validate the report format and baseline posture.
- Runs in your GitHub Actions runner, using a customer-controlled read-only role
- Private GHCR image + time-limited license secret
- Includes remediation plan generation (prioritized actions + safe verification steps)
- Intended for recurring audits (weekly/daily)
For permissions and opt-ins, see Privacy & Access.
Security posture signals (what we check)
StackSage includes baseline posture checks intended to surface obvious risks early and reduce audit blind spots. These checks are designed to be privacy-first: we prefer aggregate evidence and avoid raw sensitive policy contents.
- IAM hygiene: root MFA, root keys, password policy baseline, access key rotation signals
- Exposure basics: public security group ingress on sensitive ports, S3 public access block posture, RDS public/encryption/backup baselines
- Audit logging: CloudTrail baseline, AWS Config recorder status, high-level enablement checks
Privacy & permissions
StackSage is privacy-first by default. It runs inside your environment and produces local artifacts; it does not require exporting AWS inventory to a hosted SaaS.
Read the detailed permissions matrix and opt-ins here: /privacy-access.
Support
If you get stuck, email hello@stacksageai.com.