diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-08-17 10:46:12 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-08-17 10:46:12 +0000 |
commit | 51dfb248933e5fac12fee1be8471bb08f9554428 (patch) | |
tree | 1d25518313ca94af4257e56ef919605a219a4178 /web/api | |
parent | Adding upstream version 1.42.0. (diff) | |
download | netdata-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.c | 31 | ||||
-rw-r--r-- | web/api/web_api_v1.c | 21 | ||||
-rw-r--r-- | web/api/web_api_v2.c | 17 |
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++; |