sso_token_utils.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/auth/private/sso_token_utils.h>
  6. #include <aws/cal/hash.h>
  7. #include <aws/common/encoding.h>
  8. #include <aws/common/file.h>
  9. #include <aws/common/json.h>
  10. #if defined(_MSC_VER)
  11. # pragma warning(disable : 4232)
  12. #endif /* _MSC_VER */
  13. struct aws_string *aws_construct_sso_token_path(struct aws_allocator *allocator, const struct aws_string *input) {
  14. AWS_PRECONDITION(input);
  15. struct aws_string *sso_token_path_str = NULL;
  16. struct aws_string *home_directory = aws_get_home_directory(allocator);
  17. if (!home_directory) {
  18. return NULL;
  19. }
  20. struct aws_byte_cursor home_dir_cursor = aws_byte_cursor_from_string(home_directory);
  21. struct aws_byte_cursor input_cursor = aws_byte_cursor_from_string(input);
  22. struct aws_byte_cursor json_cursor = aws_byte_cursor_from_c_str(".json");
  23. struct aws_byte_buf sso_token_path_buf;
  24. AWS_ZERO_STRUCT(sso_token_path_buf);
  25. struct aws_byte_buf sha1_buf;
  26. AWS_ZERO_STRUCT(sha1_buf);
  27. /* append home directory */
  28. if (aws_byte_buf_init_copy_from_cursor(&sso_token_path_buf, allocator, home_dir_cursor)) {
  29. goto cleanup;
  30. }
  31. /* append sso cache directory */
  32. struct aws_byte_cursor sso_cache_dir_cursor = aws_byte_cursor_from_c_str("/.aws/sso/cache/");
  33. if (aws_byte_buf_append_dynamic(&sso_token_path_buf, &sso_cache_dir_cursor)) {
  34. goto cleanup;
  35. }
  36. /* append hex encoded sha1 of input */
  37. if (aws_byte_buf_init(&sha1_buf, allocator, AWS_SHA1_LEN) ||
  38. aws_sha1_compute(allocator, &input_cursor, &sha1_buf, 0)) {
  39. goto cleanup;
  40. }
  41. struct aws_byte_cursor sha1_cursor = aws_byte_cursor_from_buf(&sha1_buf);
  42. if (aws_hex_encode_append_dynamic(&sha1_cursor, &sso_token_path_buf)) {
  43. goto cleanup;
  44. }
  45. /* append .json */
  46. if (aws_byte_buf_append_dynamic(&sso_token_path_buf, &json_cursor)) {
  47. goto cleanup;
  48. }
  49. /* use platform-specific directory separator. */
  50. aws_normalize_directory_separator(&sso_token_path_buf);
  51. sso_token_path_str = aws_string_new_from_buf(allocator, &sso_token_path_buf);
  52. AWS_LOGF_INFO(
  53. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  54. "successfully constructed token path: %s",
  55. aws_string_c_str(sso_token_path_str));
  56. cleanup:
  57. aws_byte_buf_clean_up(&sso_token_path_buf);
  58. aws_byte_buf_clean_up(&sha1_buf);
  59. aws_string_destroy(home_directory);
  60. return sso_token_path_str;
  61. }
  62. void aws_sso_token_destroy(struct aws_sso_token *sso_token) {
  63. if (sso_token == NULL) {
  64. return;
  65. }
  66. aws_string_destroy(sso_token->access_token);
  67. aws_mem_release(sso_token->allocator, sso_token);
  68. }
  69. struct aws_sso_token *aws_sso_token_new_from_file(struct aws_allocator *allocator, const struct aws_string *file_path) {
  70. AWS_PRECONDITION(allocator);
  71. AWS_PRECONDITION(file_path);
  72. bool success = false;
  73. struct aws_sso_token *token = aws_mem_calloc(allocator, 1, sizeof(struct aws_sso_token));
  74. token->allocator = allocator;
  75. struct aws_byte_buf file_contents_buf;
  76. AWS_ZERO_STRUCT(file_contents_buf);
  77. struct aws_json_value *document_root = NULL;
  78. if (aws_byte_buf_init_from_file(&file_contents_buf, allocator, aws_string_c_str(file_path))) {
  79. AWS_LOGF_ERROR(
  80. AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso token: failed to load token file %s", aws_string_c_str(file_path));
  81. goto cleanup;
  82. }
  83. struct aws_byte_cursor document_cursor = aws_byte_cursor_from_buf(&file_contents_buf);
  84. document_root = aws_json_value_new_from_string(allocator, document_cursor);
  85. if (document_root == NULL) {
  86. AWS_LOGF_ERROR(
  87. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  88. "sso token: failed to parse sso token file %s",
  89. aws_string_c_str(file_path));
  90. aws_raise_error(AWS_AUTH_SSO_TOKEN_INVALID);
  91. goto cleanup;
  92. }
  93. struct aws_byte_cursor access_token_cursor;
  94. struct aws_json_value *access_token =
  95. aws_json_value_get_from_object(document_root, aws_byte_cursor_from_c_str("accessToken"));
  96. if (!aws_json_value_is_string(access_token) || aws_json_value_get_string(access_token, &access_token_cursor)) {
  97. AWS_LOGF_ERROR(
  98. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  99. "sso token: failed to parse accessToken from %s",
  100. aws_string_c_str(file_path));
  101. aws_raise_error(AWS_AUTH_SSO_TOKEN_INVALID);
  102. goto cleanup;
  103. }
  104. struct aws_byte_cursor expires_at_cursor;
  105. struct aws_json_value *expires_at =
  106. aws_json_value_get_from_object(document_root, aws_byte_cursor_from_c_str("expiresAt"));
  107. if (!aws_json_value_is_string(expires_at) || aws_json_value_get_string(expires_at, &expires_at_cursor)) {
  108. AWS_LOGF_ERROR(
  109. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  110. "sso token: failed to parse expiresAt from %s",
  111. aws_string_c_str(file_path));
  112. aws_raise_error(AWS_AUTH_SSO_TOKEN_INVALID);
  113. goto cleanup;
  114. }
  115. struct aws_date_time expiration;
  116. if (aws_date_time_init_from_str_cursor(&expiration, &expires_at_cursor, AWS_DATE_FORMAT_ISO_8601)) {
  117. AWS_LOGF_ERROR(
  118. AWS_LS_AUTH_CREDENTIALS_PROVIDER,
  119. "sso token: expiresAt '" PRInSTR "' in %s is not a valid ISO-8601 date string",
  120. AWS_BYTE_CURSOR_PRI(expires_at_cursor),
  121. aws_string_c_str(file_path));
  122. aws_raise_error(AWS_AUTH_SSO_TOKEN_INVALID);
  123. goto cleanup;
  124. }
  125. token->access_token = aws_string_new_from_cursor(allocator, &access_token_cursor);
  126. token->expiration = expiration;
  127. success = true;
  128. cleanup:
  129. aws_json_value_destroy(document_root);
  130. aws_byte_buf_clean_up(&file_contents_buf);
  131. if (!success) {
  132. aws_sso_token_destroy(token);
  133. token = NULL;
  134. }
  135. return token;
  136. }