summaryrefslogtreecommitdiffstats
path: root/web/api/web_api_v1.c
diff options
context:
space:
mode:
Diffstat (limited to 'web/api/web_api_v1.c')
-rw-r--r--web/api/web_api_v1.c193
1 files changed, 146 insertions, 47 deletions
diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c
index 637329696..1e4f9c41c 100644
--- a/web/api/web_api_v1.c
+++ b/web/api/web_api_v1.c
@@ -53,6 +53,35 @@ static struct {
static struct {
const char *name;
uint32_t hash;
+ CONTEXTS_V2_OPTIONS value;
+} contexts_v2_options[] = {
+ {"minify" , 0 , CONTEXT_V2_OPTION_MINIFY}
+ , {"debug" , 0 , CONTEXT_V2_OPTION_DEBUG}
+ , {"config" , 0 , CONTEXT_V2_OPTION_ALERTS_WITH_CONFIGURATIONS}
+ , {"instances" , 0 , CONTEXT_V2_OPTION_ALERTS_WITH_INSTANCES}
+ , {"values" , 0 , CONTEXT_V2_OPTION_ALERTS_WITH_VALUES}
+ , {"summary" , 0 , CONTEXT_V2_OPTION_ALERTS_WITH_SUMMARY}
+ , {NULL , 0 , 0}
+};
+
+static struct {
+ const char *name;
+ uint32_t hash;
+ CONTEXTS_V2_ALERT_STATUS value;
+} contexts_v2_alert_status[] = {
+ {"uninitialized" , 0 , CONTEXT_V2_ALERT_UNINITIALIZED}
+ , {"undefined" , 0 , CONTEXT_V2_ALERT_UNDEFINED}
+ , {"clear" , 0 , CONTEXT_V2_ALERT_CLEAR}
+ , {"raised" , 0 , CONTEXT_V2_ALERT_RAISED}
+ , {"active" , 0 , CONTEXT_V2_ALERT_RAISED}
+ , {"warning" , 0 , CONTEXT_V2_ALERT_WARNING}
+ , {"critical" , 0 , CONTEXT_V2_ALERT_CRITICAL}
+ , {NULL , 0 , 0}
+};
+
+static struct {
+ const char *name;
+ uint32_t hash;
DATASOURCE_FORMAT value;
} api_v1_data_formats[] = {
{ DATASOURCE_FORMAT_DATATABLE_JSON , 0 , DATASOURCE_DATATABLE_JSON}
@@ -91,9 +120,15 @@ static struct {
void web_client_api_v1_init(void) {
int i;
+ for(i = 0; contexts_v2_alert_status[i].name ; i++)
+ contexts_v2_alert_status[i].hash = simple_hash(contexts_v2_alert_status[i].name);
+
for(i = 0; api_v1_data_options[i].name ; i++)
api_v1_data_options[i].hash = simple_hash(api_v1_data_options[i].name);
+ for(i = 0; contexts_v2_options[i].name ; i++)
+ contexts_v2_options[i].hash = simple_hash(contexts_v2_options[i].name);
+
for(i = 0; api_v1_data_formats[i].name ; i++)
api_v1_data_formats[i].hash = simple_hash(api_v1_data_formats[i].name);
@@ -126,11 +161,11 @@ char *get_mgmt_api_key(void) {
if(fd != -1) {
char buf[GUID_LEN + 1];
if(read(fd, buf, GUID_LEN) != GUID_LEN)
- error("Failed to read management API key from '%s'", api_key_filename);
+ netdata_log_error("Failed to read management API key from '%s'", api_key_filename);
else {
buf[GUID_LEN] = '\0';
if(regenerate_guid(buf, guid) == -1) {
- error("Failed to validate management API key '%s' from '%s'.",
+ netdata_log_error("Failed to validate management API key '%s' from '%s'.",
buf, api_key_filename);
guid[0] = '\0';
@@ -150,12 +185,12 @@ char *get_mgmt_api_key(void) {
// save it
fd = open(api_key_filename, O_WRONLY|O_CREAT|O_TRUNC, 444);
if(fd == -1) {
- error("Cannot create unique management API key file '%s'. Please adjust config parameter 'netdata management api key file' to a proper path and file.", api_key_filename);
+ netdata_log_error("Cannot create unique management API key file '%s'. Please adjust config parameter 'netdata management api key file' to a proper path and file.", api_key_filename);
goto temp_key;
}
if(write(fd, guid, GUID_LEN) != GUID_LEN) {
- error("Cannot write the unique management API key file '%s'. Please adjust config parameter 'netdata management api key file' to a proper path and file with enough space left.", api_key_filename);
+ netdata_log_error("Cannot write the unique management API key file '%s'. Please adjust config parameter 'netdata management api key file' to a proper path and file with enough space left.", api_key_filename);
close(fd);
goto temp_key;
}
@@ -166,7 +201,7 @@ char *get_mgmt_api_key(void) {
return guid;
temp_key:
- info("You can still continue to use the alarm management API using the authorization token %s during this Netdata session only.", guid);
+ netdata_log_info("You can still continue to use the alarm management API using the authorization token %s during this Netdata session only.", guid);
return guid;
}
@@ -175,7 +210,7 @@ void web_client_api_v1_management_init(void) {
}
inline RRDR_OPTIONS web_client_api_request_v1_data_options(char *o) {
- RRDR_OPTIONS ret = 0x00000000;
+ RRDR_OPTIONS ret = 0;
char *tok;
while(o && *o && (tok = strsep_skip_consecutive_separators(&o, ", |"))) {
@@ -194,6 +229,78 @@ inline RRDR_OPTIONS web_client_api_request_v1_data_options(char *o) {
return ret;
}
+inline CONTEXTS_V2_OPTIONS web_client_api_request_v2_context_options(char *o) {
+ CONTEXTS_V2_OPTIONS ret = 0;
+ char *tok;
+
+ while(o && *o && (tok = strsep_skip_consecutive_separators(&o, ", |"))) {
+ if(!*tok) continue;
+
+ uint32_t hash = simple_hash(tok);
+ int i;
+ for(i = 0; contexts_v2_options[i].name ; i++) {
+ if (unlikely(hash == contexts_v2_options[i].hash && !strcmp(tok, contexts_v2_options[i].name))) {
+ ret |= contexts_v2_options[i].value;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+inline CONTEXTS_V2_ALERT_STATUS web_client_api_request_v2_alert_status(char *o) {
+ CONTEXTS_V2_ALERT_STATUS ret = 0;
+ char *tok;
+
+ while(o && *o && (tok = strsep_skip_consecutive_separators(&o, ", |"))) {
+ if(!*tok) continue;
+
+ uint32_t hash = simple_hash(tok);
+ int i;
+ for(i = 0; contexts_v2_alert_status[i].name ; i++) {
+ if (unlikely(hash == contexts_v2_alert_status[i].hash && !strcmp(tok, contexts_v2_alert_status[i].name))) {
+ ret |= contexts_v2_alert_status[i].value;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+void web_client_api_request_v2_contexts_alerts_status_to_buffer_json_array(BUFFER *wb, const char *key, CONTEXTS_V2_ALERT_STATUS options) {
+ buffer_json_member_add_array(wb, key);
+
+ RRDR_OPTIONS used = 0; // to prevent adding duplicates
+ for(int i = 0; contexts_v2_alert_status[i].name ; i++) {
+ if (unlikely((contexts_v2_alert_status[i].value & options) && !(contexts_v2_alert_status[i].value & used))) {
+ const char *name = contexts_v2_alert_status[i].name;
+ used |= contexts_v2_alert_status[i].value;
+
+ buffer_json_add_array_item_string(wb, name);
+ }
+ }
+
+ buffer_json_array_close(wb);
+}
+
+void web_client_api_request_v2_contexts_options_to_buffer_json_array(BUFFER *wb, const char *key, CONTEXTS_V2_OPTIONS options) {
+ buffer_json_member_add_array(wb, key);
+
+ RRDR_OPTIONS used = 0; // to prevent adding duplicates
+ for(int i = 0; contexts_v2_options[i].name ; i++) {
+ if (unlikely((contexts_v2_options[i].value & options) && !(contexts_v2_options[i].value & used))) {
+ const char *name = contexts_v2_options[i].name;
+ used |= contexts_v2_options[i].value;
+
+ buffer_json_add_array_item_string(wb, name);
+ }
+ }
+
+ buffer_json_array_close(wb);
+}
+
void web_client_api_request_v1_data_options_to_buffer_json_array(BUFFER *wb, const char *key, RRDR_OPTIONS options) {
buffer_json_member_add_array(wb, key);
@@ -233,7 +340,7 @@ void web_client_api_request_v1_data_options_to_string(char *buf, size_t size, RR
*write = *end = '\0';
}
-inline DATASOURCE_FORMAT web_client_api_request_v1_data_format(char *name) {
+inline uint32_t web_client_api_request_v1_data_format(char *name) {
uint32_t hash = simple_hash(name);
int i;
@@ -307,7 +414,7 @@ inline int web_client_api_request_v1_alarm_count(RRDHOST *host, struct web_clien
if(!name || !*name) continue;
if(!value || !*value) continue;
- debug(D_WEB_CLIENT, "%llu: API v1 alarm_count query param '%s' with value '%s'", w->id, name, value);
+ netdata_log_debug(D_WEB_CLIENT, "%llu: API v1 alarm_count query param '%s' with value '%s'", w->id, name, value);
char* p = value;
if(!strcmp(name, "status")) {
@@ -547,7 +654,7 @@ inline int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w,
// returns the HTTP code
static inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url) {
- debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url);
+ netdata_log_debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url);
int ret = HTTP_RESP_BAD_REQUEST;
BUFFER *dimensions = NULL;
@@ -586,7 +693,7 @@ static inline int web_client_api_request_v1_data(RRDHOST *host, struct web_clien
if(!name || !*name) continue;
if(!value || !*value) continue;
- debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);
+ netdata_log_debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);
// name and value are now the parameters
// they are not null and not empty
@@ -732,14 +839,14 @@ static inline int web_client_api_request_v1_data(RRDHOST *host, struct web_clien
if(outFileName && *outFileName) {
buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName);
- debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName);
+ netdata_log_debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName);
}
if(format == DATASOURCE_DATATABLE_JSONP) {
if(responseHandler == NULL)
responseHandler = "google.visualization.Query.setResponse";
- debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
+ netdata_log_debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName
);
@@ -793,7 +900,7 @@ cleanup:
// /api/v1/registry?action=delete&machine=${machine_guid}&name=${hostname}&url=${url}&delete_url=${delete_url}
//
// Search for the URLs of a machine:
-// /api/v1/registry?action=search&machine=${machine_guid}&name=${hostname}&url=${url}&for=${machine_guid}
+// /api/v1/registry?action=search&for=${machine_guid}
//
// Impersonate:
// /api/v1/registry?action=switch&machine=${machine_guid}&name=${hostname}&url=${url}&to=${new_person_guid}
@@ -820,16 +927,17 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
*/
}
- char person_guid[GUID_LEN + 1] = "";
-
- debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url);
+ netdata_log_debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url);
// TODO
// The browser may send multiple cookies with our id
+ char person_guid[UUID_STR_LEN] = "";
char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "=");
if(cookie)
- strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36);
+ strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], UUID_STR_LEN - 1);
+ else if(!extract_bearer_token_from_request(w, person_guid, sizeof(person_guid)))
+ person_guid[0] = '\0';
char action = '\0';
char *machine_guid = NULL,
@@ -853,7 +961,7 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
if (!name || !*name) continue;
if (!value || !*value) continue;
- debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value);
+ netdata_log_debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value);
uint32_t hash = simple_hash(name);
@@ -866,7 +974,7 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
else if(vhash == hash_search && !strcmp(value, "search")) action = 'S';
else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W';
#ifdef NETDATA_INTERNAL_CHECKS
- else error("unknown registry action '%s'", value);
+ else netdata_log_error("unknown registry action '%s'", value);
#endif /* NETDATA_INTERNAL_CHECKS */
}
/*
@@ -896,7 +1004,7 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
to_person_guid = value;
}
#ifdef NETDATA_INTERNAL_CHECKS
- else error("unused registry URL parameter '%s' with value '%s'", name, value);
+ else netdata_log_error("unused registry URL parameter '%s' with value '%s'", name, value);
#endif /* NETDATA_INTERNAL_CHECKS */
}
@@ -918,10 +1026,12 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
return web_client_permission_denied(w);
}
+ buffer_no_cacheable(w->response.data);
+
switch(action) {
case 'A':
if(unlikely(!machine_guid || !machine_url || !url_name)) {
- error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')", machine_guid ? machine_guid : "UNSET", machine_url ? machine_url : "UNSET", url_name ? url_name : "UNSET");
+ netdata_log_error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')", machine_guid ? machine_guid : "UNSET", machine_url ? machine_url : "UNSET", url_name ? url_name : "UNSET");
buffer_flush(w->response.data);
buffer_strcat(w->response.data, "Invalid registry Access request.");
return HTTP_RESP_BAD_REQUEST;
@@ -932,7 +1042,7 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
case 'D':
if(unlikely(!machine_guid || !machine_url || !delete_url)) {
- error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
+ netdata_log_error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
buffer_flush(w->response.data);
buffer_strcat(w->response.data, "Invalid registry Delete request.");
return HTTP_RESP_BAD_REQUEST;
@@ -942,19 +1052,19 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
return registry_request_delete_json(host, w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec());
case 'S':
- if(unlikely(!machine_guid || !machine_url || !search_machine_guid)) {
- error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET");
+ if(unlikely(!search_machine_guid)) {
+ netdata_log_error("Invalid registry request - search requires these parameters: for ('%s')", search_machine_guid?search_machine_guid:"UNSET");
buffer_flush(w->response.data);
buffer_strcat(w->response.data, "Invalid registry Search request.");
return HTTP_RESP_BAD_REQUEST;
}
web_client_enable_tracking_required(w);
- return registry_request_search_json(host, w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec());
+ return registry_request_search_json(host, w, person_guid, search_machine_guid);
case 'W':
if(unlikely(!machine_guid || !machine_url || !to_person_guid)) {
- error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
+ netdata_log_error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
buffer_flush(w->response.data);
buffer_strcat(w->response.data, "Invalid registry Switch request.");
return HTTP_RESP_BAD_REQUEST;
@@ -1129,12 +1239,7 @@ inline int web_client_api_request_v1_info_fill_buffer(RRDHOST *host, BUFFER *wb)
host_functions2json(host, wb);
host_collectors(host, wb);
-#ifdef DISABLE_CLOUD
- buffer_json_member_add_boolean(wb, "cloud-enabled", false);
-#else
- buffer_json_member_add_boolean(wb, "cloud-enabled",
- appconfig_get_boolean(&cloud_config, CONFIG_SECTION_GLOBAL, "enabled", true));
-#endif
+ buffer_json_member_add_boolean(wb, "cloud-enabled", netdata_cloud_enabled);
#ifdef ENABLE_ACLK
buffer_json_member_add_boolean(wb, "cloud-available", true);
@@ -1160,12 +1265,12 @@ inline int web_client_api_request_v1_info_fill_buffer(RRDHOST *host, BUFFER *wb)
buffer_json_member_add_boolean(wb, "web-enabled", web_server_mode != WEB_SERVER_MODE_NONE);
buffer_json_member_add_boolean(wb, "stream-enabled", default_rrdpush_enabled);
-#ifdef ENABLE_COMPRESSION
+#ifdef ENABLE_RRDPUSH_COMPRESSION
buffer_json_member_add_boolean(wb, "stream-compression",
host->sender && stream_has_capability(host->sender, STREAM_CAP_COMPRESSION));
-#else
+#else // ! ENABLE_RRDPUSH_COMPRESSION
buffer_json_member_add_boolean(wb, "stream-compression", false);
-#endif //ENABLE_COMPRESSION
+#endif // ENABLE_RRDPUSH_COMPRESSION
#ifdef ENABLE_HTTPS
buffer_json_member_add_boolean(wb, "https-enabled", true);
@@ -1414,12 +1519,6 @@ int web_client_api_request_v1_dbengine_stats(RRDHOST *host __maybe_unused, struc
}
#endif
-#ifdef NETDATA_DEV_MODE
-#define ACL_DEV_OPEN_ACCESS WEB_CLIENT_ACL_DASHBOARD
-#else
-#define ACL_DEV_OPEN_ACCESS 0
-#endif
-
static struct web_api_command api_commands_v1[] = {
{ "info", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_info },
{ "data", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_data },
@@ -1429,7 +1528,7 @@ static struct web_api_command api_commands_v1[] = {
{ "contexts", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_contexts },
// registry checks the ACL by itself, so we allow everything
- { "registry", 0, WEB_CLIENT_ACL_NOCHECK, web_client_api_request_v1_registry },
+ { "registry", 0, WEB_CLIENT_ACL_NOCHECK, web_client_api_request_v1_registry },
// badges can be fetched with both dashboard and badge permissions
{ "badge.svg", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC | WEB_CLIENT_ACL_BADGE, web_client_api_request_v1_badge },
@@ -1443,21 +1542,21 @@ static struct web_api_command api_commands_v1[] = {
#if defined(ENABLE_ML)
{ "ml_info", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_ml_info },
- { "ml_models", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_ml_models },
+ // { "ml_models", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_ml_models },
#endif
- { "manage/health", 0, WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_ACLK, web_client_api_request_v1_mgmt_health },
+ {"manage/health", 0, WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_ACLK_WEBRTC_DASHBOARD_WITH_BEARER, web_client_api_request_v1_mgmt_health },
{ "aclk", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_aclk_state },
{ "metric_correlations", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_metric_correlations },
{ "weights", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_weights },
- { "function", 0, WEB_CLIENT_ACL_ACLK | ACL_DEV_OPEN_ACCESS, web_client_api_request_v1_function },
- { "functions", 0, WEB_CLIENT_ACL_ACLK | ACL_DEV_OPEN_ACCESS, web_client_api_request_v1_functions },
+ {"function", 0, WEB_CLIENT_ACL_ACLK_WEBRTC_DASHBOARD_WITH_BEARER | ACL_DEV_OPEN_ACCESS, web_client_api_request_v1_function },
+ {"functions", 0, WEB_CLIENT_ACL_ACLK_WEBRTC_DASHBOARD_WITH_BEARER | ACL_DEV_OPEN_ACCESS, web_client_api_request_v1_functions },
{ "dbengine_stats", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_dbengine_stats },
// terminator
- { NULL, 0, WEB_CLIENT_ACL_NONE, NULL },
+ { NULL, 0, WEB_CLIENT_ACL_NONE, NULL },
};
inline int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url_path_endpoint) {