feat: add STS service with all 8 operations#15
Merged
Conversation
Implement AWS Security Token Service (STS) for RustStack with full API coverage across two phases: Phase 0 - Core operations: - GetCallerIdentity: returns account/ARN/user ID for caller - AssumeRole: generates temporary credentials with session tags - GetSessionToken: generates temporary credentials for current identity - GetAccessKeyInfo: extracts account ID from access key Phase 1 - Federation and advanced: - AssumeRoleWithSAML: accepts SAML assertions (no crypto validation) - AssumeRoleWithWebIdentity: accepts JWT tokens (no signature verification) - DecodeAuthorizationMessage: returns static decoded message - GetFederationToken: generates federated user credentials Architecture (3-crate pattern): - ruststack-sts-model: Smithy-codegen'd types, operations, errors - ruststack-sts-http: awsQuery protocol (form-urlencoded/XML), SigV4 routing - ruststack-sts-core: business logic, credential/session stores, tag propagation Key features: - SigV4 credential scope routing (service=sts) to disambiguate from SNS - Temporary credential generation (ASIA* access keys, session tokens) - Session tag propagation across chained AssumeRole calls - Account ID encoding in access keys (base-36) - Permissive identity resolution (unknown keys treated as root) - 50 unit tests, 16 integration tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix mismatched request IDs: pass request_id from HTTP layer through handler to XML response (was generating two different UUIDs) - Validate DurationSeconds parameter with proper range checking per AWS spec (AssumeRole: 900-43200, GetSessionToken: 900-129600, etc.) - Use error.status_code field in error_to_response instead of re-computing from error code (respects per-instance overrides) - Remove expect() in encode_base36 by building String from chars directly - Remove dead SAML base64 decode that was immediately discarded - Remove dead error_type() methods (JSON-oriented, unused in awsQuery) - Fix module doc comment: STS uses XML/awsQuery, not JSON/__type Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add sts-test.yml: 13 AWS CLI test steps covering all 8 operations, chained AssumeRole tag propagation, error cases, and Rust SDK tests - Update integration.yml to set STS_SKIP_SIGNATURE_VALIDATION=true Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AssumeRoleWithWebIdentity and AssumeRoleWithSAML are federation operations that don't require SigV4 signing (used for initial auth). The AWS CLI sends these without an Authorization header. Update STS router to match unsigned form-urlencoded POST requests (no Authorization header) in addition to SigV4 service=sts requests. Update SNS router to explicitly check service=sns in SigV4 instead of catching all form-urlencoded requests, preventing routing conflicts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ation CloudWatch SDK v1.108+ switched from awsQuery to rpcv2Cbor protocol, breaking our awsQuery-based CloudWatch router. Pin to ~1.60 (last awsQuery version) until the CloudWatch service is migrated to support the new protocol. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AWS SDK CloudWatch v1.108+ switched from awsQuery to Smithy rpcv2Cbor
protocol. Update CloudWatch HTTP service to handle both protocols:
- Detect protocol from smithy-protocol header or content-type
- Route rpcv2Cbor requests via URL path (/service/.../operation/{Op})
- Deserialize CBOR request bodies using ciborium (serde-compatible)
- Serialize CBOR responses for all 31 CloudWatch operations
- Return CBOR-encoded errors with __type and message fields
- Keep full backward compatibility with awsQuery (form-urlencoded/XML)
Also:
- Unpin aws-sdk-cloudwatch to latest (was ~1.60, now "1")
- Add ciborium and http-body to workspace dependencies
- Fix inline http-body deps in STS and CloudWatch crates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Smithy rpcv2Cbor encodes timestamps as CBOR tag 1 + epoch-seconds floats, but our model types use chrono::DateTime with serde expecting ISO 8601 strings. The AWS SDK also expects tag 1 epochs in responses. Fix by converting timestamps at the CBOR/JSON boundary: - Input: CBOR → Value → JSON (epoch→ISO transform) → deserialize - Output: serialize → JSON → Value → CBOR (ISO→epoch tag 1 transform) This handles all CloudWatch timestamp fields (StartTime, EndTime, AlarmConfigurationUpdatedTimestamp, CreationDate, LastModified, etc.) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Timestamps field (plural, Vec<DateTime>) was not being converted because is_timestamp_field only matched singular names. Also, the epoch_to_iso_string/iso_string_to_epoch functions only handled scalar values, not arrays. Fix: add array-aware convert_timestamp_value_to_json/cbor helpers and extend is_timestamp_field to match plural forms (Times, Timestamps). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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
ruststack-sts-model(Smithy codegen),ruststack-sts-http(awsQuery protocol),ruststack-sts-core(business logic)service=sts) to disambiguate from SNS (both use form-urlencoded POST)aws-sdk-stscovering all 8 operations and edge casesTest plan
cargo test -p ruststack-sts-model -p ruststack-sts-http -p ruststack-sts-core(50 tests)cargo clippy -p ruststack-sts-{model,http,core} -- -D warningscargo test -p ruststack-integration -- sts --ignored(requires running server)aws sts get-caller-identity --endpoint-url http://localhost:4566🤖 Generated with Claude Code