mirror of
https://github.com/netdata/netdata.git
synced 2025-04-13 17:19:11 +00:00
return 412 instead of 403 when a bearer token is required (#15808)
This commit is contained in:
parent
ea66e7ced4
commit
b04cf59304
4 changed files with 38 additions and 15 deletions
|
@ -192,6 +192,7 @@ int registry_request_hello_json(RRDHOST *host, struct web_client *w) {
|
|||
|
||||
buffer_json_member_add_string(w->response.data, "registry", registry.registry_to_announce);
|
||||
buffer_json_member_add_boolean(w->response.data, "anonymous_statistics", netdata_anonymous_statistics_enabled);
|
||||
buffer_json_member_add_boolean(w->response.data, "X-Netdata-Auth", true);
|
||||
|
||||
buffer_json_member_add_array(w->response.data, "nodes");
|
||||
RRDHOST *h;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
if(!bearer)
|
||||
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 || !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++;
|
||||
|
|
|
@ -22,8 +22,8 @@ inline int web_client_bearer_required(struct web_client *w) {
|
|||
w->response.data->content_type = CT_TEXT_PLAIN;
|
||||
buffer_flush(w->response.data);
|
||||
buffer_strcat(w->response.data, "An authorization bearer is required to access the resource.");
|
||||
w->response.code = HTTP_RESP_UNAUTHORIZED;
|
||||
return HTTP_RESP_UNAUTHORIZED;
|
||||
w->response.code = HTTP_RESP_PRECOND_FAIL;
|
||||
return HTTP_RESP_PRECOND_FAIL;
|
||||
}
|
||||
|
||||
static inline int bad_request_multiple_dashboard_versions(struct web_client *w) {
|
||||
|
|
Loading…
Add table
Reference in a new issue