1 - | // Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
|
2 - | /// Wrapper for event stream messages that may be signed
|
3 - | #[derive(Debug)]
|
4 - | pub struct SignedEvent<T> {
|
5 - | /// The actual event message
|
6 - | pub message: T,
|
7 - | /// Signature information if the message was signed
|
8 - | pub signature: ::std::option::Option<crate::sigv4_event_stream::SignatureInfo>,
|
9 - | }
|
10 - |
|
11 - | /// Error wrapper for signed event stream errors
|
12 - | #[derive(Debug)]
|
13 - | pub enum SignedEventError<E> {
|
14 - | /// Error from the underlying event stream
|
15 - | Event(E),
|
16 - | /// Error extracting signed message
|
17 - | InvalidSignedEvent(crate::sigv4_event_stream::ExtractionError),
|
18 - | }
|
19 - |
|
20 - | impl<E> From<E> for SignedEventError<E> {
|
21 - | fn from(err: E) -> Self {
|
22 - | SignedEventError::Event(err)
|
23 - | }
|
24 - | }
|
25 - |
|
26 - | /// Information extracted from a signed event stream message
|
27 - | #[non_exhaustive]
|
28 - | #[derive(Debug, Clone)]
|
29 - | pub struct SignatureInfo {
|
30 - | /// The chunk signature bytes from the `:chunk-signature` header
|
31 - | pub chunk_signature: Vec<u8>,
|
32 - | /// The timestamp from the `:date` header
|
33 - | pub timestamp: ::std::time::SystemTime,
|
34 - | }
|
35 - |
|
36 - | /// Error type for signed message extraction operations
|
37 - | #[non_exhaustive]
|
38 - | #[derive(Debug)]
|
39 - | pub enum ExtractionError {
|
40 - | /// The payload could not be decoded as a valid message
|
41 - | #[non_exhaustive]
|
42 - | InvalidPayload {
|
43 - | error: ::aws_smithy_eventstream::error::Error,
|
44 - | },
|
45 - | /// The timestamp header is missing or has an invalid format
|
46 - | #[non_exhaustive]
|
47 - | InvalidTimestamp,
|
48 - | }
|
49 - |
|
50 - | /// Unmarshaller wrapper that handles SigV4 signed event stream messages
|
51 - | #[derive(Debug)]
|
52 - | pub struct SigV4Unmarshaller<T> {
|
53 - | inner: T,
|
54 - | }
|
55 - |
|
56 - | impl<T> SigV4Unmarshaller<T> {
|
57 - | pub fn new(inner: T) -> Self {
|
58 - | Self { inner }
|
59 - | }
|
60 - | }
|
61 - |
|
62 - | impl<T> ::aws_smithy_eventstream::frame::UnmarshallMessage for SigV4Unmarshaller<T>
|
63 - | where
|
64 - | T: ::aws_smithy_eventstream::frame::UnmarshallMessage,
|
65 - | {
|
66 - | type Output = crate::sigv4_event_stream::SignedEvent<T::Output>;
|
67 - | type Error = crate::sigv4_event_stream::SignedEventError<T::Error>;
|
68 - |
|
69 - | fn unmarshall(
|
70 - | &self,
|
71 - | message: &::aws_smithy_types::event_stream::Message,
|
72 - | ) -> ::std::result::Result<
|
73 - | ::aws_smithy_eventstream::frame::UnmarshalledMessage<Self::Output, Self::Error>,
|
74 - | ::aws_smithy_eventstream::error::Error,
|
75 - | > {
|
76 - | // First, try to extract the signed message
|
77 - | match crate::sigv4_event_stream::extract_signed_message(message) {
|
78 - | Ok(MaybeSignedMessage::Signed {
|
79 - | message: inner_message,
|
80 - | signature,
|
81 - | }) => {
|
82 - | // Process the inner message with the base unmarshaller
|
83 - | match self.inner.unmarshall(&inner_message) {
|
84 - | Ok(unmarshalled) => match unmarshalled {
|
85 - | ::aws_smithy_eventstream::frame::UnmarshalledMessage::Event(event) => {
|
86 - | Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Event(
|
87 - | crate::sigv4_event_stream::SignedEvent {
|
88 - | message: event,
|
89 - | signature: Some(signature),
|
90 - | },
|
91 - | ))
|
92 - | }
|
93 - | ::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(err) => {
|
94 - | Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(
|
95 - | crate::sigv4_event_stream::SignedEventError::Event(err),
|
96 - | ))
|
97 - | }
|
98 - | },
|
99 - | Err(err) => Err(err),
|
100 - | }
|
101 - | }
|
102 - | Ok(MaybeSignedMessage::Unsigned) => {
|
103 - | // Process unsigned message directly
|
104 - | match self.inner.unmarshall(message) {
|
105 - | Ok(unmarshalled) => match unmarshalled {
|
106 - | ::aws_smithy_eventstream::frame::UnmarshalledMessage::Event(event) => {
|
107 - | Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Event(
|
108 - | crate::sigv4_event_stream::SignedEvent {
|
109 - | message: event,
|
110 - | signature: None,
|
111 - | },
|
112 - | ))
|
113 - | }
|
114 - | ::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(err) => {
|
115 - | Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(
|
116 - | crate::sigv4_event_stream::SignedEventError::Event(err),
|
117 - | ))
|
118 - | }
|
119 - | },
|
120 - | Err(err) => Err(err),
|
121 - | }
|
122 - | }
|
123 - | Err(extraction_err) => Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Error(
|
124 - | crate::sigv4_event_stream::SignedEventError::InvalidSignedEvent(extraction_err),
|
125 - | )),
|
126 - | }
|
127 - | }
|
128 - | }
|
129 - |
|
130 - | /// Result of extracting a potentially signed message
|
131 - | #[derive(Debug)]
|
132 - | pub enum MaybeSignedMessage {
|
133 - | /// Message was signed and has been extracted
|
134 - | Signed {
|
135 - | /// The inner message that was signed
|
136 - | message: ::aws_smithy_types::event_stream::Message,
|
137 - | /// Signature information from the outer message
|
138 - | signature: crate::sigv4_event_stream::SignatureInfo,
|
139 - | },
|
140 - | /// Message was not signed (no `:chunk-signature` header present)
|
141 - | Unsigned,
|
142 - | }
|
143 - |
|
144 - | /// Extracts the inner message from a potentially signed event stream message.
|
145 - | pub fn extract_signed_message(
|
146 - | message: &::aws_smithy_types::event_stream::Message,
|
147 - | ) -> ::std::result::Result<MaybeSignedMessage, crate::sigv4_event_stream::ExtractionError> {
|
148 - | // Check if message has chunk signature
|
149 - | let mut chunk_signature = None;
|
150 - | let mut timestamp = None;
|
151 - |
|
152 - | for header in message.headers() {
|
153 - | match header.name().as_str() {
|
154 - | ":chunk-signature" => {
|
155 - | if let ::aws_smithy_types::event_stream::HeaderValue::ByteArray(bytes) =
|
156 - | header.value()
|
157 - | {
|
158 - | chunk_signature = Some(bytes.as_ref().to_vec());
|
159 - | }
|
160 - | }
|
161 - | ":date" => {
|
162 - | if let ::aws_smithy_types::event_stream::HeaderValue::Timestamp(ts) = header.value()
|
163 - | {
|
164 - | timestamp = Some(::std::time::SystemTime::try_from(*ts).map_err(|_err| {
|
165 - | crate::sigv4_event_stream::ExtractionError::InvalidTimestamp
|
166 - | })?);
|
167 - | } else {
|
168 - | return Err(crate::sigv4_event_stream::ExtractionError::InvalidTimestamp);
|
169 - | }
|
170 - | }
|
171 - | _ => {}
|
172 - | }
|
173 - | }
|
174 - |
|
175 - | let Some(chunk_signature) = chunk_signature else {
|
176 - | return Ok(MaybeSignedMessage::Unsigned);
|
177 - | };
|
178 - |
|
179 - | let Some(timestamp) = timestamp else {
|
180 - | return Err(crate::sigv4_event_stream::ExtractionError::InvalidTimestamp);
|
181 - | };
|
182 - |
|
183 - | // Extract inner message
|
184 - | let cursor = ::std::io::Cursor::new(message.payload());
|
185 - | let inner_message = ::aws_smithy_eventstream::frame::read_message_from(cursor)
|
186 - | .map_err(|err| crate::sigv4_event_stream::ExtractionError::InvalidPayload { error: err })?;
|
187 - |
|
188 - | Ok(MaybeSignedMessage::Signed {
|
189 - | message: inner_message,
|
190 - | signature: crate::sigv4_event_stream::SignatureInfo {
|
191 - | chunk_signature,
|
192 - | timestamp,
|
193 - | },
|
194 - | })
|
195 - | }
|