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}