From 52402496fb5213d5016665806e8665fb3201fe43 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Thu, 2 May 2024 09:34:16 -0700 Subject: [PATCH 1/9] Fix bug and refactor tests to support multiple response body --- source/credentials_provider_profile.c | 14 ++++ tests/credentials_provider_sts_tests.c | 101 +++++++++++++++---------- 2 files changed, 76 insertions(+), 39 deletions(-) diff --git a/source/credentials_provider_profile.c b/source/credentials_provider_profile.c index 038322c9..10874a2e 100644 --- a/source/credentials_provider_profile.c +++ b/source/credentials_provider_profile.c @@ -32,6 +32,7 @@ static struct aws_byte_cursor s_default_session_name_pfx = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("aws-common-runtime-profile-config"); static struct aws_byte_cursor s_ec2_imds_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Ec2InstanceMetadata"); static struct aws_byte_cursor s_environment_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Environment"); +static struct aws_byte_cursor s_ecs_credentials_provider_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("EcsContainer"); #define MAX_SESSION_NAME_LEN ((size_t)64) @@ -372,6 +373,19 @@ static struct aws_credentials_provider *s_create_sts_based_provider( provider = aws_credentials_provider_new_sts(allocator, &sts_options); aws_credentials_provider_release(env_provider); + } else if (aws_string_eq_byte_cursor_ignore_case( + aws_profile_property_get_value(credential_source_property), &s_ecs_credentials_provider_name)) { + struct aws_credentials_provider_ecs_environment_options ecs_options = { + .bootstrap = options->bootstrap, + .function_table = options->function_table, + .tls_ctx = tls_ctx, + }; + struct aws_credentials_provider *ecs_provider = + aws_credentials_provider_new_ecs_from_environment(allocator, &ecs_options); + sts_options.creds_provider = ecs_provider; + provider = aws_credentials_provider_new_sts(allocator, &sts_options); + + aws_credentials_provider_release(ecs_provider); } else { AWS_LOGF_ERROR( AWS_LS_AUTH_CREDENTIALS_PROVIDER, diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index 719e2e82..8fcf8a67 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -43,7 +43,7 @@ struct aws_mock_sts_tester { int mock_failure_code; size_t fail_operations; - struct aws_byte_buf mock_body; + struct aws_array_list response_data_callbacks; struct aws_mutex lock; struct aws_condition_variable signal; @@ -125,7 +125,8 @@ static void s_invoke_mock_request_callbacks( options->on_response_header_block_done((struct aws_http_stream *)1, true, options->user_data); } - struct aws_byte_cursor data_callback_cur = aws_byte_cursor_from_buf(&s_tester.mock_body); + struct aws_byte_cursor data_callback_cur; + aws_array_list_get_at(&s_tester.response_data_callbacks, &data_callback_cur, s_tester.num_request - 1); options->on_response_body((struct aws_http_stream *)1, &data_callback_cur, options->user_data); options->on_complete( @@ -262,6 +263,10 @@ static int s_aws_sts_tester_init(struct aws_allocator *allocator) { ASSERT_NOT_NULL(s_tester.tls_ctx); aws_tls_ctx_options_clean_up(&tls_options); + if (aws_array_list_init_dynamic(&s_tester.response_data_callbacks, allocator, 10, sizeof(struct aws_byte_cursor))) { + return AWS_OP_ERR; + } + return AWS_OP_SUCCESS; } @@ -291,7 +296,7 @@ static int s_aws_sts_tester_cleanup(void) { aws_condition_variable_clean_up(&s_tester.signal); aws_mutex_clean_up(&s_tester.lock); - aws_byte_buf_clean_up(&s_tester.mock_body); + aws_array_list_clean_up(&s_tester.response_data_callbacks); aws_client_bootstrap_release(s_tester.bootstrap); aws_host_resolver_release(s_tester.resolver); @@ -335,21 +340,22 @@ static struct aws_byte_cursor s_role_arn_cur = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("arn:aws:iam::67895:role/test_role"); static struct aws_byte_cursor s_session_name_cur = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("test_session"); -static const char *success_creds_doc = "\n" - " \n" - " \n" - " \n" - " \n" - " accessKeyIdResp\n" - " secretKeyResp\n" - " sessionTokenResp\n" - " \n" - " \n" - " ... a bunch of other stuff we don't care about\n" - " \n" - " ... more stuff we don't care about\n" - " \n" - ""; +static struct aws_byte_cursor s_success_creds_doc = + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("\n" + " \n" + " \n" + " \n" + " \n" + " accessKeyIdResp\n" + " secretKeyResp\n" + " sessionTokenResp\n" + " \n" + " \n" + " ... a bunch of other stuff we don't care about\n" + " \n" + " ... more stuff we don't care about\n" + " \n" + ""); static struct aws_byte_cursor s_expected_payload = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Version=2011-06-15&Action=AssumeRole&RoleArn=arn%3Aaws%3Aiam%3A%3A67895%" @@ -392,7 +398,8 @@ static int s_credentials_provider_sts_direct_config_succeeds_fn(struct aws_alloc }; mock_aws_set_system_time(0); - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + + 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); @@ -468,10 +475,13 @@ static int s_credentials_provider_sts_direct_config_succeeds_after_retry_fn( }; mock_aws_set_system_time(0); - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); s_tester.mock_response_code = 200; s_tester.mock_failure_code = 429; s_tester.fail_operations = 2; + int expected_num_requests = 3; + for (int i = 0; i < expected_num_requests; i++) { + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); + } struct aws_credentials_provider *sts_provider = aws_credentials_provider_new_sts(allocator, &options); @@ -522,12 +532,13 @@ AWS_TEST_CASE( credentials_provider_sts_direct_config_succeeds_after_retry, s_credentials_provider_sts_direct_config_succeeds_after_retry_fn) -static const char *malformed_creds_doc = "\n" - " \n" - " \n" - " \n" - " accessKeyIdResp\n" - " "; +static struct aws_byte_cursor s_malformed_creds_doc = + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("\n" + " \n" + " \n" + " \n" + " accessKeyIdResp\n" + " "); static int s_credentials_provider_sts_direct_config_invalid_doc_fn(struct aws_allocator *allocator, void *ctx) { (void)ctx; @@ -553,7 +564,7 @@ static int s_credentials_provider_sts_direct_config_invalid_doc_fn(struct aws_al }; mock_aws_set_system_time(0); - s_tester.mock_body = aws_byte_buf_from_c_str(malformed_creds_doc); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_malformed_creds_doc); s_tester.mock_response_code = 200; struct aws_credentials_provider *sts_provider = aws_credentials_provider_new_sts(allocator, &options); @@ -675,6 +686,11 @@ static int s_credentials_provider_sts_direct_config_service_fails_fn(struct aws_ mock_aws_set_system_time(0); s_tester.mock_response_code = 529; + // Todo: What? 8 retries seems a lot + int expected_num_requests = 9; + for (int i = 0; i < expected_num_requests; i++) { + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_malformed_creds_doc); + } struct aws_credentials_provider *sts_provider = aws_credentials_provider_new_sts(allocator, &options); @@ -745,8 +761,10 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_fn(struct a .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, }; - - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + int expected_num_requests = 3; + for (int i = 0; i < expected_num_requests; i++) { + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); + } s_tester.mock_response_code = 200; struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); @@ -761,7 +779,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_fn(struct a ASSERT_SUCCESS(s_verify_credentials(s_tester.credentials)); - ASSERT_INT_EQUALS(3, s_tester.num_request); + ASSERT_INT_EQUALS(expected_num_requests, s_tester.num_request); static struct aws_byte_cursor s_expected_request_body[] = { AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Version=2011-06-15&Action=AssumeRole&RoleArn=arn%3Aaws%3Aiam%3A%3A67897%" "3Arole%2Ftest_role&RoleSessionName=test_session3&DurationSeconds=900"), @@ -854,7 +872,10 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_and_profile .function_table = &s_mock_function_table, }; - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + int expected_num_requests = 2; + for (int i = 0; i < expected_num_requests; i++) { + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); + } s_tester.mock_response_code = 200; struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); @@ -869,7 +890,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_and_profile ASSERT_SUCCESS(s_verify_credentials(s_tester.credentials)); - ASSERT_INT_EQUALS(2, s_tester.num_request); + ASSERT_INT_EQUALS(expected_num_requests, s_tester.num_request); static struct aws_byte_cursor s_expected_request_body[] = { AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Version=2011-06-15&Action=AssumeRole&RoleArn=arn%3Aaws%3Aiam%3A%3A67896%" "3Arole%2Ftest_role&RoleSessionName=test_session2&DurationSeconds=900"), @@ -960,7 +981,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_and_partial .function_table = &s_mock_function_table, }; - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); s_tester.mock_response_code = 200; struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); @@ -1021,7 +1042,7 @@ static int s_credentials_provider_sts_from_self_referencing_profile_fn(struct aw .function_table = &s_mock_function_table, }; - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); s_tester.mock_response_code = 200; struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); @@ -1123,7 +1144,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_cycle_fn( .function_table = &s_mock_function_table, }; - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); s_tester.mock_response_code = 200; struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); @@ -1184,7 +1205,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_cycle_and_p .function_table = &s_mock_function_table, }; - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); s_tester.mock_response_code = 200; struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); @@ -1231,7 +1252,7 @@ static int s_credentials_provider_sts_from_profile_config_succeeds( .function_table = &s_mock_function_table, }; - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); s_tester.mock_response_code = 200; struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); @@ -1343,7 +1364,7 @@ static int s_credentials_provider_sts_from_profile_config_environment_succeeds_f .function_table = &s_mock_function_table, }; - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); s_tester.mock_response_code = 200; struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); @@ -1433,7 +1454,7 @@ static int s_credentials_provider_sts_cache_expiration_conflict(struct aws_alloc mock_aws_set_system_time(0); mock_aws_set_high_res_time(HIGH_RES_BASE_TIME_NS); - s_tester.mock_body = aws_byte_buf_from_c_str(success_creds_doc); + 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); @@ -1489,6 +1510,7 @@ static int s_credentials_provider_sts_cache_expiration_conflict(struct aws_alloc s_cleanup_creds_callback_data(); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); aws_credentials_provider_get_credentials(cached_provider, s_get_credentials_callback, NULL); s_aws_wait_for_credentials_result(); @@ -1502,6 +1524,7 @@ static int s_credentials_provider_sts_cache_expiration_conflict(struct aws_alloc s_cleanup_creds_callback_data(); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); aws_credentials_provider_get_credentials(cached_provider, s_get_credentials_callback, NULL); s_aws_wait_for_credentials_result(); From 3d6f947a8031657322fe22dbe3902db18f5ada51 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Thu, 2 May 2024 15:22:35 -0700 Subject: [PATCH 2/9] Add test --- source/credentials_provider_ecs.c | 1 + source/credentials_provider_profile.c | 3 + tests/CMakeLists.txt | 1 + tests/credentials_provider_sts_tests.c | 126 +++++++++++++++++++++++-- 4 files changed, 125 insertions(+), 6 deletions(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index e7bbc00a..46829146 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -705,6 +705,7 @@ struct aws_credentials_provider *aws_credentials_provider_new_ecs_from_environme } else { /* Neither environment variable is set */ + AWS_LOGF_INFO(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "ECS provider full_uri and relative_uri are both not set"); aws_raise_error(AWS_AUTH_CREDENTIALS_PROVIDER_INVALID_ENVIRONMENT); goto cleanup; } diff --git a/source/credentials_provider_profile.c b/source/credentials_provider_profile.c index 10874a2e..6f2fe770 100644 --- a/source/credentials_provider_profile.c +++ b/source/credentials_provider_profile.c @@ -382,6 +382,9 @@ static struct aws_credentials_provider *s_create_sts_based_provider( }; struct aws_credentials_provider *ecs_provider = aws_credentials_provider_new_ecs_from_environment(allocator, &ecs_options); + if (!ecs_provider) { + goto done; + } sts_options.creds_provider = ecs_provider; provider = aws_credentials_provider_new_sts(allocator, &sts_options); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2f84e2e2..c0aa6a48 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -90,6 +90,7 @@ add_net_test_case(credentials_provider_sts_direct_config_connection_failed) add_net_test_case(credentials_provider_sts_direct_config_service_fails) add_net_test_case(credentials_provider_sts_from_profile_config_succeeds) add_net_test_case(credentials_provider_sts_from_profile_config_with_chain) +add_net_test_case(credentials_provider_sts_from_profile_config_with_ecs_credentials_source) add_net_test_case(credentials_provider_sts_from_profile_config_with_chain_and_profile_creds) add_net_test_case(credentials_provider_sts_from_profile_config_with_chain_and_partial_profile_creds) add_net_test_case(credentials_provider_sts_from_self_referencing_profile) diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index 8fcf8a67..f7454a32 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -175,12 +175,12 @@ static struct aws_http_stream *s_aws_http_connection_make_request_mock( struct aws_input_stream *input_stream = aws_http_message_get_body_stream(options->request); int64_t body_len = 0; - - aws_input_stream_get_length(input_stream, &body_len); - aws_byte_buf_clean_up(&mocked_request->body); - aws_byte_buf_init(&mocked_request->body, s_tester.allocator, (size_t)body_len); - aws_input_stream_read(input_stream, &mocked_request->body); - + if (input_stream != NULL) { + aws_input_stream_get_length(input_stream, &body_len); + aws_byte_buf_clean_up(&mocked_request->body); + aws_byte_buf_init(&mocked_request->body, s_tester.allocator, (size_t)body_len); + aws_input_stream_read(input_stream, &mocked_request->body); + } bool fail_request = false; if (s_tester.fail_operations) { @@ -826,6 +826,120 @@ AWS_TEST_CASE( credentials_provider_sts_from_profile_config_with_chain, s_credentials_provider_sts_from_profile_config_with_chain_fn) +AWS_STATIC_STRING_FROM_LITERAL(s_ecs_creds_env_relative_uri, "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"); +static const char *s_soure_credentials_ecs_config_file = "[default]\n" + "role_arn=arn:aws:iam::67895:role/test_role\n" + "credential_source=EcsContainer\n" + "role_session_name=test_session\n"; +static struct aws_byte_cursor s_ecs_good_response = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL( + "{\"AccessKeyId\":\"SuccessfulAccessKey\", \n \"SecretAccessKey\":\"SuccessfulSecret\", \n " + "\"Token\":\"TokenSuccess\", \n \"Expiration\":\"2020-02-25T06:03:31Z\"}"); +static int s_credentials_provider_sts_from_profile_config_with_ecs_credentials_source_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); + + /* set the relative uri environment variable*/ + char *relative_uri = "/test"; + struct aws_string *relative_uri_str = aws_string_new_from_c_str(allocator, relative_uri); + ASSERT_SUCCESS(aws_set_environment_value(s_ecs_creds_env_relative_uri, relative_uri_str)); + + s_aws_sts_tester_init(allocator); + + struct aws_string *config_contents = aws_string_new_from_c_str(allocator, s_soure_credentials_ecs_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(config_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), + .bootstrap = s_tester.bootstrap, + .function_table = &s_mock_function_table, + }; + int expected_num_requests = 2; + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_ecs_good_response); + aws_array_list_push_back(&s_tester.response_data_callbacks, &s_success_creds_doc); + + s_tester.mock_response_code = 200; + + struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options); + ASSERT_NOT_NULL(provider); + + aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL); + + s_aws_wait_for_credentials_result(); + + ASSERT_SUCCESS(s_verify_credentials(s_tester.credentials)); + + ASSERT_INT_EQUALS(expected_num_requests, s_tester.num_request); + struct aws_mock_http_request expected_mocked_request[2]; + /* expected ecs request*/ + expected_mocked_request[0] = (struct aws_mock_http_request){ + .method = aws_byte_buf_from_c_str("GET"), + .host_header = aws_byte_buf_from_c_str("169.254.170.2"), + .path = aws_byte_buf_from_c_str(relative_uri), + .body = aws_byte_buf_from_c_str(""), + .had_auth_header = false, + }; + /* expected sts request */ + expected_mocked_request[1] = (struct aws_mock_http_request){ + .method = aws_byte_buf_from_c_str("POST"), + .host_header = aws_byte_buf_from_c_str("sts.amazonaws.com"), + .path = aws_byte_buf_from_c_str("/"), + .body = aws_byte_buf_from_c_str("Version=2011-06-15&Action=AssumeRole&RoleArn=arn%3Aaws%3Aiam%3A%3A67895%" + "3Arole%2Ftest_role&RoleSessionName=test_session&DurationSeconds=900"), + .had_auth_header = true, + }; + + for (int i = 0; i < expected_num_requests; i++) { + ASSERT_BIN_ARRAYS_EQUALS( + expected_mocked_request[i].method.buffer, + expected_mocked_request[i].method.len, + s_tester.mocked_requests[i].method.buffer, + s_tester.mocked_requests[i].method.len); + ASSERT_BIN_ARRAYS_EQUALS( + expected_mocked_request[i].path.buffer, + expected_mocked_request[i].path.len, + s_tester.mocked_requests[i].path.buffer, + s_tester.mocked_requests[i].path.len); + ASSERT_TRUE(s_tester.mocked_requests[i].had_auth_header == expected_mocked_request[i].had_auth_header); + ASSERT_BIN_ARRAYS_EQUALS( + expected_mocked_request[i].host_header.buffer, + expected_mocked_request[i].host_header.len, + s_tester.mocked_requests[i].host_header.buffer, + s_tester.mocked_requests[i].host_header.len); + // AWS_LOGF_ERROR( + // AWS_LS_AUTH_CREDENTIALS_PROVIDER, + // "waahm7: \n " PRInSTR ":\n " PRInSTR "\n", + // AWS_BYTE_BUF_PRI(expected_mocked_request[i].body), + // AWS_BYTE_BUF_PRI(s_tester.mocked_requests[i].body)); + ASSERT_BIN_ARRAYS_EQUALS( + expected_mocked_request[i].body.buffer, + expected_mocked_request[i].body.len, + s_tester.mocked_requests[i].body.buffer, + s_tester.mocked_requests[i].body.len); + } + + aws_credentials_provider_release(provider); + aws_string_destroy(relative_uri_str); + aws_string_destroy(config_file_str); + aws_string_destroy(creds_file_str); + ASSERT_SUCCESS(s_aws_sts_tester_cleanup()); + + return AWS_OP_SUCCESS; +} +AWS_TEST_CASE( + credentials_provider_sts_from_profile_config_with_ecs_credentials_source, + s_credentials_provider_sts_from_profile_config_with_ecs_credentials_source_fn) + static const char *s_soure_profile_chain_and_profile_config_file = "[default]\n" "aws_access_key_id=BLAHBLAH\n" "aws_secret_access_key=BLAHBLAHBLAH\n" From 8571b5f3b2f8a924434da14df27807d68aa1f47f Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 3 May 2024 10:33:10 -0700 Subject: [PATCH 3/9] Fix up the shutdown callbacks and cleanup --- source/credentials_provider_ecs.c | 6 +++- tests/credentials_provider_sts_tests.c | 50 ++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index 46829146..0fa39491 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -400,7 +400,10 @@ static int s_make_ecs_http_query( .user_data = ecs_user_data, .request = request, }; - + /* for test with mocking http stack where make request finishes + immediately and releases client before stream activate call */ + struct aws_credentials_provider *provider = ecs_user_data->ecs_provider; + aws_credentials_provider_acquire(provider); stream = impl->function_table->aws_http_connection_make_request(ecs_user_data->connection, &request_options); if (!stream) { @@ -410,6 +413,7 @@ static int s_make_ecs_http_query( if (impl->function_table->aws_http_stream_activate(stream)) { goto on_error; } + aws_credentials_provider_release(provider); return AWS_OP_SUCCESS; diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index f7454a32..013c9a1b 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -50,6 +50,8 @@ struct aws_mock_sts_tester { struct aws_credentials *credentials; bool has_received_credentials_callback; + int mocked_connection_manager_shutdown_callback_count; + int expected_connection_manager_shutdown_callback_count; int error_code; bool fail_connection; @@ -61,22 +63,56 @@ struct aws_mock_sts_tester { struct aws_client_bootstrap *bootstrap; struct aws_tls_ctx *tls_ctx; + + aws_http_connection_manager_shutdown_complete_fn *shutdown_complete_callback; + void *shutdown_complete_user_data; }; static struct aws_mock_sts_tester s_tester; +static void s_on_shutdown_complete(void *user_data) { + (void)user_data; + + aws_mutex_lock(&s_tester.lock); + s_tester.mocked_connection_manager_shutdown_callback_count++; + aws_mutex_unlock(&s_tester.lock); + + aws_condition_variable_notify_one(&s_tester.signal); +} + +static bool s_has_tester_received_shutdown_callback(void *user_data) { + (void)user_data; + + return s_tester.mocked_connection_manager_shutdown_callback_count == + s_tester.expected_manager_shutdown_callback_count; +} + +static void s_aws_wait_for_provider_shutdown_callback(void) { + aws_mutex_lock(&s_tester.lock); + aws_condition_variable_wait_pred(&s_tester.signal, &s_tester.lock, s_has_tester_received_shutdown_callback, NULL); + aws_mutex_unlock(&s_tester.lock); +} + static struct aws_http_connection_manager *s_aws_http_connection_manager_new_mock( struct aws_allocator *allocator, const struct aws_http_connection_manager_options *options) { - - (void)allocator; - (void)options; - - return (struct aws_http_connection_manager *)1; + /* copy the shutdown callback */ + struct aws_shutdown_callback_options *shutdown_callback = + aws_mem_calloc(allocator, 1, sizeof(struct aws_shutdown_callback_options)); + shutdown_callback->shutdown_callback_fn = options->shutdown_complete_callback; + shutdown_callback->shutdown_callback_user_data = options->shutdown_complete_user_data; + return (struct aws_http_connection_manager *)shutdown_callback; } static void s_aws_http_connection_manager_release_mock(struct aws_http_connection_manager *manager) { (void)manager; + /* invoke the shutdown callback */ + struct aws_shutdown_callback_options *shutdown_callback = (struct aws_shutdown_callback_options *)manager; + if (shutdown_callback->shutdown_callback_fn != NULL) { + shutdown_callback->shutdown_callback_fn(shutdown_callback->shutdown_callback_user_data); + } + aws_mem_release(s_tester.allocator, shutdown_callback); + s_on_shutdown_complete(NULL); } static void s_aws_http_connection_manager_acquire_connection_mock( @@ -849,7 +885,8 @@ static int s_credentials_provider_sts_from_profile_config_with_ecs_credentials_s ASSERT_SUCCESS(aws_set_environment_value(s_ecs_creds_env_relative_uri, relative_uri_str)); s_aws_sts_tester_init(allocator); - + /* one for ecs provdier and one for sts provider */ + s_tester.expected_connection_manager_shutdown_callback_count = 2; struct aws_string *config_contents = aws_string_new_from_c_str(allocator, s_soure_credentials_ecs_config_file); struct aws_string *config_file_str = aws_create_process_unique_file_name(allocator); @@ -929,6 +966,7 @@ static int s_credentials_provider_sts_from_profile_config_with_ecs_credentials_s } aws_credentials_provider_release(provider); + s_aws_wait_for_provider_shutdown_callback(); aws_string_destroy(relative_uri_str); aws_string_destroy(config_file_str); aws_string_destroy(creds_file_str); From bbe56abf9714de739a69216322f6d575b981fcd2 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 3 May 2024 10:34:00 -0700 Subject: [PATCH 4/9] fix typo --- tests/credentials_provider_sts_tests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index 013c9a1b..74f7ba38 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -84,7 +84,7 @@ static bool s_has_tester_received_shutdown_callback(void *user_data) { (void)user_data; return s_tester.mocked_connection_manager_shutdown_callback_count == - s_tester.expected_manager_shutdown_callback_count; + s_tester.expected_connection_manager_shutdown_callback_count; } static void s_aws_wait_for_provider_shutdown_callback(void) { From f1caf15cdc473a69504919b365436634e340415b Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 3 May 2024 11:29:05 -0700 Subject: [PATCH 5/9] wait for shutdown in each test --- tests/credentials_provider_sts_tests.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index 74f7ba38..2271cb62 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -268,7 +268,7 @@ static struct aws_auth_http_system_vtable s_mock_function_table = { static int s_aws_sts_tester_init(struct aws_allocator *allocator) { AWS_ZERO_STRUCT(s_tester); s_tester.allocator = allocator; - + s_tester.expected_connection_manager_shutdown_callback_count = 1; aws_auth_library_init(allocator); if (aws_mutex_init(&s_tester.lock)) { @@ -477,6 +477,7 @@ static int s_credentials_provider_sts_direct_config_succeeds_fn(struct aws_alloc 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()); @@ -558,6 +559,7 @@ static int s_credentials_provider_sts_direct_config_succeeds_after_retry_fn( 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()); @@ -641,6 +643,7 @@ static int s_credentials_provider_sts_direct_config_invalid_doc_fn(struct aws_al 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()); @@ -687,6 +690,7 @@ static int s_credentials_provider_sts_direct_config_connection_failed_fn(struct ASSERT_NULL(s_tester.credentials); 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()); @@ -737,6 +741,7 @@ static int s_credentials_provider_sts_direct_config_service_fails_fn(struct aws_ ASSERT_NULL(s_tester.credentials); 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()); @@ -781,7 +786,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_fn(struct a aws_unset_environment_value(s_default_credentials_path_env_variable_name); s_aws_sts_tester_init(allocator); - + s_tester.expected_connection_manager_shutdown_callback_count = 3; struct aws_string *config_contents = aws_string_new_from_c_str(allocator, s_soure_profile_chain_config_file); struct aws_string *config_file_str = aws_create_process_unique_file_name(allocator); @@ -853,7 +858,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_fn(struct a } aws_credentials_provider_release(provider); - + s_aws_wait_for_provider_shutdown_callback(); ASSERT_SUCCESS(s_aws_sts_tester_cleanup()); return AWS_OP_SUCCESS; @@ -1006,7 +1011,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_and_profile aws_unset_environment_value(s_default_credentials_path_env_variable_name); s_aws_sts_tester_init(allocator); - + s_tester.expected_connection_manager_shutdown_callback_count = 2; struct aws_string *config_contents = aws_string_new_from_c_str(allocator, s_soure_profile_chain_and_profile_config_file); @@ -1078,7 +1083,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_and_profile } aws_credentials_provider_release(provider); - + s_aws_wait_for_provider_shutdown_callback(); ASSERT_SUCCESS(s_aws_sts_tester_cleanup()); return AWS_OP_SUCCESS; @@ -1115,7 +1120,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_and_partial aws_unset_environment_value(s_default_credentials_path_env_variable_name); s_aws_sts_tester_init(allocator); - + s_tester.expected_connection_manager_shutdown_callback_count = 2; struct aws_string *config_contents = aws_string_new_from_c_str(allocator, s_soure_profile_chain_and_partial_profile_config_file); @@ -1149,7 +1154,7 @@ static int s_credentials_provider_sts_from_profile_config_with_chain_and_partial ASSERT_NULL(s_tester.credentials); ASSERT_INT_EQUALS(s_tester.error_code, AWS_AUTH_SIGNING_NO_CREDENTIALS); aws_credentials_provider_release(provider); - + s_aws_wait_for_provider_shutdown_callback(); ASSERT_SUCCESS(s_aws_sts_tester_cleanup()); return AWS_OP_SUCCESS; @@ -1176,7 +1181,6 @@ static int s_credentials_provider_sts_from_self_referencing_profile_fn(struct aw 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_self_assume_role_config_file); @@ -1243,7 +1247,7 @@ static int s_credentials_provider_sts_from_self_referencing_profile_fn(struct aw } aws_credentials_provider_release(provider); - + s_aws_wait_for_provider_shutdown_callback(); ASSERT_SUCCESS(s_aws_sts_tester_cleanup()); return AWS_OP_SUCCESS; @@ -1449,7 +1453,7 @@ static int s_credentials_provider_sts_from_profile_config_succeeds( s_tester.mocked_requests[0].body.len); aws_credentials_provider_release(provider); - + s_aws_wait_for_provider_shutdown_callback(); ASSERT_SUCCESS(s_aws_sts_tester_cleanup()); return AWS_OP_SUCCESS; @@ -1561,6 +1565,7 @@ static int s_credentials_provider_sts_from_profile_config_environment_succeeds_f s_tester.mocked_requests[0].body.len); aws_credentials_provider_release(provider); + s_aws_wait_for_provider_shutdown_callback(); ASSERT_SUCCESS(s_aws_sts_tester_cleanup()); @@ -1684,6 +1689,7 @@ static int s_credentials_provider_sts_cache_expiration_conflict(struct aws_alloc aws_credentials_provider_release(cached_provider); 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()); From 8088ecae2fb0f6bae7d771075e3a31949310cda7 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 3 May 2024 11:50:59 -0700 Subject: [PATCH 6/9] cleanup --- source/credentials_provider_ecs.c | 5 ++++- tests/credentials_provider_sts_tests.c | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index 0fa39491..cd352ed1 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -709,7 +709,10 @@ struct aws_credentials_provider *aws_credentials_provider_new_ecs_from_environme } else { /* Neither environment variable is set */ - AWS_LOGF_INFO(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "ECS provider full_uri and relative_uri are both not set"); + AWS_LOGF_INFO( + AWS_LS_AUTH_CREDENTIALS_PROVIDER, + "ECS provider: Unable to initialize from environment because AWS_CONTAINER_CREDENTIALS_FULL_URI and " + "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI are not set."); aws_raise_error(AWS_AUTH_CREDENTIALS_PROVIDER_INVALID_ENVIRONMENT); goto cleanup; } diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index 2271cb62..e554d4b3 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -63,9 +63,6 @@ struct aws_mock_sts_tester { struct aws_client_bootstrap *bootstrap; struct aws_tls_ctx *tls_ctx; - - aws_http_connection_manager_shutdown_complete_fn *shutdown_complete_callback; - void *shutdown_complete_user_data; }; static struct aws_mock_sts_tester s_tester; From 1f078a3c1824ff11dc0d939252f8a0518463d019 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 3 May 2024 11:52:27 -0700 Subject: [PATCH 7/9] rename function --- tests/credentials_provider_sts_tests.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index e554d4b3..9700f500 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -67,7 +67,7 @@ struct aws_mock_sts_tester { static struct aws_mock_sts_tester s_tester; -static void s_on_shutdown_complete(void *user_data) { +static void s_on_connection_manager_shutdown_complete(void *user_data) { (void)user_data; aws_mutex_lock(&s_tester.lock); @@ -109,7 +109,7 @@ static void s_aws_http_connection_manager_release_mock(struct aws_http_connectio shutdown_callback->shutdown_callback_fn(shutdown_callback->shutdown_callback_user_data); } aws_mem_release(s_tester.allocator, shutdown_callback); - s_on_shutdown_complete(NULL); + s_on_connection_manager_shutdown_complete(NULL); } static void s_aws_http_connection_manager_acquire_connection_mock( From 6398574bfa2ade21c35524b47938ec0a80020b35 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 3 May 2024 11:55:12 -0700 Subject: [PATCH 8/9] cleanup --- tests/credentials_provider_sts_tests.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index 9700f500..061149a9 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -955,11 +955,6 @@ static int s_credentials_provider_sts_from_profile_config_with_ecs_credentials_s expected_mocked_request[i].host_header.len, s_tester.mocked_requests[i].host_header.buffer, s_tester.mocked_requests[i].host_header.len); - // AWS_LOGF_ERROR( - // AWS_LS_AUTH_CREDENTIALS_PROVIDER, - // "waahm7: \n " PRInSTR ":\n " PRInSTR "\n", - // AWS_BYTE_BUF_PRI(expected_mocked_request[i].body), - // AWS_BYTE_BUF_PRI(s_tester.mocked_requests[i].body)); ASSERT_BIN_ARRAYS_EQUALS( expected_mocked_request[i].body.buffer, expected_mocked_request[i].body.len, From 59090a39a8b5761b805ceda0db2d6bf1cc3d93c9 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 3 May 2024 12:12:58 -0700 Subject: [PATCH 9/9] Reduce retries to 3 --- source/credentials_provider_cognito.c | 2 +- source/credentials_provider_sts.c | 2 +- tests/credentials_provider_sts_tests.c | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/source/credentials_provider_cognito.c b/source/credentials_provider_cognito.c index ece91b8a..f918e998 100644 --- a/source/credentials_provider_cognito.c +++ b/source/credentials_provider_cognito.c @@ -22,7 +22,7 @@ #include #define COGNITO_CONNECT_TIMEOUT_DEFAULT_IN_SECONDS 5 -#define COGNITO_MAX_RETRIES 8 +#define COGNITO_MAX_RETRIES 3 #define HTTP_REQUEST_BODY_INITIAL_SIZE 1024 #define HTTP_RESPONSE_BODY_INITIAL_SIZE 4096 diff --git a/source/credentials_provider_sts.c b/source/credentials_provider_sts.c index 0832cdee..5d568885 100644 --- a/source/credentials_provider_sts.c +++ b/source/credentials_provider_sts.c @@ -54,7 +54,7 @@ static struct aws_byte_cursor s_content_length = AWS_BYTE_CUR_INIT_FROM_STRING_L static struct aws_byte_cursor s_path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/"); static struct aws_byte_cursor s_signing_region = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("us-east-1"); static struct aws_byte_cursor s_service_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("sts"); -static const int s_max_retries = 8; +static const int s_max_retries = 3; const uint16_t aws_sts_assume_role_default_duration_secs = 900; diff --git a/tests/credentials_provider_sts_tests.c b/tests/credentials_provider_sts_tests.c index 061149a9..64542426 100644 --- a/tests/credentials_provider_sts_tests.c +++ b/tests/credentials_provider_sts_tests.c @@ -723,8 +723,7 @@ static int s_credentials_provider_sts_direct_config_service_fails_fn(struct aws_ mock_aws_set_system_time(0); s_tester.mock_response_code = 529; - // Todo: What? 8 retries seems a lot - int expected_num_requests = 9; + int expected_num_requests = 4; for (int i = 0; i < expected_num_requests; i++) { aws_array_list_push_back(&s_tester.response_data_callbacks, &s_malformed_creds_doc); }