Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into jdisanti-aws-config-d…
Browse files Browse the repository at this point in the history
…irect-invoke
  • Loading branch information
jdisanti committed Sep 29, 2023
2 parents bc36fe4 + 33cd698 commit 80c87c2
Show file tree
Hide file tree
Showing 336 changed files with 7,761 additions and 1,865 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ target/

# IDEs
.idea/
.vscode/
.project
.settings
.classpath
Expand Down
58 changes: 58 additions & 0 deletions CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,70 @@ references = ["smithy-rs#2985"]
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "client" }
author = "rcoh"

[[smithy-rs]]
message = """
Structure members with the type `Option<Vec<T>>` now produce an accessor with the type `&[T]` instead of `Option<&[T]>`. This is enabled by default for clients and can be disabled by updating your smithy-build.json with the following setting:
```json
{
"codegen": {
"flattenCollectionAccessors": false,
...
}
}
```
"""
references = ["smithy-rs#2995"]
author = "rcoh"
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" }

[[aws-sdk-rust]]
message = "Structure members with the type `Option<Vec<T>>` now produce an accessor with the type `&[T]` instead of `Option<&[T]>`. To determine if the field was actually set use `.<field_name>.is_some()`."
references = ["smithy-rs#2995"]
author = "rcoh"
meta = { "breaking" = true, "tada" = false, "bug" = false }

[[smithy-rs]]
message = "Produce better docs when items are marked @required"
references = ["smithy-rs#2996"]
meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client" }
author = "rcoh"

