You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ja...@apache.org on 2020/01/04 12:59:01 UTC

[couchdb] 01/01: feat: add read-only _metrics role for _stats and _system endpoints

This is an automated email from the ASF dual-hosted git repository.

jan pushed a commit to branch feat/readonly-metrics-role
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 6a4e7b0bfd693ae8de379f21a23887f88459eec1
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sat Jan 4 13:58:15 2020 +0100

    feat: add read-only _metrics role for _stats and _system endpoints
    
    Closes #1567
---
 src/chttpd/src/chttpd_auth_request.erl   | 14 ++++++++++++++
 src/couch/include/couch_js_functions.hrl | 12 +++++++-----
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/src/chttpd/src/chttpd_auth_request.erl b/src/chttpd/src/chttpd_auth_request.erl
index 96dbf98..fa47f5b 100644
--- a/src/chttpd/src/chttpd_auth_request.erl
+++ b/src/chttpd/src/chttpd_auth_request.erl
@@ -99,6 +99,10 @@ server_authorization_check(#httpd{path_parts=[<<"_dbs_info">>]}=Req) ->
 server_authorization_check(#httpd{method=Method, path_parts=[<<"_utils">>|_]}=Req)
   when Method =:= 'HEAD' orelse Method =:= 'GET' ->
     Req;
+server_authorization_check(#httpd{path_parts=[<<"_node">>,_ , <<"_stats">>|_]}=Req) ->
+    require_metrics(Req);
+server_authorization_check(#httpd{path_parts=[<<"_node">>,_ , <<"_system">>|_]}=Req) ->
+    require_metrics(Req);
 server_authorization_check(#httpd{path_parts=[<<"_", _/binary>>|_]}=Req) ->
     require_admin(Req).
 
@@ -106,6 +110,16 @@ db_authorization_check(#httpd{path_parts=[DbName|_],user_ctx=Ctx}=Req) ->
     {_} = fabric:get_security(DbName, [{user_ctx, Ctx}]),
     Req.
 
+
+require_metrics(#httpd{user_ctx=#user_ctx{roles=UserRoles}}=Req) ->
+    IsAdmin = lists:member(<<"_admin">>, UserRoles),
+    IsMetrics = lists:member(<<"_metrics">>, UserRoles),
+    case {IsAdmin, IsMetrics} of
+        {true, _} -> Req;
+        {_, true} -> Req;
+        _ -> throw({unauthorized, <<"You are not a server admin or read-only metrics user">>})
+    end.
+
 require_admin(Req) ->
     ok = couch_httpd:verify_is_server_admin(Req),
     Req.
diff --git a/src/couch/include/couch_js_functions.hrl b/src/couch/include/couch_js_functions.hrl
index d969416..994382b 100644
--- a/src/couch/include/couch_js_functions.hrl
+++ b/src/couch/include/couch_js_functions.hrl
@@ -136,11 +136,13 @@
 
         // no system roles in users db
         for (var i = 0; i < newDoc.roles.length; i++) {
-            if (newDoc.roles[i][0] === '_') {
-                throw({
-                    forbidden:
-                    'No system roles (starting with underscore) in users db.'
-                });
+            if (newDoc.roles[i] !== '_metrics') {
+              if (newDoc.roles[i][0] === '_') {
+                  throw({
+                      forbidden:
+                      'No system roles (starting with underscore) in users db.'
+                  });
+              }
             }
         }