summaryrefslogtreecommitdiffstats
path: root/web/api
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-08-17 10:46:12 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-08-17 10:46:12 +0000
commit51dfb248933e5fac12fee1be8471bb08f9554428 (patch)
tree1d25518313ca94af4257e56ef919605a219a4178 /web/api
parentAdding upstream version 1.42.0. (diff)
downloadnetdata-upstream/1.42.1.tar.xz
netdata-upstream/1.42.1.zip
Adding upstream version 1.42.1.upstream/1.42.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'web/api')
-rw-r--r--web/api/web_api.c31
-rw-r--r--web/api/web_api_v1.c21
-rw-r--r--web/api/web_api_v2.c17
3 files changed, 55 insertions, 14 deletions
diff --git a/web/api/web_api.c b/web/api/web_api.c
index 7a4704bd5..96ab00390 100644
--- a/web/api/web_api.c
+++ b/web/api/web_api.c
@@ -5,27 +5,27 @@
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
DICTIONARY *netdata_authorized_bearers = NULL;
-static bool web_client_check_acl_and_bearer(struct web_client *w, WEB_CLIENT_ACL endpoint_acl) {
+static short int web_client_check_acl_and_bearer(struct web_client *w, WEB_CLIENT_ACL endpoint_acl) {
if(endpoint_acl == WEB_CLIENT_ACL_NONE || (endpoint_acl & WEB_CLIENT_ACL_NOCHECK))
// the endpoint is totally public
- return true;
+ return HTTP_RESP_OK;
bool acl_allows = w->acl & endpoint_acl;
if(!acl_allows)
// the channel we received the request from (w->acl) is not compatible with the endpoint
- return false;
+ return HTTP_RESP_FORBIDDEN;
if(!netdata_is_protected_by_bearer && !(endpoint_acl & WEB_CLIENT_ACL_BEARER_REQUIRED))
// bearer protection is not enabled and is not required by the endpoint
- return true;
+ return HTTP_RESP_OK;
if(!(endpoint_acl & (WEB_CLIENT_ACL_BEARER_REQUIRED|WEB_CLIENT_ACL_BEARER_OPTIONAL)))
// endpoint does not require a bearer
- return true;
+ return HTTP_RESP_OK;
if((w->acl & (WEB_CLIENT_ACL_ACLK|WEB_CLIENT_ACL_WEBRTC)))
// the request is coming from ACLK or WEBRTC (authorized already),
- return true;
+ return HTTP_RESP_OK;
// at this point we need a bearer to serve the request
// either because:
@@ -37,11 +37,11 @@ static bool web_client_check_acl_and_bearer(struct web_client *w, WEB_CLIENT_ACL
BEARER_STATUS t = api_check_bearer_token(w);
if(t == BEARER_STATUS_AVAILABLE_AND_VALIDATED)
// we have a valid bearer on the request
- return true;
+ return HTTP_RESP_OK;
netdata_log_info("BEARER: bearer is required for request: code %d", t);
- return false;
+ return HTTP_RESP_PRECOND_FAIL;
}
int web_client_api_request_vX(RRDHOST *host, struct web_client *w, char *url_path_endpoint, struct web_api_command *api_commands) {
@@ -73,8 +73,19 @@ int web_client_api_request_vX(RRDHOST *host, struct web_client *w, char *url_pat
return HTTP_RESP_BAD_REQUEST;
}
- if(unlikely(!web_client_check_acl_and_bearer(w, api_commands[i].acl)))
- return web_client_permission_denied(w);
+ short int code = web_client_check_acl_and_bearer(w, api_commands[i].acl);
+ if(code != HTTP_RESP_OK) {
+ if(code == HTTP_RESP_FORBIDDEN)
+ return web_client_permission_denied(w);
+
+ if(code == HTTP_RESP_PRECOND_FAIL)
+ return web_client_bearer_required(w);
+
+ buffer_flush(w->response.data);
+ buffer_sprintf(w->response.data, "Failed with code %d", code);
+ w->response.code = code;
+ return code;
+ }
char *query_string = (char *)buffer_tostring(w->url_query_string_decoded);
diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c
index 60962413d..6371f86b7 100644
--- a/web/api/web_api_v1.c
+++ b/web/api/web_api_v1.c
@@ -1524,6 +1524,25 @@ int web_client_api_request_v1_dbengine_stats(RRDHOST *host __maybe_unused, struc
}
#endif
+#define HLT_MGM "manage/health"
+int web_client_api_request_v1_mgmt(RRDHOST *host, struct web_client *w, char *url) {
+ const char *haystack = buffer_tostring(w->url_path_decoded);
+ char *needle;
+
+ buffer_flush(w->response.data);
+
+ if ((needle = strstr(haystack, HLT_MGM)) == NULL) {
+ buffer_strcat(w->response.data, "Invalid management request. Curently only 'health' is supported.");
+ return HTTP_RESP_NOT_FOUND;
+ }
+ needle += strlen(HLT_MGM);
+ if (*needle != '\0') {
+ buffer_strcat(w->response.data, "Invalid management request. Curently only 'health' is supported.");
+ return HTTP_RESP_NOT_FOUND;
+ }
+ return web_client_api_request_v1_mgmt_health(host, w, url);
+}
+
static struct web_api_command api_commands_v1[] = {
{ "info", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_info, 0 },
{ "data", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_data, 0 },
@@ -1550,7 +1569,7 @@ static struct web_api_command api_commands_v1[] = {
// { "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, 0 },
+ {"manage", 0, WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_ACLK, web_client_api_request_v1_mgmt, 1 },
{ "aclk", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_aclk_state, 0 },
{ "metric_correlations", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_metric_correlations, 0 },
{ "weights", 0, WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC, web_client_api_request_v1_weights, 0 },
diff --git a/web/api/web_api_v2.c b/web/api/web_api_v2.c
index 850282121..e288a5c6b 100644
--- a/web/api/web_api_v2.c
+++ b/web/api/web_api_v2.c
@@ -53,16 +53,27 @@ static time_t bearer_get_token(uuid_t *uuid) {
}
#define HTTP_REQUEST_AUTHORIZATION_BEARER "\r\nAuthorization: Bearer "
+#define HTTP_REQUEST_X_NETDATA_AUTH_BEARER "\r\nX-Netdata-Auth: Bearer "
BEARER_STATUS extract_bearer_token_from_request(struct web_client *w, char *dst, size_t dst_len) {
const char *req = buffer_tostring(w->response.data);
size_t req_len = buffer_strlen(w->response.data);
- const char *bearer = strcasestr(req, HTTP_REQUEST_AUTHORIZATION_BEARER);
+ const char *bearer = NULL;
+ const char *bearer_end = NULL;
+
+ bearer = strcasestr(req, HTTP_REQUEST_X_NETDATA_AUTH_BEARER);
+ if(bearer)
+ bearer_end = bearer + sizeof(HTTP_REQUEST_X_NETDATA_AUTH_BEARER) - 1;
+ else {
+ bearer = strcasestr(req, HTTP_REQUEST_AUTHORIZATION_BEARER);
+ if(bearer)
+ bearer_end = bearer + sizeof(HTTP_REQUEST_AUTHORIZATION_BEARER) - 1;
+ }
- if(!bearer)
+ if(!bearer || !bearer_end)
return BEARER_STATUS_NO_BEARER_IN_HEADERS;
- const char *token_start = bearer + sizeof(HTTP_REQUEST_AUTHORIZATION_BEARER) - 1;
+ const char *token_start = bearer_end;
while(isspace(*token_start))
token_start++;