Skip to content

Commit 80de569

Browse files
Sam BartlettSam BartlettZelda Hessler
authored
Expand skipped headers for sigv4 canonical request signing to include x-amzn-trace-id and authorization headers. (#2815)
## Motivation and Context When customers add x-ray headers to requests, the SigV4 signer should exclude them, or the generated canonical signature will not match the remote service's, since many services being called are written with non-rust SDKs that automatically exclude these common headers. The Rust SDK should exclude a similar set of headers to the other popular AWS SDKs. While this is not uniform across the SDKs, a minimal set should be excluded and others should be considered to be excluded in future PRs. ## Description * Expands the set of headers excluded from canonical request calculation to include "x-amzn-trace-id" and "authorization" (since authorization will be added as a part of this process). ## Testing * Added headers to exclusion test & validated with `cargo test` * `./gradlew :aws:sdk:test` ## Checklist - [x] I have updated `CHANGELOG.next.toml` if I made changes to the AWS SDK, generated SDK code, or SDK runtime crates ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._ --------- Co-authored-by: Sam Bartlett <sbartl@amazon.com> Co-authored-by: Zelda Hessler <zhessler@amazon.com>
1 parent 9c95803 commit 80de569

File tree

3 files changed

+61
-6
lines changed

3 files changed

+61
-6
lines changed

CHANGELOG.next.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
# meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client | server | all"}
1212
# author = "rcoh"
1313

14+
[[aws-sdk-rust]]
15+
message = "Automatically exclude X-Ray trace ID headers and authorization headers from SigV4 canonical request calculations."
16+
references = ["smithy-rs#2815"]
17+
meta = { "breaking" = false, "tada" = false, "bug" = true }
18+
author = "relevantsam"
19+
1420
[[aws-sdk-rust]]
1521
message = "Add accessors to Builders"
1622
references = ["smithy-rs#2791"]

aws/rust-runtime/aws-sigv4/src/http_request/canonical_request.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -774,14 +774,46 @@ mod tests {
774774
assert_eq!(creq.values.signed_headers().as_str(), "host;x-amz-date");
775775
}
776776

777-
// It should exclude user-agent and x-amz-user-agent headers from presigning
777+
// It should exclude authorization, user-agent, x-amzn-trace-id headers from presigning
778+
#[test]
779+
fn non_presigning_header_exclusion() {
780+
let request = http::Request::builder()
781+
.uri("https://some-endpoint.some-region.amazonaws.com")
782+
.header("authorization", "test-authorization")
783+
.header("content-type", "application/xml")
784+
.header("content-length", "0")
785+
.header("user-agent", "test-user-agent")
786+
.header("x-amzn-trace-id", "test-trace-id")
787+
.header("x-amz-user-agent", "test-user-agent")
788+
.body("")
789+
.unwrap();
790+
let request = SignableRequest::from(&request);
791+
792+
let settings = SigningSettings {
793+
signature_location: SignatureLocation::Headers,
794+
..Default::default()
795+
};
796+
797+
let signing_params = signing_params(settings);
798+
let canonical = CanonicalRequest::from(&request, &signing_params).unwrap();
799+
800+
let values = canonical.values.as_headers().unwrap();
801+
assert_eq!(
802+
"content-length;content-type;host;x-amz-date;x-amz-user-agent",
803+
values.signed_headers.as_str()
804+
);
805+
}
806+
807+
// It should exclude authorization, user-agent, x-amz-user-agent, x-amzn-trace-id headers from presigning
778808
#[test]
779809
fn presigning_header_exclusion() {
780810
let request = http::Request::builder()
781811
.uri("https://some-endpoint.some-region.amazonaws.com")
812+
.header("authorization", "test-authorization")
782813
.header("content-type", "application/xml")
783814
.header("content-length", "0")
784815
.header("user-agent", "test-user-agent")
816+
.header("x-amzn-trace-id", "test-trace-id")
785817
.header("x-amz-user-agent", "test-user-agent")
786818
.body("")
787819
.unwrap();

aws/rust-runtime/aws-sigv4/src/http_request/settings.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
use http::header::{HeaderName, USER_AGENT};
6+
use http::header::{HeaderName, AUTHORIZATION, USER_AGENT};
77
use std::time::Duration;
88

99
/// HTTP signing parameters
1010
pub type SigningParams<'a> = crate::SigningParams<'a, SigningSettings>;
1111

12+
const HEADER_NAME_X_RAY_TRACE_ID: &str = "x-amzn-trace-id";
13+
1214
/// HTTP-specific signing settings
1315
#[derive(Debug, PartialEq)]
1416
#[non_exhaustive]
@@ -97,15 +99,30 @@ pub enum SessionTokenMode {
9799

98100
impl Default for SigningSettings {
99101
fn default() -> Self {
100-
// The user agent header should not be signed because it may be altered by proxies
101-
const EXCLUDED_HEADERS: [HeaderName; 1] = [USER_AGENT];
102-
102+
// Headers that are potentially altered by proxies or as a part of standard service operations.
103+
// Reference:
104+
// Go SDK: <https://github.com/aws/aws-sdk-go/blob/v1.44.289/aws/signer/v4/v4.go#L92>
105+
// Java SDK: <https://github.com/aws/aws-sdk-java-v2/blob/master/core/auth/src/main/java/software/amazon/awssdk/auth/signer/internal/AbstractAws4Signer.java#L70>
106+
// JS SDK: <https://github.com/aws/aws-sdk-js/blob/master/lib/signers/v4.js#L191>
107+
// There is no single source of truth for these available, so this uses the minimum common set of the excluded options.
108+
// Instantiate this every time, because SigningSettings takes a Vec (which cannot be const);
109+
let excluded_headers = Some(
110+
[
111+
// This header is calculated as part of the signing process, so if it's present, discard it
112+
AUTHORIZATION,
113+
// Changes when sent by proxy
114+
USER_AGENT,
115+
// Changes based on the request from the client
116+
HeaderName::from_static(HEADER_NAME_X_RAY_TRACE_ID),
117+
]
118+
.to_vec(),
119+
);
103120
Self {
104121
percent_encoding_mode: PercentEncodingMode::Double,
105122
payload_checksum_kind: PayloadChecksumKind::NoHeader,
106123
signature_location: SignatureLocation::Headers,
107124
expires_in: None,
108-
excluded_headers: Some(EXCLUDED_HEADERS.to_vec()),
125+
excluded_headers,
109126
uri_path_normalization_mode: UriPathNormalizationMode::Enabled,
110127
session_token_mode: SessionTokenMode::Include,
111128
}

0 commit comments

Comments
 (0)