1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 
6 #include <aws/testing/aws_test_harness.h>
7 
8 #include "shared_credentials_test_definitions.h"
9 #include <aws/auth/credentials.h>
10 #include <aws/auth/private/credentials_utils.h>
11 #include <aws/common/clock.h>
12 #include <aws/common/condition_variable.h>
13 #include <aws/common/date_time.h>
14 #include <aws/common/environment.h>
15 #include <aws/common/string.h>
16 #include <aws/common/thread.h>
17 #include <aws/http/request_response.h>
18 #include <aws/http/status_code.h>
19 #include <aws/io/channel_bootstrap.h>
20 #include <aws/io/event_loop.h>
21 #include <aws/io/logging.h>
22 #include <aws/io/socket.h>
23 #include <aws/io/stream.h>
24 #include <aws/io/tls_channel_handler.h>
25 
26 static struct aws_mock_sts_web_identity_tester {
27     struct aws_tls_ctx *tls_ctx;
28 
29     struct aws_byte_buf request_body;
30 
31     struct aws_array_list response_data_callbacks;
32     bool is_connection_acquire_successful;
33     bool is_request_successful;
34 
35     struct aws_mutex lock;
36     struct aws_condition_variable signal;
37 
38     struct aws_credentials *credentials;
39     bool has_received_credentials_callback;
40     bool has_received_shutdown_callback;
41 
42     int attempts;
43     int response_code;
44     int error_code;
45 } s_tester;
46 
s_on_shutdown_complete(void * user_data)47 static void s_on_shutdown_complete(void *user_data) {
48     (void)user_data;
49 
50     aws_mutex_lock(&s_tester.lock);
51     s_tester.has_received_shutdown_callback = true;
52     aws_mutex_unlock(&s_tester.lock);
53 
54     aws_condition_variable_notify_one(&s_tester.signal);
55 }
56 
s_has_tester_received_shutdown_callback(void * user_data)57 static bool s_has_tester_received_shutdown_callback(void *user_data) {
58     (void)user_data;
59 
60     return s_tester.has_received_shutdown_callback;
61 }
62 
s_aws_wait_for_provider_shutdown_callback(void)63 static void s_aws_wait_for_provider_shutdown_callback(void) {
64     aws_mutex_lock(&s_tester.lock);
65     aws_condition_variable_wait_pred(&s_tester.signal, &s_tester.lock, s_has_tester_received_shutdown_callback, NULL);
66     aws_mutex_unlock(&s_tester.lock);
67 }
68 
69 struct mock_connection_manager {
70     struct aws_allocator *allocator;
71     aws_http_connection_manager_shutdown_complete_fn *shutdown_complete_callback;
72     void *shutdown_complete_user_data;
73 };
74 
s_aws_http_connection_manager_new_mock(struct aws_allocator * allocator,struct aws_http_connection_manager_options * options)75 static struct aws_http_connection_manager *s_aws_http_connection_manager_new_mock(
76     struct aws_allocator *allocator,
77     struct aws_http_connection_manager_options *options) {
78 
79     struct mock_connection_manager *mock_manager = aws_mem_calloc(allocator, 1, sizeof(struct mock_connection_manager));
80     mock_manager->allocator = allocator;
81     mock_manager->shutdown_complete_callback = options->shutdown_complete_callback;
82     mock_manager->shutdown_complete_user_data = options->shutdown_complete_user_data;
83     return (struct aws_http_connection_manager *)mock_manager;
84 }
85 
s_aws_http_connection_manager_release_mock(struct aws_http_connection_manager * manager)86 static void s_aws_http_connection_manager_release_mock(struct aws_http_connection_manager *manager) {
87     struct mock_connection_manager *mock_manager = (struct mock_connection_manager *)manager;
88     mock_manager->shutdown_complete_callback(mock_manager->shutdown_complete_user_data);
89     aws_mem_release(mock_manager->allocator, mock_manager);
90 }
91 
s_aws_http_connection_manager_acquire_connection_mock(struct aws_http_connection_manager * manager,aws_http_connection_manager_on_connection_setup_fn * callback,void * user_data)92 static void s_aws_http_connection_manager_acquire_connection_mock(
93     struct aws_http_connection_manager *manager,
94     aws_http_connection_manager_on_connection_setup_fn *callback,
95     void *user_data) {
96 
97     (void)manager;
98     (void)callback;
99     (void)user_data;
100 
101     if (s_tester.is_connection_acquire_successful) {
102         callback((struct aws_http_connection *)1, AWS_OP_SUCCESS, user_data);
103     } else {
104         aws_raise_error(AWS_ERROR_HTTP_UNKNOWN);
105         callback(NULL, AWS_OP_ERR, user_data);
106     }
107 }
108 
s_aws_http_connection_manager_release_connection_mock(struct aws_http_connection_manager * manager,struct aws_http_connection * connection)109 static int s_aws_http_connection_manager_release_connection_mock(
110     struct aws_http_connection_manager *manager,
111     struct aws_http_connection *connection) {
112 
113     (void)manager;
114     (void)connection;
115 
116     return AWS_OP_SUCCESS;
117 }
118 
s_invoke_mock_request_callbacks(const struct aws_http_make_request_options * options,struct aws_array_list * data_callbacks,bool is_request_successful)119 static void s_invoke_mock_request_callbacks(
120     const struct aws_http_make_request_options *options,
121     struct aws_array_list *data_callbacks,
122     bool is_request_successful) {
123 
124     size_t data_callback_count = aws_array_list_length(data_callbacks);
125 
126     struct aws_http_header headers[1];
127     AWS_ZERO_ARRAY(headers);
128 
129     headers[0].name = aws_byte_cursor_from_c_str("some-header");
130     headers[0].value = aws_byte_cursor_from_c_str("value");
131     options->on_response_headers(
132         (struct aws_http_stream *)1, AWS_HTTP_HEADER_BLOCK_MAIN, headers, 1, options->user_data);
133 
134     if (options->on_response_header_block_done) {
135         options->on_response_header_block_done(
136             (struct aws_http_stream *)1, data_callback_count > 0, options->user_data);
137     }
138 
139     for (size_t i = 0; i < data_callback_count; ++i) {
140         struct aws_byte_cursor data_callback_cursor;
141         if (aws_array_list_get_at(data_callbacks, &data_callback_cursor, i)) {
142             continue;
143         }
144 
145         options->on_response_body((struct aws_http_stream *)1, &data_callback_cursor, options->user_data);
146     }
147 
148     options->on_complete(
149         (struct aws_http_stream *)1,
150         is_request_successful ? AWS_ERROR_SUCCESS : AWS_ERROR_HTTP_UNKNOWN,
151         options->user_data);
152 }
153 
s_aws_http_connection_make_request_mock(struct aws_http_connection * client_connection,const struct aws_http_make_request_options * options)154 static struct aws_http_stream *s_aws_http_connection_make_request_mock(
155     struct aws_http_connection *client_connection,
156     const struct aws_http_make_request_options *options) {
157 
158     (void)client_connection;
159     (void)options;
160 
161     struct aws_byte_cursor path;
162     AWS_ZERO_STRUCT(path);
163     struct aws_input_stream *body_stream = aws_http_message_get_body_stream(options->request);
164     struct aws_allocator *allocator = s_tester.request_body.allocator;
165     aws_byte_buf_clean_up(&s_tester.request_body);
166     aws_byte_buf_init(&s_tester.request_body, allocator, 256);
167     aws_input_stream_read(body_stream, &s_tester.request_body);
168     s_invoke_mock_request_callbacks(options, &s_tester.response_data_callbacks, s_tester.is_request_successful);
169 
170     s_tester.attempts++;
171     return (struct aws_http_stream *)1;
172 }
173 
s_aws_http_stream_activate_mock(struct aws_http_stream * stream)174 static int s_aws_http_stream_activate_mock(struct aws_http_stream *stream) {
175     (void)stream;
176     return AWS_OP_SUCCESS;
177 }
178 
s_aws_http_stream_get_incoming_response_status_mock(const struct aws_http_stream * stream,int * out_status_code)179 static int s_aws_http_stream_get_incoming_response_status_mock(
180     const struct aws_http_stream *stream,
181     int *out_status_code) {
182     (void)stream;
183 
184     if (s_tester.response_code) {
185         *out_status_code = s_tester.response_code;
186     } else {
187         *out_status_code = AWS_HTTP_STATUS_CODE_200_OK;
188     }
189 
190     return AWS_OP_SUCCESS;
191 }
192 
s_aws_http_stream_release_mock(struct aws_http_stream * stream)193 static void s_aws_http_stream_release_mock(struct aws_http_stream *stream) {
194     (void)stream;
195 }
196 
s_aws_http_connection_close_mock(struct aws_http_connection * connection)197 static void s_aws_http_connection_close_mock(struct aws_http_connection *connection) {
198     (void)connection;
199 }
200 
s_aws_http_stream_get_connection_mock(const struct aws_http_stream * stream)201 static struct aws_http_connection *s_aws_http_stream_get_connection_mock(const struct aws_http_stream *stream) {
202     (void)stream;
203     return (struct aws_http_connection *)1;
204 }
205 
206 static struct aws_auth_http_system_vtable s_mock_function_table = {
207     .aws_http_connection_manager_new = s_aws_http_connection_manager_new_mock,
208     .aws_http_connection_manager_release = s_aws_http_connection_manager_release_mock,
209     .aws_http_connection_manager_acquire_connection = s_aws_http_connection_manager_acquire_connection_mock,
210     .aws_http_connection_manager_release_connection = s_aws_http_connection_manager_release_connection_mock,
211     .aws_http_connection_make_request = s_aws_http_connection_make_request_mock,
212     .aws_http_stream_activate = s_aws_http_stream_activate_mock,
213     .aws_http_stream_get_connection = s_aws_http_stream_get_connection_mock,
214     .aws_http_stream_get_incoming_response_status = s_aws_http_stream_get_incoming_response_status_mock,
215     .aws_http_stream_release = s_aws_http_stream_release_mock,
216     .aws_http_connection_close = s_aws_http_connection_close_mock};
217 
218 AWS_STATIC_STRING_FROM_LITERAL(s_sts_web_identity_foo_profile, "foo");
219 AWS_STATIC_STRING_FROM_LITERAL(s_sts_web_identity_region_env, "AWS_DEFAULT_REGION");
220 AWS_STATIC_STRING_FROM_LITERAL(s_sts_web_identity_role_arn_env, "AWS_ROLE_ARN");
221 AWS_STATIC_STRING_FROM_LITERAL(s_sts_web_identity_role_session_name_env, "AWS_ROLE_SESSION_NAME");
222 AWS_STATIC_STRING_FROM_LITERAL(s_sts_web_identity_token_file_path_env, "AWS_WEB_IDENTITY_TOKEN_FILE");
223 AWS_STATIC_STRING_FROM_LITERAL(s_sts_web_identity_token_contents, "my-test-token-contents-123-abc-xyz");
224 
s_aws_sts_web_identity_test_unset_env_parameters(void)225 static int s_aws_sts_web_identity_test_unset_env_parameters(void) {
226     ASSERT_TRUE(aws_unset_environment_value(s_sts_web_identity_region_env) == AWS_OP_SUCCESS);
227     ASSERT_TRUE(aws_unset_environment_value(s_sts_web_identity_role_arn_env) == AWS_OP_SUCCESS);
228     ASSERT_TRUE(aws_unset_environment_value(s_sts_web_identity_role_session_name_env) == AWS_OP_SUCCESS);
229     ASSERT_TRUE(aws_unset_environment_value(s_sts_web_identity_token_file_path_env) == AWS_OP_SUCCESS);
230 
231     return AWS_OP_SUCCESS;
232 }
233 
s_aws_sts_web_identity_test_init_env_parameters(struct aws_allocator * allocator,const char * region,const char * role_arn,const char * role_session_name,const char * web_identity_token_file)234 static int s_aws_sts_web_identity_test_init_env_parameters(
235     struct aws_allocator *allocator,
236     const char *region,
237     const char *role_arn,
238     const char *role_session_name,
239     const char *web_identity_token_file) {
240 
241     struct aws_string *region_str = aws_string_new_from_c_str(allocator, region);
242     ASSERT_TRUE(region_str != NULL);
243     ASSERT_TRUE(aws_set_environment_value(s_sts_web_identity_region_env, region_str) == AWS_OP_SUCCESS);
244     aws_string_destroy(region_str);
245 
246     struct aws_string *role_arn_str = aws_string_new_from_c_str(allocator, role_arn);
247     ASSERT_TRUE(role_arn_str != NULL);
248     ASSERT_TRUE(aws_set_environment_value(s_sts_web_identity_role_arn_env, role_arn_str) == AWS_OP_SUCCESS);
249     aws_string_destroy(role_arn_str);
250 
251     struct aws_string *role_session_name_str = aws_string_new_from_c_str(allocator, role_session_name);
252     ASSERT_TRUE(role_session_name_str != NULL);
253     ASSERT_TRUE(
254         aws_set_environment_value(s_sts_web_identity_role_session_name_env, role_session_name_str) == AWS_OP_SUCCESS);
255     aws_string_destroy(role_session_name_str);
256 
257     struct aws_string *web_identity_token_file_str = aws_string_new_from_c_str(allocator, web_identity_token_file);
258     ASSERT_TRUE(web_identity_token_file_str != NULL);
259     ASSERT_TRUE(
260         aws_set_environment_value(s_sts_web_identity_token_file_path_env, web_identity_token_file_str) ==
261         AWS_OP_SUCCESS);
262     aws_string_destroy(web_identity_token_file_str);
263 
264     return AWS_OP_SUCCESS;
265 }
266 
s_aws_sts_web_identity_test_init_config_profile(struct aws_allocator * allocator,const struct aws_string * config_contents)267 static int s_aws_sts_web_identity_test_init_config_profile(
268     struct aws_allocator *allocator,
269     const struct aws_string *config_contents) {
270 
271     struct aws_string *config_file_path_str = aws_create_process_unique_file_name(allocator);
272     ASSERT_TRUE(config_file_path_str != NULL);
273     ASSERT_TRUE(aws_create_profile_file(config_file_path_str, config_contents) == AWS_OP_SUCCESS);
274 
275     ASSERT_TRUE(
276         aws_set_environment_value(s_default_config_path_env_variable_name, config_file_path_str) == AWS_OP_SUCCESS);
277 
278     ASSERT_TRUE(
279         aws_set_environment_value(s_default_profile_env_variable_name, s_sts_web_identity_foo_profile) ==
280         AWS_OP_SUCCESS);
281 
282     aws_string_destroy(config_file_path_str);
283     return AWS_OP_SUCCESS;
284 }
285 
s_aws_sts_web_identity_tester_init(struct aws_allocator * allocator)286 static int s_aws_sts_web_identity_tester_init(struct aws_allocator *allocator) {
287     aws_auth_library_init(allocator);
288 
289     struct aws_tls_ctx_options tls_options;
290     aws_tls_ctx_options_init_default_client(&tls_options, allocator);
291     s_tester.tls_ctx = aws_tls_client_ctx_new(allocator, &tls_options);
292     ASSERT_NOT_NULL(s_tester.tls_ctx);
293 
294     if (aws_array_list_init_dynamic(&s_tester.response_data_callbacks, allocator, 10, sizeof(struct aws_byte_cursor))) {
295         return AWS_OP_ERR;
296     }
297 
298     if (aws_byte_buf_init(&s_tester.request_body, allocator, 256)) {
299         return AWS_OP_ERR;
300     }
301 
302     if (aws_mutex_init(&s_tester.lock)) {
303         return AWS_OP_ERR;
304     }
305 
306     if (aws_condition_variable_init(&s_tester.signal)) {
307         return AWS_OP_ERR;
308     }
309 
310     /* default to everything successful */
311     s_tester.is_connection_acquire_successful = true;
312     s_tester.is_request_successful = true;
313 
314     return AWS_OP_SUCCESS;
315 }
316 
s_aws_sts_web_identity_tester_cleanup(void)317 static void s_aws_sts_web_identity_tester_cleanup(void) {
318     aws_tls_ctx_release(s_tester.tls_ctx);
319     aws_array_list_clean_up(&s_tester.response_data_callbacks);
320     aws_byte_buf_clean_up(&s_tester.request_body);
321     aws_condition_variable_clean_up(&s_tester.signal);
322     aws_mutex_clean_up(&s_tester.lock);
323     aws_credentials_release(s_tester.credentials);
324     aws_auth_library_clean_up();
325 }
326 
s_has_tester_received_credentials_callback(void * user_data)327 static bool s_has_tester_received_credentials_callback(void *user_data) {
328     (void)user_data;
329 
330     return s_tester.has_received_credentials_callback;
331 }
332 
s_aws_wait_for_credentials_result(void)333 static void s_aws_wait_for_credentials_result(void) {
334     aws_mutex_lock(&s_tester.lock);
335     aws_condition_variable_wait_pred(
336         &s_tester.signal, &s_tester.lock, s_has_tester_received_credentials_callback, NULL);
337     aws_mutex_unlock(&s_tester.lock);
338 }
339 
s_get_credentials_callback(struct aws_credentials * credentials,int error_code,void * user_data)340 static void s_get_credentials_callback(struct aws_credentials *credentials, int error_code, void *user_data) {
341     (void)user_data;
342 
343     aws_mutex_lock(&s_tester.lock);
344     s_tester.has_received_credentials_callback = true;
345     s_tester.credentials = credentials;
346     s_tester.error_code = error_code;
347     if (credentials != NULL) {
348         aws_credentials_acquire(credentials);
349     }
350     aws_condition_variable_notify_one(&s_tester.signal);
351     aws_mutex_unlock(&s_tester.lock);
352 }
353 
s_credentials_provider_sts_web_identity_new_destroy_from_env(struct aws_allocator * allocator,void * ctx)354 static int s_credentials_provider_sts_web_identity_new_destroy_from_env(struct aws_allocator *allocator, void *ctx) {
355     (void)ctx;
356 
357     s_aws_sts_web_identity_tester_init(allocator);
358 
359     s_aws_sts_web_identity_test_unset_env_parameters();
360 
361     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
362     ASSERT_TRUE(token_file_path_str != NULL);
363     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
364 
365     s_aws_sts_web_identity_test_init_env_parameters(
366         allocator,
367         "us-east-1",
368         "arn:aws:iam::1234567890:role/test-arn",
369         "9876543210",
370         aws_string_c_str(token_file_path_str));
371     aws_string_destroy(token_file_path_str);
372 
373     struct aws_credentials_provider_sts_web_identity_options options = {
374         .bootstrap = NULL,
375         .tls_ctx = s_tester.tls_ctx,
376         .function_table = &s_mock_function_table,
377         .shutdown_options =
378             {
379                 .shutdown_callback = s_on_shutdown_complete,
380                 .shutdown_user_data = NULL,
381             },
382     };
383 
384     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
385     aws_credentials_provider_release(provider);
386 
387     s_aws_wait_for_provider_shutdown_callback();
388 
389     s_aws_sts_web_identity_tester_cleanup();
390 
391     return 0;
392 }
393 AWS_TEST_CASE(
394     credentials_provider_sts_web_identity_new_destroy_from_env,
395     s_credentials_provider_sts_web_identity_new_destroy_from_env);
396 
397 AWS_STATIC_STRING_FROM_LITERAL(
398     s_sts_web_identity_config_file_contents,
399     "[profile default]\n"
400     "region=us-east-1\n"
401     "role_arn=arn:aws:iam::1111111111:role/test-arn\n"
402     "role_session_name=2222222222\n"
403     "web_identity_token_file=/some/unreachable/path/toklen_file\n"
404     "[profile foo]\n"
405     "region=us-west-2\n"
406     "role_arn=arn:aws:iam::3333333333:role/test-arn\n"
407     "role_session_name=4444444444\n"
408     "web_identity_token_file=");
409 
s_credentials_provider_sts_web_identity_new_destroy_from_config(struct aws_allocator * allocator,void * ctx)410 static int s_credentials_provider_sts_web_identity_new_destroy_from_config(struct aws_allocator *allocator, void *ctx) {
411     (void)ctx;
412 
413     s_aws_sts_web_identity_tester_init(allocator);
414 
415     s_aws_sts_web_identity_test_unset_env_parameters();
416 
417     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
418     ASSERT_TRUE(token_file_path_str != NULL);
419     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
420 
421     struct aws_byte_buf content_buf;
422     struct aws_byte_buf existing_content =
423         aws_byte_buf_from_c_str(aws_string_c_str(s_sts_web_identity_config_file_contents));
424     aws_byte_buf_init_copy(&content_buf, allocator, &existing_content);
425     struct aws_byte_cursor cursor = aws_byte_cursor_from_string(token_file_path_str);
426     ASSERT_TRUE(aws_byte_buf_append_dynamic(&content_buf, &cursor) == AWS_OP_SUCCESS);
427     cursor = aws_byte_cursor_from_c_str("\n");
428     ASSERT_TRUE(aws_byte_buf_append_dynamic(&content_buf, &cursor) == AWS_OP_SUCCESS);
429     aws_string_destroy(token_file_path_str);
430 
431     struct aws_string *config_file_contents = aws_string_new_from_array(allocator, content_buf.buffer, content_buf.len);
432     ASSERT_TRUE(config_file_contents != NULL);
433     aws_byte_buf_clean_up(&content_buf);
434 
435     s_aws_sts_web_identity_test_init_config_profile(allocator, config_file_contents);
436     aws_string_destroy(config_file_contents);
437 
438     struct aws_credentials_provider_sts_web_identity_options options = {
439         .bootstrap = NULL,
440         .tls_ctx = s_tester.tls_ctx,
441         .function_table = &s_mock_function_table,
442         .shutdown_options =
443             {
444                 .shutdown_callback = s_on_shutdown_complete,
445                 .shutdown_user_data = NULL,
446             },
447     };
448 
449     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
450     aws_credentials_provider_release(provider);
451 
452     s_aws_wait_for_provider_shutdown_callback();
453 
454     s_aws_sts_web_identity_tester_cleanup();
455 
456     return 0;
457 }
458 AWS_TEST_CASE(
459     credentials_provider_sts_web_identity_new_destroy_from_config,
460     s_credentials_provider_sts_web_identity_new_destroy_from_config);
461 
s_credentials_provider_sts_web_identity_new_failed_without_env_and_config(struct aws_allocator * allocator,void * ctx)462 static int s_credentials_provider_sts_web_identity_new_failed_without_env_and_config(
463     struct aws_allocator *allocator,
464     void *ctx) {
465     (void)ctx;
466 
467     s_aws_sts_web_identity_tester_init(allocator);
468 
469     struct aws_string *empty_content = aws_string_new_from_c_str(allocator, "");
470     ASSERT_TRUE(empty_content != NULL);
471     s_aws_sts_web_identity_test_init_config_profile(allocator, empty_content);
472     aws_string_destroy(empty_content);
473 
474     s_aws_sts_web_identity_test_unset_env_parameters();
475 
476     ASSERT_TRUE(aws_unset_environment_value(s_default_profile_env_variable_name) == AWS_OP_SUCCESS);
477 
478     struct aws_credentials_provider_sts_web_identity_options options = {
479         .bootstrap = NULL,
480         .tls_ctx = s_tester.tls_ctx,
481         .function_table = &s_mock_function_table,
482         .shutdown_options =
483             {
484                 .shutdown_callback = s_on_shutdown_complete,
485                 .shutdown_user_data = NULL,
486             },
487     };
488 
489     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
490     ASSERT_TRUE(provider == NULL);
491 
492     s_aws_sts_web_identity_tester_cleanup();
493 
494     return 0;
495 }
496 
497 AWS_TEST_CASE(
498     credentials_provider_sts_web_identity_new_failed_without_env_and_config,
499     s_credentials_provider_sts_web_identity_new_failed_without_env_and_config);
500 
501 AWS_STATIC_STRING_FROM_LITERAL(
502     s_expected_sts_web_identity_body_message,
503     "Action=AssumeRoleWithWebIdentity&Version=2011-06-15"
504     "&RoleArn=arn%3Aaws%3Aiam%3A%3A1234567890%3Arole%2Ftest-arn&RoleSessionName=9876543210&WebIdentityToken=my-test-"
505     "token-contents-123-abc-xyz");
506 AWS_STATIC_STRING_FROM_LITERAL(
507     s_expected_sts_web_identity_body_message_config,
508     "Action=AssumeRoleWithWebIdentity&Version=2011-06-15"
509     "&RoleArn=arn%3Aaws%3Aiam%3A%3A3333333333%3Arole%2Ftest-arn&RoleSessionName=4444444444&WebIdentityToken=my-test-"
510     "token-contents-123-abc-xyz");
511 
512 AWS_STATIC_STRING_FROM_LITERAL(
513     s_good_response,
514     "<AssumeRoleWithWebIdentityResponse>"
515     "    <AssumeRoleWithWebIdentityResult>"
516     "        <AssumedRoleUser>"
517     "            <Arn>arn:aws:sts::123456789012:assumed-role/FederatedWebIdentityRole/app1</Arn>"
518     "           <AssumedRoleId>AROACLKWSDQRAOEXAMPLE:app1</AssumedRoleId>"
519     "        </AssumedRoleUser>"
520     "        <Credentials>"
521     "            <SessionToken>TokenSuccess</SessionToken>"
522     "           <SecretAccessKey>SuccessfulSecret</SecretAccessKey>"
523     "            <Expiration>2020-02-25T06:03:31Z</Expiration>"
524     "           <AccessKeyId>SuccessfulAccessKey</AccessKeyId>"
525     "        </Credentials>"
526     "       <Provider>www.amazon.com</Provider>"
527     "    </AssumeRoleWithWebIdentityResult>"
528     "   <ResponseMetadata>"
529     "        <RequestId>ad4156e9-bce1-11e2-82e6-6b6efEXAMPLE</RequestId>"
530     "   </ResponseMetadata>"
531     "</AssumeRoleWithWebIdentityResponse>");
532 AWS_STATIC_STRING_FROM_LITERAL(s_good_access_key_id, "SuccessfulAccessKey");
533 AWS_STATIC_STRING_FROM_LITERAL(s_good_secret_access_key, "SuccessfulSecret");
534 AWS_STATIC_STRING_FROM_LITERAL(s_good_session_token, "TokenSuccess");
535 AWS_STATIC_STRING_FROM_LITERAL(s_good_response_expiration, "2020-02-25T06:03:31Z");
536 
s_verify_credentials(bool request_made,bool from_config,bool got_credentials,int expected_attempts)537 static int s_verify_credentials(bool request_made, bool from_config, bool got_credentials, int expected_attempts) {
538 
539     if (request_made) {
540         if (from_config) {
541             ASSERT_CURSOR_VALUE_STRING_EQUALS(
542                 aws_byte_cursor_from_buf(&s_tester.request_body), s_expected_sts_web_identity_body_message_config);
543         } else {
544             ASSERT_CURSOR_VALUE_STRING_EQUALS(
545                 aws_byte_cursor_from_buf(&s_tester.request_body), s_expected_sts_web_identity_body_message);
546         }
547     }
548 
549     ASSERT_TRUE(s_tester.has_received_credentials_callback);
550 
551     if (got_credentials) {
552         ASSERT_TRUE(s_tester.credentials != NULL);
553         ASSERT_CURSOR_VALUE_STRING_EQUALS(
554             aws_credentials_get_access_key_id(s_tester.credentials), s_good_access_key_id);
555         ASSERT_CURSOR_VALUE_STRING_EQUALS(
556             aws_credentials_get_secret_access_key(s_tester.credentials), s_good_secret_access_key);
557         ASSERT_CURSOR_VALUE_STRING_EQUALS(
558             aws_credentials_get_session_token(s_tester.credentials), s_good_session_token);
559     } else {
560         ASSERT_TRUE(s_tester.credentials == NULL);
561     }
562 
563     ASSERT_TRUE(s_tester.attempts == expected_attempts);
564 
565     return AWS_OP_SUCCESS;
566 }
567 
s_credentials_provider_sts_web_identity_connect_failure(struct aws_allocator * allocator,void * ctx)568 static int s_credentials_provider_sts_web_identity_connect_failure(struct aws_allocator *allocator, void *ctx) {
569     (void)ctx;
570 
571     s_aws_sts_web_identity_tester_init(allocator);
572     s_tester.is_connection_acquire_successful = false;
573 
574     s_aws_sts_web_identity_test_unset_env_parameters();
575 
576     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
577     ASSERT_TRUE(token_file_path_str != NULL);
578     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
579 
580     s_aws_sts_web_identity_test_init_env_parameters(
581         allocator,
582         "us-east-1",
583         "arn:aws:iam::1234567890:role/test-arn",
584         "9876543210",
585         aws_string_c_str(token_file_path_str));
586     aws_string_destroy(token_file_path_str);
587 
588     struct aws_credentials_provider_sts_web_identity_options options = {
589         .bootstrap = NULL,
590         .tls_ctx = s_tester.tls_ctx,
591         .function_table = &s_mock_function_table,
592         .shutdown_options =
593             {
594                 .shutdown_callback = s_on_shutdown_complete,
595                 .shutdown_user_data = NULL,
596             },
597     };
598 
599     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
600 
601     aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL);
602 
603     s_aws_wait_for_credentials_result();
604 
605     ASSERT_SUCCESS(s_verify_credentials(
606         false /*no request*/, false /*from config*/, false /*get creds*/, 0 /*expected attempts*/));
607 
608     aws_credentials_provider_release(provider);
609 
610     s_aws_wait_for_provider_shutdown_callback();
611 
612     s_aws_sts_web_identity_tester_cleanup();
613 
614     return 0;
615 }
616 AWS_TEST_CASE(
617     credentials_provider_sts_web_identity_connect_failure,
618     s_credentials_provider_sts_web_identity_connect_failure);
619 
s_credentials_provider_sts_web_identity_request_failure(struct aws_allocator * allocator,void * ctx)620 static int s_credentials_provider_sts_web_identity_request_failure(struct aws_allocator *allocator, void *ctx) {
621     (void)ctx;
622 
623     s_aws_sts_web_identity_tester_init(allocator);
624     s_tester.is_request_successful = false;
625 
626     s_aws_sts_web_identity_test_unset_env_parameters();
627 
628     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
629     ASSERT_TRUE(token_file_path_str != NULL);
630     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
631 
632     s_aws_sts_web_identity_test_init_env_parameters(
633         allocator,
634         "us-east-1",
635         "arn:aws:iam::1234567890:role/test-arn",
636         "9876543210",
637         aws_string_c_str(token_file_path_str));
638     aws_string_destroy(token_file_path_str);
639 
640     struct aws_credentials_provider_sts_web_identity_options options = {
641         .bootstrap = NULL,
642         .tls_ctx = s_tester.tls_ctx,
643         .function_table = &s_mock_function_table,
644         .shutdown_options =
645             {
646                 .shutdown_callback = s_on_shutdown_complete,
647                 .shutdown_user_data = NULL,
648             },
649     };
650 
651     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
652 
653     aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL);
654 
655     s_aws_wait_for_credentials_result();
656 
657     ASSERT_SUCCESS(s_verify_credentials(
658         true /*request made*/, false /*from config*/, false /*get creds*/, 1 /*expected attempts*/));
659 
660     aws_credentials_provider_release(provider);
661 
662     s_aws_wait_for_provider_shutdown_callback();
663 
664     s_aws_sts_web_identity_tester_cleanup();
665 
666     return 0;
667 }
668 AWS_TEST_CASE(
669     credentials_provider_sts_web_identity_request_failure,
670     s_credentials_provider_sts_web_identity_request_failure);
671 
672 AWS_STATIC_STRING_FROM_LITERAL(
673     s_bad_document_response,
674     "<AssumeRoleWithWebIdentityResponse xmlns=\"Not the right doc\">Test</AssumeRoleWithWebIdentityResponse>");
675 
s_credentials_provider_sts_web_identity_bad_document_failure(struct aws_allocator * allocator,void * ctx)676 static int s_credentials_provider_sts_web_identity_bad_document_failure(struct aws_allocator *allocator, void *ctx) {
677     (void)ctx;
678 
679     s_aws_sts_web_identity_tester_init(allocator);
680 
681     s_aws_sts_web_identity_test_unset_env_parameters();
682 
683     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
684     ASSERT_TRUE(token_file_path_str != NULL);
685     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
686 
687     s_aws_sts_web_identity_test_init_env_parameters(
688         allocator,
689         "us-east-1",
690         "arn:aws:iam::1234567890:role/test-arn",
691         "9876543210",
692         aws_string_c_str(token_file_path_str));
693     aws_string_destroy(token_file_path_str);
694 
695     struct aws_byte_cursor bad_document_cursor = aws_byte_cursor_from_string(s_bad_document_response);
696     aws_array_list_push_back(&s_tester.response_data_callbacks, &bad_document_cursor);
697 
698     struct aws_credentials_provider_sts_web_identity_options options = {
699         .bootstrap = NULL,
700         .tls_ctx = s_tester.tls_ctx,
701         .function_table = &s_mock_function_table,
702         .shutdown_options =
703             {
704                 .shutdown_callback = s_on_shutdown_complete,
705                 .shutdown_user_data = NULL,
706             },
707     };
708 
709     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
710 
711     aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL);
712 
713     s_aws_wait_for_credentials_result();
714 
715     ASSERT_SUCCESS(s_verify_credentials(
716         true /*request made*/, false /*from config*/, false /*get creds*/, 1 /*expected attempts*/));
717 
718     aws_credentials_provider_release(provider);
719 
720     s_aws_wait_for_provider_shutdown_callback();
721 
722     s_aws_sts_web_identity_tester_cleanup();
723 
724     return 0;
725 }
726 AWS_TEST_CASE(
727     credentials_provider_sts_web_identity_bad_document_failure,
728     s_credentials_provider_sts_web_identity_bad_document_failure);
729 
730 AWS_STATIC_STRING_FROM_LITERAL(
731     s_retryable_error_response_1,
732     "<Error>"
733     "<Code>IDPCommunicationError</Code>"
734     "<Message>XXX</Message>"
735     "<Resource>YYY</Resource>"
736     "<RequestId>4442587FB7D0A2F9</RequestId>"
737     "</Error>");
738 
739 AWS_STATIC_STRING_FROM_LITERAL(
740     s_retryable_error_response_2,
741     "<Error>"
742     "<Code>InvalidIdentityToken</Code>"
743     "<Message>XXX</Message>"
744     "<Resource>YYY</Resource>"
745     "<RequestId>4442587FB7D0A2F9</RequestId>"
746     "</Error>");
747 
s_credentials_provider_sts_web_identity_test_retry_error1(struct aws_allocator * allocator,void * ctx)748 static int s_credentials_provider_sts_web_identity_test_retry_error1(struct aws_allocator *allocator, void *ctx) {
749     (void)ctx;
750 
751     s_aws_sts_web_identity_tester_init(allocator);
752     s_tester.response_code = AWS_HTTP_STATUS_CODE_400_BAD_REQUEST;
753     s_aws_sts_web_identity_test_unset_env_parameters();
754 
755     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
756     ASSERT_TRUE(token_file_path_str != NULL);
757     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
758 
759     s_aws_sts_web_identity_test_init_env_parameters(
760         allocator,
761         "us-east-1",
762         "arn:aws:iam::1234567890:role/test-arn",
763         "9876543210",
764         aws_string_c_str(token_file_path_str));
765     aws_string_destroy(token_file_path_str);
766 
767     struct aws_byte_cursor bad_document_cursor = aws_byte_cursor_from_string(s_retryable_error_response_1);
768     aws_array_list_push_back(&s_tester.response_data_callbacks, &bad_document_cursor);
769 
770     struct aws_credentials_provider_sts_web_identity_options options = {
771         .bootstrap = NULL,
772         .tls_ctx = s_tester.tls_ctx,
773         .function_table = &s_mock_function_table,
774         .shutdown_options =
775             {
776                 .shutdown_callback = s_on_shutdown_complete,
777                 .shutdown_user_data = NULL,
778             },
779     };
780 
781     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
782 
783     aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL);
784 
785     s_aws_wait_for_credentials_result();
786 
787     ASSERT_SUCCESS(s_verify_credentials(
788         true /*request made*/, false /*from config*/, false /*get creds*/, 3 /*expected attempts*/));
789 
790     aws_credentials_provider_release(provider);
791 
792     s_aws_wait_for_provider_shutdown_callback();
793 
794     s_aws_sts_web_identity_tester_cleanup();
795 
796     return 0;
797 }
798 AWS_TEST_CASE(
799     credentials_provider_sts_web_identity_test_retry_error1,
800     s_credentials_provider_sts_web_identity_test_retry_error1);
801 
s_credentials_provider_sts_web_identity_test_retry_error2(struct aws_allocator * allocator,void * ctx)802 static int s_credentials_provider_sts_web_identity_test_retry_error2(struct aws_allocator *allocator, void *ctx) {
803     (void)ctx;
804 
805     s_aws_sts_web_identity_tester_init(allocator);
806     s_tester.response_code = AWS_HTTP_STATUS_CODE_400_BAD_REQUEST;
807     s_aws_sts_web_identity_test_unset_env_parameters();
808 
809     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
810     ASSERT_TRUE(token_file_path_str != NULL);
811     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
812 
813     s_aws_sts_web_identity_test_init_env_parameters(
814         allocator,
815         "us-east-1",
816         "arn:aws:iam::1234567890:role/test-arn",
817         "9876543210",
818         aws_string_c_str(token_file_path_str));
819     aws_string_destroy(token_file_path_str);
820 
821     struct aws_byte_cursor bad_document_cursor = aws_byte_cursor_from_string(s_retryable_error_response_2);
822     aws_array_list_push_back(&s_tester.response_data_callbacks, &bad_document_cursor);
823 
824     struct aws_credentials_provider_sts_web_identity_options options = {
825         .bootstrap = NULL,
826         .tls_ctx = s_tester.tls_ctx,
827         .function_table = &s_mock_function_table,
828         .shutdown_options =
829             {
830                 .shutdown_callback = s_on_shutdown_complete,
831                 .shutdown_user_data = NULL,
832             },
833     };
834 
835     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
836 
837     aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL);
838 
839     s_aws_wait_for_credentials_result();
840 
841     ASSERT_SUCCESS(s_verify_credentials(
842         true /*request made*/, false /*from config*/, false /*get creds*/, 3 /*expected attempts*/));
843 
844     aws_credentials_provider_release(provider);
845 
846     s_aws_wait_for_provider_shutdown_callback();
847 
848     s_aws_sts_web_identity_tester_cleanup();
849 
850     return 0;
851 }
852 AWS_TEST_CASE(
853     credentials_provider_sts_web_identity_test_retry_error2,
854     s_credentials_provider_sts_web_identity_test_retry_error2);
855 
s_credentials_provider_sts_web_identity_basic_success_env(struct aws_allocator * allocator,void * ctx)856 static int s_credentials_provider_sts_web_identity_basic_success_env(struct aws_allocator *allocator, void *ctx) {
857     (void)ctx;
858 
859     s_aws_sts_web_identity_tester_init(allocator);
860 
861     s_aws_sts_web_identity_test_unset_env_parameters();
862 
863     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
864     ASSERT_TRUE(token_file_path_str != NULL);
865     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
866 
867     s_aws_sts_web_identity_test_init_env_parameters(
868         allocator,
869         "us-east-1",
870         "arn:aws:iam::1234567890:role/test-arn",
871         "9876543210",
872         aws_string_c_str(token_file_path_str));
873     aws_string_destroy(token_file_path_str);
874 
875     struct aws_byte_cursor good_response_cursor = aws_byte_cursor_from_string(s_good_response);
876     aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor);
877 
878     struct aws_credentials_provider_sts_web_identity_options options = {
879         .bootstrap = NULL,
880         .tls_ctx = s_tester.tls_ctx,
881         .function_table = &s_mock_function_table,
882         .shutdown_options =
883             {
884                 .shutdown_callback = s_on_shutdown_complete,
885                 .shutdown_user_data = NULL,
886             },
887     };
888 
889     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
890 
891     aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL);
892 
893     s_aws_wait_for_credentials_result();
894 
895     ASSERT_SUCCESS(s_verify_credentials(
896         true /*request made*/, false /*from config*/, true /*get creds*/, 1 /*expected attempts*/));
897 
898     struct aws_date_time expiration;
899     struct aws_byte_cursor date_cursor = aws_byte_cursor_from_string(s_good_response_expiration);
900     aws_date_time_init_from_str_cursor(&expiration, &date_cursor, AWS_DATE_FORMAT_ISO_8601);
901     ASSERT_INT_EQUALS(
902         aws_credentials_get_expiration_timepoint_seconds(s_tester.credentials), (uint64_t)expiration.timestamp);
903 
904     aws_credentials_provider_release(provider);
905 
906     s_aws_wait_for_provider_shutdown_callback();
907 
908     s_aws_sts_web_identity_tester_cleanup();
909 
910     return 0;
911 }
912 
913 AWS_TEST_CASE(
914     credentials_provider_sts_web_identity_basic_success_env,
915     s_credentials_provider_sts_web_identity_basic_success_env);
916 
s_credentials_provider_sts_web_identity_basic_success_config(struct aws_allocator * allocator,void * ctx)917 static int s_credentials_provider_sts_web_identity_basic_success_config(struct aws_allocator *allocator, void *ctx) {
918     (void)ctx;
919 
920     s_aws_sts_web_identity_tester_init(allocator);
921 
922     s_aws_sts_web_identity_test_unset_env_parameters();
923 
924     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
925     ASSERT_TRUE(token_file_path_str != NULL);
926     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
927 
928     struct aws_byte_buf content_buf;
929     struct aws_byte_buf existing_content =
930         aws_byte_buf_from_c_str(aws_string_c_str(s_sts_web_identity_config_file_contents));
931     aws_byte_buf_init_copy(&content_buf, allocator, &existing_content);
932     struct aws_byte_cursor cursor = aws_byte_cursor_from_string(token_file_path_str);
933     ASSERT_TRUE(aws_byte_buf_append_dynamic(&content_buf, &cursor) == AWS_OP_SUCCESS);
934     cursor = aws_byte_cursor_from_c_str("\n");
935     ASSERT_TRUE(aws_byte_buf_append_dynamic(&content_buf, &cursor) == AWS_OP_SUCCESS);
936     aws_string_destroy(token_file_path_str);
937 
938     struct aws_string *config_file_contents = aws_string_new_from_array(allocator, content_buf.buffer, content_buf.len);
939     ASSERT_TRUE(config_file_contents != NULL);
940     aws_byte_buf_clean_up(&content_buf);
941 
942     s_aws_sts_web_identity_test_init_config_profile(allocator, config_file_contents);
943     aws_string_destroy(config_file_contents);
944 
945     struct aws_byte_cursor good_response_cursor = aws_byte_cursor_from_string(s_good_response);
946     aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor);
947 
948     struct aws_credentials_provider_sts_web_identity_options options = {
949         .bootstrap = NULL,
950         .tls_ctx = s_tester.tls_ctx,
951         .function_table = &s_mock_function_table,
952         .shutdown_options =
953             {
954                 .shutdown_callback = s_on_shutdown_complete,
955                 .shutdown_user_data = NULL,
956             },
957     };
958 
959     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
960 
961     aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL);
962 
963     s_aws_wait_for_credentials_result();
964 
965     ASSERT_SUCCESS(
966         s_verify_credentials(true /*request made*/, true /*from config*/, true /*get creds*/, 1 /*expected attempts*/));
967 
968     struct aws_date_time expiration;
969     struct aws_byte_cursor date_cursor = aws_byte_cursor_from_string(s_good_response_expiration);
970     aws_date_time_init_from_str_cursor(&expiration, &date_cursor, AWS_DATE_FORMAT_ISO_8601);
971     ASSERT_INT_EQUALS(
972         aws_credentials_get_expiration_timepoint_seconds(s_tester.credentials), (uint64_t)expiration.timestamp);
973 
974     aws_credentials_provider_release(provider);
975 
976     s_aws_wait_for_provider_shutdown_callback();
977 
978     s_aws_sts_web_identity_tester_cleanup();
979 
980     return 0;
981 }
982 
983 AWS_TEST_CASE(
984     credentials_provider_sts_web_identity_basic_success_config,
985     s_credentials_provider_sts_web_identity_basic_success_config);
986 
987 AWS_STATIC_STRING_FROM_LITERAL(
988     s_good_response_first_part,
989     "<AssumeRoleWithWebIdentityResponse>"
990     "    <AssumeRoleWithWebIdentityResult>"
991     "        <AssumedRoleUser>"
992     "            <Arn>arn:aws:sts::123456789012:assumed-role/FederatedWebIdentityRole/app1</Arn>"
993     "           <AssumedRoleId>AROACLKWSDQRAOEXAMPLE:app1</AssumedRoleId>"
994     "        </AssumedRoleUser>"
995     "        <Credentials>");
996 AWS_STATIC_STRING_FROM_LITERAL(
997     s_good_response_second_part,
998     "            <SessionToken>TokenSuccess</SessionToken>"
999     "           <SecretAccessKey>SuccessfulSecret</SecretAccessKey>"
1000     "            <Expiration>2020-02-25T06:03:31Z</Expiration>"
1001     "           <AccessKeyId>SuccessfulAccessKey</AccessKeyId>"
1002     "        </Credentials>"
1003     "       <Provider>www.amazon.com</Provider>"
1004     "    </AssumeRoleWithWebIdentityResult>"
1005     "   <ResponseMetadata>");
1006 AWS_STATIC_STRING_FROM_LITERAL(
1007     s_good_response_third_part,
1008 
1009     "        <RequestId>ad4156e9-bce1-11e2-82e6-6b6efEXAMPLE</RequestId>"
1010     "   </ResponseMetadata>"
1011     "</AssumeRoleWithWebIdentityResponse>");
1012 
s_credentials_provider_sts_web_identity_success_multi_part_doc(struct aws_allocator * allocator,void * ctx)1013 static int s_credentials_provider_sts_web_identity_success_multi_part_doc(struct aws_allocator *allocator, void *ctx) {
1014     (void)ctx;
1015 
1016     s_aws_sts_web_identity_tester_init(allocator);
1017 
1018     s_aws_sts_web_identity_test_unset_env_parameters();
1019 
1020     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
1021     ASSERT_TRUE(token_file_path_str != NULL);
1022     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
1023 
1024     s_aws_sts_web_identity_test_init_env_parameters(
1025         allocator,
1026         "us-east-1",
1027         "arn:aws:iam::1234567890:role/test-arn",
1028         "9876543210",
1029         aws_string_c_str(token_file_path_str));
1030     aws_string_destroy(token_file_path_str);
1031 
1032     struct aws_byte_cursor good_response_cursor1 = aws_byte_cursor_from_string(s_good_response_first_part);
1033     struct aws_byte_cursor good_response_cursor2 = aws_byte_cursor_from_string(s_good_response_second_part);
1034     struct aws_byte_cursor good_response_cursor3 = aws_byte_cursor_from_string(s_good_response_third_part);
1035     aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor1);
1036     aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor2);
1037     aws_array_list_push_back(&s_tester.response_data_callbacks, &good_response_cursor3);
1038 
1039     struct aws_credentials_provider_sts_web_identity_options options = {
1040         .bootstrap = NULL,
1041         .tls_ctx = s_tester.tls_ctx,
1042         .function_table = &s_mock_function_table,
1043         .shutdown_options =
1044             {
1045                 .shutdown_callback = s_on_shutdown_complete,
1046                 .shutdown_user_data = NULL,
1047             },
1048     };
1049 
1050     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
1051 
1052     aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL);
1053 
1054     s_aws_wait_for_credentials_result();
1055 
1056     ASSERT_SUCCESS(s_verify_credentials(
1057         true /*request made*/, false /*from config*/, true /*get creds*/, 1 /*expected attempts*/));
1058 
1059     struct aws_date_time expiration;
1060     struct aws_byte_cursor date_cursor = aws_byte_cursor_from_string(s_good_response_expiration);
1061     aws_date_time_init_from_str_cursor(&expiration, &date_cursor, AWS_DATE_FORMAT_ISO_8601);
1062     ASSERT_INT_EQUALS(
1063         aws_credentials_get_expiration_timepoint_seconds(s_tester.credentials), (uint64_t)expiration.timestamp);
1064 
1065     aws_credentials_provider_release(provider);
1066 
1067     s_aws_wait_for_provider_shutdown_callback();
1068 
1069     s_aws_sts_web_identity_tester_cleanup();
1070 
1071     return 0;
1072 }
1073 AWS_TEST_CASE(
1074     credentials_provider_sts_web_identity_success_multi_part_doc,
1075     s_credentials_provider_sts_web_identity_success_multi_part_doc);
1076 
s_credentials_provider_sts_web_identity_real_new_destroy(struct aws_allocator * allocator,void * ctx)1077 static int s_credentials_provider_sts_web_identity_real_new_destroy(struct aws_allocator *allocator, void *ctx) {
1078     (void)ctx;
1079 
1080     aws_auth_library_init(allocator);
1081 
1082     s_aws_sts_web_identity_test_unset_env_parameters();
1083 
1084     struct aws_string *token_file_path_str = aws_create_process_unique_file_name(allocator);
1085     ASSERT_TRUE(token_file_path_str != NULL);
1086     ASSERT_TRUE(aws_create_profile_file(token_file_path_str, s_sts_web_identity_token_contents) == AWS_OP_SUCCESS);
1087 
1088     s_aws_sts_web_identity_test_init_env_parameters(
1089         allocator,
1090         "us-east-1",
1091         "arn:aws:iam::1234567890:role/test-arn",
1092         "9876543210",
1093         aws_string_c_str(token_file_path_str));
1094     aws_string_destroy(token_file_path_str);
1095 
1096     s_aws_sts_web_identity_tester_init(allocator);
1097 
1098     struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL);
1099 
1100     struct aws_host_resolver_default_options resolver_options = {
1101         .el_group = el_group,
1102         .max_entries = 8,
1103     };
1104     struct aws_host_resolver *resolver = aws_host_resolver_new_default(allocator, &resolver_options);
1105 
1106     struct aws_client_bootstrap_options bootstrap_options = {
1107         .event_loop_group = el_group,
1108         .host_resolver = resolver,
1109     };
1110     struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
1111 
1112     struct aws_credentials_provider_sts_web_identity_options options = {
1113         .bootstrap = bootstrap,
1114         .tls_ctx = s_tester.tls_ctx,
1115         .shutdown_options =
1116             {
1117                 .shutdown_callback = s_on_shutdown_complete,
1118                 .shutdown_user_data = NULL,
1119             },
1120     };
1121 
1122     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
1123 
1124     aws_credentials_provider_get_credentials(provider, s_get_credentials_callback, NULL);
1125 
1126     s_aws_wait_for_credentials_result();
1127 
1128     aws_credentials_provider_release(provider);
1129 
1130     s_aws_wait_for_provider_shutdown_callback();
1131 
1132     aws_client_bootstrap_release(bootstrap);
1133     aws_host_resolver_release(resolver);
1134     aws_event_loop_group_release(el_group);
1135 
1136     s_aws_sts_web_identity_tester_cleanup();
1137 
1138     aws_auth_library_clean_up();
1139 
1140     return 0;
1141 }
1142 AWS_TEST_CASE(
1143     credentials_provider_sts_web_identity_real_new_destroy,
1144     s_credentials_provider_sts_web_identity_real_new_destroy);
1145