@cryptotaxi247 / netdata-1 / commits / 37d599cb6

adds child query support to ACLK (#10030)

* allows cloud to query children

Timotej S committed Dec 1, 2020 at 18:27 UTC 37d599cb65cb3c433dfd9aa2a129261c53e1f72a
4 files changed +74 -23
aclk/aclk_common.h
-2
@@ -98,8 +98,6 @@ const char *aclk_proxy_type_to_s(ACLK_PROXY_TYPE *type);
98 #define ACLK_PROXY_ENV "env"
99 #define ACLK_PROXY_CONFIG_VAR "proxy"
100
101 -#define ACLK_CLOUD_REQ_V2_PREFIX "GET /api/v1/"
102 -
101 ACLK_PROXY_TYPE aclk_verify_proxy(const char *string);
102 const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type);
103 void safe_log_proxy_censor(char *proxy);
aclk/aclk_query.c
+8 -4
@@ -60,8 +60,11 @@ static void aclk_query_free(struct aclk_query *this_query)
60 freez(this_query->topic);
61 if (likely(this_query->query))
62 freez(this_query->query);
63 - if(this_query->data && this_query->cmd == ACLK_CMD_CLOUD_QUERY_2)
64 - freez(this_query->data);
63 + if(this_query->data && this_query->cmd == ACLK_CMD_CLOUD_QUERY_2) {
64 + struct aclk_cloud_req_v2 *del = (struct aclk_cloud_req_v2 *)this_query->data;
65 + freez(del->data);
66 + freez(del);
67 + }
68 if (likely(this_query->msg_id))
69 freez(this_query->msg_id);
70 freez(this_query);
@@ -396,6 +399,7 @@ static int aclk_execute_query_v2(struct aclk_query *this_query)
399 int retval = 0;
400 usec_t t;
401 BUFFER *local_buffer = NULL;
402 + struct aclk_cloud_req_v2 *cloud_req = (struct aclk_cloud_req_v2 *)this_query->data;
403
404 #ifdef NETDATA_WITH_ZLIB
405 int z_ret;
@@ -422,11 +426,11 @@ static int aclk_execute_query_v2(struct aclk_query *this_query)
426 mysep = strrchr(this_query->query, '/');
427
428 // execute the query
425 - t = aclk_web_api_request_v1(localhost, w, mysep ? mysep + 1 : "noop", this_query->created_boot_time);
429 + t = aclk_web_api_request_v1(cloud_req->host, w, mysep ? mysep + 1 : "noop", this_query->created_boot_time);
430
431 #ifdef NETDATA_WITH_ZLIB
432 // check if gzip encoding can and should be used
429 - if ((start = strstr((char *)this_query->data, WEB_HDR_ACCEPT_ENC))) {
433 + if ((start = strstr(cloud_req->data, WEB_HDR_ACCEPT_ENC))) {
434 start += strlen(WEB_HDR_ACCEPT_ENC);
435 end = strstr(start, "\x0D\x0A");
436 start = strstr(start, "gzip");
aclk/aclk_query.h
+5
@@ -25,6 +25,11 @@ struct aclk_query_threads {
25 int count;
26 };
27
28 +struct aclk_cloud_req_v2 {
29 + char *data;
30 + RRDHOST *host;
31 +};
32 +
33 void *aclk_query_main_thread(void *ptr);
34 int aclk_queue_query(char *token, void *data, char *msg_type, char *query, int run_after, int internal, ACLK_CMD cmd);
35
aclk/aclk_rx_msgs.c
+61 -17
@@ -15,18 +15,55 @@ static inline int aclk_extract_v2_data(char *payload, char **data)
15 return 0;
16 }
17
18 -static inline int aclk_v2_payload_get_query(const char *payload, struct aclk_request *req)
18 +#define ACLK_GET_REQ "GET "
19 +#define ACLK_CHILD_REQ "/host/"
20 +#define ACLK_CLOUD_REQ_V2_PREFIX "/api/v1/"
21 +#define STRNCMP_CONSTANT_PREFIX(str, const_pref) strncmp(str, const_pref, strlen(const_pref))
22 +static inline int aclk_v2_payload_get_query(struct aclk_cloud_req_v2 *cloud_req, struct aclk_request *req)
23 {
20 - const char *start, *end;
24 + const char *start, *end, *ptr;
25 + char uuid_str[UUID_STR_LEN];
26 + uuid_t uuid;
27
22 - if(strncmp(payload, ACLK_CLOUD_REQ_V2_PREFIX, strlen(ACLK_CLOUD_REQ_V2_PREFIX))) {
23 - errno = 0;
28 + errno = 0;
29 +
30 + if(STRNCMP_CONSTANT_PREFIX(cloud_req->data, ACLK_GET_REQ)) {
31 + error("Only accepting GET HTTP requests from CLOUD");
32 + return 1;
33 + }
34 + start = ptr = cloud_req->data + strlen(ACLK_GET_REQ);
35 +
36 + if(!STRNCMP_CONSTANT_PREFIX(ptr, ACLK_CHILD_REQ)) {
37 + ptr += strlen(ACLK_CHILD_REQ);
38 + if(strlen(ptr) < UUID_STR_LEN) {
39 + error("the child id in URL too short \"%s\"", start);
40 + return 1;
41 + }
42 +
43 + strncpyz(uuid_str, ptr, UUID_STR_LEN - 1);
44 +
45 + for(int i = 0; i < UUID_STR_LEN && uuid_str[i]; i++)
46 + uuid_str[i] = tolower(uuid_str[i]);
47 +
48 + if(ptr[0] && uuid_parse(uuid_str, uuid)) {
49 + error("Got Child query (/host/XXX/...) host id \"%s\" doesn't look like valid GUID", uuid_str);
50 + return 1;
51 + }
52 + ptr += UUID_STR_LEN - 1;
53 +
54 + cloud_req->host = rrdhost_find_by_guid(uuid_str, 0);
55 + if(!cloud_req->host) {
56 + error("Cannot find host with GUID \"%s\"", uuid_str);
57 + return 1;
58 + }
59 + }
60 +
61 + if(STRNCMP_CONSTANT_PREFIX(ptr, ACLK_CLOUD_REQ_V2_PREFIX)) {
62 error("Only accepting requests that start with \"%s\" from CLOUD.", ACLK_CLOUD_REQ_V2_PREFIX);
63 return 1;
64 }
27 - start = payload + 4;
65
29 - if(!(end = strstr(payload, " HTTP/1.1\x0D\x0A"))) {
66 + if(!(end = strstr(ptr, " HTTP/1.1\x0D\x0A"))) {
67 errno = 0;
68 error("Doesn't look like HTTP GET request.");
69 return 1;
@@ -88,6 +125,7 @@ static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, cha
125 {
126 HTTP_CHECK_AGENT_INITIALIZED();
127
128 + struct aclk_cloud_req_v2 *cloud_req;
129 char *data;
130
131 errno = 0;
@@ -104,32 +142,38 @@ static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, cha
142 return 1;
143 }
144
107 - if (unlikely(aclk_v2_payload_get_query(data, cloud_to_agent))) {
145 + cloud_req = mallocz(sizeof(struct aclk_cloud_req_v2));
146 + cloud_req->data = data;
147 + cloud_req->host = localhost;
148 +
149 + if (unlikely(aclk_v2_payload_get_query(cloud_req, cloud_to_agent))) {
150 error("Could not extract payload from query");
109 - freez(data);
110 - return 1;
151 + goto cleanup;
152 }
153
154 if (unlikely(!cloud_to_agent->callback_topic)) {
155 error("Missing callback_topic");
115 - freez(data);
116 - return 1;
156 + goto cleanup;
157 }
158
159 if (unlikely(!cloud_to_agent->msg_id)) {
160 error("Missing msg_id");
121 - freez(data);
122 - return 1;
161 + goto cleanup;
162 }
163
164 // aclk_queue_query takes ownership of data pointer
165 if (unlikely(aclk_queue_query(
127 - cloud_to_agent->callback_topic, data, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0,
128 - ACLK_CMD_CLOUD_QUERY_2)))
129 - debug(D_ACLK, "ACLK failed to queue incoming \"http\" message");
166 + cloud_to_agent->callback_topic, cloud_req, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0,
167 + ACLK_CMD_CLOUD_QUERY_2))) {
168 + error("ACLK failed to queue incoming \"http\" v2 message");
169 + goto cleanup;
170 + }
171
131 - UNUSED(cloud_to_agent);
172 return 0;
173 +cleanup:
174 + freez(cloud_req->data);
175 + freez(cloud_req);
176 + return 1;
177 }
178
179 // This handles `version` message from cloud used to negotiate