Skip to content

feat(actions): vend AWS STS web identity sessions#137

Merged
pquerna merged 7 commits into
mainfrom
paul.querna/aws-sts-web-identity-action
Jul 23, 2026
Merged

feat(actions): vend AWS STS web identity sessions#137
pquerna merged 7 commits into
mainfrom
paul.querna/aws-sts-web-identity-action

Conversation

@c1-squire-dev

@c1-squire-dev c1-squire-dev Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an AWS-specific global action for credential vending without modeling ephemeral STS sessions as durable resources.

  • accepts a C1-issued, short-lived OIDC token
  • invokes AssumeRoleWithWebIdentity against a customer-configured trust relationship
  • bounds requested duration to AWS's 900–43200 second range
  • validates AWS role-session names and optional inline session-policy JSON
  • accepts exactly one canonical age recipient
  • encrypts the full STS credential envelope before it crosses the connector boundary
  • returns only ciphertext, encryption key ID, expiration, and assumed-role ARN
  • maps common AWS identity, authorization, and throttling failures to actionable gRPC statuses
  • rejects incomplete STS responses rather than emitting unusable credential material

The C1 platform remains responsible for OIDC token issuance, entitlement and approval resolution, audience/subject claims, idempotent request tracking, supplying the encryption recipient, storing/decrypting the encrypted result, and audit. AWS remains responsible for validating the role trust policy and limiting session duration.

Customer prerequisite

The customer creates an IAM OIDC provider for the C1 issuer and a target role whose trust policy restricts issuer, audience, and subject. C1 then invokes this action with the target role ARN, a per-request OIDC token, and a platform-controlled age recipient.

Security boundary

The connector never returns plaintext AWS credentials. The optional session policy can only narrow the target role's permissions; it can be used for contextual restrictions such as an aws:SourceIp deny boundary. The target role trust policy remains the authoritative AWS-side admission boundary.

Validation

  • go test ./...
  • go build ./cmd/baton-aws
  • golangci-lint run

@c1-squire-dev
c1-squire-dev Bot requested a review from a team July 22, 2026 08:17
Comment thread pkg/connector/sts_actions.go Outdated
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@-

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@c1-squire-dev

c1-squire-dev Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Outer-loop security correction: the action no longer returns plaintext STS fields in a generic response. It now requires a platform-provided age recipient, encrypts the complete credential envelope inside baton-aws, and returns only base64 age ciphertext, its recipient-derived key ID, expiration, and assumed-role ARN. Full go test ./... passes.

@c1-squire-dev
c1-squire-dev Bot force-pushed the paul.querna/aws-sts-web-identity-action branch from 5bc9f80 to 566ef10 Compare July 22, 2026 08:22

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Connector PR Review: feat(actions): vend AWS STS web identity sessions

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: loaded .claude/skills/ci-review.md from trusted base 0f99d9e.
Review mode: full
View review run

Review Summary
Scanned the full PR diff for security and correctness. This PR adds a new additive global action (assume_role_with_web_identity) that exchanges a C1-issued OIDC token for an STS session and age-encrypts the credential envelope before returning it; the security boundary is sound (never returns plaintext, single canonical age recipient enforced, all inputs validated, and AWS errors mapped to appropriate gRPC codes). The change is additive with no breaking changes, go.mod correctly promotes filippo.io/age from indirect to direct with no go.sum change needed, docs are updated, and test coverage is strong (happy path with round-trip decryption, error-code mapping, invalid duration, invalid inputs, and incomplete-credential cases). No blocking issues found.

Security Issues
None found.

Correctness Issues
None found.

Suggestions

  • pkg/connector/sts_actions.go:117 — json.Valid accepts any valid JSON (e.g. a bare string or number), not just a policy object; AWS then rejects non-object policies as MalformedPolicyDocument (mapped to InvalidArgument), so behavior is safe, but unmarshaling policy_json into a JSON object would fail faster with a clearer local error.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

Comment thread pkg/connector/sts_actions.go Outdated
Comment thread go.mod Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@c1-squire-dev
c1-squire-dev Bot force-pushed the paul.querna/aws-sts-web-identity-action branch from b549f6e to 7dfdc3b Compare July 23, 2026 01:05
@c1-squire-dev

c1-squire-dev Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (b1f19c3, including #138) and force-pushed with lease. The semantic conflict was an already-landed SDK attribute migration; I kept current-main behavior and removed unrelated sso_user churn. I also tightened the action boundary after re-review: canonical single-recipient age input, AWS-compatible session names, valid/size-bounded session-policy JSON, and complete STS credential-response validation. Local gates pass: go test ./..., go build ./cmd/baton-aws, and golangci-lint run.

Comment thread pkg/connector/sts_actions.go

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@c1-squire-dev

c1-squire-dev Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Followed up on the fresh automated-review suggestion in deacb92: InvalidParameterValue, MalformedPolicyDocument, and PackedPolicyTooLarge now map to gRPC InvalidArgument, with table-driven coverage. These are deterministic caller failures and should not be surfaced as retryable internal failures. Re-ran go test ./... and golangci-lint run locally.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

pquerna and others added 7 commits July 23, 2026 17:29
Add a global action that exchanges a C1-issued OIDC token for a bounded AssumeRoleWithWebIdentity session, with optional restrictive session policy and secret-marked outputs.

Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
Translate AWS identity, authorization, and throttling failures to actionable gRPC statuses and document the OIDC trust and encrypted action contract.

Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
Move profiles, status, and creation timestamps off deprecated trait fields and resolve action schema lint findings.

Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
Use the standard RFC3339 layout and upgrade age to v1.3.1, including the vendored HPKE dependency.

Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
Reject noncanonical encryption recipients, invalid AWS session names and policies, and incomplete credential responses. Drop unrelated resource-status churn carried through the rebase.

Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
Map AWS policy and parameter validation failures to InvalidArgument so callers do not retry deterministic request failures.

Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
@c1-squire-dev
c1-squire-dev Bot force-pushed the paul.querna/aws-sts-web-identity-action branch from deacb92 to 08ff89d Compare July 23, 2026 17:30
DurationSeconds: awsSdk.Int32(int32(duration)),
}
if policy, exists := actions.GetStringArg(args, "policy_json"); exists && strings.TrimSpace(policy) != "" {
if len(policy) > maxSTSSessionPolicyLength || !json.Valid([]byte(policy)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: json.Valid accepts any valid JSON token (bare string, number, boolean), not just a policy object. AWS will still reject non-object policies as MalformedPolicyDocument (mapped to InvalidArgument), so this is not a correctness bug — but unmarshaling into a map[string]any (or checking the first non-space byte opens an object) would reject invalid shapes locally with a clearer error before the STS call.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@pquerna
pquerna merged commit d6357ef into main Jul 23, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant