Skip to content

Commit

Permalink
Add support for AWS_REGION as well
Browse files Browse the repository at this point in the history
  • Loading branch information
waahm7 committed May 8, 2024
1 parent 843f1fa commit 9ae6ec4
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 14 deletions.
12 changes: 9 additions & 3 deletions include/aws/auth/credentials.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,14 +360,14 @@ struct aws_credentials_provider_x509_options {
---------------------------------------------------------------------------------
| Parameter | Environment Variable Name | Config File Property Name |
----------------------------------------------------------------------------------
| region | AWS_DEFAULT_REGION | region |
| region | AWS_REGION/AWS_DEFAULT_REGION| region |
| role_arn | AWS_ROLE_ARN | role_arn |
| role_session_name | AWS_ROLE_SESSION_NAME | role_session_name |
| token_file_path | AWS_WEB_IDENTITY_TOKEN_FILE | web_identity_token_file |
|--------------------------------------------------------------------------------|
* The order of resolution is the following
* 1. Parameters
* 2. Environment Variables
* 2. Environment Variables (in case of region, AWS_REGION is preferred over AWS_DEFAULT_REGION)
* 3. Config File
*/
struct aws_credentials_provider_sts_web_identity_options {
Expand Down Expand Up @@ -465,8 +465,14 @@ struct aws_credentials_provider_sso_options {
};

/**
* Configuration options for the STS credentials provider
* Configuration options for the STS credentials provider.
* STS Credentials Provider will try to automatically resolve the region and use a regional STS endpoint if successful.
* The region resolution order is the following:
* 1. AWS_REGION environment variable
* 2. AWS_DEFAULT_REGION environment variable
* 3. the region property in the config file
*/

struct aws_credentials_provider_sts_options {
/*
* Connection bootstrap to use for any network connections made while sourcing credentials
Expand Down
8 changes: 8 additions & 0 deletions include/aws/auth/private/credentials_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ struct aws_profile_collection *aws_load_profile_collection_from_config_file(
struct aws_allocator *allocator,
struct aws_byte_cursor config_file_name_override);

/*
* Resolve region from environment in the following order
* 1. AWS_REGION
* 2. AWS_DEFAULT_REGION
*/
AWS_AUTH_API
struct aws_string *aws_credentials_provider_resolve_region_from_env(struct aws_allocator *allocator);

AWS_EXTERN_C_END

#endif /* AWS_AUTH_CREDENTIALS_PRIVATE_H */
14 changes: 6 additions & 8 deletions source/credentials_provider_sts.c
Original file line number Diff line number Diff line change
Expand Up @@ -671,27 +671,25 @@ static struct aws_credentials_provider_vtable s_aws_credentials_provider_sts_vta
};

AWS_STATIC_STRING_FROM_LITERAL(s_region_config, "region");
AWS_STATIC_STRING_FROM_LITERAL(s_region_env, "AWS_DEFAULT_REGION");

/*
* Try to resolve the region in the following order
* 1. Check `AWS_REGION` environment variable
* 1. Check `AWS_DEFAULT_REGION` environment variable
* 2. check `region` config file property.
*/
static struct aws_string *s_resolve_region(
struct aws_allocator *allocator,
const struct aws_credentials_provider_sts_options *options) {
struct aws_profile_collection *profile_collection = NULL;
struct aws_string *region = NULL;
struct aws_string *profile_name = NULL;

/* check environment variable */
aws_get_environment_value(allocator, s_region_env, &region);

/* check environment variable first */
struct aws_string *region = aws_credentials_provider_resolve_region_from_env(allocator);
if (region != NULL && region->len > 0) {
return region;
}

struct aws_profile_collection *profile_collection = NULL;
struct aws_string *profile_name = NULL;

/* check the config file */
if (options->profile_collection_cached) {
profile_collection = aws_profile_collection_acquire(options->profile_collection_cached);
Expand Down
9 changes: 7 additions & 2 deletions source/credentials_provider_sts_web_identity.c
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,6 @@ static void s_on_connection_manager_shutdown(void *user_data) {
}

AWS_STATIC_STRING_FROM_LITERAL(s_region_config, "region");
AWS_STATIC_STRING_FROM_LITERAL(s_region_env, "AWS_DEFAULT_REGION");
AWS_STATIC_STRING_FROM_LITERAL(s_role_arn_config, "role_arn");
AWS_STATIC_STRING_FROM_LITERAL(s_role_arn_env, "AWS_ROLE_ARN");
AWS_STATIC_STRING_FROM_LITERAL(s_role_session_name_config, "role_session_name");
Expand Down Expand Up @@ -956,7 +955,13 @@ static struct sts_web_identity_parameters *s_parameters_new(
parameters->allocator = allocator;

bool success = false;
struct aws_string *region = s_check_or_get_with_env(allocator, s_region_env, options->region);
struct aws_string *region = NULL;
if (options->region.len > 0) {
region = aws_string_new_from_cursor(allocator, &options->region);
} else {
region = aws_credentials_provider_resolve_region_from_env(allocator);
}

struct aws_string *role_arn = s_check_or_get_with_env(allocator, s_role_arn_env, options->role_arn);
struct aws_string *role_session_name =
s_check_or_get_with_env(allocator, s_role_session_name_env, options->role_session_name);
Expand Down
16 changes: 16 additions & 0 deletions source/credentials_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,3 +399,19 @@ int aws_credentials_provider_construct_regional_endpoint(
aws_byte_buf_clean_up(out_endpoint);
return AWS_OP_ERR;
}

AWS_STATIC_STRING_FROM_LITERAL(s_region_env, "AWS_REGION");
AWS_STATIC_STRING_FROM_LITERAL(s_default_region_env, "AWS_DEFAULT_REGION");

struct aws_string *aws_credentials_provider_resolve_region_from_env(struct aws_allocator *allocator) {
struct aws_string *region = NULL;

/* check AWS_REGION environment variable first */
aws_get_environment_value(allocator, s_region_env, &region);
if (region != NULL && region->len > 0) {
return region;
}

aws_get_environment_value(allocator, s_default_region_env, &region);
return region;
}
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ add_net_test_case(credentials_provider_sts_web_identity_real_new_destroy)

add_net_test_case(credentials_provider_sts_direct_config_succeeds)
add_net_test_case(credentials_provider_sts_direct_config_with_region_succeeds)
add_net_test_case(credentials_provider_sts_direct_config_with_default_region_succeeds)
add_net_test_case(credentials_provider_sts_direct_config_with_region_from_config_succeeds)
add_net_test_case(credentials_provider_sts_direct_config_succeeds_after_retry)
add_net_test_case(credentials_provider_sts_direct_config_invalid_doc)
Expand Down
91 changes: 90 additions & 1 deletion tests/credentials_provider_sts_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ static struct aws_auth_http_system_vtable s_mock_function_table = {
.aws_http_connection_close = s_aws_http_connection_close_mock};

AWS_STATIC_STRING_FROM_LITERAL(s_config_file_path_env_variable_name, "AWS_CONFIG_FILE");
AWS_STATIC_STRING_FROM_LITERAL(s_region_env_variable_name, "AWS_DEFAULT_REGION");
AWS_STATIC_STRING_FROM_LITERAL(s_region_env_variable_name, "AWS_REGION");
AWS_STATIC_STRING_FROM_LITERAL(s_region_default_env_variable_name, "AWS_DEFAULT_REGION");

static int s_aws_sts_tester_init(struct aws_allocator *allocator) {
AWS_ZERO_STRUCT(s_tester);
Expand Down Expand Up @@ -307,6 +308,7 @@ static int s_aws_sts_tester_init(struct aws_allocator *allocator) {
* set the environment so that it doesn't mess with tests
*/
aws_unset_environment_value(s_region_env_variable_name);
aws_unset_environment_value(s_region_default_env_variable_name);
struct aws_string *cur_directory = aws_string_new_from_c_str(allocator, ".");
aws_set_environment_value(s_config_file_path_env_variable_name, cur_directory);
aws_string_destroy(cur_directory);
Expand Down Expand Up @@ -500,8 +502,12 @@ static int s_credentials_provider_sts_direct_config_with_region_succeeds_fn(
(void)ctx;

s_aws_sts_tester_init(allocator);
/* verify that it picks the s_region_env_variable_name if both are set */
struct aws_string *region = aws_string_new_from_c_str(allocator, "us-west-2");
struct aws_string *default_region = aws_string_new_from_c_str(allocator, "us-east-1");
aws_set_environment_value(s_region_env_variable_name, region);
aws_set_environment_value(s_region_default_env_variable_name, default_region);
aws_string_destroy(default_region);
aws_string_destroy(region);

struct aws_credentials_provider_static_options static_options = {
Expand Down Expand Up @@ -577,6 +583,89 @@ AWS_TEST_CASE(
credentials_provider_sts_direct_config_with_region_succeeds,
s_credentials_provider_sts_direct_config_with_region_succeeds_fn)

static int s_credentials_provider_sts_direct_config_with_default_region_succeeds_fn(
struct aws_allocator *allocator,
void *ctx) {
(void)ctx;

s_aws_sts_tester_init(allocator);
struct aws_string *default_region = aws_string_new_from_c_str(allocator, "us-east-1");
aws_set_environment_value(s_region_default_env_variable_name, default_region);
aws_string_destroy(default_region);

struct aws_credentials_provider_static_options static_options = {
.access_key_id = s_access_key_cur,
.secret_access_key = s_secret_key_cur,
.session_token = s_session_token_cur,
};
struct aws_credentials_provider *static_provider = aws_credentials_provider_new_static(allocator, &static_options);

struct aws_credentials_provider_sts_options options = {
.creds_provider = static_provider,
.bootstrap = s_tester.bootstrap,
.tls_ctx = s_tester.tls_ctx,
.role_arn = s_role_arn_cur,
.session_name = s_session_name_cur,
.duration_seconds = 0,
.function_table = &s_mock_function_table,
.system_clock_fn = mock_aws_get_system_time,
};

mock_aws_set_system_time(0);

aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc);
s_tester.mock_response_code = 200;

struct aws_credentials_provider *sts_provider = aws_credentials_provider_new_sts(allocator, &options);

aws_credentials_provider_get_credentials(sts_provider, s_get_credentials_callback, NULL);

s_aws_wait_for_credentials_result();

ASSERT_SUCCESS(s_verify_credentials(s_tester.credentials));
ASSERT_TRUE(aws_credentials_get_expiration_timepoint_seconds(s_tester.credentials) == 900);

const char *expected_method = "POST";
ASSERT_BIN_ARRAYS_EQUALS(
expected_method,
strlen(expected_method),
s_tester.mocked_requests[0].method.buffer,
s_tester.mocked_requests[0].method.len);

const char *expected_path = "/";
ASSERT_BIN_ARRAYS_EQUALS(
expected_path,
strlen(expected_path),
s_tester.mocked_requests[0].path.buffer,
s_tester.mocked_requests[0].path.len);

ASSERT_TRUE(s_tester.mocked_requests[0].had_auth_header);

const char *expected_host_header = "sts.us-east-1.amazonaws.com";
ASSERT_BIN_ARRAYS_EQUALS(
expected_host_header,
strlen(expected_host_header),
s_tester.mocked_requests[0].host_header.buffer,
s_tester.mocked_requests[0].host_header.len);

ASSERT_BIN_ARRAYS_EQUALS(
s_expected_payload.ptr,
s_expected_payload.len,
s_tester.mocked_requests[0].body.buffer,
s_tester.mocked_requests[0].body.len);

aws_credentials_provider_release(sts_provider);
s_aws_wait_for_provider_shutdown_callback();
aws_credentials_provider_release(static_provider);
ASSERT_SUCCESS(s_aws_sts_tester_cleanup());

return AWS_OP_SUCCESS;
}

AWS_TEST_CASE(
credentials_provider_sts_direct_config_with_default_region_succeeds,
s_credentials_provider_sts_direct_config_with_default_region_succeeds_fn)

static int s_credentials_provider_sts_direct_config_with_region_from_config_succeeds_fn(
struct aws_allocator *allocator,
void *ctx) {
Expand Down

0 comments on commit 9ae6ec4

Please sign in to comment.