[[aws-sdk-rust]]
message = "The `futures_core::stream::Stream` trait has been removed from public API. It should not affect usual SDK use cases. If your code uses paginators, you do not need to use the `Stream` trait or its exntension traits, but only the `next`, `try_next`, `collect`, and `try_collect` methods are supported on `PaginationStream`. Other stream operations that were previously available through the trait or its extension traits can be added later in a backward compatible manner. Finally, `fn_stream` has been moved to be a child module of `pagination_stream`."
references = ["smithy-rs#2978"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "ysaito1001"

[[smithy-rs]]
message = "The `futures_core::stream::Stream` trait has been removed from public API. `FnStream` only supports `next`, `try_next`, `collect`, and `try_collect` methods. [`TryFlatMap::flat_map`](https://docs.rs/aws-smithy-async/latest/aws_smithy_async/future/pagination_stream/struct.TryFlatMap.html#method.flat_map) returns [`PaginationStream`](https://docs.rs/aws-smithy-async/latest/aws_smithy_async/future/pagination_stream/struct.PaginationStream.html), which should be preferred to `FnStream` at an interface level. Other stream operations that were previously available through the trait or its extension traits can be added later in a backward compatible manner. Finally, `fn_stream` has been moved to be a child module of `pagination_stream`."
references = ["smithy-rs#2978"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "ysaito1001"

[[smithy-rs]]
message = "Python middleware can set URI. This can be used to route a request to a different handler."
references = ["smithy-rs#3005"]
meta = { "breaking" = false, "tada" = true, "bug" = false, "target" = "server" }
author = "drganjoo"

[[aws-sdk-rust]]
message = "Add support for Sigv4A request signing. Sigv4a signing will be used automatically when appropriate for a given operation. Currently, it's used for S3 and EventBridge."
references = ["smithy-rs#1797"]
meta = { "breaking" = true, "tada" = true, "bug" = false }
author = "Velfi"

[[aws-sdk-rust]]
message = "The `futures_core::stream::Stream` trait has been removed from [`ByteStream`](https://docs.rs/aws-smithy-http/latest/aws_smithy_http/byte_stream/struct.ByteStream.html). The methods mentioned in the [doc](https://docs.rs/aws-smithy-http/latest/aws_smithy_http/byte_stream/struct.ByteStream.html#getting-data-out-of-a-bytestream) will continue to be supported. Other stream operations that were previously available through the trait or its extension traits can be added later in a backward compatible manner."
references = ["smithy-rs#2983"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "ysaito1001"

[[smithy-rs]]
message = "The `futures_core::stream::Stream` trait has been removed from [`ByteStream`](https://docs.rs/aws-smithy-http/latest/aws_smithy_http/byte_stream/struct.ByteStream.html). The methods mentioned in the [doc](https://docs.rs/aws-smithy-http/latest/aws_smithy_http/byte_stream/struct.ByteStream.html#getting-data-out-of-a-bytestream) will continue to be supported. Other stream operations that were previously available through the trait or its extension traits can be added later in a backward compatible manner."
references = ["smithy-rs#2983"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "ysaito1001"

[[smithy-rs]]
message = "`StaticUriEndpointResolver`'s `uri` constructor now takes a `String` instead of a `Uri`."
references = ["smithy-rs#2997"]
Expand Down
2 changes: 1 addition & 1 deletion aws/rust-runtime/aws-endpoint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ mod test {
let req = AwsAuthStage.apply(req).expect("should succeed");
assert_eq!(
req.properties().get(),
Some(&SigningRegion::from(Region::new("us-east-override")))
Some(&SigningRegion::from_static("us-east-override"))
);
assert_eq!(
req.properties().get(),
Expand Down
1 change: 0 additions & 1 deletion aws/rust-runtime/aws-inlineable/src/glacier_checksums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use bytes::Buf;
use bytes_utils::SegmentedBuf;
use http::header::HeaderName;
use ring::digest::{Context, Digest, SHA256};
use tokio_stream::StreamExt;

const TREE_HASH_HEADER: &str = "x-amz-sha256-tree-hash";
const X_AMZ_CONTENT_SHA256: &str = "x-amz-content-sha256";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// This code is referenced in generated code, so the compiler doesn't realize it is used.
#![allow(dead_code)]

use aws_runtime::auth::sigv4::SigV4OperationSigningConfig;
use aws_runtime::auth::SigV4OperationSigningConfig;
use aws_sigv4::http_request::SignableBody;
use aws_smithy_http::body::SdkBody;
use aws_smithy_http::byte_stream;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! Interceptor for handling Smithy `@httpChecksum` request checksumming with AWS SigV4
use aws_http::content_encoding::{AwsChunkedBody, AwsChunkedBodyOptions};
use aws_runtime::auth::sigv4::SigV4OperationSigningConfig;
use aws_runtime::auth::SigV4OperationSigningConfig;
use aws_sigv4::http_request::SignableBody;
use aws_smithy_checksums::ChecksumAlgorithm;
use aws_smithy_checksums::{body::calculate, http::HttpChecksum};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use crate::presigning::PresigningConfig;
use crate::serialization_settings::HeaderSerializationSettings;
use aws_runtime::auth::sigv4::{HttpSignatureType, SigV4OperationSigningConfig};
use aws_runtime::auth::{HttpSignatureType, SigV4OperationSigningConfig};
use aws_runtime::invocation_id::InvocationIdInterceptor;
use aws_runtime::request_info::RequestInfoInterceptor;
use aws_runtime::user_agent::UserAgentInterceptor;
Expand Down
1 change: 1 addition & 0 deletions aws/rust-runtime/aws-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ repository = "https://github.com/awslabs/smithy-rs"
[features]
event-stream = ["dep:aws-smithy-eventstream", "aws-sigv4/sign-eventstream"]
test-util = []
sigv4a = ["aws-sigv4/sigv4a"]

[dependencies]
aws-credential-types = { path = "../aws-credential-types" }
Expand Down
191 changes: 191 additions & 0 deletions aws/rust-runtime/aws-runtime/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,196 @@
* SPDX-License-Identifier: Apache-2.0
*/

use aws_sigv4::http_request::{
PayloadChecksumKind, PercentEncodingMode, SessionTokenMode, SignableBody, SignatureLocation,
SigningSettings, UriPathNormalizationMode,
};
use aws_smithy_runtime_api::client::auth::AuthSchemeEndpointConfig;
use aws_smithy_runtime_api::client::identity::Identity;
use aws_smithy_types::config_bag::{Storable, StoreReplace};
use aws_smithy_types::Document;
use aws_types::region::{Region, SigningRegion, SigningRegionSet};
use aws_types::SigningName;
use std::error::Error as StdError;
use std::fmt;
use std::time::Duration;

/// Auth implementations for SigV4.
pub mod sigv4;

#[cfg(feature = "sigv4a")]
/// Auth implementations for SigV4a.
pub mod sigv4a;

/// Type of SigV4 signature.
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum HttpSignatureType {
/// A signature for a full http request should be computed, with header updates applied to the signing result.
HttpRequestHeaders,

/// A signature for a full http request should be computed, with query param updates applied to the signing result.
///
/// This is typically used for presigned URLs.
HttpRequestQueryParams,
}

/// Signing options for SigV4.
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct SigningOptions {
/// Apply URI encoding twice.
pub double_uri_encode: bool,
/// Apply a SHA-256 payload checksum.
pub content_sha256_header: bool,
/// Normalize the URI path before signing.
pub normalize_uri_path: bool,
/// Omit the session token from the signature.
pub omit_session_token: bool,
/// Optional override for the payload to be used in signing.
pub payload_override: Option<SignableBody<'static>>,
/// Signature type.
pub signature_type: HttpSignatureType,
/// Whether or not the signature is optional.
pub signing_optional: bool,
/// Optional expiration (for presigning)
pub expires_in: Option<Duration>,
}

impl Default for SigningOptions {
fn default() -> Self {
Self {
double_uri_encode: true,
content_sha256_header: false,
normalize_uri_path: true,
omit_session_token: false,
payload_override: None,
signature_type: HttpSignatureType::HttpRequestHeaders,
signing_optional: false,
expires_in: None,
}
}
}

/// SigV4 signing configuration for an operation
///
/// Although these fields MAY be customized on a per request basis, they are generally static
/// for a given operation
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct SigV4OperationSigningConfig {
/// AWS region to sign for.
///
/// For an up-to-date list of AWS regions, see <https://docs.aws.amazon.com/general/latest/gr/rande.html>
pub region: Option<SigningRegion>,
/// AWS region set to sign for.
///
/// A comma-separated list of AWS regions. Examples include typical AWS regions as well as 'wildcard' regions
pub region_set: Option<SigningRegionSet>,
/// AWS service to sign for.
pub name: Option<SigningName>,
/// Signing options.
pub signing_options: SigningOptions,
}

impl Storable for SigV4OperationSigningConfig {
type Storer = StoreReplace<Self>;
}

fn settings(operation_config: &SigV4OperationSigningConfig) -> SigningSettings {
let mut settings = SigningSettings::default();
settings.percent_encoding_mode = if operation_config.signing_options.double_uri_encode {
PercentEncodingMode::Double
} else {
PercentEncodingMode::Single
};
settings.payload_checksum_kind = if operation_config.signing_options.content_sha256_header {
PayloadChecksumKind::XAmzSha256
} else {
PayloadChecksumKind::NoHeader
};
settings.uri_path_normalization_mode = if operation_config.signing_options.normalize_uri_path {
UriPathNormalizationMode::Enabled
} else {
UriPathNormalizationMode::Disabled
};
settings.session_token_mode = if operation_config.signing_options.omit_session_token {
SessionTokenMode::Exclude
} else {
SessionTokenMode::Include
};
settings.signature_location = match operation_config.signing_options.signature_type {
HttpSignatureType::HttpRequestHeaders => SignatureLocation::Headers,
HttpSignatureType::HttpRequestQueryParams => SignatureLocation::QueryParams,
};
settings.expires_in = operation_config.signing_options.expires_in;
settings
}

#[derive(Debug)]
enum SigV4SigningError {
MissingOperationSigningConfig,
MissingSigningRegion,
#[cfg(feature = "sigv4a")]
MissingSigningRegionSet,
MissingSigningName,
WrongIdentityType(Identity),
BadTypeInEndpointAuthSchemeConfig(&'static str),
}

impl fmt::Display for SigV4SigningError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use SigV4SigningError::*;
let mut w = |s| f.write_str(s);
match self {
MissingOperationSigningConfig => w("missing operation signing config"),
MissingSigningRegion => w("missing signing region"),
#[cfg(feature = "sigv4a")]
MissingSigningRegionSet => w("missing signing region set"),
MissingSigningName => w("missing signing name"),
WrongIdentityType(identity) => {
write!(f, "wrong identity type for SigV4/sigV4a. Expected AWS credentials but got `{identity:?}`")
}
BadTypeInEndpointAuthSchemeConfig(field_name) => {
write!(
f,
"unexpected type for `{field_name}` in endpoint auth scheme config",
)
}
}
}
}

impl StdError for SigV4SigningError {}

fn extract_endpoint_auth_scheme_signing_name(
endpoint_config: &AuthSchemeEndpointConfig<'_>,
) -> Result<Option<SigningName>, SigV4SigningError> {
use SigV4SigningError::BadTypeInEndpointAuthSchemeConfig as UnexpectedType;

match extract_field_from_endpoint_config("signingName", endpoint_config) {
Some(Document::String(s)) => Ok(Some(SigningName::from(s.to_string()))),
None => Ok(None),
_ => Err(UnexpectedType("signingName")),
}
}

fn extract_endpoint_auth_scheme_signing_region(
endpoint_config: &AuthSchemeEndpointConfig<'_>,
) -> Result<Option<SigningRegion>, SigV4SigningError> {
use SigV4SigningError::BadTypeInEndpointAuthSchemeConfig as UnexpectedType;

match extract_field_from_endpoint_config("signingRegion", endpoint_config) {
Some(Document::String(s)) => Ok(Some(SigningRegion::from(Region::new(s.clone())))),
None => Ok(None),
_ => Err(UnexpectedType("signingRegion")),
}
}

fn extract_field_from_endpoint_config<'a>(
field_name: &'static str,
endpoint_config: &'a AuthSchemeEndpointConfig<'_>,
) -> Option<&'a Document> {
endpoint_config
.as_document()
.and_then(Document::as_object)
.and_then(|config| config.get(field_name))
}
Loading

0 comments on commit 80c87c2

Please sign in to comment.