endpoints_standard_lib.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/common/json.h>
  6. #include <aws/common/string.h>
  7. #include <aws/common/uri.h>
  8. #include <aws/sdkutils/private/endpoints_types_impl.h>
  9. #include <aws/sdkutils/private/endpoints_util.h>
  10. #include <aws/sdkutils/resource_name.h>
  11. static struct aws_byte_cursor s_scheme_http = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("http");
  12. static struct aws_byte_cursor s_scheme_https = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("https");
  13. static int s_resolve_fn_is_set(
  14. struct aws_allocator *allocator,
  15. struct aws_array_list *argv,
  16. struct aws_endpoints_resolution_scope *scope,
  17. struct aws_endpoints_value *out_value) {
  18. int result = AWS_OP_SUCCESS;
  19. struct aws_endpoints_value argv_value = {0};
  20. if (aws_array_list_length(argv) != 1 ||
  21. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_ANY, &argv_value)) {
  22. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve args for isSet.");
  23. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  24. goto on_done;
  25. }
  26. out_value->type = AWS_ENDPOINTS_VALUE_BOOLEAN;
  27. out_value->v.boolean = argv_value.type != AWS_ENDPOINTS_VALUE_NONE;
  28. on_done:
  29. aws_endpoints_value_clean_up(&argv_value);
  30. return result;
  31. }
  32. static int s_resolve_fn_not(
  33. struct aws_allocator *allocator,
  34. struct aws_array_list *argv,
  35. struct aws_endpoints_resolution_scope *scope,
  36. struct aws_endpoints_value *out_value) {
  37. int result = AWS_OP_SUCCESS;
  38. struct aws_endpoints_value argv_value = {0};
  39. if (aws_array_list_length(argv) != 1 ||
  40. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_BOOLEAN, &argv_value)) {
  41. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve args for not.");
  42. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  43. goto on_done;
  44. }
  45. out_value->type = AWS_ENDPOINTS_VALUE_BOOLEAN;
  46. out_value->v.boolean = !argv_value.v.boolean;
  47. on_done:
  48. aws_endpoints_value_clean_up(&argv_value);
  49. return result;
  50. }
  51. static int s_resolve_fn_get_attr(
  52. struct aws_allocator *allocator,
  53. struct aws_array_list *argv,
  54. struct aws_endpoints_resolution_scope *scope,
  55. struct aws_endpoints_value *out_value) {
  56. int result = AWS_OP_SUCCESS;
  57. struct aws_endpoints_value argv_value = {0};
  58. struct aws_endpoints_value argv_path = {0};
  59. if (aws_array_list_length(argv) != 2 ||
  60. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_ANY, &argv_value) ||
  61. aws_endpoints_argv_expect(allocator, scope, argv, 1, AWS_ENDPOINTS_VALUE_STRING, &argv_path)) {
  62. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve args for get attr.");
  63. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  64. goto on_done;
  65. }
  66. struct aws_byte_cursor path_cur = argv_path.v.owning_cursor_string.cur;
  67. if (argv_value.type == AWS_ENDPOINTS_VALUE_OBJECT) {
  68. if (aws_endpoints_path_through_object(allocator, &argv_value, path_cur, out_value)) {
  69. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to path through object.");
  70. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  71. goto on_done;
  72. }
  73. } else if (argv_value.type == AWS_ENDPOINTS_VALUE_ARRAY) {
  74. if (aws_endpoints_path_through_array(allocator, scope, &argv_value, path_cur, out_value)) {
  75. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to path through array.");
  76. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  77. goto on_done;
  78. }
  79. } else {
  80. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Invalid value type for pathing through.");
  81. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  82. goto on_done;
  83. }
  84. on_done:
  85. aws_endpoints_value_clean_up(&argv_value);
  86. aws_endpoints_value_clean_up(&argv_path);
  87. return result;
  88. }
  89. static int s_resolve_fn_substring(
  90. struct aws_allocator *allocator,
  91. struct aws_array_list *argv,
  92. struct aws_endpoints_resolution_scope *scope,
  93. struct aws_endpoints_value *out_value) {
  94. int result = AWS_OP_SUCCESS;
  95. struct aws_endpoints_value input_value = {0};
  96. struct aws_endpoints_value start_value = {0};
  97. struct aws_endpoints_value stop_value = {0};
  98. struct aws_endpoints_value reverse_value = {0};
  99. if (aws_array_list_length(argv) != 4 ||
  100. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_STRING, &input_value) ||
  101. aws_endpoints_argv_expect(allocator, scope, argv, 1, AWS_ENDPOINTS_VALUE_NUMBER, &start_value) ||
  102. aws_endpoints_argv_expect(allocator, scope, argv, 2, AWS_ENDPOINTS_VALUE_NUMBER, &stop_value) ||
  103. aws_endpoints_argv_expect(allocator, scope, argv, 3, AWS_ENDPOINTS_VALUE_BOOLEAN, &reverse_value)) {
  104. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve args for substring.");
  105. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  106. goto on_done;
  107. }
  108. if (start_value.v.number >= stop_value.v.number ||
  109. input_value.v.owning_cursor_string.cur.len < stop_value.v.number) {
  110. out_value->type = AWS_ENDPOINTS_VALUE_NONE;
  111. goto on_done;
  112. }
  113. for (size_t idx = 0; idx < input_value.v.owning_cursor_string.cur.len; ++idx) {
  114. if (input_value.v.owning_cursor_string.cur.ptr[idx] > 127) {
  115. out_value->type = AWS_ENDPOINTS_VALUE_NONE;
  116. goto on_done;
  117. }
  118. }
  119. if (!reverse_value.v.boolean) {
  120. size_t start = (size_t)start_value.v.number;
  121. size_t end = (size_t)stop_value.v.number;
  122. struct aws_byte_cursor substring = {
  123. .ptr = input_value.v.owning_cursor_string.cur.ptr + start,
  124. .len = end - start,
  125. };
  126. out_value->type = AWS_ENDPOINTS_VALUE_STRING;
  127. out_value->v.owning_cursor_string = aws_endpoints_owning_cursor_from_cursor(allocator, substring);
  128. } else {
  129. size_t r_start = input_value.v.owning_cursor_string.cur.len - (size_t)stop_value.v.number;
  130. size_t r_stop = input_value.v.owning_cursor_string.cur.len - (size_t)start_value.v.number;
  131. struct aws_byte_cursor substring = {
  132. .ptr = input_value.v.owning_cursor_string.cur.ptr + r_start,
  133. .len = r_stop - r_start,
  134. };
  135. out_value->type = AWS_ENDPOINTS_VALUE_STRING;
  136. out_value->v.owning_cursor_string = aws_endpoints_owning_cursor_from_cursor(allocator, substring);
  137. }
  138. on_done:
  139. aws_endpoints_value_clean_up(&input_value);
  140. aws_endpoints_value_clean_up(&start_value);
  141. aws_endpoints_value_clean_up(&stop_value);
  142. aws_endpoints_value_clean_up(&reverse_value);
  143. return result;
  144. }
  145. static int s_resolve_fn_string_equals(
  146. struct aws_allocator *allocator,
  147. struct aws_array_list *argv,
  148. struct aws_endpoints_resolution_scope *scope,
  149. struct aws_endpoints_value *out_value) {
  150. int result = AWS_OP_SUCCESS;
  151. struct aws_endpoints_value argv_value_1 = {0};
  152. struct aws_endpoints_value argv_value_2 = {0};
  153. if (aws_array_list_length(argv) != 2 ||
  154. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_STRING, &argv_value_1) ||
  155. aws_endpoints_argv_expect(allocator, scope, argv, 1, AWS_ENDPOINTS_VALUE_STRING, &argv_value_2)) {
  156. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve stringEquals.");
  157. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  158. goto on_done;
  159. }
  160. out_value->type = AWS_ENDPOINTS_VALUE_BOOLEAN;
  161. out_value->v.boolean =
  162. aws_byte_cursor_eq(&argv_value_1.v.owning_cursor_string.cur, &argv_value_2.v.owning_cursor_string.cur);
  163. on_done:
  164. aws_endpoints_value_clean_up(&argv_value_1);
  165. aws_endpoints_value_clean_up(&argv_value_2);
  166. return result;
  167. }
  168. static int s_resolve_fn_boolean_equals(
  169. struct aws_allocator *allocator,
  170. struct aws_array_list *argv,
  171. struct aws_endpoints_resolution_scope *scope,
  172. struct aws_endpoints_value *out_value) {
  173. int result = AWS_OP_SUCCESS;
  174. struct aws_endpoints_value argv_value_1 = {0};
  175. struct aws_endpoints_value argv_value_2 = {0};
  176. if (aws_array_list_length(argv) != 2 ||
  177. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_BOOLEAN, &argv_value_1) ||
  178. aws_endpoints_argv_expect(allocator, scope, argv, 1, AWS_ENDPOINTS_VALUE_BOOLEAN, &argv_value_2)) {
  179. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve booleanEquals.");
  180. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  181. goto on_done;
  182. }
  183. out_value->type = AWS_ENDPOINTS_VALUE_BOOLEAN;
  184. out_value->v.boolean = argv_value_1.v.boolean == argv_value_2.v.boolean;
  185. on_done:
  186. aws_endpoints_value_clean_up(&argv_value_1);
  187. aws_endpoints_value_clean_up(&argv_value_2);
  188. return result;
  189. }
  190. static int s_resolve_fn_uri_encode(
  191. struct aws_allocator *allocator,
  192. struct aws_array_list *argv,
  193. struct aws_endpoints_resolution_scope *scope,
  194. struct aws_endpoints_value *out_value) {
  195. int result = AWS_OP_SUCCESS;
  196. struct aws_byte_buf buf = {0};
  197. struct aws_endpoints_value argv_value = {0};
  198. if (aws_array_list_length(argv) != 1 ||
  199. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_STRING, &argv_value)) {
  200. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve parameter to uri encode.");
  201. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  202. goto on_done;
  203. }
  204. if (aws_byte_buf_init(&buf, allocator, 10)) {
  205. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve parameter to uri encode.");
  206. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  207. goto on_done;
  208. }
  209. if (aws_byte_buf_append_encoding_uri_param(&buf, &argv_value.v.owning_cursor_string.cur)) {
  210. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to uri encode value.");
  211. aws_byte_buf_clean_up(&buf);
  212. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  213. goto on_done;
  214. }
  215. out_value->type = AWS_ENDPOINTS_VALUE_STRING;
  216. out_value->v.owning_cursor_string =
  217. aws_endpoints_owning_cursor_from_string(aws_string_new_from_buf(allocator, &buf));
  218. on_done:
  219. aws_endpoints_value_clean_up(&argv_value);
  220. aws_byte_buf_clean_up(&buf);
  221. return result;
  222. }
  223. static bool s_is_uri_ip(struct aws_byte_cursor host, bool is_uri_encoded) {
  224. return aws_is_ipv4(host) || aws_is_ipv6(host, is_uri_encoded);
  225. }
  226. static int s_resolve_fn_parse_url(
  227. struct aws_allocator *allocator,
  228. struct aws_array_list *argv,
  229. struct aws_endpoints_resolution_scope *scope,
  230. struct aws_endpoints_value *out_value) {
  231. int result = AWS_OP_SUCCESS;
  232. struct aws_uri uri;
  233. struct aws_json_value *root = NULL;
  234. struct aws_endpoints_value argv_url = {0};
  235. if (aws_array_list_length(argv) != 1 ||
  236. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_STRING, &argv_url)) {
  237. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve args for parse url.");
  238. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  239. goto on_done;
  240. }
  241. if (aws_uri_init_parse(&uri, allocator, &argv_url.v.owning_cursor_string.cur)) {
  242. out_value->type = AWS_ENDPOINTS_VALUE_NONE;
  243. /* reset error from parser, since non-uri strings should successfully resolve to none. */
  244. aws_reset_error();
  245. goto on_done;
  246. }
  247. if (aws_uri_query_string(&uri)->len > 0) {
  248. out_value->type = AWS_ENDPOINTS_VALUE_NONE;
  249. goto on_done;
  250. }
  251. const struct aws_byte_cursor *scheme = aws_uri_scheme(&uri);
  252. AWS_ASSERT(scheme != NULL);
  253. root = aws_json_value_new_object(allocator);
  254. if (scheme->len == 0) {
  255. out_value->type = AWS_ENDPOINTS_VALUE_NONE;
  256. goto on_done;
  257. }
  258. if (!(aws_byte_cursor_eq(scheme, &s_scheme_http) || aws_byte_cursor_eq(scheme, &s_scheme_https))) {
  259. out_value->type = AWS_ENDPOINTS_VALUE_NONE;
  260. goto on_done;
  261. }
  262. if (aws_json_value_add_to_object(
  263. root, aws_byte_cursor_from_c_str("scheme"), aws_json_value_new_string(allocator, *scheme))) {
  264. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to add scheme to object.");
  265. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  266. goto on_done;
  267. }
  268. const struct aws_byte_cursor *authority = aws_uri_authority(&uri);
  269. AWS_ASSERT(authority != NULL);
  270. if (authority->len == 0) {
  271. out_value->type = AWS_ENDPOINTS_VALUE_NONE;
  272. goto on_done;
  273. }
  274. if (aws_json_value_add_to_object(
  275. root, aws_byte_cursor_from_c_str("authority"), aws_json_value_new_string(allocator, *authority))) {
  276. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to add authority to object.");
  277. goto on_done;
  278. }
  279. const struct aws_byte_cursor *path = aws_uri_path(&uri);
  280. if (aws_json_value_add_to_object(
  281. root, aws_byte_cursor_from_c_str("path"), aws_json_value_new_string(allocator, *path))) {
  282. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to add path to object.");
  283. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  284. goto on_done;
  285. }
  286. struct aws_byte_cursor normalized_path_cur = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("normalizedPath");
  287. struct aws_byte_buf normalized_path_buf;
  288. if (aws_byte_buf_init_from_normalized_uri_path(allocator, *path, &normalized_path_buf) ||
  289. aws_json_value_add_to_object(
  290. root,
  291. normalized_path_cur,
  292. aws_json_value_new_string(allocator, aws_byte_cursor_from_buf(&normalized_path_buf)))) {
  293. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to normalize path.");
  294. aws_byte_buf_clean_up(&normalized_path_buf);
  295. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  296. goto on_done;
  297. }
  298. aws_byte_buf_clean_up(&normalized_path_buf);
  299. const struct aws_byte_cursor *host_name = aws_uri_host_name(&uri);
  300. bool is_ip = s_is_uri_ip(*host_name, true);
  301. if (aws_json_value_add_to_object(
  302. root, aws_byte_cursor_from_c_str("isIp"), aws_json_value_new_boolean(allocator, is_ip))) {
  303. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to add isIp to object.");
  304. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  305. goto on_done;
  306. }
  307. struct aws_byte_buf buf;
  308. if (aws_byte_buf_init(&buf, allocator, 0)) {
  309. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed init buffer for parseUrl return.");
  310. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  311. goto on_done;
  312. }
  313. if (aws_byte_buf_append_json_string(root, &buf)) {
  314. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to create JSON object.");
  315. aws_byte_buf_clean_up(&buf);
  316. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  317. goto on_done;
  318. }
  319. out_value->type = AWS_ENDPOINTS_VALUE_OBJECT;
  320. out_value->v.owning_cursor_object =
  321. aws_endpoints_owning_cursor_from_string(aws_string_new_from_buf(allocator, &buf));
  322. aws_byte_buf_clean_up(&buf);
  323. on_done:
  324. aws_uri_clean_up(&uri);
  325. aws_endpoints_value_clean_up(&argv_url);
  326. aws_json_value_destroy(root);
  327. return result;
  328. }
  329. static int s_resolve_is_valid_host_label(
  330. struct aws_allocator *allocator,
  331. struct aws_array_list *argv,
  332. struct aws_endpoints_resolution_scope *scope,
  333. struct aws_endpoints_value *out_value) {
  334. struct aws_endpoints_value argv_value = {0};
  335. struct aws_endpoints_value argv_allow_subdomains = {0};
  336. if (aws_array_list_length(argv) != 2 ||
  337. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_STRING, &argv_value) ||
  338. aws_endpoints_argv_expect(allocator, scope, argv, 1, AWS_ENDPOINTS_VALUE_BOOLEAN, &argv_allow_subdomains)) {
  339. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve not.");
  340. goto on_error;
  341. }
  342. out_value->type = AWS_ENDPOINTS_VALUE_BOOLEAN;
  343. out_value->v.boolean =
  344. aws_is_valid_host_label(argv_value.v.owning_cursor_string.cur, argv_allow_subdomains.v.boolean);
  345. aws_endpoints_value_clean_up(&argv_value);
  346. aws_endpoints_value_clean_up(&argv_allow_subdomains);
  347. return AWS_OP_SUCCESS;
  348. on_error:
  349. aws_endpoints_value_clean_up(&argv_value);
  350. aws_endpoints_value_clean_up(&argv_allow_subdomains);
  351. return aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  352. }
  353. static int s_resolve_fn_aws_partition(
  354. struct aws_allocator *allocator,
  355. struct aws_array_list *argv,
  356. struct aws_endpoints_resolution_scope *scope,
  357. struct aws_endpoints_value *out_value) {
  358. int result = AWS_OP_SUCCESS;
  359. struct aws_endpoints_value argv_region = {0};
  360. if (aws_array_list_length(argv) != 1 ||
  361. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_STRING, &argv_region)) {
  362. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve arguments for partitions.");
  363. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  364. goto on_done;
  365. }
  366. struct aws_hash_element *element = NULL;
  367. struct aws_byte_cursor key = argv_region.v.owning_cursor_string.cur;
  368. if (aws_hash_table_find(&scope->partitions->region_to_partition_info, &key, &element)) {
  369. AWS_LOGF_ERROR(
  370. AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to find partition info. " PRInSTR, AWS_BYTE_CURSOR_PRI(key));
  371. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  372. goto on_done;
  373. }
  374. if (element != NULL) {
  375. out_value->type = AWS_ENDPOINTS_VALUE_OBJECT;
  376. out_value->v.owning_cursor_object =
  377. aws_endpoints_owning_cursor_create(allocator, ((struct aws_partition_info *)element->value)->info);
  378. goto on_done;
  379. }
  380. key = aws_map_region_to_partition(key);
  381. if (key.len == 0) {
  382. key = aws_byte_cursor_from_c_str("aws");
  383. }
  384. if (aws_hash_table_find(&scope->partitions->region_to_partition_info, &key, &element) || element == NULL) {
  385. AWS_LOGF_ERROR(
  386. AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to find partition info. " PRInSTR, AWS_BYTE_CURSOR_PRI(key));
  387. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  388. goto on_done;
  389. }
  390. out_value->type = AWS_ENDPOINTS_VALUE_OBJECT;
  391. out_value->v.owning_cursor_object =
  392. aws_endpoints_owning_cursor_create(allocator, ((struct aws_partition_info *)element->value)->info);
  393. on_done:
  394. aws_endpoints_value_clean_up(&argv_region);
  395. return result;
  396. }
  397. static int s_resolve_fn_aws_parse_arn(
  398. struct aws_allocator *allocator,
  399. struct aws_array_list *argv,
  400. struct aws_endpoints_resolution_scope *scope,
  401. struct aws_endpoints_value *out_value) {
  402. int result = AWS_OP_SUCCESS;
  403. struct aws_json_value *object = NULL;
  404. struct aws_endpoints_value argv_value = {0};
  405. if (aws_array_list_length(argv) != 1 ||
  406. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_STRING, &argv_value)) {
  407. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve parseArn.");
  408. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  409. goto on_done;
  410. }
  411. struct aws_resource_name arn;
  412. if (aws_resource_name_init_from_cur(&arn, &argv_value.v.owning_cursor_string.cur)) {
  413. out_value->type = AWS_ENDPOINTS_VALUE_NONE;
  414. goto on_done;
  415. }
  416. object = aws_json_value_new_object(allocator);
  417. if (object == NULL) {
  418. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to init object for parseArn.");
  419. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  420. goto on_done;
  421. }
  422. if (arn.partition.len == 0 || arn.resource_id.len == 0 || arn.service.len == 0) {
  423. out_value->type = AWS_ENDPOINTS_VALUE_NONE;
  424. goto on_done;
  425. }
  426. /* Split resource id into components, either on : or / */
  427. /* TODO: support multiple delims in existing split helper? */
  428. struct aws_json_value *resource_id_node = aws_json_value_new_array(allocator);
  429. size_t start = 0;
  430. for (size_t i = 0; i < arn.resource_id.len; ++i) {
  431. if (arn.resource_id.ptr[i] == '/' || arn.resource_id.ptr[i] == ':') {
  432. struct aws_byte_cursor cur = {
  433. .ptr = arn.resource_id.ptr + start,
  434. .len = i - start,
  435. };
  436. struct aws_json_value *element = aws_json_value_new_string(allocator, cur);
  437. if (element == NULL || aws_json_value_add_array_element(resource_id_node, element)) {
  438. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to add resource id element");
  439. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  440. goto on_done;
  441. }
  442. start = i + 1;
  443. }
  444. }
  445. if (start <= arn.resource_id.len) {
  446. struct aws_byte_cursor cur = {
  447. .ptr = arn.resource_id.ptr + start,
  448. .len = arn.resource_id.len - start,
  449. };
  450. struct aws_json_value *element = aws_json_value_new_string(allocator, cur);
  451. if (element == NULL || aws_json_value_add_array_element(resource_id_node, element)) {
  452. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to add resource id element");
  453. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  454. goto on_done;
  455. }
  456. }
  457. if (aws_json_value_add_to_object(
  458. object, aws_byte_cursor_from_c_str("partition"), aws_json_value_new_string(allocator, arn.partition)) ||
  459. aws_json_value_add_to_object(
  460. object, aws_byte_cursor_from_c_str("service"), aws_json_value_new_string(allocator, arn.service)) ||
  461. aws_json_value_add_to_object(
  462. object, aws_byte_cursor_from_c_str("region"), aws_json_value_new_string(allocator, arn.region)) ||
  463. aws_json_value_add_to_object(
  464. object, aws_byte_cursor_from_c_str("accountId"), aws_json_value_new_string(allocator, arn.account_id)) ||
  465. aws_json_value_add_to_object(object, aws_byte_cursor_from_c_str("resourceId"), resource_id_node)) {
  466. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to add elements to object for parseArn.");
  467. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  468. goto on_done;
  469. }
  470. out_value->type = AWS_ENDPOINTS_VALUE_OBJECT;
  471. out_value->v.owning_cursor_object =
  472. aws_endpoints_owning_cursor_from_string(aws_string_new_from_json(allocator, object));
  473. if (out_value->v.owning_cursor_object.cur.len == 0) {
  474. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to create string from json.");
  475. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  476. goto on_done;
  477. }
  478. on_done:
  479. aws_json_value_destroy(object);
  480. aws_endpoints_value_clean_up(&argv_value);
  481. return result;
  482. }
  483. static int s_resolve_is_virtual_hostable_s3_bucket(
  484. struct aws_allocator *allocator,
  485. struct aws_array_list *argv,
  486. struct aws_endpoints_resolution_scope *scope,
  487. struct aws_endpoints_value *out_value) {
  488. int result = AWS_OP_SUCCESS;
  489. struct aws_endpoints_value argv_value = {0};
  490. struct aws_endpoints_value argv_allow_subdomains = {0};
  491. if (aws_array_list_length(argv) != 2 ||
  492. aws_endpoints_argv_expect(allocator, scope, argv, 0, AWS_ENDPOINTS_VALUE_STRING, &argv_value) ||
  493. aws_endpoints_argv_expect(allocator, scope, argv, 1, AWS_ENDPOINTS_VALUE_BOOLEAN, &argv_allow_subdomains)) {
  494. AWS_LOGF_ERROR(AWS_LS_SDKUTILS_ENDPOINTS_RESOLVE, "Failed to resolve args for isVirtualHostableS3Bucket.");
  495. result = aws_raise_error(AWS_ERROR_SDKUTILS_ENDPOINTS_RESOLVE_FAILED);
  496. goto on_done;
  497. }
  498. struct aws_byte_cursor label_cur = argv_value.v.owning_cursor_string.cur;
  499. bool has_uppercase_chars = false;
  500. for (size_t i = 0; i < label_cur.len; ++i) {
  501. if (label_cur.ptr[i] >= 'A' && label_cur.ptr[i] <= 'Z') {
  502. has_uppercase_chars = true;
  503. break;
  504. }
  505. }
  506. out_value->type = AWS_ENDPOINTS_VALUE_BOOLEAN;
  507. out_value->v.boolean = (label_cur.len >= 3 && label_cur.len <= 63) && !has_uppercase_chars &&
  508. aws_is_valid_host_label(label_cur, argv_allow_subdomains.v.boolean) &&
  509. !aws_is_ipv4(label_cur);
  510. on_done:
  511. aws_endpoints_value_clean_up(&argv_value);
  512. aws_endpoints_value_clean_up(&argv_allow_subdomains);
  513. return result;
  514. }
  515. typedef int(standard_lib_function_fn)(
  516. struct aws_allocator *allocator,
  517. struct aws_array_list *argv,
  518. struct aws_endpoints_resolution_scope *scope,
  519. struct aws_endpoints_value *out_value);
  520. static standard_lib_function_fn *s_resolve_fn_vt[AWS_ENDPOINTS_FN_LAST] = {
  521. [AWS_ENDPOINTS_FN_IS_SET] = s_resolve_fn_is_set,
  522. [AWS_ENDPOINTS_FN_NOT] = s_resolve_fn_not,
  523. [AWS_ENDPOINTS_FN_GET_ATTR] = s_resolve_fn_get_attr,
  524. [AWS_ENDPOINTS_FN_SUBSTRING] = s_resolve_fn_substring,
  525. [AWS_ENDPOINTS_FN_STRING_EQUALS] = s_resolve_fn_string_equals,
  526. [AWS_ENDPOINTS_FN_BOOLEAN_EQUALS] = s_resolve_fn_boolean_equals,
  527. [AWS_ENDPOINTS_FN_URI_ENCODE] = s_resolve_fn_uri_encode,
  528. [AWS_ENDPOINTS_FN_PARSE_URL] = s_resolve_fn_parse_url,
  529. [AWS_ENDPOINTS_FN_IS_VALID_HOST_LABEL] = s_resolve_is_valid_host_label,
  530. [AWS_ENDPOINTS_FN_AWS_PARTITION] = s_resolve_fn_aws_partition,
  531. [AWS_ENDPOINTS_FN_AWS_PARSE_ARN] = s_resolve_fn_aws_parse_arn,
  532. [AWS_ENDPOINTS_FN_AWS_IS_VIRTUAL_HOSTABLE_S3_BUCKET] = s_resolve_is_virtual_hostable_s3_bucket,
  533. };
  534. int aws_endpoints_dispatch_standard_lib_fn_resolve(
  535. enum aws_endpoints_fn_type type,
  536. struct aws_allocator *allocator,
  537. struct aws_array_list *argv,
  538. struct aws_endpoints_resolution_scope *scope,
  539. struct aws_endpoints_value *out_value) {
  540. return s_resolve_fn_vt[type](allocator, argv, scope, out_value);
  541. }