Add aws-backup-coverage-review skill - #71
Open
vediyappan-kk wants to merge 7 commits into
Open
Conversation
Adds a read-only skill that reports AWS Backup coverage and posture across all enabled Regions of an account. AWS Backup Audit Manager's coverage control requires AWS Config resource recording plus a framework and a report plan that has already run, so in accounts without that setup an operator cannot ask what is not being backed up. This skill computes the answer live from read-only APIs and uses AWS Config only as an optimization. Coverage is modelled as five states rather than a boolean: Protected, Stale, SelectedNotProtected, Unprotected, and OptInBlocked. The last three all render as healthy in the AWS Backup console, which is what makes them worth a skill. 21 fixed numbered checks across 5 dimensions, with a mandatory 21-row Check Coverage Matrix so no check can be silently dropped. Thresholds match the Backup Audit Manager control defaults so output is comparable with Audit Manager. Permission gaps are excluded from the coverage denominator and cap the rating rather than being scored as coverage gaps. Read-only throughout, with an explicit API allowlist and hard denials on any Put/Delete/Create/Update/Start operation. CloudTrail is deliberately unused. Also adds the llms.txt entry and an EnableAwsBackupCoverageReview parameter, condition, read-only inline policy, and SkillPolicySummary line in cloudformation/devops-agent-skill-policies.yaml.
Addresses TFC domain review feedback on observability. Adds two checks to the Coverage integrity dimension, taking the total to 23: - 5.4 verifies an Audit Manager report plan is scheduled in each Region that has backup activity. Report plans are per Region, so a single plan can look like account-wide reporting when it is not. - 5.5 verifies an Audit Manager framework is configured where protected resources exist. A report plan alone reports job activity without evaluating control compliance, so the two are complementary. The finding notes the AWS Config dependency where the recorder is inactive. Both consume ListReportPlans and ListFrameworks, which the data collection phase already gathered but no check previously used. Checks 5.1 to 5.3 ask whether protection is real; 5.4 and 5.5 ask whether a decline in it would be noticed. Coverage is a point-in-time state, and without scheduled reporting or evaluated controls a regression surfaces only when someone next runs a review by hand. Also updates the check count across all assertions, adds remediation text and three AWS documentation references, and corrects the check-inventory eval case which asserted the previous count.
Re-ran Agent Skill Eval against the current content so the committed evidence matches the code. Root passed: true, Overall Grade A (0.91) — audit 98/100, trigger 1.00, functional outcome and style 1.00, PARETO_BETTER (quality +0.51, cost -62.5%). Also broadens one assertion in the membership-vs-protection case. It previously accepted only the literal strings "not protection" / "is not protection" / "not the same", and failed a correct answer that said "membership alone is never protection". The assertion still requires the negation, it just no longer depends on one phrasing of it.
Live testing showed the report being replaced by a conversational summary in roughly half of runs, correlating with the host delegating the account sweep to a research subagent — which does not reliably load the skill's reference files. Instruction inside the skill did not fix this across four attempts. Follows the pattern every report-producing skill in this repository already uses: report output is specified in a paired custom agent's system prompt rather than in the skill alone. Adds custom-agents/aws-backup-coverage-review/ with the standard Goal/Approach/Constraints/Output structure, restating the report structure and the 23-row check matrix so the artifact is produced even when references/ is not loaded. Also adds a remediation boundary to the skill. In testing, after the review the agent proposed and then attempted DeleteBackupSelection and CreateBackupSelection; only IAM refused it. The skill documented hard denials on those calls but said nothing about what to do when a user asks for a fix. It now returns the exact change and resource identifiers for a human to apply, and declines to attempt the call rather than relying on IAM to stop it. Reinforces per-Region enumeration completeness after a run reported "I did not get to check FSx, Redshift, Timestream, Storage Gateway, or EKS" — a type that was never queried is indistinguishable in the report from a type with no resources, and the second reads as full coverage.
Tools are now selectable directly on the Create agent form, so the separate Edit -> Chat step to add use_aws is no longer needed. Keeps the chat flow as a documented fallback for Agent Spaces on an older release, since the form there has no Tools selector.
A live run reported 33 CloudFormation stacks against 56 actual. It probed the 18 Regions with no backup activity using ListBackupPlans and ListProtectedResources only, found them empty, and stopped — missing 22 stacks spread across those Regions by StackSets and CDK bootstrap. AWS Backup APIs returning nothing means AWS Backup is not configured there, which is the finding rather than a reason to stop looking. A Region with no backup plans and 40 unprotected resources is the case this review exists to surface. A Region may now be dropped only after the Phase 3 inventory calls have run and returned zero for every type, and the Scope table must state how each Region was established as empty. Calls out the bulk types this trips on, since StackSet instances, CDK bootstrap stacks, and replication buckets are commonly spread across every enabled Region regardless of where backups are configured.
…inferred A live run reported S3 as opted in for us-east-1 and us-west-2 and opted out for us-east-2. The actual ResourceTypeOptInPreference is the exact inverse: S3 is false in us-east-1 and us-west-2 and true in us-east-2. The same run inverted CloudFormation for us-east-2, and presented the change as a correction to an earlier run that had been right. This is a worse class of error than a miscount: it sends the operator to change opt-in in the wrong Region, and it carried false confidence because it was framed as a fix. The likely cause is inferring opt-in from the absence of a matching selection rather than reading the boolean. Check 1.1 now requires the literal boolean from DescribeRegionSettings.ResourceTypeOptInPreference for the specific Region, quoted in the observed column, and explicitly forbids inferring it from a missing selection, from AdvancedBackupSettings, or from resources being unprotected. Where the boolean cannot be quoted the Region is marked Unconfirmed rather than asserting a direction, and a re-run may not contradict an earlier value without citing the response that justifies it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds
aws-backup-coverage-review, a read-only skill that reports AWS Backup coverage and posture across all enabled Regions of an account.Why. AWS Backup Audit Manager can answer "what isn't backed up?", but its
BACKUP_RESOURCES_PROTECTED_BY_BACKUP_PLANcontrol requires AWS Config resource recording, a framework, and a report plan that has already run. Accounts without that setup cannot answer the question at the moment an operator asks it. This skill computes the answer live from read-only APIs, building its own resource inventory and diffing it againstListProtectedResources, and treats AWS Config as an optimization rather than a prerequisite.The core model is that coverage is not binary. Every eligible resource resolves to one of six states:
ProtectedStaleSelectedNotProtectedUnprotectedOptInBlockedOrphanedRecoveryPointListProtectedResourcesafter the resource was deletedThe middle three all render as healthy in the AWS Backup console, which is what makes them worth a skill. Testing surfaced a real instance of this: a backup selection that named a resource by literal ARN after that resource had been deleted, so every scheduled job failed while the plan still showed as active with a recent execution date — and the resources that had replaced it were covered by nothing.
Structure. 21 fixed, numbered checks across 5 dimensions (service enablement, coverage, plan quality, vault posture, coverage integrity), with a mandatory 21-row Check Coverage Matrix so no check can be silently dropped — following the
analytics-opensearch-expertisepattern. Thresholds match the AWS Backup Audit Manager control defaults so output is comparable with Audit Manager.Read-only throughout, with an explicit API allowlist and hard denials on any
Put*/Delete*/Create*/Update*/Start*. CloudTrail is deliberately unused, since the agent tool policy currently classifies that namespace as mutative. Permission gaps are excluded from the coverage denominator and cap the rating rather than being scored as coverage gaps — a blind spot is not a coverage gap.Non-duplication. No existing skill covers the AWS Backup service.
storage-s3-resiliency-expertiseexplicitly excludes it ("Do NOT use for … EFS, FSx, AWS Backup, or Storage Gateway").rds-operation-reviewcovers RDS-nativeBackupRetentionPeriod. Open PR #26 (drift-detection-baseline) has one row checking RDSBackupRetentionPeriodand DynamoDB PITR — that is service-native configuration, not the AWS Backup service, and there is no overlap in APIs or findings.IAM. Verified with
iam:SimulatePrincipalPolicyagainst live agent roles:AIDevOpsAgentAccessPolicyalready allows 43 of the 49 actions used. Only five need adding —backup:GetSupportedResourceTypes,config:SelectResourceConfig,dsql:ListClusters,storagegateway:ListFileShares,storagegateway:ListVolumes— all read-only. Added under a newEnableAwsBackupCoverageReviewparameter incloudformation/devops-agent-skill-policies.yaml. Every mutating AWS Backup action (StartBackupJob,StartRestoreJob,StartCopyJob,DeleteRecoveryPoint,DeleteBackupPlan,PutBackupVaultLockConfiguration,UpdateRegionSettings) was confirmed denied on all roles tested, so the read-only guarantee is enforced by IAM rather than only by the skill's instructions.Also in this PR:
llms.txtentry.Type of change
Testing
Agent Skill Eval — root
"passed": true, Overall Grade A (0.91)Note on the functional score: the sub-scores are outcome 1.0, style 1.0, efficiency 1.0, process 0.21.
process_scoreismin(1, mean_tool_calls_with / mean_tool_calls_without), so it drops precisely because the skill reaches the answer in fewer tool calls than the no-skill baseline. Every functional assertion passes. The single INFO finding isSKILL.mdbody size against the 5,000-token guideline.Manual DevOps Agent testing — tested over repeated runs across several Agent Spaces against a test account with real backup plans, vaults, and coverage gaps. Prompts were always phrased as an operator would ("What isn't being backed up in this account?"), never naming the skill. Triggering was consistent in every run.
Early runs surfaced accurate findings but returned them as a conversational summary rather than the report. Adding an Output Contract, an inlined report skeleton, and a countable self-check to
SKILL.mdimproved this but did not make it reliable — the failures correlated with the host delegating the account sweep to a research subagent, which does not reliably load the skill's reference files.The fix was to follow the pattern every report-producing skill in this repository already uses: a paired custom agent whose system prompt restates the report structure. Since adding
custom-agents/aws-backup-coverage-review/, runs executed through the custom agent have produced the complete report artifact consistently — all required sections, the full 23-row Check Coverage Matrix, and self-consistent arithmetic. The skill remains usable on its own in chat, where it produces the findings but not reliably the full report; that is documented in the skill README.Findings verified independently with direct read-only API calls against the test account. Across runs the skill correctly identified: unprotected EC2, EBS, Aurora, DynamoDB, DocumentDB, EKS, S3 and CloudFormation resources; a backup selection referencing a deleted EC2 instance whose jobs had been failing silently with
InvalidInstanceID.NotFound; per-Region resource type opt-in states; an orphaned recovery point for an EFS file system deleted four years earlier, correctly excluded from both numerator and denominator; sub-35-day retention on three plans; absent cross-Region and cross-account copies; unlocked vaults; missing vault access policies and failure notifications; and absent Audit Manager report plans and frameworks including the AWS Config dependency that blocks framework controls.Two behaviours were added in response to live testing and are worth calling out, because both are safety-relevant:
DeleteBackupSelectionandCreateBackupSelectionwhen asked to fix a finding. IAM refused it, but the skill had said nothing about what to do when a user asks for remediation. It now returns the exact change and resource identifiers for a human to apply and declines to attempt the call, rather than relying on IAM to stop it.Known limitation, also stated in the README. Per-resource states are reliable: a named ARN reported as unprotected is a verified fact, and the findings and remediation are sound. Aggregate counts are less precise. In the most recent verified run the account-wide total was 103 eligible resources against 108 actual, with the gap entirely in CloudFormation stacks (51 reported against 56 actual). S3 bucket counts and per-Region attribution were exact. The skill therefore presents the coverage percentage as indicative, names the Coverage Matrix as the record of record, and never lets a coverage total influence a severity. I would rather state this plainly than imply a precision the skill does not have.
Also validated:
mkdocs build --strictpasses and both the skill and custom agent catalog pages render with correct metadata, tools and skills extracted;aws cloudformation validate-templatepasses and resolves the new parameter; every AWS documentation URL inreferences/backup-best-practices.mdreturns HTTP 200; the 23 check IDs are identical betweenreferences/coverage-logic.mdand the Check Coverage Matrix inreferences/report-format.md; andiam:SimulatePrincipalPolicyagainst live agent roles confirms all 7 mutating AWS Backup actions remain denied with the five added read actions in place.One platform issue encountered, unrelated to this skill.
backup:ListRestoreTestingPlansis cancelled inside DevOps Agent, reported by the agent as being classified a mutative operation, in every Region and on every role tested — including roles whereiam:SimulatePrincipalPolicyconfirms the action is allowed and where the API succeeds when called directly outside the agent. Check 5.1 therefore returnsToolingFailurerather than a verdict. Every otherbackup:List*call in the same runs succeeded, so this appears specific rather than namespace-wide. Raising separately.License confirmation