From 6922cf9f6d799622d3683a6f056718a3eb82d923 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Thu, 11 Jan 2024 10:22:12 -0800 Subject: [PATCH] Fix chain with static creds case --- source/credentials_provider_profile.c | 11 +++-- tests/CMakeLists.txt | 1 + tests/credentials_provider_sts_tests.c | 61 ++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/source/credentials_provider_profile.c b/source/credentials_provider_profile.c index 647c7b95..b149e333 100644 --- a/source/credentials_provider_profile.c +++ b/source/credentials_provider_profile.c @@ -465,10 +465,13 @@ static struct aws_credentials_provider *s_credentials_provider_new_profile_inter AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "hash_table_find failed"); goto on_finished; } - if (element != NULL && !profile_contains_static_cred) { - // recursion - aws_raise_error(AWS_AUTH_PROFILE_CREDENTIALS_PROVIDER_CYCLE_FAILURE); - goto on_finished; + if (element != NULL) { + /* profiles can contain self reference but no circular chain */ + if (!profile_contains_static_cred || aws_hash_table_get_entry_count(source_profile_table) > 1) { + AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "assumeRole chain contains a circular reference"); + aws_raise_error(AWS_AUTH_PROFILE_CREDENTIALS_PROVIDER_CYCLE_FAILURE); + goto on_finished; + } } aws_hash_table_put(source_profile_table, (void *)&profile_name_cursor, NULL, 0); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7e4f95b0..e927389f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -91,6 +91,7 @@ add_net_test_case(credentials_provider_sts_from_profile_config_with_chain) add_net_test_case(credentials_provider_sts_from_profile_config_with_chain_and_profile_creds) add_net_test_case(credentials_provider_sts_from_self_referencing_profile) add_net_test_case(credentials_provider_sts_from_profile_config_with_chain_cycle) +add_net_test_case(credentials_provider_sts_from_profile_config_with_chain_cycle_and_static_creds) add_net_test_case(credentials_provider_sts_from_profile_config_manual_tls_succeeds) add_net_test_case(credentials_provider_sts_from_profile_config_environment_succeeds) add_net_test_case(credentials_provider_sts_cache_expiration_conflict) diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index 4f553b1e..1f10675b 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -1068,6 +1068,67 @@ AWS_TEST_CASE( credentials_provider_sts_from_profile_config_with_chain_cycle, s_credentials_provider_sts_from_profile_config_with_chain_cycle_fn) +static const char *s_soure_profile_chain_cycle_and_static_creds_config_file = + "[roletest]\n" + "role_arn=arn:aws:iam::67895:role/test_role\n" + "source_profile=roletest2\n" + "role_session_name=test_session\n" + "aws_access_key_id=BLAHBLAH\n" + "aws_secret_access_key=BLAHBLAHBLAH\n" + "[roletest2]\n" + "role_arn=arn:aws:iam::67896:role/test_role\n" + "source_profile=roletest3\n" + "role_session_name=test_session2\n" + "[roletest3]\n" + "role_arn=arn:aws:iam::67897:role/test_role\n" + "source_profile=roletest\n" + "role_session_name=test_session3\n"; + +static int s_credentials_provider_sts_from_profile_config_with_chain_cycle_and_static_creds_fn( + struct aws_allocator *allocator, + void *ctx) { + (void)ctx; + + aws_unset_environment_value(s_default_profile_env_variable_name); + aws_unset_environment_value(s_default_config_path_env_variable_name); + aws_unset_environment_value(s_default_credentials_path_env_variable_name); + + s_aws_sts_tester_init(allocator); + + struct aws_string *config_contents = + aws_string_new_from_c_str(allocator, s_soure_profile_chain_cycle_and_static_creds_config_file); + + struct aws_string *config_file_str = aws_create_process_unique_file_name(allocator); + struct aws_string *creds_file_str = aws_create_process_unique_file_name(allocator); + + ASSERT_SUCCESS(aws_create_profile_file(creds_file_str, config_contents)); + aws_string_destroy(config_contents); + + struct aws_credentials_provider_profile_options options = { + .config_file_name_override = aws_byte_cursor_from_string(config_file_str), + .credentials_file_name_override = aws_byte_cursor_from_string(creds_file_str), + .profile_name_override = aws_byte_cursor_from_c_str("roletest"), + .bootstrap = s_tester.bootstrap, + .function_table = &s_mock_function_table, + }; + + s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + s_tester.mock_response_code = 200; + + struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); + ASSERT_NULL(provider); + ASSERT_INT_EQUALS(AWS_AUTH_PROFILE_CREDENTIALS_PROVIDER_CYCLE_FAILURE, aws_last_error()); + + ASSERT_SUCCESS(s_aws_sts_tester_cleanup()); + aws_string_destroy(config_file_str); + aws_string_destroy(creds_file_str); + + return AWS_OP_SUCCESS; +} +AWS_TEST_CASE( + credentials_provider_sts_from_profile_config_with_chain_cycle_and_static_creds, + s_credentials_provider_sts_from_profile_config_with_chain_cycle_and_static_creds_fn) + static int s_credentials_provider_sts_from_profile_config_succeeds( struct aws_allocator *allocator, void *ctx,