http_auth.c 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "http_auth.h"
  3. #define BEARER_TOKEN_EXPIRATION 86400
  4. bool netdata_is_protected_by_bearer = false; // this is controlled by cloud, at the point the agent logs in - this should also be saved to /var/lib/netdata
  5. static DICTIONARY *netdata_authorized_bearers = NULL;
  6. struct bearer_token {
  7. uuid_t cloud_account_id;
  8. char cloud_user_name[CLOUD_USER_NAME_LENGTH];
  9. HTTP_ACCESS access;
  10. time_t created_s;
  11. time_t expires_s;
  12. };
  13. bool web_client_bearer_token_auth(struct web_client *w, const char *v) {
  14. if(!uuid_parse_flexi(v, w->auth.bearer_token)) {
  15. char uuid_str[UUID_COMPACT_STR_LEN];
  16. uuid_unparse_lower_compact(w->auth.bearer_token, uuid_str);
  17. struct bearer_token *z = dictionary_get(netdata_authorized_bearers, uuid_str);
  18. if (z && z->expires_s > now_monotonic_sec()) {
  19. w->access = z->access;
  20. strncpyz(w->auth.client_name, z->cloud_user_name, sizeof(w->auth.client_name) - 1);
  21. uuid_copy(w->auth.cloud_account_id, z->cloud_account_id);
  22. web_client_flags_clear_auth(w);
  23. web_client_flag_set(w, WEB_CLIENT_FLAG_AUTH_BEARER);
  24. return true;
  25. }
  26. }
  27. else
  28. nd_log(NDLS_DAEMON, NDLP_NOTICE, "Invalid bearer token '%s' received.", v);
  29. return false;
  30. }
  31. static void bearer_token_cleanup(void) {
  32. static time_t attempts = 0;
  33. if(++attempts % 1000 != 0)
  34. return;
  35. time_t now_s = now_monotonic_sec();
  36. struct bearer_token *z;
  37. dfe_start_read(netdata_authorized_bearers, z) {
  38. if(z->expires_s < now_s)
  39. dictionary_del(netdata_authorized_bearers, z_dfe.name);
  40. }
  41. dfe_done(z);
  42. dictionary_garbage_collect(netdata_authorized_bearers);
  43. }
  44. void bearer_tokens_init(void) {
  45. netdata_authorized_bearers = dictionary_create_advanced(
  46. DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
  47. NULL, sizeof(struct bearer_token));
  48. }
  49. time_t bearer_create_token(uuid_t *uuid, struct web_client *w) {
  50. char uuid_str[UUID_COMPACT_STR_LEN];
  51. uuid_generate_random(*uuid);
  52. uuid_unparse_lower_compact(*uuid, uuid_str);
  53. struct bearer_token t = { 0 }, *z;
  54. z = dictionary_set(netdata_authorized_bearers, uuid_str, &t, sizeof(t));
  55. if(!z->created_s) {
  56. z->created_s = now_monotonic_sec();
  57. z->expires_s = z->created_s + BEARER_TOKEN_EXPIRATION;
  58. z->access = w->access;
  59. uuid_copy(z->cloud_account_id, w->auth.cloud_account_id);
  60. strncpyz(z->cloud_user_name, w->auth.client_name, sizeof(z->cloud_account_id) - 1);
  61. }
  62. bearer_token_cleanup();
  63. return now_realtime_sec() + BEARER_TOKEN_EXPIRATION;
  64. }
  65. bool extract_bearer_token_from_request(struct web_client *w, char *dst, size_t dst_len) {
  66. if(!web_client_flag_check(w, WEB_CLIENT_FLAG_AUTH_BEARER) || dst_len != UUID_STR_LEN)
  67. return false;
  68. uuid_unparse_lower(w->auth.bearer_token, dst);
  69. return true;
  70. }