Skip to content

Commit de4be56

Browse files
authored
Add support for environment token provider for services whose SigV4 signing names are bedrock (#4241)
## Motivation and Context Adds support for environment token provider for AWS services whose SigV4 service signing name matches `bedrock`. Setting this environment variable, `AWS_BEARER_TOKEN_BEDROCK`, allows SDKs to prefer the `httpBearerAuth` auth scheme and to retrieve a `Token` value from the said environment. ## Description Customers would use the environment variable in question like so: ``` // export AWS_BEARER_TOKEN_BEDROCK=my-token let sdk_config = aws_config::defaults(BehaviorVersion::latest()).load().await; let bedrock_client = aws_sdk_bedrock::Client::new(&sdk_config); // call an operation on `bedrock_client`... ``` Under the hood, this is equivalent roughly to ``` let sdk_config = aws_config::defaults(BehaviorVersion::latest()).load().await; let bedrock_config = aws_sdk_bedrock::config::Builder::from(sdk_config) .auth_scheme_preference([HTTP_BEARER_AUTH_SCHEME_ID]) .token_provider(Token::new("my-token", None)) .build(); let bedrock_client = aws_sdk_bedrock::Client::from_conf(bedrock_config); // call an operation on `bedrock_client`... ``` This behind-the-scenes convenience is implemented in `impl From<&SdkConfig> for Builder`, similar to how a service-specific environment is implemented for the [endpoint URL](https://docs.aws.amazon.com/sdkref/latest/guide/feature-ss-endpoints.html#ss-endpoints-envar). However, `impl From<&SdkConfig> for Builder` implies that customers need to create a service client from `SdkConfig` (typically through [ConfigLoader::load](https://docs.rs/aws-config/latest/aws_config/struct.ConfigLoader.html#method.load)) in order to take advantage of the environment variable. If customers create the service client directly from the service config builder, the environment variable will not be applied, i.e. ``` // export AWS_BEARER_TOKEN_BEDROCK=my-token let bedrock_config = aws_sdk_bedrock::Config::builder() // other configurations .build(); let bedrock_client = aws_sdk_bedrock::Client::from_conf(bedrock_config); // `bedrock_client` neither prefers HTTP_BEARER_AUTH_SCHEME_ID nor sets a Token with my-token. ``` ## Testing - Added integration tests for `bedrockruntime` (whose model is already checked in to `aws/sdk/aws-models`) ## Checklist - [x] For changes to the AWS SDK, generated SDK code, or SDK runtime crates, I have created a changelog entry Markdown file in the `.changelog` directory, specifying "aws-sdk-rust" in the `applies_to` key. ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._
1 parent 0642b3b commit de4be56

File tree

24 files changed

+4954
-936
lines changed

24 files changed

+4954
-936
lines changed

.changelog/1753975543.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
applies_to:
3+
- aws-sdk-rust
4+
authors:
5+
- ysaito1001
6+
references:
7+
- smithy-rs#4241
8+
breaking: false
9+
new_feature: true
10+
bug_fix: false
11+
---
12+
Add support for environment token provider for AWS services whose SigV4 service signing name matches `bedrock`. Setting this environment variable, `AWS_BEARER_TOKEN_BEDROCK`, allows SDKs to prefer the `httpBearerAuth` auth scheme and to retrieve a Token value from the said environment. Customers would use the environment variable as follows:
13+
```
14+
// export AWS_BEARER_TOKEN_BEDROCK=my-token
15+
let sdk_config = aws_config::defaults(BehaviorVersion::latest()).load().await;
16+
let bedrock_client = aws_sdk_bedrock::Client::new(&sdk_config);
17+
// call an operation on `bedrock_client`...
18+
```
19+
Under the hood, this is equivalent roughly to
20+
```
21+
let sdk_config = aws_config::defaults(BehaviorVersion::latest()).load().await;
22+
let bedrock_config = aws_sdk_bedrock::config::Builder::from(sdk_config)
23+
.auth_scheme_preference([HTTP_BEARER_AUTH_SCHEME_ID])
24+
.token_provider(Token::new("my-token", None))
25+
.build();
26+
let bedrock_client = aws_sdk_bedrock::Client::from_conf(bedrock_config);
27+
// call an operation on `bedrock_client`...
28+
```
29+
However, note that if customers create the service client directly from the service config builder, the environment variable will not be applied:
30+
```
31+
// export AWS_BEARER_TOKEN_BEDROCK=my-token
32+
let bedrock_config = aws_sdk_bedrock::Config::builder()
33+
// other configurations
34+
.build();
35+
let bedrock_client = aws_sdk_bedrock::Client::from_conf(bedrock_config);
36+
// `bedrock_client` neither prefers HTTP_BEARER_AUTH_SCHEME_ID nor sets a Token with my-token.
37+
```

aws/rust-runtime/Cargo.lock

Lines changed: 21 additions & 38 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aws/rust-runtime/aws-config/src/lib.rs

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -894,31 +894,13 @@ mod loader {
894894
TriStateOption::ExplicitlyUnset => None,
895895
};
896896

897-
let token_provider = match self.token_provider {
898-
Some(provider) => Some(provider),
899-
None => {
900-
#[cfg(feature = "sso")]
901-
{
902-
let mut builder =
903-
crate::default_provider::token::DefaultTokenChain::builder()
904-
.configure(conf.clone());
905-
builder.set_region(region.clone());
906-
Some(SharedTokenProvider::new(builder.build().await))
907-
}
908-
#[cfg(not(feature = "sso"))]
909-
{
910-
None
911-
}
912-
}
913-
};
914-
915897
let profiles = conf.profile().await;
916898
let service_config = EnvServiceConfig {
917899
env: conf.env(),
918900
env_config_sections: profiles.cloned().unwrap_or_default(),
919901
};
920902
let mut builder = SdkConfig::builder()
921-
.region(region)
903+
.region(region.clone())
922904
.retry_config(retry_config)
923905
.timeout_config(timeout_config)
924906
.time_source(time_source)
@@ -950,6 +932,30 @@ mod loader {
950932
}
951933
};
952934

