summaryrefslogtreecommitdiffstats
path: root/aclk
diff options
context:
space:
mode:
authorTimotej S <6674623+underhood@users.noreply.github.com>2020-12-01 18:27:03 +0100
committerGitHub <noreply@github.com>2020-12-01 18:27:03 +0100
commit37d599cb65cb3c433dfd9aa2a129261c53e1f72a (patch)
treea2b8efd6d3fb4f999527cd04d14c63fd9bb58a1a /aclk
parent7e4385f2e8659d55090360343baffc551c4d3f6d (diff)
adds child query support to ACLK (#10030)
* allows cloud to query children
Diffstat (limited to 'aclk')
-rw-r--r--aclk/aclk_common.h2
-rw-r--r--aclk/aclk_query.c12
-rw-r--r--aclk/aclk_query.h5
-rw-r--r--aclk/aclk_rx_msgs.c78
4 files changed, 74 insertions, 23 deletions
diff --git a/aclk/aclk_common.h b/aclk/aclk_common.h
index 015e4b8bbd..f03ec3b5ed 100644
--- a/aclk/aclk_common.h
+++ b/aclk/aclk_common.h
@@ -98,8 +98,6 @@ const char *aclk_proxy_type_to_s(ACLK_PROXY_TYPE *type);
#define ACLK_PROXY_ENV "env"
#define ACLK_PROXY_CONFIG_VAR "proxy"
-#define ACLK_CLOUD_REQ_V2_PREFIX "GET /api/v1/"
-
ACLK_PROXY_TYPE aclk_verify_proxy(const char *string);
const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type);
void safe_log_proxy_censor(char *proxy);
diff --git a/aclk/aclk_query.c b/aclk/aclk_query.c
index be58c2209b..09934754e3 100644
--- a/aclk/aclk_query.c
+++ b/aclk/aclk_query.c
@@ -60,8 +60,11 @@ static void aclk_query_free(struct aclk_query *this_query)
freez(this_query->topic);
if (likely(this_query->query))
freez(this_query->query);
- if(this_query->data && this_query->cmd == ACLK_CMD_CLOUD_QUERY_2)
- freez(this_query->data);
+ if(this_query->data && this_query->cmd == ACLK_CMD_CLOUD_QUERY_2) {
+ struct aclk_cloud_req_v2 *del = (struct aclk_cloud_req_v2 *)this_query->data;
+ freez(del->data);
+ freez(del);
+ }
if (likely(this_query->msg_id))
freez(this_query->msg_id);
freez(this_query);
@@ -396,6 +399,7 @@ static int aclk_execute_query_v2(struct aclk_query *this_query)
int retval = 0;
usec_t t;
BUFFER *local_buffer = NULL;
+ struct aclk_cloud_req_v2 *cloud_req = (struct aclk_cloud_req_v2 *)this_query->data;
#ifdef NETDATA_WITH_ZLIB
int z_ret;
@@ -422,11 +426,11 @@ static int aclk_execute_query_v2(struct aclk_query *this_query)
mysep = strrchr(this_query->query, '/');
// execute the query
- t = aclk_web_api_request_v1(localhost, w, mysep ? mysep + 1 : "noop", this_query->created_boot_time);
+ t = aclk_web_api_request_v1(cloud_req->host, w, mysep ? mysep + 1 : "noop", this_query->created_boot_time);
#ifdef NETDATA_WITH_ZLIB
// check if gzip encoding can and should be used
- if ((start = strstr((char *)this_query->data, WEB_HDR_ACCEPT_ENC))) {
+ if ((start = strstr(cloud_req->data, WEB_HDR_ACCEPT_ENC))) {
start += strlen(WEB_HDR_ACCEPT_ENC);
end = strstr(start, "\x0D\x0A");
start = strstr(start, "gzip");
diff --git a/aclk/aclk_query.h b/aclk/aclk_query.h
index 8c7d7cbd07..53eef13922 100644
--- a/aclk/aclk_query.h
+++ b/aclk/aclk_query.h
@@ -25,6 +25,11 @@ struct aclk_query_threads {
int count;
};
+struct aclk_cloud_req_v2 {
+ char *data;
+ RRDHOST *host;
+};
+
void *aclk_query_main_thread(void *ptr);
int aclk_queue_query(char *token, void *data, char *msg_type, char *query, int run_after, int internal, ACLK_CMD cmd);
diff --git a/aclk/aclk_rx_msgs.c b/aclk/aclk_rx_msgs.c
index b90f60d9a8..73c1f8673f 100644
--- a/aclk/aclk_rx_msgs.c
+++ b/aclk/aclk_rx_msgs.c
@@ -15,18 +15,55 @@ static inline int aclk_extract_v2_data(char *payload, char **data)
return 0;
}
-static inline int aclk_v2_payload_get_query(const char *payload, struct aclk_request *req)
+#define ACLK_GET_REQ "GET "
+#define ACLK_CHILD_REQ "/host/"
+#define ACLK_CLOUD_REQ_V2_PREFIX "/api/v1/"
+#define STRNCMP_CONSTANT_PREFIX(str, const_pref) strncmp(str, const_pref, strlen(const_pref))
+static inline int aclk_v2_payload_get_query(struct aclk_cloud_req_v2 *cloud_req, struct aclk_request *req)
{
- const char *start, *end;
+ const char *start, *end, *ptr;
+ char uuid_str[UUID_STR_LEN];
+ uuid_t uuid;
- if(strncmp(payload, ACLK_CLOUD_REQ_V2_PREFIX, strlen(ACLK_CLOUD_REQ_V2_PREFIX))) {
- errno = 0;
+ errno = 0;
+
+ if(STRNCMP_CONSTANT_PREFIX(cloud_req->data, ACLK_GET_REQ)) {
+ error("Only accepting GET HTTP requests from CLOUD");
+ return 1;
+ }
+ start = ptr = cloud_req->data + strlen(ACLK_GET_REQ);
+
+ if(!STRNCMP_CONSTANT_PREFIX(ptr, ACLK_CHILD_REQ)) {
+ ptr += strlen(ACLK_CHILD_REQ);
+ if(strlen(ptr) < UUID_STR_LEN) {
+ error("the child id in URL too short \"%s\"", start);
+ return 1;
+ }
+
+ strncpyz(uuid_str, ptr, UUID_STR_LEN - 1);
+
+ for(int i = 0; i < UUID_STR_LEN && uuid_str[i]; i++)
+ uuid_str[i] = tolower(uuid_str[i]);
+
+ if(ptr[0] && uuid_parse(uuid_str, uuid)) {
+ error("Got Child query (/host/XXX/...) host id \"%s\" doesn't look like valid GUID", uuid_str);
+ return 1;
+ }
+ ptr += UUID_STR_LEN - 1;
+
+ cloud_req->host = rrdhost_find_by_guid(uuid_str, 0);
+ if(!cloud_req->host) {
+ error("Cannot find host with GUID \"%s\"", uuid_str);
+ return 1;
+ }
+ }
+
+ if(STRNCMP_CONSTANT_PREFIX(ptr, ACLK_CLOUD_REQ_V2_PREFIX)) {
error("Only accepting requests that start with \"%s\" from CLOUD.", ACLK_CLOUD_REQ_V2_PREFIX);
return 1;
}
- start = payload + 4;
- if(!(end = strstr(payload, " HTTP/1.1\x0D\x0A"))) {
+ if(!(end = strstr(ptr, " HTTP/1.1\x0D\x0A"))) {
errno = 0;
error("Doesn't look like HTTP GET request.");
return 1;
@@ -88,6 +125,7 @@ static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, cha
{
HTTP_CHECK_AGENT_INITIALIZED();
+ struct aclk_cloud_req_v2 *cloud_req;
char *data;
errno = 0;
@@ -104,32 +142,38 @@ static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, cha
return 1;
}
- if (unlikely(aclk_v2_payload_get_query(data, cloud_to_agent))) {
+ cloud_req = mallocz(sizeof(struct aclk_cloud_req_v2));
+ cloud_req->data = data;
+ cloud_req->host = localhost;
+
+ if (unlikely(aclk_v2_payload_get_query(cloud_req, cloud_to_agent))) {
error("Could not extract payload from query");
- freez(data);
- return 1;
+ goto cleanup;
}
if (unlikely(!cloud_to_agent->callback_topic)) {
error("Missing callback_topic");
- freez(data);
- return 1;
+ goto cleanup;
}
if (unlikely(!cloud_to_agent->msg_id)) {
error("Missing msg_id");
- freez(data);
- return 1;
+ goto cleanup;
}
// aclk_queue_query takes ownership of data pointer
if (unlikely(aclk_queue_query(
- cloud_to_agent->callback_topic, data, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0,
- ACLK_CMD_CLOUD_QUERY_2)))
- debug(D_ACLK, "ACLK failed to queue incoming \"http\" message");
+ cloud_to_agent->callback_topic, cloud_req, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0,
+ ACLK_CMD_CLOUD_QUERY_2))) {
+ error("ACLK failed to queue incoming \"http\" v2 message");
+ goto cleanup;
+ }
- UNUSED(cloud_to_agent);
return 0;
+cleanup:
+ freez(cloud_req->data);
+ freez(cloud_req);
+ return 1;
}
// This handles `version` message from cloud used to negotiate