aws_sigv4/http_request/settings.rs
1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6use http0::header::{AUTHORIZATION, TRANSFER_ENCODING, USER_AGENT};
7use std::borrow::Cow;
8use std::time::Duration;
9
10const HEADER_NAME_X_RAY_TRACE_ID: &str = "x-amzn-trace-id";
11
12/// HTTP-specific signing settings
13#[derive(Clone, Debug, PartialEq)]
14#[non_exhaustive]
15pub struct SigningSettings {
16 /// Specifies how to encode the request URL when signing. Some services do not decode
17 /// the path prior to checking the signature, requiring clients to actually _double-encode_
18 /// the URI in creating the canonical request in order to pass a signature check.
19 pub percent_encoding_mode: PercentEncodingMode,
20
21 /// Add an additional checksum header
22 pub payload_checksum_kind: PayloadChecksumKind,
23
24 /// Where to put the signature
25 pub signature_location: SignatureLocation,
26
27 /// For presigned requests, how long the presigned request is valid for
28 pub expires_in: Option<Duration>,
29
30 /// Headers that should be excluded from the signing process
31 pub excluded_headers: Option<Vec<Cow<'static, str>>>,
32
33 /// Specifies whether the absolute path component of the URI should be normalized during signing.
34 pub uri_path_normalization_mode: UriPathNormalizationMode,
35
36 /// Some services require X-Amz-Security-Token to be included in the
37 /// canonical request. Other services require only it to be added after
38 /// calculating the signature.
39 pub session_token_mode: SessionTokenMode,
40
41 /// Some services require an alternative session token header or query param instead of
42 /// `x-amz-security-token` or `X-Amz-Security-Token`.
43 pub session_token_name_override: Option<&'static str>,
44}
45
46/// HTTP payload checksum type
47#[non_exhaustive]
48#[derive(Clone, Copy, Debug, Eq, PartialEq)]
49pub enum PayloadChecksumKind {
50 /// Add x-amz-checksum-sha256 to the canonical request
51 ///
52 /// This setting is required for S3
53 XAmzSha256,
54
55 /// Do not add an additional header when creating the canonical request
56 ///
57 /// This is "normal mode" and will work for services other than S3
58 NoHeader,
59}
60
61/// Config value to specify how to encode the request URL when signing.
62///
63/// We assume the URI will be encoded _once_ prior to transmission. Some services
64/// do not decode the path prior to checking the signature, requiring clients to actually
65/// _double-encode_ the URI in creating the canonical request in order to pass a signature check.
66#[non_exhaustive]
67#[derive(Clone, Copy, Debug, Eq, PartialEq)]
68pub enum PercentEncodingMode {
69 /// Re-encode the resulting URL (e.g. %30 becomes `%2530)
70 Double,
71
72 /// Take the resulting URL as-is
73 Single,
74}
75
76/// Config value to specify whether the canonical request's URI path should be normalized.
77/// <https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html>
78///
79/// URI path normalization is performed based on <https://www.rfc-editor.org/rfc/rfc3986>.
80#[non_exhaustive]
81#[derive(Clone, Copy, Debug, Eq, PartialEq)]
82pub enum UriPathNormalizationMode {
83 /// Normalize the URI path according to RFC3986
84 Enabled,
85
86 /// Don't normalize the URI path (S3, for example, rejects normalized paths in some instances)
87 Disabled,
88}
89
90impl From<bool> for UriPathNormalizationMode {
91 fn from(value: bool) -> Self {
92 if value {
93 UriPathNormalizationMode::Enabled
94 } else {
95 UriPathNormalizationMode::Disabled
96 }
97 }
98}
99
100/// Config value to specify whether X-Amz-Security-Token should be part of the canonical request.
101/// <http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html#temporary-security-credentials>
102#[non_exhaustive]
103#[derive(Clone, Copy, Debug, Eq, PartialEq)]
104pub enum SessionTokenMode {
105 /// Include in the canonical request before calculating the signature.
106 Include,
107
108 /// Exclude in the canonical request.
109 Exclude,
110}
111
112impl Default for SigningSettings {
113 fn default() -> Self {
114 // Headers that are potentially altered by proxies or as a part of standard service operations.
115 // Reference:
116 // Go SDK: <https://github.com/aws/aws-sdk-go/blob/v1.44.289/aws/signer/v4/v4.go#L92>
117 // 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>
118 // JS SDK: <https://github.com/aws/aws-sdk-js/blob/master/lib/signers/v4.js#L191>
119 // There is no single source of truth for these available, so this uses the minimum common set of the excluded options.
120 // Instantiate this every time, because SigningSettings takes a Vec (which cannot be const);
121 let excluded_headers = Some(
122 [
123 // This header is calculated as part of the signing process, so if it's present, discard it
124 Cow::Borrowed(AUTHORIZATION.as_str()),
125 // Changes when sent by proxy
126 Cow::Borrowed(USER_AGENT.as_str()),
127 // Changes based on the request from the client
128 Cow::Borrowed(HEADER_NAME_X_RAY_TRACE_ID),
129 // Hop by hop header, can be erased by Cloudfront
130 Cow::Borrowed(TRANSFER_ENCODING.as_str()),
131 ]
132 .to_vec(),
133 );
134 Self {
135 percent_encoding_mode: PercentEncodingMode::Double,
136 payload_checksum_kind: PayloadChecksumKind::NoHeader,
137 signature_location: SignatureLocation::Headers,
138 expires_in: None,
139 excluded_headers,
140 uri_path_normalization_mode: UriPathNormalizationMode::Enabled,
141 session_token_mode: SessionTokenMode::Include,
142 session_token_name_override: None,
143 }
144 }
145}
146
147/// Where to place signing values in the HTTP request
148#[non_exhaustive]
149#[derive(Copy, Clone, Debug, Eq, PartialEq)]
150pub enum SignatureLocation {
151 /// Place the signature in the request headers
152 Headers,
153 /// Place the signature in the request query parameters
154 QueryParams,
155}