935+
let token_provider = match self.token_provider {
936+
Some(provider) => {
937+
builder.insert_origin("token_provider", Origin::shared_config());
938+
Some(provider)
939+
}
940+
None => {
941+
#[cfg(feature = "sso")]
942+
{
943+
let mut builder =
944+
crate::default_provider::token::DefaultTokenChain::builder()
945+
.configure(conf.clone());
946+
builder.set_region(region);
947+
Some(SharedTokenProvider::new(builder.build().await))
948+
}
949+
#[cfg(not(feature = "sso"))]
950+
{
951+
None
952+
}
953+
// Not setting `Origin` in this arm, and that's good for now as long as we know
954+
// it's not programmatically set in the shared config.
955+
// We can consider adding `Origin::Default` if needed.
956+
}
957+
};
958+
953959
builder.set_endpoint_url(endpoint_url);
954960
builder.set_behavior_version(self.behavior_version);
955961
builder.set_http_client(self.http_client);
@@ -989,9 +995,12 @@ mod loader {
989995

990996
let auth_scheme_preference =
991997
if let Some(auth_scheme_preference) = self.auth_scheme_preference {
998+
builder.insert_origin("auth_scheme_preference", Origin::shared_config());
992999
Some(auth_scheme_preference)
9931000
} else {
9941001
auth_scheme_preference::auth_scheme_preference_provider(&conf).await
1002+
// Not setting `Origin` in this arm, and that's good for now as long as we know
1003+
// it's not programmatically set in the shared config.
9951004
};
9961005

9971006
builder.set_request_checksum_calculation(request_checksum_calculation);

aws/rust-runtime/aws-credential-types/src/credential_feature.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub enum AwsCredentialFeature {
4545
CredentialsHttp,
4646
/// An operation called using credentials resolved from the instance metadata service (IMDS)
4747
CredentialsImds,
48+
/// An operation called using a Bearer token resolved from service-specific environment variables
49+
BearerServiceEnvVars,
4850
}
4951

5052
impl Storable for AwsCredentialFeature {

aws/rust-runtime/aws-runtime/src/sdk_feature.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ use aws_smithy_types::config_bag::{Storable, StoreAppend};
1414
pub enum AwsSdkFeature {
1515
/// Indicates that an operation was called by the S3 Transfer Manager
1616
S3Transfer,
17+
/// Calling an SSO-OIDC operation as part of the SSO login flow, when using the OAuth2.0 device code grant
18+
SsoLoginDevice,
19+
/// Calling an SSO-OIDC operation as part of the SSO login flow, when using the OAuth2.0 authorization code grant
20+
SsoLoginAuth,
1721
}
1822

1923
impl Storable for AwsSdkFeature {

aws/rust-runtime/aws-runtime/src/user_agent/metrics.rs

Lines changed: 8 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,10 @@ iterable_enum!(
161161
CredentialsBoto2ConfigFile,
162162
CredentialsAwsSdkStore,
163163
CredentialsHttp,
164-
CredentialsImds
164+
CredentialsImds,
165+
SsoLoginDevice,
166+
SsoLoginAuth,
167+
BearerServiceEnvVars
165168
);
166169

167170
pub(crate) trait ProvideBusinessMetric {
@@ -214,6 +217,8 @@ impl ProvideBusinessMetric for AwsSdkFeature {
214217
use AwsSdkFeature::*;
215218
match self {
216219
S3Transfer => Some(BusinessMetric::S3Transfer),
220+
SsoLoginDevice => Some(BusinessMetric::SsoLoginDevice),
221+
SsoLoginAuth => Some(BusinessMetric::SsoLoginAuth),
217222
}
218223
}
219224
}
@@ -248,6 +253,7 @@ impl ProvideBusinessMetric for AwsCredentialFeature {
248253
CredentialsProcess => Some(BusinessMetric::CredentialsProcess),
249254
CredentialsHttp => Some(BusinessMetric::CredentialsHttp),
250255
CredentialsImds => Some(BusinessMetric::CredentialsImds),
256+
BearerServiceEnvVars => Some(BusinessMetric::BearerServiceEnvVars),
251257
otherwise => {
252258
// This may occur if a customer upgrades only the `aws-smithy-runtime-api` crate
253259
// while continuing to use an outdated version of an SDK crate or the `aws-credential-types`
@@ -336,64 +342,7 @@ mod tests {
336342

337343
#[test]
338344
fn feature_id_to_metric_value() {
339-
const EXPECTED: &str = r#"
340-
{
341-
"RESOURCE_MODEL": "A",
342-
"WAITER": "B",
343-
"PAGINATOR": "C",
344-
"RETRY_MODE_LEGACY": "D",
345-
"RETRY_MODE_STANDARD": "E",
346-
"RETRY_MODE_ADAPTIVE": "F",
347-
"S3_TRANSFER": "G",
348-
"S3_CRYPTO_V1N": "H",
349-
"S3_CRYPTO_V2": "I",
350-
"S3_EXPRESS_BUCKET": "J",
351-
"S3_ACCESS_GRANTS": "K",
352-
"GZIP_REQUEST_COMPRESSION": "L",
353-
"PROTOCOL_RPC_V2_CBOR": "M",
354-
"ENDPOINT_OVERRIDE": "N",
355-
"ACCOUNT_ID_ENDPOINT": "O",
356-
"ACCOUNT_ID_MODE_PREFERRED": "P",
357-
"ACCOUNT_ID_MODE_DISABLED": "Q",
358-
"ACCOUNT_ID_MODE_REQUIRED": "R",
359-
"SIGV4A_SIGNING": "S",
360-
"RESOLVED_ACCOUNT_ID": "T",
361-
"FLEXIBLE_CHECKSUMS_REQ_CRC32" : "U",
362-
"FLEXIBLE_CHECKSUMS_REQ_CRC32C" : "V",
363-
"FLEXIBLE_CHECKSUMS_REQ_CRC64" : "W",
364-
"FLEXIBLE_CHECKSUMS_REQ_SHA1" : "X",
365-
"FLEXIBLE_CHECKSUMS_REQ_SHA256" : "Y",
366-
"FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED" : "Z",
367-
"FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED" : "a",
368-
"FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED" : "b",
369-
"FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED" : "c",
370-
"DDB_MAPPER" : "d",
371-
"CREDENTIALS_CODE" : "e",
372-
"CREDENTIALS_JVM_SYSTEM_PROPERTIES" : "f",
373-
"CREDENTIALS_ENV_VARS" : "g",
374-
"CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN" : "h",
375-
"CREDENTIALS_STS_ASSUME_ROLE" : "i",
376-
"CREDENTIALS_STS_ASSUME_ROLE_SAML" : "j",
377-
"CREDENTIALS_STS_ASSUME_ROLE_WEB_ID" : "k",
378-
"CREDENTIALS_STS_FEDERATION_TOKEN" : "l",
379-
"CREDENTIALS_STS_SESSION_TOKEN" : "m",
380-
"CREDENTIALS_PROFILE" : "n",
381-
"CREDENTIALS_PROFILE_SOURCE_PROFILE" : "o",
382-
"CREDENTIALS_PROFILE_NAMED_PROVIDER" : "p",
383-
"CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN" : "q",
384-
"CREDENTIALS_PROFILE_SSO" : "r",
385-
"CREDENTIALS_SSO" : "s",
386-
"CREDENTIALS_PROFILE_SSO_LEGACY" : "t",
387-
"CREDENTIALS_SSO_LEGACY" : "u",
388-
"CREDENTIALS_PROFILE_PROCESS" : "v",
389-
"CREDENTIALS_PROCESS" : "w",
390-
"CREDENTIALS_BOTO2_CONFIG_FILE" : "x",
391-
"CREDENTIALS_AWS_SDK_STORE" : "y",
392-
"CREDENTIALS_HTTP" : "z",
393-
"CREDENTIALS_IMDS" : "0"
394-
395-
}
396-
"#;
345+
const EXPECTED: &str = include_str!("test_data/feature_id_to_metric_value.json");
397346

398347
let expected: HashMap<&str, &str> = serde_json::from_str(EXPECTED).unwrap();
399348
assert_eq!(expected.len(), FEATURE_ID_TO_METRIC_VALUE.len());

0 commit comments

Comments
 (0)