credentials_provider_imds.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/auth/aws_imds_client.h>
  6. #include <aws/auth/credentials.h>
  7. #include <aws/auth/private/credentials_utils.h>
  8. #include <aws/common/string.h>
  9. #if defined(_MSC_VER)
  10. # pragma warning(disable : 4204)
  11. #endif /* _MSC_VER */
  12. struct aws_credentials_provider_imds_impl {
  13. struct aws_imds_client *client;
  14. };
  15. static int s_credentials_provider_imds_get_credentials_async(
  16. struct aws_credentials_provider *provider,
  17. aws_on_get_credentials_callback_fn callback,
  18. void *user_data);
  19. static void s_on_imds_client_shutdown(void *user_data);
  20. static void s_credentials_provider_imds_destroy(struct aws_credentials_provider *provider) {
  21. struct aws_credentials_provider_imds_impl *impl = provider->impl;
  22. if (impl == NULL) {
  23. return;
  24. }
  25. if (impl->client) {
  26. /* release IMDS client, cleanup will finish when its shutdown callback fires */
  27. aws_imds_client_release(impl->client);
  28. } else {
  29. /* If provider setup failed halfway through, IMDS client might not exist.
  30. * In this case invoke shutdown completion callback directly to finish cleanup */
  31. s_on_imds_client_shutdown(provider);
  32. }
  33. }
  34. static void s_on_imds_client_shutdown(void *user_data) {
  35. struct aws_credentials_provider *provider = user_data;
  36. aws_credentials_provider_invoke_shutdown_callback(provider);
  37. aws_mem_release(provider->allocator, provider);
  38. }
  39. static struct aws_credentials_provider_vtable s_aws_credentials_provider_imds_vtable = {
  40. .get_credentials = s_credentials_provider_imds_get_credentials_async,
  41. .destroy = s_credentials_provider_imds_destroy,
  42. };
  43. struct aws_credentials_provider *aws_credentials_provider_new_imds(
  44. struct aws_allocator *allocator,
  45. const struct aws_credentials_provider_imds_options *options) {
  46. if (!options->bootstrap) {
  47. AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "Client bootstrap is required for querying IMDS");
  48. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  49. return NULL;
  50. }
  51. struct aws_credentials_provider *provider = NULL;
  52. struct aws_credentials_provider_imds_impl *impl = NULL;
  53. aws_mem_acquire_many(
  54. allocator,
  55. 2,
  56. &provider,
  57. sizeof(struct aws_credentials_provider),
  58. &impl,
  59. sizeof(struct aws_credentials_provider_imds_impl));
  60. if (!provider) {
  61. return NULL;
  62. }
  63. AWS_ZERO_STRUCT(*provider);
  64. AWS_ZERO_STRUCT(*impl);
  65. aws_credentials_provider_init_base(provider, allocator, &s_aws_credentials_provider_imds_vtable, impl);
  66. struct aws_imds_client_options client_options = {
  67. .bootstrap = options->bootstrap,
  68. .function_table = options->function_table,
  69. .imds_version = options->imds_version,
  70. .shutdown_options =
  71. {
  72. .shutdown_callback = s_on_imds_client_shutdown,
  73. .shutdown_user_data = provider,
  74. },
  75. };
  76. impl->client = aws_imds_client_new(allocator, &client_options);
  77. if (!impl->client) {
  78. goto on_error;
  79. }
  80. provider->shutdown_options = options->shutdown_options;
  81. return provider;
  82. on_error:
  83. aws_credentials_provider_destroy(provider);
  84. return NULL;
  85. }
  86. /*
  87. * Tracking structure for each outstanding async query to an imds provider
  88. */
  89. struct imds_provider_user_data {
  90. /* immutable post-creation */
  91. struct aws_allocator *allocator;
  92. struct aws_credentials_provider *imds_provider;
  93. aws_on_get_credentials_callback_fn *original_callback;
  94. struct aws_byte_buf role;
  95. void *original_user_data;
  96. };
  97. static void s_imds_provider_user_data_destroy(struct imds_provider_user_data *user_data) {
  98. if (user_data == NULL) {
  99. return;
  100. }
  101. aws_byte_buf_clean_up(&user_data->role);
  102. aws_credentials_provider_release(user_data->imds_provider);
  103. aws_mem_release(user_data->allocator, user_data);
  104. }
  105. static struct imds_provider_user_data *s_imds_provider_user_data_new(
  106. struct aws_credentials_provider *imds_provider,
  107. aws_on_get_credentials_callback_fn callback,
  108. void *user_data) {
  109. struct imds_provider_user_data *wrapped_user_data =
  110. aws_mem_calloc(imds_provider->allocator, 1, sizeof(struct imds_provider_user_data));
  111. if (wrapped_user_data == NULL) {
  112. goto on_error;
  113. }
  114. if (aws_byte_buf_init(&wrapped_user_data->role, imds_provider->allocator, 100)) {
  115. goto on_error;
  116. }
  117. wrapped_user_data->allocator = imds_provider->allocator;
  118. wrapped_user_data->imds_provider = imds_provider;
  119. aws_credentials_provider_acquire(imds_provider);
  120. wrapped_user_data->original_user_data = user_data;
  121. wrapped_user_data->original_callback = callback;
  122. return wrapped_user_data;
  123. on_error:
  124. s_imds_provider_user_data_destroy(wrapped_user_data);
  125. return NULL;
  126. }
  127. static void s_on_get_credentials(const struct aws_credentials *credentials, int error_code, void *user_data) {
  128. (void)error_code;
  129. struct imds_provider_user_data *wrapped_user_data = user_data;
  130. wrapped_user_data->original_callback(
  131. (struct aws_credentials *)credentials, error_code, wrapped_user_data->original_user_data);
  132. s_imds_provider_user_data_destroy(wrapped_user_data);
  133. }
  134. static void s_on_get_role(const struct aws_byte_buf *role, int error_code, void *user_data) {
  135. struct imds_provider_user_data *wrapped_user_data = user_data;
  136. if (!role || error_code || role->len == 0) {
  137. goto on_error;
  138. }
  139. struct aws_byte_cursor role_cursor = aws_byte_cursor_from_buf(role);
  140. if (aws_byte_buf_append_dynamic(&wrapped_user_data->role, &role_cursor)) {
  141. goto on_error;
  142. }
  143. struct aws_credentials_provider_imds_impl *impl = wrapped_user_data->imds_provider->impl;
  144. if (aws_imds_client_get_credentials(
  145. impl->client, aws_byte_cursor_from_buf(&wrapped_user_data->role), s_on_get_credentials, user_data)) {
  146. goto on_error;
  147. }
  148. return;
  149. on_error:
  150. wrapped_user_data->original_callback(
  151. NULL, AWS_AUTH_CREDENTIALS_PROVIDER_IMDS_SOURCE_FAILURE, wrapped_user_data->original_user_data);
  152. s_imds_provider_user_data_destroy(wrapped_user_data);
  153. }
  154. static int s_credentials_provider_imds_get_credentials_async(
  155. struct aws_credentials_provider *provider,
  156. aws_on_get_credentials_callback_fn callback,
  157. void *user_data) {
  158. struct aws_credentials_provider_imds_impl *impl = provider->impl;
  159. struct imds_provider_user_data *wrapped_user_data = s_imds_provider_user_data_new(provider, callback, user_data);
  160. if (wrapped_user_data == NULL) {
  161. goto error;
  162. }
  163. if (aws_imds_client_get_attached_iam_role(impl->client, s_on_get_role, wrapped_user_data)) {
  164. goto error;
  165. }
  166. return AWS_OP_SUCCESS;
  167. error:
  168. s_imds_provider_user_data_destroy(wrapped_user_data);
  169. return AWS_OP_ERR;
  170. }