-
Notifications
You must be signed in to change notification settings - Fork 224
Description
Problem
Event stream operations that include an initial-request message send that message unsigned, even when the operation requires SigV4 authentication and all subsequent messages are properly signed.
Root Cause
The issue is in the client codegen for event streams with initial requests:
The generated code creates the initial message and immediately serializes it to bytes:
let initial_message = initial_message(body);
let mut buffer = Vec::new();
write_message_to(&initial_message, &mut buffer)?;
let initial_message_stream = futures_util::stream::iter(vec![Ok(buffer.into())]);
let adapter = message_stream_adaptor;
initial_message_stream.chain(adapter)The problem is that initial_message is written to bytes before being chained with the MessageStreamAdapter. The adapter is what signs messages in its poll_next() implementation, but the initial message bytes bypass this entirely.
For comparison, regular event messages flow through the adapter's signing pipeline:
- Poll stream for message
- Marshall message
- Sign message
- Write signed message to bytes
But the initial message is already bytes when chained, so step 3 never happens.
Impact
Any AWS service operation using event streams with initial-request messages will:
- Send the initial message without a signature
- Potentially fail authentication if the service validates initial message signatures
- Have inconsistent behavior between the initial message and subsequent messages
Reproduction
The server-side tests show this is expected to work:
https://github.com/smithy-lang/smithy-rs/blob/main/codegen-server-test/integration-tests/eventstreams/tests/structured_eventstream_tests.rs#L701-L703
Server code handles signed initial messages correctly, but client codegen doesn't generate them.
Solution
The initial message needs to flow through the same marshalling/signing pipeline as regular events. This likely requires:
- Not serializing the initial message during request serialization
- Including it in the stream that goes through MessageStreamAdapter
- Ensuring the marshaller can handle initial-request message types
The challenge is that signing happens after HTTP request signing (which provides the signature for the first event stream message), so the initial message can't be signed during serialization - it needs to be deferred like other event messages.