credentials_provider_ecs.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/auth/credentials.h>
  6. #include <aws/auth/private/credentials_utils.h>
  7. #include <aws/common/clock.h>
  8. #include <aws/common/date_time.h>
  9. #include <aws/common/string.h>
  10. #include <aws/http/connection.h>
  11. #include <aws/http/connection_manager.h>
  12. #include <aws/http/request_response.h>
  13. #include <aws/http/status_code.h>
  14. #include <aws/io/logging.h>
  15. #include <aws/io/socket.h>
  16. #include <aws/io/tls_channel_handler.h>
  17. #include <aws/io/uri.h>
  18. #if defined(_MSC_VER)
  19. # pragma warning(disable : 4204)
  20. # pragma warning(disable : 4232)
  21. #endif /* _MSC_VER */
  22. /* ecs task role credentials body response is currently ~ 1300 characters + name length */
  23. #define ECS_RESPONSE_SIZE_INITIAL 2048
  24. #define ECS_RESPONSE_SIZE_LIMIT 10000
  25. #define ECS_CONNECT_TIMEOUT_DEFAULT_IN_SECONDS 2
  26. static void s_on_connection_manager_shutdown(void *user_data);
  27. struct aws_credentials_provider_ecs_impl {
  28. struct aws_http_connection_manager *connection_manager;
  29. const struct aws_auth_http_system_vtable *function_table;
  30. struct aws_string *host;
  31. struct aws_string *path_and_query;
  32. struct aws_string *auth_token;
  33. };
  34. /*
  35. * Tracking structure for each outstanding async query to an ecs provider
  36. */
  37. struct aws_credentials_provider_ecs_user_data {
  38. /* immutable post-creation */
  39. struct aws_allocator *allocator;
  40. struct aws_credentials_provider *ecs_provider;
  41. aws_on_get_credentials_callback_fn *original_callback;
  42. void *original_user_data;
  43. /* mutable */
  44. struct aws_http_connection *connection;
  45. struct aws_http_message *request;
  46. struct aws_byte_buf current_result;
  47. int status_code;
  48. int error_code;
  49. };
  50. static void s_aws_credentials_provider_ecs_user_data_destroy(struct aws_credentials_provider_ecs_user_data *user_data) {
  51. if (user_data == NULL) {
  52. return;
  53. }
  54. struct aws_credentials_provider_ecs_impl *impl = user_data->ecs_provider->impl;
  55. if (user_data->connection) {
  56. impl->function_table->aws_http_connection_manager_release_connection(
  57. impl->connection_manager, user_data->connection);
  58. }
  59. aws_byte_buf_clean_up(&user_data->current_result);
  60. if (user_data->request) {
  61. aws_http_message_destroy(user_data->request);
  62. }
  63. aws_credentials_provider_release(user_data->ecs_provider);
  64. aws_mem_release(user_data->allocator, user_data);
  65. }
  66. static struct aws_credentials_provider_ecs_user_data *s_aws_credentials_provider_ecs_user_data_new(
  67. struct aws_credentials_provider *ecs_provider,
  68. aws_on_get_credentials_callback_fn callback,
  69. void *user_data) {
  70. struct aws_credentials_provider_ecs_user_data *wrapped_user_data =
  71. aws_mem_calloc(ecs_provider->allocator, 1, sizeof(struct aws_credentials_provider_ecs_user_data));
  72. if (wrapped_user_data == NULL) {
  73. goto on_error;
  74. }
  75. wrapped_user_data->allocator = ecs_provider->allocator;
  76. wrapped_user_data->ecs_provider = ecs_provider;
  77. aws_credentials_provider_acquire(ecs_provider);
  78. wrapped_user_data->original_user_data = user_data;
  79. wrapped_user_data->original_callback = callback;
  80. if (aws_byte_buf_init(&wrapped_user_data->current_result, ecs_provider->allocator, ECS_RESPONSE_SIZE_INITIAL)) {
  81. goto on_error;
  82. }
  83. return wrapped_user_data;
  84. on_error:
  85. s_aws_credentials_provider_ecs_user_data_destroy(wrapped_user_data);
  86. return NULL;
  87. }
  88. static void s_aws_credentials_provider_ecs_user_data_reset_response(
  89. struct aws_credentials_provider_ecs_user_data *ecs_user_data) {
  90. ecs_user_data->current_result.len = 0;
  91. ecs_user_data->status_code = 0;
  92. if (ecs_user_data->request) {
  93. aws_http_message_destroy(ecs_user_data->request);
  94. ecs_user_data->request = NULL;
  95. }
  96. }
  97. /*
  98. * In general, the ECS document looks something like:
  99. {
  100. "Code" : "Success",
  101. "LastUpdated" : "2019-05-28T18:03:09Z",
  102. "Type" : "AWS-HMAC",
  103. "AccessKeyId" : "...",
  104. "SecretAccessKey" : "...",
  105. "Token" : "...",
  106. "Expiration" : "2019-05-29T00:21:43Z"
  107. }
  108. *
  109. * No matter the result, this always gets called assuming that esc_user_data is successfully allocated
  110. */
  111. static void s_ecs_finalize_get_credentials_query(struct aws_credentials_provider_ecs_user_data *ecs_user_data) {
  112. /* Try to build credentials from whatever, if anything, was in the result */
  113. struct aws_credentials *credentials = NULL;
  114. struct aws_parse_credentials_from_json_doc_options parse_options = {
  115. .access_key_id_name = "AccessKeyId",
  116. .secret_access_key_name = "SecretAccessKey",
  117. .token_name = "Token",
  118. .expiration_name = "Expiration",
  119. .token_required = true,
  120. .expiration_required = true,
  121. };
  122. if (aws_byte_buf_append_null_terminator(&ecs_user_data->current_result) == AWS_OP_SUCCESS) {
  123. credentials = aws_parse_credentials_from_json_document(
  124. ecs_user_data->allocator, (const char *)ecs_user_data->current_result.buffer, &parse_options);
  125. } else {
  126. AWS_LOGF_ERROR(
  127. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  128. "(id=%p) ECS credentials provider failed to add null terminating char to resulting buffer.",
  129. (void *)ecs_user_data->ecs_provider);
  130. }
  131. if (credentials != NULL) {
  132. AWS_LOGF_INFO(
  133. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  134. "(id=%p) ECS credentials provider successfully queried instance role credentials",
  135. (void *)ecs_user_data->ecs_provider);
  136. } else {
  137. /* no credentials, make sure we have a valid error to report */
  138. if (ecs_user_data->error_code == AWS_ERROR_SUCCESS) {
  139. ecs_user_data->error_code = aws_last_error();
  140. if (ecs_user_data->error_code == AWS_ERROR_SUCCESS) {
  141. ecs_user_data->error_code = AWS_AUTH_CREDENTIALS_PROVIDER_ECS_SOURCE_FAILURE;
  142. }
  143. }
  144. AWS_LOGF_WARN(
  145. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  146. "(id=%p) ECS credentials provider failed to query instance role credentials with error %d(%s)",
  147. (void *)ecs_user_data->ecs_provider,
  148. ecs_user_data->error_code,
  149. aws_error_str(ecs_user_data->error_code));
  150. }
  151. /* pass the credentials back */
  152. ecs_user_data->original_callback(credentials, ecs_user_data->error_code, ecs_user_data->original_user_data);
  153. /* clean up */
  154. s_aws_credentials_provider_ecs_user_data_destroy(ecs_user_data);
  155. aws_credentials_release(credentials);
  156. }
  157. static int s_ecs_on_incoming_body_fn(
  158. struct aws_http_stream *stream,
  159. const struct aws_byte_cursor *data,
  160. void *user_data) {
  161. (void)stream;
  162. struct aws_credentials_provider_ecs_user_data *ecs_user_data = user_data;
  163. struct aws_credentials_provider_ecs_impl *impl = ecs_user_data->ecs_provider->impl;
  164. AWS_LOGF_TRACE(
  165. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  166. "(id=%p) ECS credentials provider received %zu response bytes",
  167. (void *)ecs_user_data->ecs_provider,
  168. data->len);
  169. if (data->len + ecs_user_data->current_result.len > ECS_RESPONSE_SIZE_LIMIT) {
  170. impl->function_table->aws_http_connection_close(ecs_user_data->connection);
  171. AWS_LOGF_ERROR(
  172. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  173. "(id=%p) ECS credentials provider query response exceeded maximum allowed length",
  174. (void *)ecs_user_data->ecs_provider);
  175. return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
  176. }
  177. if (aws_byte_buf_append_dynamic(&ecs_user_data->current_result, data)) {
  178. impl->function_table->aws_http_connection_close(ecs_user_data->connection);
  179. AWS_LOGF_ERROR(
  180. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  181. "(id=%p) ECS credentials provider query error appending response",
  182. (void *)ecs_user_data->ecs_provider);
  183. return AWS_OP_ERR;
  184. }
  185. return AWS_OP_SUCCESS;
  186. }
  187. static int s_ecs_on_incoming_headers_fn(
  188. struct aws_http_stream *stream,
  189. enum aws_http_header_block header_block,
  190. const struct aws_http_header *header_array,
  191. size_t num_headers,
  192. void *user_data) {
  193. (void)header_array;
  194. (void)num_headers;
  195. if (header_block != AWS_HTTP_HEADER_BLOCK_MAIN) {
  196. return AWS_OP_SUCCESS;
  197. }
  198. struct aws_credentials_provider_ecs_user_data *ecs_user_data = user_data;
  199. if (header_block == AWS_HTTP_HEADER_BLOCK_MAIN) {
  200. if (ecs_user_data->status_code == 0) {
  201. struct aws_credentials_provider_ecs_impl *impl = ecs_user_data->ecs_provider->impl;
  202. if (impl->function_table->aws_http_stream_get_incoming_response_status(
  203. stream, &ecs_user_data->status_code)) {
  204. AWS_LOGF_ERROR(
  205. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  206. "(id=%p) ECS credentials provider failed to get http status code",
  207. (void *)ecs_user_data->ecs_provider);
  208. return AWS_OP_ERR;
  209. }
  210. AWS_LOGF_DEBUG(
  211. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  212. "(id=%p) ECS credentials provider query received http status code %d",
  213. (void *)ecs_user_data->ecs_provider,
  214. ecs_user_data->status_code);
  215. }
  216. }
  217. return AWS_OP_SUCCESS;
  218. }
  219. static void s_ecs_query_task_role_credentials(struct aws_credentials_provider_ecs_user_data *ecs_user_data);
  220. static void s_ecs_on_stream_complete_fn(struct aws_http_stream *stream, int error_code, void *user_data) {
  221. struct aws_credentials_provider_ecs_user_data *ecs_user_data = user_data;
  222. aws_http_message_destroy(ecs_user_data->request);
  223. ecs_user_data->request = NULL;
  224. struct aws_credentials_provider_ecs_impl *impl = ecs_user_data->ecs_provider->impl;
  225. impl->function_table->aws_http_stream_release(stream);
  226. /*
  227. * On anything other than a 200, nullify the response and pretend there was
  228. * an error
  229. */
  230. if (ecs_user_data->status_code != AWS_HTTP_STATUS_CODE_200_OK || error_code != AWS_OP_SUCCESS) {
  231. ecs_user_data->current_result.len = 0;
  232. if (error_code != AWS_OP_SUCCESS) {
  233. ecs_user_data->error_code = error_code;
  234. } else {
  235. ecs_user_data->error_code = AWS_AUTH_CREDENTIALS_PROVIDER_HTTP_STATUS_FAILURE;
  236. }
  237. }
  238. s_ecs_finalize_get_credentials_query(ecs_user_data);
  239. }
  240. AWS_STATIC_STRING_FROM_LITERAL(s_ecs_accept_header, "Accept");
  241. AWS_STATIC_STRING_FROM_LITERAL(s_ecs_accept_header_value, "application/json");
  242. AWS_STATIC_STRING_FROM_LITERAL(s_ecs_user_agent_header, "User-Agent");
  243. AWS_STATIC_STRING_FROM_LITERAL(s_ecs_user_agent_header_value, "aws-sdk-crt/ecs-credentials-provider");
  244. AWS_STATIC_STRING_FROM_LITERAL(s_ecs_authorization_header, "Authorization");
  245. AWS_STATIC_STRING_FROM_LITERAL(s_ecs_accept_encoding_header, "Accept-Encoding");
  246. AWS_STATIC_STRING_FROM_LITERAL(s_ecs_accept_encoding_header_value, "identity");
  247. AWS_STATIC_STRING_FROM_LITERAL(s_ecs_host_header, "Host");
  248. static int s_make_ecs_http_query(
  249. struct aws_credentials_provider_ecs_user_data *ecs_user_data,
  250. struct aws_byte_cursor *uri) {
  251. AWS_FATAL_ASSERT(ecs_user_data->connection);
  252. struct aws_http_stream *stream = NULL;
  253. struct aws_http_message *request = aws_http_message_new_request(ecs_user_data->allocator);
  254. if (request == NULL) {
  255. return AWS_OP_ERR;
  256. }
  257. struct aws_credentials_provider_ecs_impl *impl = ecs_user_data->ecs_provider->impl;
  258. struct aws_http_header host_header = {
  259. .name = aws_byte_cursor_from_string(s_ecs_host_header),
  260. .value = aws_byte_cursor_from_string(impl->host),
  261. };
  262. if (aws_http_message_add_header(request, host_header)) {
  263. goto on_error;
  264. }
  265. if (impl->auth_token != NULL) {
  266. struct aws_http_header auth_header = {
  267. .name = aws_byte_cursor_from_string(s_ecs_authorization_header),
  268. .value = aws_byte_cursor_from_string(impl->auth_token),
  269. };
  270. if (aws_http_message_add_header(request, auth_header)) {
  271. goto on_error;
  272. }
  273. }
  274. struct aws_http_header accept_header = {
  275. .name = aws_byte_cursor_from_string(s_ecs_accept_header),
  276. .value = aws_byte_cursor_from_string(s_ecs_accept_header_value),
  277. };
  278. if (aws_http_message_add_header(request, accept_header)) {
  279. goto on_error;
  280. }
  281. struct aws_http_header accept_encoding_header = {
  282. .name = aws_byte_cursor_from_string(s_ecs_accept_encoding_header),
  283. .value = aws_byte_cursor_from_string(s_ecs_accept_encoding_header_value),
  284. };
  285. if (aws_http_message_add_header(request, accept_encoding_header)) {
  286. goto on_error;
  287. }
  288. struct aws_http_header user_agent_header = {
  289. .name = aws_byte_cursor_from_string(s_ecs_user_agent_header),
  290. .value = aws_byte_cursor_from_string(s_ecs_user_agent_header_value),
  291. };
  292. if (aws_http_message_add_header(request, user_agent_header)) {
  293. goto on_error;
  294. }
  295. if (aws_http_message_set_request_path(request, *uri)) {
  296. goto on_error;
  297. }
  298. if (aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("GET"))) {
  299. goto on_error;
  300. }
  301. ecs_user_data->request = request;
  302. struct aws_http_make_request_options request_options = {
  303. .self_size = sizeof(request_options),
  304. .on_response_headers = s_ecs_on_incoming_headers_fn,
  305. .on_response_header_block_done = NULL,
  306. .on_response_body = s_ecs_on_incoming_body_fn,
  307. .on_complete = s_ecs_on_stream_complete_fn,
  308. .user_data = ecs_user_data,
  309. .request = request,
  310. };
  311. stream = impl->function_table->aws_http_connection_make_request(ecs_user_data->connection, &request_options);
  312. if (!stream) {
  313. goto on_error;
  314. }
  315. if (impl->function_table->aws_http_stream_activate(stream)) {
  316. goto on_error;
  317. }
  318. return AWS_OP_SUCCESS;
  319. on_error:
  320. impl->function_table->aws_http_stream_release(stream);
  321. aws_http_message_destroy(request);
  322. ecs_user_data->request = NULL;
  323. return AWS_OP_ERR;
  324. }
  325. static void s_ecs_query_task_role_credentials(struct aws_credentials_provider_ecs_user_data *ecs_user_data) {
  326. AWS_FATAL_ASSERT(ecs_user_data->connection);
  327. struct aws_credentials_provider_ecs_impl *impl = ecs_user_data->ecs_provider->impl;
  328. /* "Clear" the result */
  329. s_aws_credentials_provider_ecs_user_data_reset_response(ecs_user_data);
  330. struct aws_byte_cursor uri_cursor = aws_byte_cursor_from_string(impl->path_and_query);
  331. if (s_make_ecs_http_query(ecs_user_data, &uri_cursor) == AWS_OP_ERR) {
  332. s_ecs_finalize_get_credentials_query(ecs_user_data);
  333. }
  334. }
  335. static void s_ecs_on_acquire_connection(struct aws_http_connection *connection, int error_code, void *user_data) {
  336. struct aws_credentials_provider_ecs_user_data *ecs_user_data = user_data;
  337. if (connection == NULL) {
  338. AWS_LOGF_WARN(
  339. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  340. "id=%p: ECS provider failed to acquire a connection, error code %d(%s)",
  341. (void *)ecs_user_data->ecs_provider,
  342. error_code,
  343. aws_error_str(error_code));
  344. ecs_user_data->error_code = error_code;
  345. s_ecs_finalize_get_credentials_query(ecs_user_data);
  346. return;
  347. }
  348. ecs_user_data->connection = connection;
  349. s_ecs_query_task_role_credentials(ecs_user_data);
  350. }
  351. static int s_credentials_provider_ecs_get_credentials_async(
  352. struct aws_credentials_provider *provider,
  353. aws_on_get_credentials_callback_fn callback,
  354. void *user_data) {
  355. struct aws_credentials_provider_ecs_impl *impl = provider->impl;
  356. struct aws_credentials_provider_ecs_user_data *wrapped_user_data =
  357. s_aws_credentials_provider_ecs_user_data_new(provider, callback, user_data);
  358. if (wrapped_user_data == NULL) {
  359. goto error;
  360. }
  361. impl->function_table->aws_http_connection_manager_acquire_connection(
  362. impl->connection_manager, s_ecs_on_acquire_connection, wrapped_user_data);
  363. return AWS_OP_SUCCESS;
  364. error:
  365. s_aws_credentials_provider_ecs_user_data_destroy(wrapped_user_data);
  366. return AWS_OP_ERR;
  367. }
  368. static void s_credentials_provider_ecs_destroy(struct aws_credentials_provider *provider) {
  369. struct aws_credentials_provider_ecs_impl *impl = provider->impl;
  370. if (impl == NULL) {
  371. return;
  372. }
  373. aws_string_destroy(impl->path_and_query);
  374. aws_string_destroy(impl->auth_token);
  375. aws_string_destroy(impl->host);
  376. /* aws_http_connection_manager_release will eventually leads to call of s_on_connection_manager_shutdown,
  377. * which will do memory release for provider and impl. So We should be freeing impl
  378. * related memory first, then call aws_http_connection_manager_release.
  379. */
  380. if (impl->connection_manager) {
  381. impl->function_table->aws_http_connection_manager_release(impl->connection_manager);
  382. } else {
  383. /* If provider setup failed halfway through, connection_manager might not exist.
  384. * In this case invoke shutdown completion callback directly to finish cleanup */
  385. s_on_connection_manager_shutdown(provider);
  386. }
  387. /* freeing the provider takes place in the shutdown callback below */
  388. }
  389. static struct aws_credentials_provider_vtable s_aws_credentials_provider_ecs_vtable = {
  390. .get_credentials = s_credentials_provider_ecs_get_credentials_async,
  391. .destroy = s_credentials_provider_ecs_destroy,
  392. };
  393. static void s_on_connection_manager_shutdown(void *user_data) {
  394. struct aws_credentials_provider *provider = user_data;
  395. aws_credentials_provider_invoke_shutdown_callback(provider);
  396. aws_mem_release(provider->allocator, provider);
  397. }
  398. struct aws_credentials_provider *aws_credentials_provider_new_ecs(
  399. struct aws_allocator *allocator,
  400. const struct aws_credentials_provider_ecs_options *options) {
  401. struct aws_credentials_provider *provider = NULL;
  402. struct aws_credentials_provider_ecs_impl *impl = NULL;
  403. aws_mem_acquire_many(
  404. allocator,
  405. 2,
  406. &provider,
  407. sizeof(struct aws_credentials_provider),
  408. &impl,
  409. sizeof(struct aws_credentials_provider_ecs_impl));
  410. if (!provider) {
  411. return NULL;
  412. }
  413. AWS_ZERO_STRUCT(*provider);
  414. AWS_ZERO_STRUCT(*impl);
  415. aws_credentials_provider_init_base(provider, allocator, &s_aws_credentials_provider_ecs_vtable, impl);
  416. struct aws_tls_connection_options tls_connection_options;
  417. AWS_ZERO_STRUCT(tls_connection_options);
  418. if (options->tls_ctx) {
  419. aws_tls_connection_options_init_from_ctx(&tls_connection_options, options->tls_ctx);
  420. struct aws_byte_cursor host = options->host;
  421. if (aws_tls_connection_options_set_server_name(&tls_connection_options, allocator, &host)) {
  422. AWS_LOGF_ERROR(
  423. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  424. "(id=%p): failed to create a tls connection options with error %s",
  425. (void *)provider,
  426. aws_error_debug_str(aws_last_error()));
  427. goto on_error;
  428. }
  429. }
  430. struct aws_socket_options socket_options;
  431. AWS_ZERO_STRUCT(socket_options);
  432. socket_options.type = AWS_SOCKET_STREAM;
  433. socket_options.domain = AWS_SOCKET_IPV4;
  434. socket_options.connect_timeout_ms = (uint32_t)aws_timestamp_convert(
  435. ECS_CONNECT_TIMEOUT_DEFAULT_IN_SECONDS, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_MILLIS, NULL);
  436. struct aws_http_connection_manager_options manager_options;
  437. AWS_ZERO_STRUCT(manager_options);
  438. manager_options.bootstrap = options->bootstrap;
  439. manager_options.initial_window_size = ECS_RESPONSE_SIZE_LIMIT;
  440. manager_options.socket_options = &socket_options;
  441. manager_options.host = options->host;
  442. if (options->port == 0) {
  443. manager_options.port = options->tls_ctx ? 443 : 80;
  444. } else {
  445. manager_options.port = options->port;
  446. }
  447. manager_options.max_connections = 2;
  448. manager_options.shutdown_complete_callback = s_on_connection_manager_shutdown;
  449. manager_options.shutdown_complete_user_data = provider;
  450. manager_options.tls_connection_options = options->tls_ctx ? &tls_connection_options : NULL;
  451. impl->function_table = options->function_table;
  452. if (impl->function_table == NULL) {
  453. impl->function_table = g_aws_credentials_provider_http_function_table;
  454. }
  455. impl->connection_manager = impl->function_table->aws_http_connection_manager_new(allocator, &manager_options);
  456. if (impl->connection_manager == NULL) {
  457. goto on_error;
  458. }
  459. if (options->auth_token.len != 0) {
  460. impl->auth_token = aws_string_new_from_cursor(allocator, &options->auth_token);
  461. if (impl->auth_token == NULL) {
  462. goto on_error;
  463. }
  464. }
  465. impl->path_and_query = aws_string_new_from_cursor(allocator, &options->path_and_query);
  466. if (impl->path_and_query == NULL) {
  467. goto on_error;
  468. }
  469. impl->host = aws_string_new_from_cursor(allocator, &options->host);
  470. if (impl->host == NULL) {
  471. goto on_error;
  472. }
  473. provider->shutdown_options = options->shutdown_options;
  474. aws_tls_connection_options_clean_up(&tls_connection_options);
  475. return provider;
  476. on_error:
  477. aws_tls_connection_options_clean_up(&tls_connection_options);
  478. aws_credentials_provider_destroy(provider);
  479. return NULL;
  480. }