Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
Zelda Hessler committed Aug 17, 2023
1 parent 2d61502 commit f0573aa
Show file tree
Hide file tree
Showing 35 changed files with 326 additions and 251 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,12 @@ message = """Several breaking changes were made to the aws-sigv4 API to remove t
references = ["smithy-rs#2921"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "rcoh"

[[aws-sdk-rust]]
message = """
All versions of SigningParams have been updated to contain an [`Identity`](https://docs.rs/aws-smithy-runtime-api/latest/aws_smithy_runtime_api/client/identity/struct.Identity.html)
as opposed to AWS credentials in `&str` form. [Read more](https://github.com/awslabs/aws-sdk-rust/discussions/868).
"""
references = ["smithy-rs#2913"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "Velfi"
4 changes: 1 addition & 3 deletions aws/rust-runtime/aws-credential-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ test-util = []
[dependencies]
aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async" }
aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types" }
aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] }
fastrand = "2.0.0"
tokio = { version = "1.23.1", features = ["sync"] }
tracing = "0.1"
Expand All @@ -28,9 +29,6 @@ env_logger = "0.9.0"

tokio = { version = "1.23.1", features = ["full", "test-util", "rt"] }
tracing-test = "0.2.4"
# TODO(https://github.com/awslabs/smithy-rs/issues/2619): Remove this
# workaround once the fixed is upstreamed.
regex = { version = "1.0", features = ["unicode-case", "unicode-perl"] }

[package.metadata.docs.rs]
all-features = true
Expand Down
46 changes: 34 additions & 12 deletions aws/rust-runtime/aws-credential-types/src/credentials_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use zeroize::Zeroizing;

use aws_smithy_runtime_api::client::identity::Identity;

/// AWS SDK Credentials
///
/// An opaque struct representing credentials that may be used in an AWS SDK, modeled on
Expand Down Expand Up @@ -140,18 +142,6 @@ impl Credentials {
)
}

/// Creates a test `Credentials`.
#[cfg(feature = "test-util")]
pub fn for_tests() -> Self {
Self::new(
"ANOTREAL",
"notrealrnrELgWzOk3IfjzDKtFBhDby",
Some("notarealsessiontoken".to_string()),
None,
"test",
)
}

/// Returns the access key ID.
pub fn access_key_id(&self) -> &str {
&self.0.access_key_id
Expand All @@ -178,6 +168,38 @@ impl Credentials {
}
}

#[cfg(feature = "test-util")]
impl Credentials {
/// Creates a test `Credentials` with no session token.
pub fn for_tests() -> Self {
Self::new(
"ANOTREAL",
"notrealrnrELgWzOk3IfjzDKtFBhDby",
None,
None,
"test",
)
}

/// Creates a test `Credentials` that include a session token.
pub fn for_tests_with_session_token() -> Self {
Self::new(
"ANOTREAL",
"notrealrnrELgWzOk3IfjzDKtFBhDby",
Some("notarealsessiontoken".to_string()),
None,
"test",
)
}
}

impl From<Credentials> for Identity {
fn from(val: Credentials) -> Self {
let expiry = val.expiry();
Identity::new(val, expiry)
}
}

#[cfg(test)]
mod test {
use crate::Credentials;
Expand Down
5 changes: 3 additions & 2 deletions aws/rust-runtime/aws-inlineable/tests/middleware_e2e_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ fn test_operation() -> Operation<TestOperationParser, AwsResponseRetryClassifier
));
aws_http::auth::set_credentials_cache(
conf,
CredentialsCache::lazy()
.create_cache(SharedCredentialsProvider::new(Credentials::for_tests())),
CredentialsCache::lazy().create_cache(SharedCredentialsProvider::new(
Credentials::for_tests_with_session_token(),
)),
);
conf.insert(SigningRegion::from_static("test-region"));
conf.insert(OperationSigningConfig::default_config());
Expand Down
61 changes: 32 additions & 29 deletions aws/rust-runtime/aws-runtime/src/auth/sigv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,22 +217,25 @@ impl SigV4Signer {

fn signing_params<'a>(
settings: SigningSettings,
credentials: &'a Credentials,
identity: &'a Identity,
operation_config: &'a SigV4OperationSigningConfig,
request_timestamp: SystemTime,
) -> Result<SigningParams<'a>, SigV4SigningError> {
let creds = identity
.data::<Credentials>()
.ok_or_else(|| SigV4SigningError::WrongIdentityType(identity.clone()))?;

if let Some(expires_in) = settings.expires_in {
if let Some(creds_expires_time) = credentials.expiry() {
if let Some(creds_expires_time) = creds.expiry() {
let presigned_expires_time = request_timestamp + expires_in;
if presigned_expires_time > creds_expires_time {
tracing::warn!(EXPIRATION_WARNING);
}
}
}

let mut builder = SigningParams::builder()
.access_key(credentials.access_key_id())
.secret_key(credentials.secret_access_key())
let builder = SigningParams::builder()
.identity(identity)
.region(
operation_config
.region
Expand All @@ -249,7 +252,6 @@ impl SigV4Signer {
)
.time(request_timestamp)
.settings(settings);
builder.set_security_token(credentials.session_token());
Ok(builder.build().expect("all required fields set"))
}

Expand Down Expand Up @@ -324,18 +326,18 @@ impl Signer for SigV4Signer {
Self::extract_operation_config(auth_scheme_endpoint_config, config_bag)?;
let request_time = runtime_components.time_source().unwrap_or_default().now();

let credentials = if let Some(creds) = identity.data::<Credentials>() {
creds
} else if operation_config.signing_options.signing_optional {
tracing::debug!("skipped SigV4 signing since signing is optional for this operation and there are no credentials");
return Ok(());
} else {
return Err(SigV4SigningError::WrongIdentityType(identity.clone()).into());
if identity.data::<Credentials>().is_none() {
if operation_config.signing_options.signing_optional {
tracing::debug!("skipped SigV4 signing since signing is optional for this operation and there are no credentials");
return Ok(());
} else {
return Err(SigV4SigningError::WrongIdentityType(identity.clone()).into());
}
};

let settings = Self::settings(&operation_config);
let signing_params =
Self::signing_params(settings, credentials, &operation_config, request_time)?;
Self::signing_params(settings, identity, &operation_config, request_time)?;

let (signing_instructions, _signature) = {
// A body that is already in memory can be signed directly. A body that is not in memory
Expand Down Expand Up @@ -382,7 +384,7 @@ impl Signer for SigV4Signer {
signer_sender
.send(Box::new(SigV4MessageSigner::new(
_signature,
credentials.clone(),
identity.clone(),
Region::new(signing_params.region().to_string()).into(),
signing_params.service_name().to_string().into(),
time_source,
Expand All @@ -397,19 +399,19 @@ impl Signer for SigV4Signer {

#[cfg(feature = "event-stream")]
mod event_stream {
use aws_credential_types::Credentials;
use aws_sigv4::event_stream::{sign_empty_message, sign_message};
use aws_sigv4::SigningParams;
use aws_smithy_async::time::SharedTimeSource;
use aws_smithy_eventstream::frame::{Message, SignMessage, SignMessageError};
use aws_smithy_runtime_api::client::identity::Identity;
use aws_types::region::SigningRegion;
use aws_types::SigningService;

/// Event Stream SigV4 signing implementation.
#[derive(Debug)]
pub(super) struct SigV4MessageSigner {
last_signature: String,
credentials: Credentials,
identity: Identity,
signing_region: SigningRegion,
signing_service: SigningService,
time: SharedTimeSource,
Expand All @@ -418,29 +420,27 @@ mod event_stream {
impl SigV4MessageSigner {
pub(super) fn new(
last_signature: String,
credentials: Credentials,
identity: Identity,
signing_region: SigningRegion,
signing_service: SigningService,
time: SharedTimeSource,
) -> Self {
Self {
last_signature,
credentials,
identity,
signing_region,
signing_service,
time,
}
}

fn signing_params(&self) -> SigningParams<'_, ()> {
let mut builder = SigningParams::builder()
.access_key(self.credentials.access_key_id())
.secret_key(self.credentials.secret_access_key())
let builder = SigningParams::builder()
.identity(&self.identity)
.region(self.signing_region.as_ref())
.service_name(self.signing_service.as_ref())
.time(self.time.now())
.settings(());
builder.set_security_token(self.credentials.session_token());
builder.build().unwrap()
}
}
Expand All @@ -467,9 +467,11 @@ mod event_stream {

#[cfg(test)]
mod tests {
use super::*;
use crate::auth::sigv4::event_stream::SigV4MessageSigner;
use aws_credential_types::Credentials;
use aws_smithy_async::time::SharedTimeSource;
use aws_smithy_eventstream::frame::{HeaderValue, Message, SignMessage};

use aws_types::region::Region;
use aws_types::region::SigningRegion;
use aws_types::SigningService;
Expand All @@ -484,7 +486,7 @@ mod event_stream {
let region = Region::new("us-east-1");
let mut signer = check_send_sync(SigV4MessageSigner::new(
"initial-signature".into(),
Credentials::for_tests(),
Credentials::for_tests_with_session_token().into(),
SigningRegion::from(region),
SigningService::from_static("transcribe"),
SharedTimeSource::new(UNIX_EPOCH + Duration::new(1611160427, 0)),
Expand Down Expand Up @@ -534,13 +536,14 @@ mod tests {
let mut settings = SigningSettings::default();
settings.expires_in = Some(creds_expire_in - Duration::from_secs(10));

let credentials = Credentials::new(
let identity = Credentials::new(
"test-access-key",
"test-secret-key",
Some("test-session-token".into()),
Some(now + creds_expire_in),
"test",
);
)
.into();
let operation_config = SigV4OperationSigningConfig {
region: Some(SigningRegion::from_static("test")),
service: Some(SigningService::from_static("test")),
Expand All @@ -555,13 +558,13 @@ mod tests {
payload_override: None,
},
};
SigV4Signer::signing_params(settings, &credentials, &operation_config, now).unwrap();
SigV4Signer::signing_params(settings, &identity, &operation_config, now).unwrap();
assert!(!logs_contain(EXPIRATION_WARNING));

let mut settings = SigningSettings::default();
settings.expires_in = Some(creds_expire_in + Duration::from_secs(10));

SigV4Signer::signing_params(settings, &credentials, &operation_config, now).unwrap();
SigV4Signer::signing_params(settings, &identity, &operation_config, now).unwrap();
assert!(logs_contain(EXPIRATION_WARNING));
}

Expand Down
1 change: 1 addition & 0 deletions aws/rust-runtime/aws-sig-auth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ aws-sigv4 = { path = "../aws-sigv4", features = ["http0-compat"] }
aws-smithy-eventstream = { path = "../../../rust-runtime/aws-smithy-eventstream", optional = true }
aws-smithy-http = { path = "../../../rust-runtime/aws-smithy-http" }
aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async" }
aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api" }
aws-types = { path = "../aws-types" }
http = "0.2.2"
tracing = "0.1"
Expand Down
1 change: 1 addition & 0 deletions aws/rust-runtime/aws-sig-auth/external-types.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ allowed_external_types = [
"aws_smithy_http::*",
"aws_types::*",
"http::request::Request",
"aws_smithy_runtime_api::client::identity::Identity",

# TODO(https://github.com/awslabs/smithy-rs/issues/1193): Once tooling permits it, only allow the following types in the `event-stream` feature
"aws_smithy_eventstream::frame::SignMessage",
Expand Down
Loading

0 comments on commit f0573aa

Please sign in to comment.