credentials_provider_x509.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  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. #include <aws/common/json.h>
  19. #if defined(_MSC_VER)
  20. # pragma warning(disable : 4204)
  21. # pragma warning(disable : 4232)
  22. #endif /* _MSC_VER */
  23. /* IoT Core credentials body response is currently ~ 1100 Bytes*/
  24. #define X509_RESPONSE_SIZE_INITIAL 1024
  25. #define X509_RESPONSE_SIZE_LIMIT 2048
  26. #define X509_CONNECT_TIMEOUT_DEFAULT_IN_SECONDS 2
  27. struct aws_credentials_provider_x509_impl {
  28. struct aws_http_connection_manager *connection_manager;
  29. const struct aws_auth_http_system_vtable *function_table;
  30. struct aws_byte_buf thing_name;
  31. struct aws_byte_buf role_alias_path;
  32. struct aws_byte_buf endpoint;
  33. struct aws_tls_connection_options tls_connection_options;
  34. };
  35. /*
  36. * Tracking structure for each outstanding async query to an x509 provider
  37. */
  38. struct aws_credentials_provider_x509_user_data {
  39. /* immutable post-creation */
  40. struct aws_allocator *allocator;
  41. struct aws_credentials_provider *x509_provider;
  42. aws_on_get_credentials_callback_fn *original_callback;
  43. void *original_user_data;
  44. /* mutable */
  45. struct aws_http_connection *connection;
  46. struct aws_http_message *request;
  47. struct aws_byte_buf response;
  48. int status_code;
  49. int error_code;
  50. };
  51. static void s_aws_credentials_provider_x509_user_data_destroy(
  52. struct aws_credentials_provider_x509_user_data *user_data) {
  53. if (user_data == NULL) {
  54. return;
  55. }
  56. struct aws_credentials_provider_x509_impl *impl = user_data->x509_provider->impl;
  57. if (user_data->connection) {
  58. impl->function_table->aws_http_connection_manager_release_connection(
  59. impl->connection_manager, user_data->connection);
  60. }
  61. aws_byte_buf_clean_up(&user_data->response);
  62. if (user_data->request) {
  63. aws_http_message_destroy(user_data->request);
  64. }
  65. aws_credentials_provider_release(user_data->x509_provider);
  66. aws_mem_release(user_data->allocator, user_data);
  67. }
  68. static struct aws_credentials_provider_x509_user_data *s_aws_credentials_provider_x509_user_data_new(
  69. struct aws_credentials_provider *x509_provider,
  70. aws_on_get_credentials_callback_fn callback,
  71. void *user_data) {
  72. struct aws_credentials_provider_x509_user_data *wrapped_user_data =
  73. aws_mem_calloc(x509_provider->allocator, 1, sizeof(struct aws_credentials_provider_x509_user_data));
  74. if (wrapped_user_data == NULL) {
  75. goto on_error;
  76. }
  77. wrapped_user_data->allocator = x509_provider->allocator;
  78. wrapped_user_data->x509_provider = x509_provider;
  79. aws_credentials_provider_acquire(x509_provider);
  80. wrapped_user_data->original_user_data = user_data;
  81. wrapped_user_data->original_callback = callback;
  82. if (aws_byte_buf_init(&wrapped_user_data->response, x509_provider->allocator, X509_RESPONSE_SIZE_INITIAL)) {
  83. goto on_error;
  84. }
  85. return wrapped_user_data;
  86. on_error:
  87. s_aws_credentials_provider_x509_user_data_destroy(wrapped_user_data);
  88. return NULL;
  89. }
  90. static void s_aws_credentials_provider_x509_user_data_reset_response(
  91. struct aws_credentials_provider_x509_user_data *x509_user_data) {
  92. x509_user_data->response.len = 0;
  93. x509_user_data->status_code = 0;
  94. if (x509_user_data->request) {
  95. aws_http_message_destroy(x509_user_data->request);
  96. x509_user_data->request = NULL;
  97. }
  98. }
  99. /*
  100. * In general, the returned json document looks something like:
  101. {
  102. "credentials": {
  103. "accessKeyId" : "...",
  104. "secretAccessKey" : "...",
  105. "sessionToken" : "...",
  106. "expiration" : "2019-05-29T00:21:43Z"
  107. }
  108. }
  109. */
  110. static struct aws_credentials *s_parse_credentials_from_iot_core_document(
  111. struct aws_allocator *allocator,
  112. struct aws_byte_buf *document) {
  113. struct aws_credentials *credentials = NULL;
  114. struct aws_json_value *document_root = NULL;
  115. if (aws_byte_buf_append_null_terminator(document)) {
  116. goto done;
  117. }
  118. struct aws_byte_cursor document_cursor = aws_byte_cursor_from_buf(document);
  119. document_root = aws_json_value_new_from_string(allocator, document_cursor);
  120. if (document_root == NULL) {
  121. AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "Failed to parse IoT Core response as Json document.");
  122. goto done;
  123. }
  124. /*
  125. * pull out the root "Credentials" components
  126. */
  127. struct aws_json_value *creds =
  128. aws_json_value_get_from_object(document_root, aws_byte_cursor_from_c_str("credentials"));
  129. if (!aws_json_value_is_object(creds)) {
  130. AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "Failed to parse credentials from IoT Core response.");
  131. goto done;
  132. }
  133. struct aws_parse_credentials_from_json_doc_options parse_options = {
  134. .access_key_id_name = "accessKeyId",
  135. .secret_access_key_name = "secretAccessKey",
  136. .token_name = "sessionToken",
  137. .expiration_name = "expiration",
  138. .expiration_format = AWS_PCEF_STRING_ISO_8601_DATE,
  139. .token_required = true,
  140. .expiration_required = false,
  141. };
  142. credentials = aws_parse_credentials_from_aws_json_object(allocator, creds, &parse_options);
  143. if (!credentials) {
  144. AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "X509 credentials provider failed to parse credentials");
  145. }
  146. done:
  147. if (document_root != NULL) {
  148. aws_json_value_destroy(document_root);
  149. }
  150. return credentials;
  151. }
  152. /*
  153. * No matter the result, this always gets called assuming that x509_user_data is successfully allocated
  154. */
  155. static void s_x509_finalize_get_credentials_query(struct aws_credentials_provider_x509_user_data *x509_user_data) {
  156. /* Try to build credentials from whatever, if anything, was in the result */
  157. struct aws_credentials *credentials =
  158. s_parse_credentials_from_iot_core_document(x509_user_data->allocator, &x509_user_data->response);
  159. if (credentials != NULL) {
  160. AWS_LOGF_INFO(
  161. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  162. "(id=%p) X509 credentials provider successfully queried credentials",
  163. (void *)x509_user_data->x509_provider);
  164. } else {
  165. if (x509_user_data->error_code == AWS_ERROR_SUCCESS) {
  166. x509_user_data->error_code = aws_last_error();
  167. if (x509_user_data->error_code == AWS_ERROR_SUCCESS) {
  168. x509_user_data->error_code = AWS_AUTH_CREDENTIALS_PROVIDER_X509_SOURCE_FAILURE;
  169. }
  170. }
  171. AWS_LOGF_WARN(
  172. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  173. "(id=%p) X509 credentials provider failed to query credentials with error %d(%s)",
  174. (void *)x509_user_data->x509_provider,
  175. x509_user_data->error_code,
  176. aws_error_str(x509_user_data->error_code));
  177. }
  178. /* pass the credentials back */
  179. x509_user_data->original_callback(credentials, x509_user_data->error_code, x509_user_data->original_user_data);
  180. /* clean up */
  181. s_aws_credentials_provider_x509_user_data_destroy(x509_user_data);
  182. aws_credentials_release(credentials);
  183. }
  184. static int s_x509_on_incoming_body_fn(
  185. struct aws_http_stream *stream,
  186. const struct aws_byte_cursor *data,
  187. void *user_data) {
  188. (void)stream;
  189. struct aws_credentials_provider_x509_user_data *x509_user_data = user_data;
  190. struct aws_credentials_provider_x509_impl *impl = x509_user_data->x509_provider->impl;
  191. AWS_LOGF_TRACE(
  192. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  193. "(id=%p) X509 credentials provider received %zu response bytes",
  194. (void *)x509_user_data->x509_provider,
  195. data->len);
  196. if (data->len + x509_user_data->response.len > X509_RESPONSE_SIZE_LIMIT) {
  197. impl->function_table->aws_http_connection_close(x509_user_data->connection);
  198. AWS_LOGF_ERROR(
  199. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  200. "(id=%p) X509 credentials provider query response exceeded maximum allowed length",
  201. (void *)x509_user_data->x509_provider);
  202. return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
  203. }
  204. if (aws_byte_buf_append_dynamic(&x509_user_data->response, data)) {
  205. impl->function_table->aws_http_connection_close(x509_user_data->connection);
  206. AWS_LOGF_ERROR(
  207. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  208. "(id=%p) X509 credentials provider query error appending response",
  209. (void *)x509_user_data->x509_provider);
  210. return AWS_OP_ERR;
  211. }
  212. return AWS_OP_SUCCESS;
  213. }
  214. static int s_x509_on_incoming_headers_fn(
  215. struct aws_http_stream *stream,
  216. enum aws_http_header_block header_block,
  217. const struct aws_http_header *header_array,
  218. size_t num_headers,
  219. void *user_data) {
  220. (void)header_array;
  221. (void)num_headers;
  222. if (header_block != AWS_HTTP_HEADER_BLOCK_MAIN) {
  223. return AWS_OP_SUCCESS;
  224. }
  225. struct aws_credentials_provider_x509_user_data *x509_user_data = user_data;
  226. if (header_block == AWS_HTTP_HEADER_BLOCK_MAIN) {
  227. if (x509_user_data->status_code == 0) {
  228. struct aws_credentials_provider_x509_impl *impl = x509_user_data->x509_provider->impl;
  229. if (impl->function_table->aws_http_stream_get_incoming_response_status(
  230. stream, &x509_user_data->status_code)) {
  231. AWS_LOGF_ERROR(
  232. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  233. "(id=%p) X509 credentials provider failed to get http status code",
  234. (void *)x509_user_data->x509_provider);
  235. return AWS_OP_ERR;
  236. }
  237. AWS_LOGF_DEBUG(
  238. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  239. "(id=%p) X509 credentials provider query received http status code %d",
  240. (void *)x509_user_data->x509_provider,
  241. x509_user_data->status_code);
  242. }
  243. }
  244. return AWS_OP_SUCCESS;
  245. }
  246. static void s_x509_on_stream_complete_fn(struct aws_http_stream *stream, int error_code, void *user_data) {
  247. struct aws_credentials_provider_x509_user_data *x509_user_data = user_data;
  248. aws_http_message_destroy(x509_user_data->request);
  249. x509_user_data->request = NULL;
  250. struct aws_credentials_provider_x509_impl *impl = x509_user_data->x509_provider->impl;
  251. impl->function_table->aws_http_stream_release(stream);
  252. /*
  253. * On anything other than a 200, nullify the response and pretend there was
  254. * an error
  255. */
  256. if (x509_user_data->status_code != AWS_HTTP_STATUS_CODE_200_OK || error_code != AWS_OP_SUCCESS) {
  257. x509_user_data->response.len = 0;
  258. if (error_code != AWS_OP_SUCCESS) {
  259. x509_user_data->error_code = error_code;
  260. } else {
  261. x509_user_data->error_code = AWS_AUTH_CREDENTIALS_PROVIDER_HTTP_STATUS_FAILURE;
  262. }
  263. }
  264. s_x509_finalize_get_credentials_query(x509_user_data);
  265. }
  266. AWS_STATIC_STRING_FROM_LITERAL(s_x509_accept_header, "Accept");
  267. AWS_STATIC_STRING_FROM_LITERAL(s_x509_accept_header_value, "*/*");
  268. AWS_STATIC_STRING_FROM_LITERAL(s_x509_user_agent_header, "User-Agent");
  269. AWS_STATIC_STRING_FROM_LITERAL(s_x509_user_agent_header_value, "aws-sdk-crt/x509-credentials-provider");
  270. AWS_STATIC_STRING_FROM_LITERAL(s_x509_h1_0_keep_alive_header, "Connection");
  271. AWS_STATIC_STRING_FROM_LITERAL(s_x509_h1_0_keep_alive_header_value, "keep-alive");
  272. AWS_STATIC_STRING_FROM_LITERAL(s_x509_thing_name_header, "x-amzn-iot-thingname");
  273. AWS_STATIC_STRING_FROM_LITERAL(s_x509_host_header, "Host");
  274. static int s_make_x509_http_query(
  275. struct aws_credentials_provider_x509_user_data *x509_user_data,
  276. struct aws_byte_cursor *request_path) {
  277. AWS_FATAL_ASSERT(x509_user_data->connection);
  278. struct aws_http_stream *stream = NULL;
  279. struct aws_http_message *request = aws_http_message_new_request(x509_user_data->allocator);
  280. if (request == NULL) {
  281. return AWS_OP_ERR;
  282. }
  283. struct aws_credentials_provider_x509_impl *impl = x509_user_data->x509_provider->impl;
  284. struct aws_http_header thing_name_header = {
  285. .name = aws_byte_cursor_from_string(s_x509_thing_name_header),
  286. .value = aws_byte_cursor_from_buf(&impl->thing_name),
  287. };
  288. if (aws_http_message_add_header(request, thing_name_header)) {
  289. goto on_error;
  290. }
  291. struct aws_http_header accept_header = {
  292. .name = aws_byte_cursor_from_string(s_x509_accept_header),
  293. .value = aws_byte_cursor_from_string(s_x509_accept_header_value),
  294. };
  295. if (aws_http_message_add_header(request, accept_header)) {
  296. goto on_error;
  297. }
  298. struct aws_http_header user_agent_header = {
  299. .name = aws_byte_cursor_from_string(s_x509_user_agent_header),
  300. .value = aws_byte_cursor_from_string(s_x509_user_agent_header_value),
  301. };
  302. if (aws_http_message_add_header(request, user_agent_header)) {
  303. goto on_error;
  304. }
  305. struct aws_http_header keep_alive_header = {
  306. .name = aws_byte_cursor_from_string(s_x509_h1_0_keep_alive_header),
  307. .value = aws_byte_cursor_from_string(s_x509_h1_0_keep_alive_header_value),
  308. };
  309. if (aws_http_message_add_header(request, keep_alive_header)) {
  310. goto on_error;
  311. }
  312. struct aws_http_header host_header = {
  313. .name = aws_byte_cursor_from_string(s_x509_host_header),
  314. .value = aws_byte_cursor_from_buf(&impl->endpoint),
  315. };
  316. if (aws_http_message_add_header(request, host_header)) {
  317. goto on_error;
  318. }
  319. if (aws_http_message_set_request_path(request, *request_path)) {
  320. goto on_error;
  321. }
  322. if (aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("GET"))) {
  323. goto on_error;
  324. }
  325. x509_user_data->request = request;
  326. struct aws_http_make_request_options request_options = {
  327. .self_size = sizeof(request_options),
  328. .on_response_headers = s_x509_on_incoming_headers_fn,
  329. .on_response_header_block_done = NULL,
  330. .on_response_body = s_x509_on_incoming_body_fn,
  331. .on_complete = s_x509_on_stream_complete_fn,
  332. .user_data = x509_user_data,
  333. .request = request,
  334. };
  335. stream = impl->function_table->aws_http_connection_make_request(x509_user_data->connection, &request_options);
  336. if (!stream) {
  337. goto on_error;
  338. }
  339. if (impl->function_table->aws_http_stream_activate(stream)) {
  340. goto on_error;
  341. }
  342. return AWS_OP_SUCCESS;
  343. on_error:
  344. impl->function_table->aws_http_stream_release(stream);
  345. aws_http_message_destroy(request);
  346. x509_user_data->request = NULL;
  347. return AWS_OP_ERR;
  348. }
  349. static void s_x509_query_credentials(struct aws_credentials_provider_x509_user_data *x509_user_data) {
  350. AWS_FATAL_ASSERT(x509_user_data->connection);
  351. struct aws_credentials_provider_x509_impl *impl = x509_user_data->x509_provider->impl;
  352. /* "Clear" the result */
  353. s_aws_credentials_provider_x509_user_data_reset_response(x509_user_data);
  354. struct aws_byte_cursor request_path_cursor = aws_byte_cursor_from_buf(&impl->role_alias_path);
  355. if (s_make_x509_http_query(x509_user_data, &request_path_cursor) == AWS_OP_ERR) {
  356. s_x509_finalize_get_credentials_query(x509_user_data);
  357. }
  358. }
  359. static void s_x509_on_acquire_connection(struct aws_http_connection *connection, int error_code, void *user_data) {
  360. struct aws_credentials_provider_x509_user_data *x509_user_data = user_data;
  361. if (connection == NULL) {
  362. AWS_LOGF_WARN(
  363. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  364. "id=%p: X509 provider failed to acquire a connection, error code %d(%s)",
  365. (void *)x509_user_data->x509_provider,
  366. error_code,
  367. aws_error_str(error_code));
  368. x509_user_data->error_code = error_code;
  369. s_x509_finalize_get_credentials_query(x509_user_data);
  370. return;
  371. }
  372. x509_user_data->connection = connection;
  373. s_x509_query_credentials(x509_user_data);
  374. }
  375. static int s_credentials_provider_x509_get_credentials_async(
  376. struct aws_credentials_provider *provider,
  377. aws_on_get_credentials_callback_fn callback,
  378. void *user_data) {
  379. struct aws_credentials_provider_x509_impl *impl = provider->impl;
  380. struct aws_credentials_provider_x509_user_data *wrapped_user_data =
  381. s_aws_credentials_provider_x509_user_data_new(provider, callback, user_data);
  382. if (wrapped_user_data == NULL) {
  383. goto error;
  384. }
  385. impl->function_table->aws_http_connection_manager_acquire_connection(
  386. impl->connection_manager, s_x509_on_acquire_connection, wrapped_user_data);
  387. return AWS_OP_SUCCESS;
  388. error:
  389. s_aws_credentials_provider_x509_user_data_destroy(wrapped_user_data);
  390. return AWS_OP_ERR;
  391. }
  392. static void s_credentials_provider_x509_destroy(struct aws_credentials_provider *provider) {
  393. struct aws_credentials_provider_x509_impl *impl = provider->impl;
  394. if (impl == NULL) {
  395. return;
  396. }
  397. aws_byte_buf_clean_up(&impl->thing_name);
  398. aws_byte_buf_clean_up(&impl->role_alias_path);
  399. aws_byte_buf_clean_up(&impl->endpoint);
  400. aws_tls_connection_options_clean_up(&impl->tls_connection_options);
  401. /* aws_http_connection_manager_release will eventually leads to call of s_on_connection_manager_shutdown,
  402. * which will do memory release for provider and impl. So We should be freeing impl
  403. * related memory first, then call aws_http_connection_manager_release.
  404. */
  405. impl->function_table->aws_http_connection_manager_release(impl->connection_manager);
  406. /* freeing the provider takes place in the shutdown callback below */
  407. }
  408. static struct aws_credentials_provider_vtable s_aws_credentials_provider_x509_vtable = {
  409. .get_credentials = s_credentials_provider_x509_get_credentials_async,
  410. .destroy = s_credentials_provider_x509_destroy,
  411. };
  412. static void s_on_connection_manager_shutdown(void *user_data) {
  413. struct aws_credentials_provider *provider = user_data;
  414. aws_credentials_provider_invoke_shutdown_callback(provider);
  415. aws_mem_release(provider->allocator, provider);
  416. }
  417. struct aws_credentials_provider *aws_credentials_provider_new_x509(
  418. struct aws_allocator *allocator,
  419. const struct aws_credentials_provider_x509_options *options) {
  420. struct aws_credentials_provider *provider = NULL;
  421. struct aws_credentials_provider_x509_impl *impl = NULL;
  422. if (options->tls_connection_options == NULL || options->thing_name.len == 0 || options->role_alias.len == 0) {
  423. AWS_LOGF_ERROR(
  424. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  425. "To create an X.509 creds provider, a tls_connection_options, an IoT thing name and an IAM role alias are "
  426. "required.");
  427. goto on_error;
  428. }
  429. aws_mem_acquire_many(
  430. allocator,
  431. 2,
  432. &provider,
  433. sizeof(struct aws_credentials_provider),
  434. &impl,
  435. sizeof(struct aws_credentials_provider_x509_impl));
  436. if (!provider) {
  437. return NULL;
  438. }
  439. AWS_ZERO_STRUCT(*provider);
  440. AWS_ZERO_STRUCT(*impl);
  441. aws_credentials_provider_init_base(provider, allocator, &s_aws_credentials_provider_x509_vtable, impl);
  442. if (aws_tls_connection_options_copy(&impl->tls_connection_options, options->tls_connection_options)) {
  443. goto on_error;
  444. }
  445. struct aws_byte_cursor server_name = options->endpoint;
  446. if (aws_tls_connection_options_set_server_name(&impl->tls_connection_options, allocator, &(server_name))) {
  447. AWS_LOGF_ERROR(
  448. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  449. "(id=%p): failed to set tls connection options's server name with error %s",
  450. (void *)provider,
  451. aws_error_debug_str(aws_last_error()));
  452. goto on_error;
  453. }
  454. struct aws_socket_options socket_options;
  455. AWS_ZERO_STRUCT(socket_options);
  456. socket_options.type = AWS_SOCKET_STREAM;
  457. socket_options.domain = AWS_SOCKET_IPV4;
  458. socket_options.connect_timeout_ms = (uint32_t)aws_timestamp_convert(
  459. X509_CONNECT_TIMEOUT_DEFAULT_IN_SECONDS, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_MILLIS, NULL);
  460. struct aws_http_connection_manager_options manager_options;
  461. AWS_ZERO_STRUCT(manager_options);
  462. manager_options.bootstrap = options->bootstrap;
  463. manager_options.initial_window_size = X509_RESPONSE_SIZE_LIMIT;
  464. manager_options.socket_options = &socket_options;
  465. manager_options.host = options->endpoint;
  466. manager_options.port = 443;
  467. manager_options.max_connections = 2;
  468. manager_options.shutdown_complete_callback = s_on_connection_manager_shutdown;
  469. manager_options.shutdown_complete_user_data = provider;
  470. manager_options.tls_connection_options = &impl->tls_connection_options;
  471. manager_options.proxy_options = options->proxy_options;
  472. impl->function_table = options->function_table;
  473. if (impl->function_table == NULL) {
  474. impl->function_table = g_aws_credentials_provider_http_function_table;
  475. }
  476. impl->connection_manager = impl->function_table->aws_http_connection_manager_new(allocator, &manager_options);
  477. if (impl->connection_manager == NULL) {
  478. goto on_error;
  479. }
  480. if (aws_byte_buf_init_copy_from_cursor(&impl->thing_name, allocator, options->thing_name)) {
  481. goto on_error;
  482. }
  483. if (aws_byte_buf_init_copy_from_cursor(&impl->endpoint, allocator, options->endpoint)) {
  484. goto on_error;
  485. }
  486. /* the expected path is "/role-aliases/<your role alias>/credentials" */
  487. struct aws_byte_cursor prefix_cursor = aws_byte_cursor_from_c_str("/role-aliases/");
  488. if (aws_byte_buf_init_copy_from_cursor(&impl->role_alias_path, allocator, prefix_cursor)) {
  489. goto on_error;
  490. }
  491. if (aws_byte_buf_append_dynamic(&impl->role_alias_path, &options->role_alias)) {
  492. goto on_error;
  493. }
  494. struct aws_byte_cursor creds_cursor = aws_byte_cursor_from_c_str("/credentials");
  495. if (aws_byte_buf_append_dynamic(&impl->role_alias_path, &creds_cursor)) {
  496. goto on_error;
  497. }
  498. provider->shutdown_options = options->shutdown_options;
  499. return provider;
  500. on_error:
  501. aws_credentials_provider_destroy(provider);
  502. return NULL;
  503. }