fix(01-harness): stop 07-oauth reporting success for a failed invoke, and leaking on failure - #1877
Open
rmncardoso wants to merge 1 commit into
Open
Conversation
… and leaking on failure
InvokeHarness over HTTPS returns HTTP 200 and reports agent-side failures as
{"message": ...} frames inside the event stream. The parser read only
obj["delta"], discarded those frames, printed "(No text deltas found in
stream)", and then printed the full success narrative claiming all three auth
hops had worked. Separately, the script had no try/finally, so a failure
anywhere between Step 1a and Step 4 left two Cognito pools, a credential
provider, a Lambda, a gateway + target, a harness and three IAM roles alive.
Correctness:
- Raise on non-200, collect and raise on stream error frames, and raise when
there are neither deltas nor an error frame.
- Grant the 8 memory/event actions the harness needs at runtime; CreateMemory
and ListMemories take no memory ID, so they must be scoped to "*".
- Replace three fall-through polls with deadline loops that raise on terminal
status and on timeout.
- Wrap provisioning in try/finally so cleanup always runs.
- _wait_gone no longer reports success on timeout.
- Do not print "Cleanup complete!" when resources were skipped.
- _ensure_policy publishes a new default version instead of swallowing
EntityAlreadyExists, pruning the oldest non-default at the 5-version limit.
- Paginate the Cognito pool lookup and every AgentCore list call
(ListHarnesses, ListGateways, ListGatewayTargets) through one helper.
- Match the gateway and target conflict fallbacks on name; the target fallback
took the first target it saw, which returns the wrong id on a gateway that
carries any other target.
- Drop the N+1 get_gateway in the gateway fallback; ListGateways returns name.
- _del_role can now delete a policy that has non-default versions.
- Convert six `except Exception: pass` handlers into reported skips.
Docs and lint:
- README: document the IAM permissions the walkthrough needs, and drop the
`pip install requests` step -- requests is already in ../../requirements.txt.
- utils/lambda_function_code.py: fix a latent import-order violation and a
docstring that named the wrong tools.
|
Latest scan for commit: Security Scan ResultsScan Metadata
SummaryScanner ResultsThe table below shows findings by scanner, with status based on severity thresholds and dependencies: Column Explanations: Severity Levels (S/C/H/M/L/I):
Other Columns:
Scanner Results:
Severity Thresholds (Thresh Column):
Threshold Source: Values in parentheses indicate where the threshold is configured:
Statistics calculation:
|
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.
Summary
07-oauthprinted a full success narrative even when the agent invocation failed, and leaked every resource it created if any step raised. Every fix below was reproduced against upstreammainand re-verified live in a real AWS account (7 deploy/teardown cycles).Correctness
InvokeHarnessover HTTPS returns HTTP 200 and reports agent-side failures as{"message": ...}frames inside the binary event stream. The parser read onlyobj["delta"], discarded them, printed(No text deltas found in stream)plus raw bytes, and then printed the success narrative claiming all three auth hops had worked. Now: raise on non-200, collect and raise on error frames, and raise when there are neither deltas nor an error frame.AccessDeniedExceptiononListEvents. Added the 8 memory/event actions.CreateMemoryandListMemoriestake no memory ID, so they areimplicitDenyundermemory/*and must be scoped to"*"(confirmed withiam:SimulateCustomPolicy); the other 6 stay onmemory/*.CREATING— surfacing as a confusing HTTP error rather than the real cause. Replaced with deadline loops that raise on terminal status and on timeout.try/finally. A failure between Step 1a and Step 4 left two Cognito pools, a credential provider, a Lambda, a gateway + target, a harness and three IAM roles alive — all billable, and all blocking the next run withConflictException._wait_gonereturned success on timeout; it now returns a boolean the caller honours.✅ Cleanup complete!printed even when resources had been skipped._ensure_policyswallowedEntityAlreadyExists, so a re-run silently kept a stale policy document. It now publishes a new default version, pruning the oldest non-default at the 5-version service limit._del_rolecould not delete a policy that had non-default versions.ListHarnesses,ListGatewaysandListGatewayTargetsall return anextToken. Routed through a singleiter_paginatedhelper. This has two distinct consequences, neither of which mentions pagination: a lookup afterConflictExceptionfails with "conflict but not found" for a resource that demonstrably exists, and cleanup reports "not found" and walks past a resource it created — leaking it, and in the harness case leaking its managed memory with it.targetId— and the poll then waits on a resource this script never created.get_gatewayper gateway in the gateway conflict fallback;ListGatewaysalready reportsname, so only the match needs describing. The original described every gateway in the account, which on a busy account risks throttling during what is meant to be a recovery path.Also converted 6
except Exception: passhandlers into reported skips, so cleanup failures are visible instead of silent.Docs and lint
pip install requests— already line 9 of../../requirements.txt. Added a permission table (enumerated by walking the AST of every boto3 call in the sample) and a helper-function table.utils/lambda_function_code.pycarried a latent import-order violation and a docstring naming the wrong tools. It had never failed CI because CI lints only changed files and this file had never been modified.Testing
7 live deploy/teardown cycles in
us-west-2, on a fresh-account baseline:Deleted 13 resources, skipped 1--skip-cleanupDeleted 14 resources, skipped 0; policiesv1→v2 default--skip-cleanup, final bytesDeleted 13 resources, skipped 1Every run exited 0, and after each one the account returned to its exact pre-flight baseline with zero leaked resources. The harness's managed
harness_*memory self-reaps a couple of minutes after the harness delete completes — confirmed, so cleanup does not need to (and cannot) delete it directly.Also: 63 unit checks covering the branches a healthy account cannot reach (terminal statuses, timeouts, policy-version pruning, pagination across a page boundary, and static assertions that the success narrative sits after every guard that protects it).
ruff checkandruff format --checkare clean on all four files at both ruff 0.15.0 and 0.16.1.Deliberately unchanged
_wait_gone's broadexcept— a missing gateway raisesAccessDeniedException, notResourceNotFoundException(verified live), so narrowing it would break the "gone" detection.