From db02f8a2adb12c573930a1980f6d57278185be28 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 11:07:33 -0700 Subject: [PATCH 01/20] add mocked server --- .builder/action/mock_server_setup.py | 44 +++++++ builder.json | 5 +- include/aws/auth/auth.h | 1 + source/auth.c | 3 + source/credentials_provider_ecs.c | 49 ++++++++ tests/CMakeLists.txt | 5 + tests/credentials_provider_ecs_tests.c | 118 ++++++++++++++++++ ...entials_provider_ecs_success_response.json | 12 ++ tests/mock_server/mock_auth_server.py | 45 +++++++ 9 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 .builder/action/mock_server_setup.py create mode 100644 tests/mock_server/credentials_provider_ecs_success_response.json create mode 100644 tests/mock_server/mock_auth_server.py diff --git a/.builder/action/mock_server_setup.py b/.builder/action/mock_server_setup.py new file mode 100644 index 00000000..d9b1def0 --- /dev/null +++ b/.builder/action/mock_server_setup.py @@ -0,0 +1,44 @@ +""" +Setup local mock server for tests +""" + +import Builder + +import os +import sys +import subprocess +import atexit + + +class MockServerSetup(Builder.Action): + """ + Set up this machine for running the mock server test + + This action should be run in the 'pre_build_steps' or 'build_steps' stage. + """ + + def run(self, env): + if not env.project.needs_tests(env): + print("Skipping mock server setup because tests disabled for project") + return + + self.env = env + python_path = sys.executable + # # install dependency for mock server + # self.env.shell.exec(python_path, + # '-m', 'pip', 'install', 'h11', 'trio', 'proxy.py', check=True) + # # check the deps can be import correctly + # self.env.shell.exec(python_path, + # '-c', 'import h11, trio', check=True) + + # set cmake flag so mock server tests are enabled + env.project.config['cmake_args'].extend( + ['-DENABLE_MOCK_SERVER_TESTS=ON', '-DASSERT_LOCK_HELD=ON']) + + base_dir = os.path.dirname(os.path.realpath(__file__)) + dir = os.path.join(base_dir, "..", "..", "tests", "mock_server") + process = subprocess.Popen([python_path, "mock_auth_server.py"], cwd=dir) + + @atexit.register + def close_mock_server(): + process.terminate() diff --git a/builder.json b/builder.json index f256c7c2..e8ff5e78 100644 --- a/builder.json +++ b/builder.json @@ -20,5 +20,8 @@ "test_steps": [ "auth-ci-prep", "test" + ], + "pre_build_steps": [ + "mock-server-setup" ] -} +} \ No newline at end of file diff --git a/include/aws/auth/auth.h b/include/aws/auth/auth.h index 7899cb89..fcd50cd0 100644 --- a/include/aws/auth/auth.h +++ b/include/aws/auth/auth.h @@ -52,6 +52,7 @@ enum aws_auth_errors { AWS_AUTH_IMDS_CLIENT_SOURCE_FAILURE, AWS_AUTH_PROFILE_STS_CREDENTIALS_PROVIDER_CYCLE_FAILURE, AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_TOKEN_FILE_PATH, + AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_HOST, AWS_AUTH_ERROR_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_AUTH_PACKAGE_ID) }; diff --git a/source/auth.c b/source/auth.c index 1e8be09e..0261d156 100644 --- a/source/auth.c +++ b/source/auth.c @@ -112,6 +112,9 @@ static struct aws_error_info s_errors[] = { AWS_DEFINE_ERROR_INFO_AUTH( AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_TOKEN_FILE_PATH, "Failed to read the ECS token file specified in the AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE environment variable."), + AWS_DEFINE_ERROR_INFO_AUTH( + AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_HOST, + "Failed to establish connection. The specified host is not allowed. It must be a loopback address, ECS/EKS container host, or use HTTPS."), }; /* clang-format on */ diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index 4f7497cb..ea8b6bae 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ struct aws_credentials_provider_ecs_impl { struct aws_string *path_and_query; struct aws_string *auth_token_file_path; struct aws_string *auth_token; + bool is_https; }; /* @@ -431,6 +433,39 @@ static void s_ecs_query_task_role_credentials(struct aws_credentials_provider_ec } } +static bool s_is_valid_remote_host_ip( + struct aws_credentials_provider_ecs_user_data *ecs_user_data, + struct aws_http_connection *connection) { + struct aws_credentials_provider_ecs_impl *impl = ecs_user_data->ecs_provider->impl; + + if (impl->is_https) { + return true; + } + + bool result = false; + + const struct aws_byte_cursor address = + aws_byte_cursor_from_c_str(aws_http_connection_get_remote_endpoint(connection)->address); + if (aws_is_ipv4(address)) { + const struct aws_byte_cursor ipv4_loopback_address_prefix = aws_byte_cursor_from_c_str("127."); + const struct aws_byte_cursor ecs_container_host_address = aws_byte_cursor_from_c_str("169.254.170.2"); + const struct aws_byte_cursor eks_container_host_address = aws_byte_cursor_from_c_str("169.254.170.23"); + + result |= aws_byte_cursor_starts_with(&address, &ipv4_loopback_address_prefix); + result |= aws_byte_cursor_eq(&address, &ecs_container_host_address); + result |= aws_byte_cursor_eq(&address, &eks_container_host_address); + } else { + // TODO: is this the correct way to compare ip v6 address? + const struct aws_byte_cursor ipv6_loopback_address = aws_byte_cursor_from_c_str("::1"); + const struct aws_byte_cursor eks_container_host_ipv6_address = aws_byte_cursor_from_c_str("fd00:ec2::23"); + + result |= aws_byte_cursor_eq(&address, &ipv6_loopback_address); + result |= aws_byte_cursor_eq(&address, &eks_container_host_ipv6_address); + } + + return result; +} + static void s_ecs_on_acquire_connection(struct aws_http_connection *connection, int error_code, void *user_data) { struct aws_credentials_provider_ecs_user_data *ecs_user_data = user_data; @@ -447,6 +482,19 @@ static void s_ecs_on_acquire_connection(struct aws_http_connection *connection, return; } + if (!s_is_valid_remote_host_ip(ecs_user_data, connection)) { + AWS_LOGF_ERROR( + AWS_LS_AUTH_CREDENTIALS_PROVIDER, + "id=%p: ECS provider failed to establish connection to a valid remote with error %d(%s)", + (void *)ecs_user_data->ecs_provider, + AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_HOST, + aws_error_str(AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_HOST)); + + ecs_user_data->error_code = AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_HOST; + s_ecs_finalize_get_credentials_query(ecs_user_data); + return; + } + ecs_user_data->connection = connection; s_ecs_query_task_role_credentials(ecs_user_data); @@ -555,6 +603,7 @@ struct aws_credentials_provider *aws_credentials_provider_new_ecs( aws_error_debug_str(aws_last_error())); goto on_error; } + impl->is_https = true; } struct aws_socket_options socket_options; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c65161bd..1e5c7742 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -57,6 +57,11 @@ add_test_case(credentials_provider_ecs_no_auth_token_success) add_test_case(credentials_provider_ecs_success_multi_part_doc) add_test_case(credentials_provider_ecs_real_new_destroy) +if(ENABLE_MOCK_SERVER_TESTS) + add_test_case(credentials_provider_ecs_mocked_server_basic_ipv4_success) + add_test_case(credentials_provider_ecs_mocked_server_basic_ipv6_success) +endif() + if(AWS_BUILDING_ON_ECS) add_test_case(credentials_provider_ecs_real_success) endif() diff --git a/tests/credentials_provider_ecs_tests.c b/tests/credentials_provider_ecs_tests.c index fa6d384a..c0ec9cfe 100644 --- a/tests/credentials_provider_ecs_tests.c +++ b/tests/credentials_provider_ecs_tests.c @@ -536,6 +536,124 @@ static int s_credentials_provider_ecs_basic_success(struct aws_allocator *alloca AWS_TEST_CASE(credentials_provider_ecs_basic_success, s_credentials_provider_ecs_basic_success); +static int s_credentials_provider_ecs_mocked_server_basic_ipv6_success(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + s_aws_ecs_tester_init(allocator); + + struct aws_byte_cursor good_response_cursor = aws_byte_cursor_from_string(s_good_response); + aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor); + + struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL); + + struct aws_host_resolver_default_options resolver_options = { + .el_group = el_group, + .max_entries = 8, + }; + struct aws_host_resolver *resolver = aws_host_resolver_new_default(allocator, &resolver_options); + + struct aws_client_bootstrap_options bootstrap_options = { + .event_loop_group = el_group, + .host_resolver = resolver, + }; + struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options); + + struct aws_credentials_provider_ecs_options options = { + .bootstrap = bootstrap, + .shutdown_options = + { + .shutdown_callback = s_on_shutdown_complete, + .shutdown_user_data = NULL, + }, + .host = aws_byte_cursor_from_c_str("0:0:0:0:0:0:0:1"), + .port = 8080, + .path_and_query = aws_byte_cursor_from_c_str("/credentials_provider_ecs_success_response"), + }; + + struct aws_credentials_provider *provider = aws_credentials_provider_new_ecs(allocator, &options); + + aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL); + s_aws_wait_for_credentials_result(); + ASSERT_NOT_NULL(s_tester.credentials); + ASSERT_TRUE(s_tester.error_code == AWS_OP_SUCCESS); + + aws_credentials_provider_release(provider); + s_aws_wait_for_provider_shutdown_callback(); + + aws_client_bootstrap_release(bootstrap); + aws_host_resolver_release(resolver); + aws_event_loop_group_release(el_group); + + s_aws_ecs_tester_cleanup(); + + aws_auth_library_clean_up(); + + return 0; +} + +AWS_TEST_CASE( + credentials_provider_ecs_mocked_server_basic_ipv6_success, + s_credentials_provider_ecs_mocked_server_basic_ipv6_success); + +static int s_credentials_provider_ecs_mocked_server_basic_ipv4_success(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + s_aws_ecs_tester_init(allocator); + + struct aws_byte_cursor good_response_cursor = aws_byte_cursor_from_string(s_good_response); + aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor); + + struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL); + + struct aws_host_resolver_default_options resolver_options = { + .el_group = el_group, + .max_entries = 8, + }; + struct aws_host_resolver *resolver = aws_host_resolver_new_default(allocator, &resolver_options); + + struct aws_client_bootstrap_options bootstrap_options = { + .event_loop_group = el_group, + .host_resolver = resolver, + }; + struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options); + + struct aws_credentials_provider_ecs_options options = { + .bootstrap = bootstrap, + .shutdown_options = + { + .shutdown_callback = s_on_shutdown_complete, + .shutdown_user_data = NULL, + }, + .host = aws_byte_cursor_from_c_str("127.0.0.1"), + .port = 8080, + .path_and_query = aws_byte_cursor_from_c_str("/credentials_provider_ecs_success_response"), + }; + + struct aws_credentials_provider *provider = aws_credentials_provider_new_ecs(allocator, &options); + + aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL); + s_aws_wait_for_credentials_result(); + ASSERT_NOT_NULL(s_tester.credentials); + ASSERT_TRUE(s_tester.error_code == AWS_OP_SUCCESS); + + aws_credentials_provider_release(provider); + s_aws_wait_for_provider_shutdown_callback(); + + aws_client_bootstrap_release(bootstrap); + aws_host_resolver_release(resolver); + aws_event_loop_group_release(el_group); + + s_aws_ecs_tester_cleanup(); + + aws_auth_library_clean_up(); + + return 0; +} + +AWS_TEST_CASE( + credentials_provider_ecs_mocked_server_basic_ipv4_success, + s_credentials_provider_ecs_mocked_server_basic_ipv4_success); + AWS_STATIC_STRING_FROM_LITERAL(s_ecs_creds_env_token_file, "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE"); AWS_STATIC_STRING_FROM_LITERAL(s_ecs_creds_env_token, "AWS_CONTAINER_AUTHORIZATION_TOKEN"); diff --git a/tests/mock_server/credentials_provider_ecs_success_response.json b/tests/mock_server/credentials_provider_ecs_success_response.json new file mode 100644 index 00000000..d082551e --- /dev/null +++ b/tests/mock_server/credentials_provider_ecs_success_response.json @@ -0,0 +1,12 @@ +{ + "response_code": 200, + "headers": { + "Content-type": "keep-alive" + }, + "body": { + "AccessKeyId": "SuccessfulAccessKey", + "SecretAccessKey": "SuccessfulSecret", + "Token": "TokenSuccess", + "Expiration": "2020-02-25T06:03:31Z" + } +} \ No newline at end of file diff --git a/tests/mock_server/mock_auth_server.py b/tests/mock_server/mock_auth_server.py new file mode 100644 index 00000000..785a09bb --- /dev/null +++ b/tests/mock_server/mock_auth_server.py @@ -0,0 +1,45 @@ +import socket +import json +import os +from http.server import HTTPServer, SimpleHTTPRequestHandler + + +class MyHandler(SimpleHTTPRequestHandler): + def do_GET(self): + # Serve a JSON file named after the path + json_file_path = self.path.lstrip('/') # Remove leading slash for correct file path + if json_file_path: # Check if there is a filename in the path + file_path = os.path.join(os.path.dirname(__file__), json_file_path + '.json') + if os.path.isfile(file_path): + with open(file_path, 'r') as file: + try: + data = json.load(file) + self.send_response(data['response_code']) + response_body = json.dumps(data['body']).encode('utf-8') + self.send_header('Content-Type', 'application/json') + self.send_header('Content-Length', str(len(response_body))) + for header, value in data['headers'].items(): + self.send_header(header, value) + self.end_headers() + self.wfile.write(response_body) + except json.JSONDecodeError: + self.send_error(500, "Json Decode Error") + except KeyError as e: + self.send_error(500, f"Malformed JSON structure: missing {str(e)}") + return + self.send_error(404, "File not found") + + + +# Creating an ipv6 server listens to both ipv4 and ipv6 addresses +class HTTPServerV6(HTTPServer): + address_family = socket.AF_INET6 + + +def main(): + server = HTTPServerV6(('::', 8080), MyHandler) + server.serve_forever() + + +if __name__ == '__main__': + main() From bd4562edec705a5842d9d5b14442914b74925ddb Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 11:21:44 -0700 Subject: [PATCH 02/20] fail fast is false --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 711e3eaf..bc8bc348 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,7 @@ jobs: linux-compat: runs-on: ubuntu-20.04 # latest strategy: + fail-fast: false matrix: image: - manylinux1-x64 @@ -40,6 +41,7 @@ jobs: linux-compiler-compat: runs-on: ubuntu-20.04 # latest strategy: + fail-fast: false matrix: compiler: - clang-3 @@ -80,6 +82,7 @@ jobs: windows-vc14: runs-on: windows-2019 # windows-2019 is last env with Visual Studio 2015 (v14.0) strategy: + fail-fast: false matrix: arch: [x86, x64] steps: From 8f0d14e9596fc7e368ec60946957e861dd86e328 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 11:24:12 -0700 Subject: [PATCH 03/20] Fix fail-fast --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc8bc348..53d3e35f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: linux-compat: runs-on: ubuntu-20.04 # latest strategy: - fail-fast: false + fail-fast: false matrix: image: - manylinux1-x64 @@ -41,7 +41,7 @@ jobs: linux-compiler-compat: runs-on: ubuntu-20.04 # latest strategy: - fail-fast: false + fail-fast: false matrix: compiler: - clang-3 @@ -82,7 +82,7 @@ jobs: windows-vc14: runs-on: windows-2019 # windows-2019 is last env with Visual Studio 2015 (v14.0) strategy: - fail-fast: false + fail-fast: false matrix: arch: [x86, x64] steps: From d2cb25cdd9263e0d6ec8765eb7d701b79c546a9d Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 11:37:09 -0700 Subject: [PATCH 04/20] If not mocked --- source/credentials_provider_ecs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index ea8b6bae..be3aa39f 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -468,6 +468,7 @@ static bool s_is_valid_remote_host_ip( static void s_ecs_on_acquire_connection(struct aws_http_connection *connection, int error_code, void *user_data) { struct aws_credentials_provider_ecs_user_data *ecs_user_data = user_data; + struct aws_credentials_provider_ecs_impl *impl = ecs_user_data->ecs_provider->impl; if (connection == NULL) { AWS_LOGF_WARN( @@ -482,7 +483,8 @@ static void s_ecs_on_acquire_connection(struct aws_http_connection *connection, return; } - if (!s_is_valid_remote_host_ip(ecs_user_data, connection)) { + if (impl->function_table == g_aws_credentials_provider_http_function_table && + !s_is_valid_remote_host_ip(ecs_user_data, connection)) { AWS_LOGF_ERROR( AWS_LS_AUTH_CREDENTIALS_PROVIDER, "id=%p: ECS provider failed to establish connection to a valid remote with error %d(%s)", From d2b722e36f184c9f5d004bfb13ec0ac69e597e92 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 11:57:36 -0700 Subject: [PATCH 05/20] Github runners do not support ipv6 tests, so only check for ipv4 --- source/credentials_provider_ecs.c | 3 +-- tests/CMakeLists.txt | 2 +- tests/credentials_provider_ecs_tests.c | 12 ++++++------ tests/mock_server/mock_auth_server.py | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index be3aa39f..bf4a7830 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -482,6 +482,7 @@ static void s_ecs_on_acquire_connection(struct aws_http_connection *connection, s_ecs_finalize_get_credentials_query(ecs_user_data); return; } + ecs_user_data->connection = connection; if (impl->function_table == g_aws_credentials_provider_http_function_table && !s_is_valid_remote_host_ip(ecs_user_data, connection)) { @@ -497,8 +498,6 @@ static void s_ecs_on_acquire_connection(struct aws_http_connection *connection, return; } - ecs_user_data->connection = connection; - s_ecs_query_task_role_credentials(ecs_user_data); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1e5c7742..11d0b21d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -59,7 +59,7 @@ add_test_case(credentials_provider_ecs_real_new_destroy) if(ENABLE_MOCK_SERVER_TESTS) add_test_case(credentials_provider_ecs_mocked_server_basic_ipv4_success) - add_test_case(credentials_provider_ecs_mocked_server_basic_ipv6_success) + add_test_case(credentials_provider_ecs_mocked_server_basic_ipv4_invalid) endif() if(AWS_BUILDING_ON_ECS) diff --git a/tests/credentials_provider_ecs_tests.c b/tests/credentials_provider_ecs_tests.c index c0ec9cfe..bdedea5d 100644 --- a/tests/credentials_provider_ecs_tests.c +++ b/tests/credentials_provider_ecs_tests.c @@ -536,7 +536,7 @@ static int s_credentials_provider_ecs_basic_success(struct aws_allocator *alloca AWS_TEST_CASE(credentials_provider_ecs_basic_success, s_credentials_provider_ecs_basic_success); -static int s_credentials_provider_ecs_mocked_server_basic_ipv6_success(struct aws_allocator *allocator, void *ctx) { +static int s_credentials_provider_ecs_mocked_server_basic_ipv4_invalid(struct aws_allocator *allocator, void *ctx) { (void)ctx; s_aws_ecs_tester_init(allocator); @@ -565,7 +565,7 @@ static int s_credentials_provider_ecs_mocked_server_basic_ipv6_success(struct aw .shutdown_callback = s_on_shutdown_complete, .shutdown_user_data = NULL, }, - .host = aws_byte_cursor_from_c_str("0:0:0:0:0:0:0:1"), + .host = aws_byte_cursor_from_c_str("10.6.129.5"), .port = 8080, .path_and_query = aws_byte_cursor_from_c_str("/credentials_provider_ecs_success_response"), }; @@ -574,8 +574,8 @@ static int s_credentials_provider_ecs_mocked_server_basic_ipv6_success(struct aw aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL); s_aws_wait_for_credentials_result(); - ASSERT_NOT_NULL(s_tester.credentials); - ASSERT_TRUE(s_tester.error_code == AWS_OP_SUCCESS); + ASSERT_NULL(s_tester.credentials); + ASSERT_TRUE(s_tester.error_code == AWS_AUTH_CREDENTIALS_PROVIDER_ECS_INVALID_HOST); aws_credentials_provider_release(provider); s_aws_wait_for_provider_shutdown_callback(); @@ -592,8 +592,8 @@ static int s_credentials_provider_ecs_mocked_server_basic_ipv6_success(struct aw } AWS_TEST_CASE( - credentials_provider_ecs_mocked_server_basic_ipv6_success, - s_credentials_provider_ecs_mocked_server_basic_ipv6_success); + credentials_provider_ecs_mocked_server_basic_ipv4_invalid, + s_credentials_provider_ecs_mocked_server_basic_ipv4_invalid); static int s_credentials_provider_ecs_mocked_server_basic_ipv4_success(struct aws_allocator *allocator, void *ctx) { (void)ctx; diff --git a/tests/mock_server/mock_auth_server.py b/tests/mock_server/mock_auth_server.py index 785a09bb..e2ec2cf5 100644 --- a/tests/mock_server/mock_auth_server.py +++ b/tests/mock_server/mock_auth_server.py @@ -33,11 +33,11 @@ def do_GET(self): # Creating an ipv6 server listens to both ipv4 and ipv6 addresses class HTTPServerV6(HTTPServer): - address_family = socket.AF_INET6 + address_family = socket.AF_INET def main(): - server = HTTPServerV6(('::', 8080), MyHandler) + server = HTTPServerV6(('0.0.0.0', 8080), MyHandler) server.serve_forever() From 9bb9a19056997bc213ef8422716ef923ad003f4b Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 12:55:05 -0700 Subject: [PATCH 06/20] Just use google.com for invalid address --- tests/credentials_provider_ecs_tests.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/credentials_provider_ecs_tests.c b/tests/credentials_provider_ecs_tests.c index bdedea5d..1afdd51d 100644 --- a/tests/credentials_provider_ecs_tests.c +++ b/tests/credentials_provider_ecs_tests.c @@ -565,9 +565,8 @@ static int s_credentials_provider_ecs_mocked_server_basic_ipv4_invalid(struct aw .shutdown_callback = s_on_shutdown_complete, .shutdown_user_data = NULL, }, - .host = aws_byte_cursor_from_c_str("10.6.129.5"), - .port = 8080, - .path_and_query = aws_byte_cursor_from_c_str("/credentials_provider_ecs_success_response"), + .host = aws_byte_cursor_from_c_str("google.com"), + .port = 80, }; struct aws_credentials_provider *provider = aws_credentials_provider_new_ecs(allocator, &options); From 1df8151323b1a21761015e765cd585b01823e0ad Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 13:32:11 -0700 Subject: [PATCH 07/20] Better bootstrap null handling --- source/credentials_provider_ecs.c | 14 ++- tests/credentials_provider_ecs_tests.c | 121 +++++++------------------ 2 files changed, 47 insertions(+), 88 deletions(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index bf4a7830..7b181990 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -454,13 +454,17 @@ static bool s_is_valid_remote_host_ip( result |= aws_byte_cursor_starts_with(&address, &ipv4_loopback_address_prefix); result |= aws_byte_cursor_eq(&address, &ecs_container_host_address); result |= aws_byte_cursor_eq(&address, &eks_container_host_address); - } else { - // TODO: is this the correct way to compare ip v6 address? + } else if (aws_is_ipv6) { const struct aws_byte_cursor ipv6_loopback_address = aws_byte_cursor_from_c_str("::1"); + const struct aws_byte_cursor ipv6_loopback_address_verbose = aws_byte_cursor_from_c_str("0:0:0:0:0:0:0:1"); const struct aws_byte_cursor eks_container_host_ipv6_address = aws_byte_cursor_from_c_str("fd00:ec2::23"); + const struct aws_byte_cursor eks_container_host_ipv6_address_verbose = + aws_byte_cursor_from_c_str("fd00:ec2:0:0:0:0:0:23"); result |= aws_byte_cursor_eq(&address, &ipv6_loopback_address); + result |= aws_byte_cursor_eq(&address, &ipv6_loopback_address_verbose); result |= aws_byte_cursor_eq(&address, &eks_container_host_ipv6_address); + result |= aws_byte_cursor_eq(&address, &eks_container_host_ipv6_address_verbose); } return result; @@ -571,6 +575,12 @@ struct aws_credentials_provider *aws_credentials_provider_new_ecs( struct aws_allocator *allocator, const struct aws_credentials_provider_ecs_options *options) { + if (!options->bootstrap) { + AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "a bootstrap instance must be provided"); + aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); + return NULL; + } + struct aws_credentials_provider *provider = NULL; struct aws_credentials_provider_ecs_impl *impl = NULL; diff --git a/tests/credentials_provider_ecs_tests.c b/tests/credentials_provider_ecs_tests.c index 1afdd51d..6692d933 100644 --- a/tests/credentials_provider_ecs_tests.c +++ b/tests/credentials_provider_ecs_tests.c @@ -39,6 +39,10 @@ struct aws_mock_ecs_tester { uint32_t selected_port; int error_code; + + struct aws_event_loop_group *el_group; + struct aws_host_resolver *host_resolver; + struct aws_client_bootstrap *bootstrap; }; static struct aws_mock_ecs_tester s_tester; @@ -233,6 +237,20 @@ static int s_aws_ecs_tester_init(struct aws_allocator *allocator) { s_tester.is_connection_acquire_successful = true; s_tester.is_request_successful = true; + s_tester.el_group = aws_event_loop_group_new_default(allocator, 1, NULL); + + struct aws_host_resolver_default_options resolver_options = { + .el_group = s_tester.el_group, + .max_entries = 8, + }; + s_tester.host_resolver = aws_host_resolver_new_default(allocator, &resolver_options); + + struct aws_client_bootstrap_options bootstrap_options = { + .event_loop_group = s_tester.el_group, + .host_resolver = s_tester.host_resolver, + }; + s_tester.bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options); + return AWS_OP_SUCCESS; } @@ -243,6 +261,9 @@ static void s_aws_ecs_tester_cleanup(void) { aws_condition_variable_clean_up(&s_tester.signal); aws_mutex_clean_up(&s_tester.lock); aws_credentials_release(s_tester.credentials); + aws_client_bootstrap_release(s_tester.bootstrap); + aws_host_resolver_release(s_tester.host_resolver); + aws_event_loop_group_release(s_tester.el_group); aws_auth_library_clean_up(); } @@ -277,7 +298,7 @@ static int s_credentials_provider_ecs_new_destroy(struct aws_allocator *allocato s_aws_ecs_tester_init(allocator); struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -311,7 +332,7 @@ static int s_credentials_provider_ecs_connect_failure(struct aws_allocator *allo s_tester.is_connection_acquire_successful = false; struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -358,7 +379,7 @@ static int s_credentials_provider_ecs_request_failure(struct aws_allocator *allo s_tester.is_request_successful = false; struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -412,7 +433,7 @@ static int s_credentials_provider_ecs_bad_document_failure(struct aws_allocator aws_array_list_push_back(&s_tester.response_data_callbacks, &bad_document_cursor); struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -515,7 +536,7 @@ static int s_credentials_provider_ecs_basic_success(struct aws_allocator *alloca aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor); struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -544,22 +565,8 @@ static int s_credentials_provider_ecs_mocked_server_basic_ipv4_invalid(struct aw struct aws_byte_cursor good_response_cursor = aws_byte_cursor_from_string(s_good_response); aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor); - struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL); - - struct aws_host_resolver_default_options resolver_options = { - .el_group = el_group, - .max_entries = 8, - }; - struct aws_host_resolver *resolver = aws_host_resolver_new_default(allocator, &resolver_options); - - struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = el_group, - .host_resolver = resolver, - }; - struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options); - struct aws_credentials_provider_ecs_options options = { - .bootstrap = bootstrap, + .bootstrap = s_tester.bootstrap, .shutdown_options = { .shutdown_callback = s_on_shutdown_complete, @@ -579,10 +586,6 @@ static int s_credentials_provider_ecs_mocked_server_basic_ipv4_invalid(struct aw aws_credentials_provider_release(provider); s_aws_wait_for_provider_shutdown_callback(); - aws_client_bootstrap_release(bootstrap); - aws_host_resolver_release(resolver); - aws_event_loop_group_release(el_group); - s_aws_ecs_tester_cleanup(); aws_auth_library_clean_up(); @@ -602,22 +605,8 @@ static int s_credentials_provider_ecs_mocked_server_basic_ipv4_success(struct aw struct aws_byte_cursor good_response_cursor = aws_byte_cursor_from_string(s_good_response); aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor); - struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL); - - struct aws_host_resolver_default_options resolver_options = { - .el_group = el_group, - .max_entries = 8, - }; - struct aws_host_resolver *resolver = aws_host_resolver_new_default(allocator, &resolver_options); - - struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = el_group, - .host_resolver = resolver, - }; - struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options); - struct aws_credentials_provider_ecs_options options = { - .bootstrap = bootstrap, + .bootstrap = s_tester.bootstrap, .shutdown_options = { .shutdown_callback = s_on_shutdown_complete, @@ -638,10 +627,6 @@ static int s_credentials_provider_ecs_mocked_server_basic_ipv4_success(struct aw aws_credentials_provider_release(provider); s_aws_wait_for_provider_shutdown_callback(); - aws_client_bootstrap_release(bootstrap); - aws_host_resolver_release(resolver); - aws_event_loop_group_release(el_group); - s_aws_ecs_tester_cleanup(); aws_auth_library_clean_up(); @@ -675,7 +660,7 @@ static int s_credentials_provider_ecs_basic_success_token_file(struct aws_alloca struct aws_byte_cursor good_response_cursor = aws_byte_cursor_from_string(s_good_response); aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor); struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -731,7 +716,7 @@ static int s_credentials_provider_ecs_basic_success_token_env(struct aws_allocat struct aws_byte_cursor auth_token_cursor = aws_byte_cursor_from_string(auth_token); aws_set_environment_value(s_ecs_creds_env_token, auth_token); struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -771,7 +756,7 @@ static int s_credentials_provider_ecs_basic_success_token_env_with_parameter_tok struct aws_byte_cursor expected_token_cursor = aws_byte_cursor_from_c_str("t-token-4321-xyz"); struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -807,7 +792,7 @@ static int s_credentials_provider_ecs_no_auth_token_success(struct aws_allocator aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor); struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -845,7 +830,7 @@ static int s_credentials_provider_ecs_success_multi_part_doc(struct aws_allocato aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor3); struct aws_credentials_provider_ecs_options options = { - .bootstrap = NULL, + .bootstrap = s_tester.bootstrap, .function_table = &s_mock_function_table, .shutdown_options = { @@ -904,22 +889,8 @@ static int s_credentials_provider_ecs_real_new_destroy(struct aws_allocator *all s_aws_ecs_tester_init(allocator); - struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL); - - struct aws_host_resolver_default_options resolver_options = { - .el_group = el_group, - .max_entries = 8, - }; - struct aws_host_resolver *resolver = aws_host_resolver_new_default(allocator, &resolver_options); - - struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = el_group, - .host_resolver = resolver, - }; - struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options); - struct aws_credentials_provider_ecs_options options = { - .bootstrap = bootstrap, + .bootstrap = s_tester.bootstrap, .shutdown_options = { .shutdown_callback = s_on_shutdown_complete, @@ -940,10 +911,6 @@ static int s_credentials_provider_ecs_real_new_destroy(struct aws_allocator *all s_aws_wait_for_provider_shutdown_callback(); - aws_client_bootstrap_release(bootstrap); - aws_host_resolver_release(resolver); - aws_event_loop_group_release(el_group); - s_aws_ecs_tester_cleanup(); aws_auth_library_clean_up(); @@ -960,22 +927,8 @@ static int s_credentials_provider_ecs_real_success(struct aws_allocator *allocat s_aws_ecs_tester_init(allocator); - struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL); - - struct aws_host_resolver_default_options resolver_options = { - .el_group = el_group, - .max_entries = 8, - }; - struct aws_host_resolver *resolver = aws_host_resolver_new_default(allocator, &resolver_options); - - struct aws_client_bootstrap_options bootstrap_options = { - .event_loop_group = el_group, - .host_resolver = resolver, - }; - struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options); - struct aws_credentials_provider_ecs_options options = { - .bootstrap = bootstrap, + .bootstrap = s_tester.bootstrap, .shutdown_options = { .shutdown_callback = s_on_shutdown_complete, @@ -1002,10 +955,6 @@ static int s_credentials_provider_ecs_real_success(struct aws_allocator *allocat s_aws_ecs_tester_cleanup(); - aws_client_bootstrap_release(bootstrap); - aws_host_resolver_release(resolver); - aws_event_loop_group_release(el_group); - aws_auth_library_clean_up(); return 0; From a3fe1854bdfa1c917d469b9fb600c965ec10acf1 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 13:34:27 -0700 Subject: [PATCH 08/20] rename functions --- source/credentials_provider_ecs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index 7b181990..252d4cd5 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -446,7 +446,7 @@ static bool s_is_valid_remote_host_ip( const struct aws_byte_cursor address = aws_byte_cursor_from_c_str(aws_http_connection_get_remote_endpoint(connection)->address); - if (aws_is_ipv4(address)) { + if (aws_host_utils_is_ipv4(address)) { const struct aws_byte_cursor ipv4_loopback_address_prefix = aws_byte_cursor_from_c_str("127."); const struct aws_byte_cursor ecs_container_host_address = aws_byte_cursor_from_c_str("169.254.170.2"); const struct aws_byte_cursor eks_container_host_address = aws_byte_cursor_from_c_str("169.254.170.23"); @@ -454,7 +454,7 @@ static bool s_is_valid_remote_host_ip( result |= aws_byte_cursor_starts_with(&address, &ipv4_loopback_address_prefix); result |= aws_byte_cursor_eq(&address, &ecs_container_host_address); result |= aws_byte_cursor_eq(&address, &eks_container_host_address); - } else if (aws_is_ipv6) { + } else if (aws_host_utils_is_ipv6) { const struct aws_byte_cursor ipv6_loopback_address = aws_byte_cursor_from_c_str("::1"); const struct aws_byte_cursor ipv6_loopback_address_verbose = aws_byte_cursor_from_c_str("0:0:0:0:0:0:0:1"); const struct aws_byte_cursor eks_container_host_ipv6_address = aws_byte_cursor_from_c_str("fd00:ec2::23"); From ea816ae519987b2bf5ff0796b79b1f16d6784774 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 13:39:04 -0700 Subject: [PATCH 09/20] fix typo --- source/credentials_provider_ecs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index 252d4cd5..0105821d 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -454,7 +454,7 @@ static bool s_is_valid_remote_host_ip( result |= aws_byte_cursor_starts_with(&address, &ipv4_loopback_address_prefix); result |= aws_byte_cursor_eq(&address, &ecs_container_host_address); result |= aws_byte_cursor_eq(&address, &eks_container_host_address); - } else if (aws_host_utils_is_ipv6) { + } else if (aws_host_utils_is_ipv6(address)) { const struct aws_byte_cursor ipv6_loopback_address = aws_byte_cursor_from_c_str("::1"); const struct aws_byte_cursor ipv6_loopback_address_verbose = aws_byte_cursor_from_c_str("0:0:0:0:0:0:0:1"); const struct aws_byte_cursor eks_container_host_ipv6_address = aws_byte_cursor_from_c_str("fd00:ec2::23"); From 62b6733138d94cd90486b9cecbbcf5ab1361ca8b Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 13:43:15 -0700 Subject: [PATCH 10/20] Use different port from s3 mock server --- tests/credentials_provider_ecs_tests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/credentials_provider_ecs_tests.c b/tests/credentials_provider_ecs_tests.c index 6692d933..2f46fc46 100644 --- a/tests/credentials_provider_ecs_tests.c +++ b/tests/credentials_provider_ecs_tests.c @@ -613,7 +613,7 @@ static int s_credentials_provider_ecs_mocked_server_basic_ipv4_success(struct aw .shutdown_user_data = NULL, }, .host = aws_byte_cursor_from_c_str("127.0.0.1"), - .port = 8080, + .port = 7070, .path_and_query = aws_byte_cursor_from_c_str("/credentials_provider_ecs_success_response"), }; From 1eaf146fdf59e6a41cd9b833fe912072b03fa153 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 13:46:49 -0700 Subject: [PATCH 11/20] fix typo --- source/credentials_provider_ecs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index 0105821d..21a46986 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -454,7 +454,7 @@ static bool s_is_valid_remote_host_ip( result |= aws_byte_cursor_starts_with(&address, &ipv4_loopback_address_prefix); result |= aws_byte_cursor_eq(&address, &ecs_container_host_address); result |= aws_byte_cursor_eq(&address, &eks_container_host_address); - } else if (aws_host_utils_is_ipv6(address)) { + } else if (aws_host_utils_is_ipv6(address, false)) { const struct aws_byte_cursor ipv6_loopback_address = aws_byte_cursor_from_c_str("::1"); const struct aws_byte_cursor ipv6_loopback_address_verbose = aws_byte_cursor_from_c_str("0:0:0:0:0:0:0:1"); const struct aws_byte_cursor eks_container_host_ipv6_address = aws_byte_cursor_from_c_str("fd00:ec2::23"); From b7edcec3a8a68520c0391fd7994c1959054e68e4 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 14:05:04 -0700 Subject: [PATCH 12/20] update server --- tests/mock_server/mock_auth_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mock_server/mock_auth_server.py b/tests/mock_server/mock_auth_server.py index e2ec2cf5..cbce3e13 100644 --- a/tests/mock_server/mock_auth_server.py +++ b/tests/mock_server/mock_auth_server.py @@ -37,7 +37,7 @@ class HTTPServerV6(HTTPServer): def main(): - server = HTTPServerV6(('0.0.0.0', 8080), MyHandler) + server = HTTPServerV6(('0.0.0.0', 7070), MyHandler) server.serve_forever() From e10cc80fc39ca4d48234cdcb41cf80039d79dc2c Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 14:27:47 -0700 Subject: [PATCH 13/20] different mock config name --- .builder/action/mock_server_setup.py | 2 +- CMakeLists.txt | 2 ++ tests/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.builder/action/mock_server_setup.py b/.builder/action/mock_server_setup.py index d9b1def0..10c9ab41 100644 --- a/.builder/action/mock_server_setup.py +++ b/.builder/action/mock_server_setup.py @@ -33,7 +33,7 @@ def run(self, env): # set cmake flag so mock server tests are enabled env.project.config['cmake_args'].extend( - ['-DENABLE_MOCK_SERVER_TESTS=ON', '-DASSERT_LOCK_HELD=ON']) + ['-DENABLE_AUTH_MOCK_SERVER_TESTS=ON', '-DASSERT_LOCK_HELD=ON']) base_dir = os.path.dirname(os.path.realpath(__file__)) dir = os.path.join(base_dir, "..", "..", "tests", "mock_server") diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f43c289..026657b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,8 @@ include(AwsFindPackage) option(BUILD_RELOCATABLE_BINARIES "Build Relocatable Binaries, this will turn off features that will fail on older kernels than used for the build." OFF) +option(ENABLE_AUTH_MOCK_SERVER_TESTS "Whether to run the integration tests that rely on pre-configured mock server" OFF) + file(GLOB AWS_AUTH_ROOT_HEADERS "include/aws/auth/*.h" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 11d0b21d..815e3ecb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -57,7 +57,7 @@ add_test_case(credentials_provider_ecs_no_auth_token_success) add_test_case(credentials_provider_ecs_success_multi_part_doc) add_test_case(credentials_provider_ecs_real_new_destroy) -if(ENABLE_MOCK_SERVER_TESTS) +if(ENABLE_AUTH_MOCK_SERVER_TESTS) add_test_case(credentials_provider_ecs_mocked_server_basic_ipv4_success) add_test_case(credentials_provider_ecs_mocked_server_basic_ipv4_invalid) endif() From 2e4a21218cb2f234df8114cc93ae878cf252147b Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Fri, 19 Apr 2024 15:00:13 -0700 Subject: [PATCH 14/20] remove comments --- .builder/action/mock_server_setup.py | 6 ------ builder.json | 3 ++- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.builder/action/mock_server_setup.py b/.builder/action/mock_server_setup.py index 10c9ab41..4eb95753 100644 --- a/.builder/action/mock_server_setup.py +++ b/.builder/action/mock_server_setup.py @@ -24,12 +24,6 @@ def run(self, env): self.env = env python_path = sys.executable - # # install dependency for mock server - # self.env.shell.exec(python_path, - # '-m', 'pip', 'install', 'h11', 'trio', 'proxy.py', check=True) - # # check the deps can be import correctly - # self.env.shell.exec(python_path, - # '-c', 'import h11, trio', check=True) # set cmake flag so mock server tests are enabled env.project.config['cmake_args'].extend( diff --git a/builder.json b/builder.json index e8ff5e78..d1463dd2 100644 --- a/builder.json +++ b/builder.json @@ -24,4 +24,5 @@ "pre_build_steps": [ "mock-server-setup" ] -} \ No newline at end of file +} + From 228fb27e69cc2dca2b71126d60cb619fba987cf8 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Mon, 22 Apr 2024 11:01:59 -0700 Subject: [PATCH 15/20] Add comment --- source/credentials_provider_ecs.c | 1 + .../mock_server/credentials_provider_ecs_success_response.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index 21a46986..9efc02a2 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -488,6 +488,7 @@ static void s_ecs_on_acquire_connection(struct aws_http_connection *connection, } ecs_user_data->connection = connection; + /* validate ip address if the connection manager is not mocked */ if (impl->function_table == g_aws_credentials_provider_http_function_table && !s_is_valid_remote_host_ip(ecs_user_data, connection)) { AWS_LOGF_ERROR( diff --git a/tests/mock_server/credentials_provider_ecs_success_response.json b/tests/mock_server/credentials_provider_ecs_success_response.json index d082551e..bac64ae6 100644 --- a/tests/mock_server/credentials_provider_ecs_success_response.json +++ b/tests/mock_server/credentials_provider_ecs_success_response.json @@ -9,4 +9,5 @@ "Token": "TokenSuccess", "Expiration": "2020-02-25T06:03:31Z" } -} \ No newline at end of file +} + From 89e2d2c27ae7ceff84fe6c7a591169b706c6e147 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Mon, 22 Apr 2024 11:04:03 -0700 Subject: [PATCH 16/20] Add comment again --- source/credentials_provider_ecs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index 9efc02a2..adf29006 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -455,6 +455,7 @@ static bool s_is_valid_remote_host_ip( result |= aws_byte_cursor_eq(&address, &ecs_container_host_address); result |= aws_byte_cursor_eq(&address, &eks_container_host_address); } else if (aws_host_utils_is_ipv6(address, false)) { + /* Check for both the short form and long form of an IPv6 address to be safe. */ const struct aws_byte_cursor ipv6_loopback_address = aws_byte_cursor_from_c_str("::1"); const struct aws_byte_cursor ipv6_loopback_address_verbose = aws_byte_cursor_from_c_str("0:0:0:0:0:0:0:1"); const struct aws_byte_cursor eks_container_host_ipv6_address = aws_byte_cursor_from_c_str("fd00:ec2::23"); From 3c5fa1c782f37c3c8a1142da9b2d7ddacb620af9 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Mon, 22 Apr 2024 11:14:01 -0700 Subject: [PATCH 17/20] Add comments regarding ip address rules --- include/aws/auth/credentials.h | 5 +++++ source/credentials_provider_ecs.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/aws/auth/credentials.h b/include/aws/auth/credentials.h index 0c0ca12e..ddaba8c5 100644 --- a/include/aws/auth/credentials.h +++ b/include/aws/auth/credentials.h @@ -241,6 +241,11 @@ struct aws_credentials_provider_imds_options { * TODO: Support AWS_CONTAINER_CREDENTIALS_RELATIVE_URI and AWS_CONTAINER_CREDENTIALS_FULL_URI * parameters. * + * The host must use either HTTPS or the resolved IP address must satisfy one of the following: + * 1. within the loopback CIDR (IPv4 127.0.0.0/8, IPv6 ::1/128) + * 2. corresponds to the ECS container host 169.254.170.2 + * 3. corresponds to the EKS container host IPs (IPv4 169.254.170.23, IPv6 fd00:ec2::23) + * * For the Authorization token, there are three ways (in order of priority). * 1. auth_token parameter * 2. AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE (env var which contains absolute path to the token file. The file will be diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index adf29006..da00848e 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -432,7 +432,12 @@ static void s_ecs_query_task_role_credentials(struct aws_credentials_provider_ec s_ecs_finalize_get_credentials_query(ecs_user_data); } } - +/* + * The host must use either HTTPS or the resolved IP address must satisfy one of the following: + * 1. within the loopback CIDR (IPv4 127.0.0.0/8, IPv6 ::1/128) + * 2. corresponds to the ECS container host 169.254.170.2 + * 3. corresponds to the EKS container host IPs (IPv4 169.254.170.23, IPv6 fd00:ec2::23) + */ static bool s_is_valid_remote_host_ip( struct aws_credentials_provider_ecs_user_data *ecs_user_data, struct aws_http_connection *connection) { From ec434c24ffe894c02dca0b11638574e20ac13519 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Mon, 22 Apr 2024 11:22:01 -0700 Subject: [PATCH 18/20] Add a todo for ipv6 --- tests/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 815e3ecb..7abc6df0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -58,6 +58,7 @@ add_test_case(credentials_provider_ecs_success_multi_part_doc) add_test_case(credentials_provider_ecs_real_new_destroy) if(ENABLE_AUTH_MOCK_SERVER_TESTS) + # TODO: Add IPv6 tests when the Github runner support it. See: https://github.com/actions/runner-images/issues/668 add_test_case(credentials_provider_ecs_mocked_server_basic_ipv4_success) add_test_case(credentials_provider_ecs_mocked_server_basic_ipv4_invalid) endif() From f99dce18367980198f00cf01a3b17dbe71079969 Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Mon, 22 Apr 2024 13:16:33 -0700 Subject: [PATCH 19/20] Log the remote endpoint ip address --- source/credentials_provider_ecs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index da00848e..3afb1c5c 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -451,6 +451,11 @@ static bool s_is_valid_remote_host_ip( const struct aws_byte_cursor address = aws_byte_cursor_from_c_str(aws_http_connection_get_remote_endpoint(connection)->address); + AWS_LOGF_INFO( + AWS_LS_AUTH_CREDENTIALS_PROVIDER, + "id=%p: the ip address of connected remove endpoint is " PRInSTR "", + (void *)ecs_user_data->ecs_provider, + AWS_BYTE_CURSOR_PRI(address)); if (aws_host_utils_is_ipv4(address)) { const struct aws_byte_cursor ipv4_loopback_address_prefix = aws_byte_cursor_from_c_str("127."); const struct aws_byte_cursor ecs_container_host_address = aws_byte_cursor_from_c_str("169.254.170.2"); From c3cae4235c3a3e94e0c3e585e31452f7cf65b4cb Mon Sep 17 00:00:00 2001 From: Waqar Ahmed Khan Date: Tue, 7 May 2024 13:31:47 -0700 Subject: [PATCH 20/20] Update source/credentials_provider_ecs.c Co-authored-by: Michael Graeb --- source/credentials_provider_ecs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/credentials_provider_ecs.c b/source/credentials_provider_ecs.c index 3afb1c5c..c38b25c2 100644 --- a/source/credentials_provider_ecs.c +++ b/source/credentials_provider_ecs.c @@ -464,6 +464,7 @@ static bool s_is_valid_remote_host_ip( result |= aws_byte_cursor_starts_with(&address, &ipv4_loopback_address_prefix); result |= aws_byte_cursor_eq(&address, &ecs_container_host_address); result |= aws_byte_cursor_eq(&address, &eks_container_host_address); + } else if (aws_host_utils_is_ipv6(address, false)) { /* Check for both the short form and long form of an IPv6 address to be safe. */ const struct aws_byte_cursor ipv6_loopback_address = aws_byte_cursor_from_c_str("::1");