You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by dm...@apache.org on 2022/06/21 18:24:52 UTC

[trafficserver] branch 10-Dev updated: JSON-RPC: Add support for handler to pass information about the specifics when registering. (#8865)

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

dmeden pushed a commit to branch 10-Dev
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/10-Dev by this push:
     new ddcb091b8 JSON-RPC: Add support for handler to pass information about the specifics when registering. (#8865)
ddcb091b8 is described below

commit ddcb091b8c1eed26a175e102470a6ffa2c6db9f7
Author: Damian Meden <da...@gmail.com>
AuthorDate: Tue Jun 21 19:24:46 2022 +0100

    JSON-RPC: Add support for handler to pass information about the specifics when registering. (#8865)
    
    * This change adds support for passing Handler Options when registering a new JSON-RPC endpoint handler.
    To support this a new class Context is introduced as well as a Handler option class, this changes sets the base for
    future work around the handler registration and the Plugin API.
    
    * This commit adds documentation to support the JSON-RPC handler registration. It also fixes some bad links and typos.
    
    * Add late check for peers credentials on client's socket. RPC handler can now decide if they want to be administrative restricted or not.
    Add documentation support for this.
    
    * Address review suggestions
    
    Co-authored-by: Damian Meden <dm...@apache.org>
---
 doc/admin-guide/files/jsonrpc.yaml.en.rst          |  45 ++++---
 .../command-line/traffic_ctl_jsonrpc.en.rst        |   2 +-
 doc/developer-guide/jsonrpc/HandlerError.en.rst    |   2 +-
 doc/developer-guide/jsonrpc/index.en.rst           |   1 +
 doc/developer-guide/jsonrpc/jsonrpc-api.en.rst     |  19 ++-
 .../jsonrpc/jsonrpc-architecture.en.rst            |  60 +--------
 .../jsonrpc/jsonrpc-handler-development.en.rst     |   7 +-
 .../jsonrpc/jsonrpc-node-errors.en.rst             | 143 +++++++++++++++++++++
 doc/developer-guide/jsonrpc/jsonrpc-node.en.rst    |   7 +-
 .../jsonrpc/traffic_ctl-development.en.rst         |   7 +-
 include/ts/apidefs.h.in                            |  12 ++
 mgmt2/config/FileManager.cc                        |  11 +-
 mgmt2/rpc/Makefile.am                              |   4 +-
 mgmt2/rpc/jsonrpc/Context.cc                       |  35 +++++
 mgmt2/rpc/jsonrpc/Context.h                        |  77 +++++++++++
 mgmt2/rpc/jsonrpc/Defs.h                           |  25 ++--
 mgmt2/rpc/jsonrpc/JsonRPC.h                        |  10 +-
 mgmt2/rpc/jsonrpc/JsonRPCManager.cc                | 111 ++++++++--------
 mgmt2/rpc/jsonrpc/JsonRPCManager.h                 |  56 +++++---
 mgmt2/rpc/jsonrpc/error/RPCError.cc                |   2 +
 mgmt2/rpc/jsonrpc/error/RPCError.h                 |   5 +-
 mgmt2/rpc/jsonrpc/json/YAMLCodec.h                 |  50 ++-----
 .../rpc/jsonrpc/unit_tests/test_basic_protocol.cc  |  14 +-
 mgmt2/rpc/server/IPCSocketServer.cc                |  42 +++++-
 mgmt2/rpc/server/IPCSocketServer.h                 |   6 +
 mgmt2/rpc/server/unit_tests/test_rpcserver.cc      |   7 +
 src/traffic_server/HostStatus.cc                   |   6 +-
 src/traffic_server/RpcAdminPubHandlers.cc          |  35 +++--
 28 files changed, 550 insertions(+), 251 deletions(-)

diff --git a/doc/admin-guide/files/jsonrpc.yaml.en.rst b/doc/admin-guide/files/jsonrpc.yaml.en.rst
index 4c9970988..86fb8f368 100644
--- a/doc/admin-guide/files/jsonrpc.yaml.en.rst
+++ b/doc/admin-guide/files/jsonrpc.yaml.en.rst
@@ -1,3 +1,4 @@
+
 .. Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
@@ -56,7 +57,7 @@ In order for programs to communicate with |TS|, the server exposes a
 will find some of the configurable arguments that can be changed.
 
 
-.. _admnin-jsonrpc-configuration:
+.. _admin-jsonrpc-configuration:
 
 Configuration
 =============
@@ -68,9 +69,9 @@ Configuration
 If a non-default configuration is needed, the following describes the configuration
 structure.
 
-File `jsonrpc.yaml` is a YAML format. The default configuration is:
+File `jsonrpc.yaml` is a YAML format. The default configuration looks like:
 
-.. code:: yaml
+.. code-block:: yaml
 
    rpc:
      enabled: true
@@ -90,26 +91,34 @@ Field Name            Description
 IPC Socket (``unix``)
 ---------------------
 
-===================================== ==========================================
+Unix Domain Socket related configuration.
+
+===================================== =========================================================================================
 Field Name                            Description
-===================================== ==========================================
-``lock_path_name``                    Lock path, including the file name.
-                                      (changing this may have impacts in
-                                      :program:`traffic_ctl`)
-``sock_path_name``                    Sock path, including the file name. This
-                                      will be used as ``sockaddr_un.sun_path``
-                                      (changing this may have impacts in :program:`traffic_ctl`)
+===================================== =========================================================================================
+``lock_path_name``                    Lock path, including the file name. (changing this may have impacts in :program:`traffic_ctl`)
+``sock_path_name``                    Sock path, including the file name. This will be used as ``sockaddr_un.sun_path``. (changing
+                                      this may have impacts in :program:`traffic_ctl`)
 ``backlog``                           Check https://man7.org/linux/man-pages/man2/listen.2.html
-``max_retry_on_transient_errors``     Number of times the implementation is
-                                      allowed to retry when a transient error is
-                                      encountered.
-``restricted_api``                    Used to set rpc unix socket permissions.
-                                      If restricted `0700` will be set, otherwise
-                                      `0777`. ``true`` by default.
-===================================== ==========================================
+``max_retry_on_transient_errors``     Number of times the implementation is allowed to retry when a transient error is encountered.
+``restricted_api``                    This setting specifies whether the jsonrpc node access should be restricted to root processes.
+                                      If this is set to ``false``, then on platforms that support passing process credentials, non-root
+                                      processes will be allowed to make read-only JSONRPC calls. Any calls that modify server state
+                                      (eg. setting a configuration variable) will still be restricted to root processes. If set to ``true``
+                                      then only root processes will be allowed to perform any api call.
+                                      If restricted, the Unix Domain Socket will be created with `0700` permissions, otherwise `0777`.
+                                      ``true`` by default.
+                                      In case of an unauthorized call is made, a corresponding rpc error will be returned, you can
+                                      check :ref:`jsonrpc-node-errors-unauthorized-action` for details about the errors.
+===================================== =========================================================================================
 
 
 .. note::
 
    Currently, there is only 1 communication mechanism supported. Unix Domain Sockets
 
+
+See also
+========
+
+:ref:`traffic_ctl_jsonrpc`
diff --git a/doc/appendices/command-line/traffic_ctl_jsonrpc.en.rst b/doc/appendices/command-line/traffic_ctl_jsonrpc.en.rst
index acfe4f267..94f0e5667 100644
--- a/doc/appendices/command-line/traffic_ctl_jsonrpc.en.rst
+++ b/doc/appendices/command-line/traffic_ctl_jsonrpc.en.rst
@@ -604,5 +604,5 @@ See also
 
 :manpage:`records.config(5)`,
 :manpage:`storage.config(5)`,
-:ref:`admnin-jsonrpc-configuration`,
+:ref:`admin-jsonrpc-configuration`,
 :ref:`jsonrpc-protocol`
diff --git a/doc/developer-guide/jsonrpc/HandlerError.en.rst b/doc/developer-guide/jsonrpc/HandlerError.en.rst
index 03f824b9d..cf78d0e91 100644
--- a/doc/developer-guide/jsonrpc/HandlerError.en.rst
+++ b/doc/developer-guide/jsonrpc/HandlerError.en.rst
@@ -26,7 +26,7 @@ API Handler error codes
 ***********************
 
 High level handler error codes, each particular handler can be fit into one of the following categories.
-A good approach could be the following. This required coordination among all the errors, just for now, this soluction seems ok.
+A good approach could be the following. This required coordination among all the errors, just for now, this solution seems ok.
 
 .. code-block:: cpp
 
diff --git a/doc/developer-guide/jsonrpc/index.en.rst b/doc/developer-guide/jsonrpc/index.en.rst
index 3706257fd..7d06cc713 100644
--- a/doc/developer-guide/jsonrpc/index.en.rst
+++ b/doc/developer-guide/jsonrpc/index.en.rst
@@ -28,6 +28,7 @@ JSONRPC
    jsonrpc-architecture.en
    jsonrpc-api.en
    jsonrpc-node.en
+   jsonrpc-node-errors.en
    jsonrpc-handler-development.en
    jsonrpc-client-api.en
    traffic_ctl-development.en
diff --git a/doc/developer-guide/jsonrpc/jsonrpc-api.en.rst b/doc/developer-guide/jsonrpc/jsonrpc-api.en.rst
index 3391909fc..75179cfb8 100644
--- a/doc/developer-guide/jsonrpc/jsonrpc-api.en.rst
+++ b/doc/developer-guide/jsonrpc/jsonrpc-api.en.rst
@@ -960,7 +960,7 @@ Request:
 
 Response:
 
-The response will contain the default `success_response`  or an :cpp:class:`RPCErrorCode`.
+The response will contain the default `success_response`  or a proper rpc error, check :ref:`jsonrpc-node-errors` for mode details.
 
 
 Validation:
@@ -1070,7 +1070,7 @@ Parameters
 Result
 ~~~~~~
 
-This api will only inform for errors during the metric update. Errors will be tracked down in the :cpp:class:`RPCErrorCode` field.
+This api will only inform for errors during the metric update. Errors will be tracked down in the `error` field.
 
 .. note::
 
@@ -1095,7 +1095,7 @@ Request:
 
 Response:
 
-The response will contain the default `success_response`  or an :cpp:class:`RPCErrorCode`.
+The response will contain the default `success_response`  or an error. :ref:`jsonrpc-node-errors`.
 
 
 .. _admin_host_set_status:
@@ -1164,7 +1164,7 @@ marking this reason as "down" in that case.
 Result
 ~~~~~~
 
-The response will contain the default `success_response`  or an :cpp:class:`RPCErrorCode`.
+The response will contain the default `success_response`  or an error. :ref:`jsonrpc-node-errors`.
 
 
 Examples
@@ -1260,7 +1260,7 @@ Parameters
 Result
 ~~~~~~
 
-The response will contain the default `success_response`  or an :cpp:class:`RPCErrorCode`.
+The response will contain the default `success_response`  or an error. :ref:`jsonrpc-node-errors`.
 
 
 Examples
@@ -1302,7 +1302,7 @@ Field                   Type          Description
 Result
 ~~~~~~
 
-The response will contain the default `success_response`  or an :cpp:class:`RPCErrorCode`.
+The response will contain the default `success_response`  or an error. :ref:`jsonrpc-node-errors`.
 
 .. note::
 
@@ -1380,7 +1380,7 @@ Field                   Type          Description
 Result
 ~~~~~~
 
-The response will contain the default `success_response`  or an :cpp:class:`RPCErrorCode`.
+The response will contain the default `success_response`  or an error. :ref:`jsonrpc-node-errors`.
 
 Examples
 ~~~~~~~~
@@ -1781,3 +1781,8 @@ Response:
          ]
       }
    }
+
+See also
+========
+
+:ref:`jsonrpc-node-errors`
diff --git a/doc/developer-guide/jsonrpc/jsonrpc-architecture.en.rst b/doc/developer-guide/jsonrpc/jsonrpc-architecture.en.rst
index 4025cbd30..91489c5e9 100644
--- a/doc/developer-guide/jsonrpc/jsonrpc-architecture.en.rst
+++ b/doc/developer-guide/jsonrpc/jsonrpc-architecture.en.rst
@@ -55,7 +55,7 @@ IPC
 
 The current server implementation runs on an IPC Socket(Unix Domain Socket). This server implements an iterative server style.
 The implementation runs on a dedicated ``TSThread`` and as their style express, this performs blocking calls to all the registered handlers.
-Configuration for this particular server style can be found in the admin section :ref:`admnin-jsonrpc-configuration`.
+Configuration for this particular server style can be found in the admin section :ref:`admin-jsonrpc-configuration`.
 
 
 Using the JSONRPC mechanism
@@ -464,61 +464,6 @@ Response:
       }
 
 
-.. _rpc-error-code:
-
-Internally we have defined an ``enum`` class that keeps track of the errors that the server will inform in most of the cases.
-Some of this errors are already defined by the `JSONRPC`_ specs and some (``>=1``) are defined by |TS|.
-
-.. class:: RPCErrorCode
-
-   Defines the API error codes that will be used in case of any RPC error.
-
-   .. enumerator:: INVALID_REQUEST  = -32600
-   .. enumerator:: METHOD_NOT_FOUND = -32601
-   .. enumerator:: INVALID_PARAMS   = -32602
-   .. enumerator:: INTERNAL_ERROR   = -32603
-   .. enumerator:: PARSE_ERROR      = -32700
-
-      `JSONRPC`_ defined errors.
-
-   .. enumerator:: InvalidVersion     = 1
-
-      The passed version is invalid. must be 2.0
-
-   .. enumerator:: InvalidVersionType = 2
-
-      The passed version field type is invalid. must be a ``string``
-
-   .. enumerator:: MissingVersion = 3
-
-      Version field is missing from the request. This field is mandatory.
-
-   .. enumerator:: InvalidMethodType = 4
-
-      The passed method field type is invalid. must be a ``string``
-
-   .. enumerator:: MissingMethod = 5
-
-      Method field is missing from the request. This field is mandatory.
-
-   .. enumerator:: InvalidParamType = 6
-
-      The passed parameter field type is not valid.
-
-   .. enumerator:: InvalidIdType = 7
-
-      The passed id field type is invalid.
-
-   .. enumerator:: NullId = 8
-
-      The passed if is ``null``
-
-   .. enumerator:: ExecutionError = 9
-
-      An error occurred during the execution of the RPC call. This error is used as a generic High level error. The details details about
-      the error, in most cases are specified in the ``data`` field.
-
-
 .. information:
 
    According to the |RPC| specs, if you get an error, the ``result`` field will not be set. |TS| will grant this.
@@ -535,5 +480,6 @@ Development Guide
 See also
 ========
 
-:ref:`admnin-jsonrpc-configuration`,
+:ref:`admin-jsonrpc-configuration`,
+:ref:`jsonrpc-node-errors`,
 :ref:`traffic_ctl_jsonrpc`
diff --git a/doc/developer-guide/jsonrpc/jsonrpc-handler-development.en.rst b/doc/developer-guide/jsonrpc/jsonrpc-handler-development.en.rst
index 94ae293a9..f79b21a2c 100644
--- a/doc/developer-guide/jsonrpc/jsonrpc-handler-development.en.rst
+++ b/doc/developer-guide/jsonrpc/jsonrpc-handler-development.en.rst
@@ -186,7 +186,7 @@ We recommend some ways to deal with this:
 
 This can be set in case you would like to let the server to respond with an |RPC| error, ``ExecutionError`` will be used to catch all the
 errors that are fired from within the function call, either by setting the proper errata or by throwing an exception.
-Please check the `rpc-error-code` and in particular ``ExecutionError = 9``. Also check :ref:`jsonrpc-handler-errors`
+Please check the :ref:`jsonrpc-node-errors` and in particular ``ExecutionError = 9``. Also check :ref:`jsonrpc-handler-errors`
 
 .. important::
 
@@ -420,7 +420,10 @@ Important Notes
 * To interact directly with the |RPC| node, please check :ref:`jsonrpc-node`
 
 
-:ref:`admnin-jsonrpc-configuration`
+See also
+========
+
+:ref:`admin-jsonrpc-configuration`
 :ref:`jsonrpc-protocol`
 :ref:`developer-guide-traffic_ctl-development`
 
diff --git a/doc/developer-guide/jsonrpc/jsonrpc-node-errors.en.rst b/doc/developer-guide/jsonrpc/jsonrpc-node-errors.en.rst
new file mode 100644
index 000000000..0d9253f08
--- /dev/null
+++ b/doc/developer-guide/jsonrpc/jsonrpc-node-errors.en.rst
@@ -0,0 +1,143 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License.
+
+.. include:: ../../common.defs
+
+.. highlight:: cpp
+.. default-domain:: cpp
+
+.. _JSONRPC: https://www.jsonrpc.org/specification
+.. _JSON: https://www.json.org/json-en.html
+
+
+.. _jsonrpc-node-errors:
+
+
+JSON RPC errors
+***************
+
+A list of codes and descriptions of errors that could be send back from the JSONRPC server. JSONRPC response messages could contains
+different set of errors in the following format:
+
+.. note::
+
+   Check  :ref:`jsonrpc-error` for details about the error structure.
+
+
+.. code-block::json
+
+   {
+      "error": {
+         "code": -32601,
+         "message": "Method not found"
+      },
+      "id": "ded7018e-0720-11eb-abe2-001fc69cc946",
+      "jsonrpc": "2.0"
+   }
+
+In some cases the data field could be populated:
+
+.. code-block:: json
+
+   {
+      "jsonrpc": "2.0",
+      "error":{
+         "code": 10,
+         "message": "Unauthorized action",
+         "data":[
+            {
+               "code": 2,
+               "message":"Denied privileged API access for uid=XXX gid=XXX"
+            }
+         ]
+      },
+      "id":"5e273ec0-3e3b-4a81-90ec-aeee3d38073f"
+   }
+
+
+.. _jsonrpc-node-errors-standard-errors:
+
+Standard errors
+===============
+
+=============== ========================================= =========================================================
+Field           Message                                   Description
+=============== ========================================= =========================================================
+-32700          Parse error                               Invalid JSON was received by the server.
+                                                          An error occurred on the server while parsing the JSON text.
+-32600          Invalid Request                           The JSON sent is not a valid Request object.
+-32601          Method not found                          The method does not exist / is not available.
+-32602          Invalid params                            Invalid method parameter(s).
+-32603          Internal error                            Internal `JSONRPC`_ error.
+=============== ========================================= =========================================================
+
+.. _jsonrpc-node-errors-custom-errors:
+
+Custom errors
+=============
+
+The following error list are defined by the server.
+
+=============== ========================================= =========================================================
+Field           Message                                   Description
+=============== ========================================= =========================================================
+1               Invalid version, 2.0 only                 The server only accepts version field equal to `2.0`.
+2               Invalid version type, should be a string  Version field should be a literal string.
+3               Missing version field                     No version field present, version field is mandatory.
+4               Invalid method type, should be a string   The method field should be a literal string.
+5               Missing method field                      No method field present, method field is mandatory.
+6               Invalid params type. A Structured value   Params field should be a structured type, list or structure.
+                is expected                               This is similar to `-32602`
+7               Invalid id type                           If field should be a literal string.
+8               Use of null as id is discouraged          Id field value is null, as per the specs this is discouraged,
+                                                          the server will not accept it.
+9               Error during execution                    An error occurred during the execution of the RPC call.
+                                                          This error is used as a generic High level error. The specifics
+                                                          details about the error, in most cases are specified in the
+                                                          ``data`` field.
+10              Unauthorized action                       The rpc method will not be invoked because the action is not
+                                                          permitted by some constraint or authorization issue.Check
+                                                          :ref:`jsonrpc-node-errors-unauthorized-action` for mode details.
+=============== ========================================= =========================================================
+
+.. _jsonrpc-node-errors-unauthorized-action:
+
+Unauthorized action
+-------------------
+
+Under this error, the `data` field could be populated with the following errors, eventually more than one could be in set.
+
+.. code-block:: json
+
+   "data":[
+      {
+         "code":2,
+         "message":"Denied privileged API access for uid=XXX gid=XXX"
+      }
+   ]
+
+=============== ========================================= =========================================================
+Field           Message                                   Description
+=============== ========================================= =========================================================
+1               Error getting peer credentials: {}        Something happened while trying to get the peers credentials.
+                                                          The error string will show the error code(`errno`) returned by the
+                                                          server.
+2               Denied privileged API access for uid={}   Permission denied. Unix Socket credentials were checked and they haven't meet
+                gid={}                                    the required policy. The handler was configured as restricted
+                                                          and the socket credentials failed to validate. Check TBC for
+                                                          more information.
+=============== ========================================= =========================================================
diff --git a/doc/developer-guide/jsonrpc/jsonrpc-node.en.rst b/doc/developer-guide/jsonrpc/jsonrpc-node.en.rst
index 204e7b357..25b63a505 100644
--- a/doc/developer-guide/jsonrpc/jsonrpc-node.en.rst
+++ b/doc/developer-guide/jsonrpc/jsonrpc-node.en.rst
@@ -36,7 +36,7 @@ IPC Node
 ========
 
 You can directly connect to the Unix Domain Socket used for the |RPC| node, the location of the sockets
-will depend purely on how did you configure the server, please check :ref:`admnin-jsonrpc-configuration` for
+will depend purely on how did you configure the server, please check :ref:`admin-jsonrpc-configuration` for
 information regarding configuration.
 
 
@@ -57,3 +57,8 @@ Using traffic_ctl
 :program:`traffic_ctl` can also be used to directly send raw |RPC| messages to the server's node, :program:`traffic_ctl` provides
 several options to achieve this, please check ``traffic_ctl_rpc``.
 
+
+Error responses
+---------------
+
+The server will indicate in case of any error processing the call, check :ref:`jsonrpc-node-errors` for more details.
diff --git a/doc/developer-guide/jsonrpc/traffic_ctl-development.en.rst b/doc/developer-guide/jsonrpc/traffic_ctl-development.en.rst
index 3a219578c..957c00a3f 100644
--- a/doc/developer-guide/jsonrpc/traffic_ctl-development.en.rst
+++ b/doc/developer-guide/jsonrpc/traffic_ctl-development.en.rst
@@ -208,7 +208,10 @@ There is code that was written in this way by design, ``RecordPrinter`` and ``Re
 that needs to query and print records without any major hassle.
 
 
+See also
+========
 
-:ref:`admnin-jsonrpc-configuration`,
+:ref:`admin-jsonrpc-configuration`,
 :ref:`traffic_ctl_jsonrpc`,
-:ref:`jsonrpc_development`
+:ref:`jsonrpc_development`,
+:ref:`jsonrpc-node-errors`
diff --git a/include/ts/apidefs.h.in b/include/ts/apidefs.h.in
index 36f19b033..f0be4e8d6 100644
--- a/include/ts/apidefs.h.in
+++ b/include/ts/apidefs.h.in
@@ -1479,6 +1479,18 @@ namespace ts
 }
 #endif
 
+///
+/// @brief JSON-RPC Handler options
+///
+/// This class holds information about how a handler will be managed and delivered when called. The JSON-RPC manager would use this
+/// object to perform certain validation.
+///
+typedef struct TSRPCHandlerOptions_s {
+  struct Auth {
+    int restricted; ///< Tells the RPC Manager if the call can be delivered or not based on the config rules.
+  } auth;
+} TSRPCHandlerOptions;
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/mgmt2/config/FileManager.cc b/mgmt2/config/FileManager.cc
index a2880cf83..4bb6aa9a3 100644
--- a/mgmt2/config/FileManager.cc
+++ b/mgmt2/config/FileManager.cc
@@ -91,12 +91,11 @@ FileManager::FileManager()
   this->registerCallback(&handle_file_reload);
 
   // Register the files registry jsonrpc endpoint
-  rpc::add_method_handler(
-    "filemanager.get_files_registry",
-    [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> {
-      return get_files_registry_rpc_endpoint(id, req);
-    },
-    &rpc::core_ats_rpc_service_provider_handle);
+  rpc::add_method_handler("filemanager.get_files_registry",
+                          [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> {
+                            return get_files_registry_rpc_endpoint(id, req);
+                          },
+                          &rpc::core_ats_rpc_service_provider_handle, {{rpc::NON_RESTRICTED_API}});
 }
 
 // FileManager::~FileManager
diff --git a/mgmt2/rpc/Makefile.am b/mgmt2/rpc/Makefile.am
index 26ca19236..d4de43b0e 100644
--- a/mgmt2/rpc/Makefile.am
+++ b/mgmt2/rpc/Makefile.am
@@ -45,7 +45,9 @@ libjsonrpc_protocol_COMMON = \
 	jsonrpc/error/RPCError.cc \
 	jsonrpc/error/RPCError.h \
 	jsonrpc/JsonRPCManager.cc \
-	jsonrpc/JsonRPCManager.h
+	jsonrpc/JsonRPCManager.h \
+	jsonrpc/Context.cc \
+	jsonrpc/Context.h
 
 libjsonrpc_protocol_la_SOURCES = \
 	$(libjsonrpc_protocol_COMMON)
diff --git a/mgmt2/rpc/jsonrpc/Context.cc b/mgmt2/rpc/jsonrpc/Context.cc
new file mode 100644
index 000000000..a0a3793f8
--- /dev/null
+++ b/mgmt2/rpc/jsonrpc/Context.cc
@@ -0,0 +1,35 @@
+/**
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+#include "Context.h"
+
+namespace rpc
+{
+// --- Call Context impl
+ts::Errata
+Context::Auth::is_blocked(TSRPCHandlerOptions const &options) const
+{
+  ts::Errata out;
+  // check every registered callback and see if they have something to say. Then report back to the manager
+  for (auto &&check : _checkers) {
+    check(options, out);
+  }
+  return out;
+};
+} // namespace rpc
diff --git a/mgmt2/rpc/jsonrpc/Context.h b/mgmt2/rpc/jsonrpc/Context.h
new file mode 100644
index 000000000..fb78d338e
--- /dev/null
+++ b/mgmt2/rpc/jsonrpc/Context.h
@@ -0,0 +1,77 @@
+/**
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+#pragma once
+
+#include <vector>
+#include <functional>
+#include <string_view>
+
+#include "tscore/Errata.h"
+#include "ts/apidefs.h"
+#include "rpc/handlers/common/ErrorUtils.h"
+
+namespace rpc
+{
+constexpr bool RESTRICTED_API{true};
+constexpr bool NON_RESTRICTED_API{false};
+///
+/// @brief RPC call context class.
+///
+/// This class is used to carry information from the transport logic to the rpc invocation logic, the transport may need to block
+/// some rpc handlers from being executed which at the time of finish ups reading the raw message is yet too early to know the
+/// actual handler.
+///
+class Context
+{
+  using checker_cb = std::function<void(TSRPCHandlerOptions const &, ts::Errata &)>;
+  /// @brief Internal class to hold the permission checker part.
+  struct Auth {
+    /// Checks for permissions. This function checks for every registered permission checker.
+    ///
+    /// @param options Registered handler options.
+    /// @return ts::Errata The errata will be filled by each of the registered checkers, if there was any issue validating the
+    ///                    call, then the errata reflects that.
+    ts::Errata is_blocked(TSRPCHandlerOptions const &options) const;
+
+    /// Add permission checkers.
+    template <typename F>
+    void
+    add_checker(F &&f)
+    {
+      _checkers.emplace_back(std::forward<F>(f));
+    }
+
+  private:
+    std::vector<checker_cb> _checkers; ///< cb collection.
+  } _auth;
+
+public:
+  Auth &
+  get_auth()
+  {
+    return _auth;
+  }
+  Auth const &
+  get_auth() const
+  {
+    return _auth;
+  }
+};
+} // namespace rpc
diff --git a/mgmt2/rpc/jsonrpc/Defs.h b/mgmt2/rpc/jsonrpc/Defs.h
index 9c321f6f1..f528ad111 100644
--- a/mgmt2/rpc/jsonrpc/Defs.h
+++ b/mgmt2/rpc/jsonrpc/Defs.h
@@ -45,12 +45,18 @@ public:
 };
 
 struct RPCResponseInfo {
-  RPCResponseInfo(std::optional<std::string> const &id_) : id(id_) {}
+  RPCResponseInfo(std::string const &id_) : id{id_} {} // Convenient
   RPCResponseInfo() = default;
 
-  RPCHandlerResponse callResult;
-  std::error_code rpcError;
-  std::optional<std::string> id;
+  struct Error {
+    std::error_code ec;
+    ts::Errata data;
+  };
+
+  std::string id; //!< incoming request id (only used for method calls, empty means it's a notification as requests with empty id
+                  //!< will not pass the validation)
+  Error error;    //!< Error code and details.
+  RPCHandlerResponse callResult; //!< the actual handler's response
 };
 
 ///
@@ -61,17 +67,18 @@ struct RPCResponseInfo {
 struct RPCRequestInfo {
   RPCRequestInfo() = default;
   RPCRequestInfo(std::string const &version, std::string const &mid) : jsonrpc(version), id(mid) {}
-  std::string jsonrpc;           //!<  JsonRPC version ( we only allow 2.0 ). @see yamlcpp_json_decoder
-  std::string method;            //!< incoming method name.
-  std::optional<std::string> id; //!< incoming request if (only used for method calls.)
-  YAML::Node params;             //!< incoming parameter structure.
+  std::string jsonrpc; //!<  JsonRPC version ( we only allow 2.0 ). @see yamlcpp_json_decoder
+  std::string method;  //!< incoming method name.
+  std::string id;    //!< incoming request id (only used for method calls, empty means it's a notification as requests with empty id
+                     //!< will not pass the validation)
+  YAML::Node params; //!< incoming parameter structure.
 
   /// Convenience functions that checks for the type of request. If contains id then it should be handle as method call, otherwise
   /// will be a notification.
   bool
   is_notification() const
   {
-    return !id.has_value();
+    return id.empty();
   }
   bool
   is_method() const
diff --git a/mgmt2/rpc/jsonrpc/JsonRPC.h b/mgmt2/rpc/jsonrpc/JsonRPC.h
index 8af97399e..acf8cfd07 100644
--- a/mgmt2/rpc/jsonrpc/JsonRPC.h
+++ b/mgmt2/rpc/jsonrpc/JsonRPC.h
@@ -24,7 +24,7 @@
 
 namespace rpc
 {
-/// Generic and global JSONRPC service provider info object. It's recommended to use this object when registring your new handler
+/// Generic and global JSONRPC service provider info object. It's recommended to use this object when registering your new handler
 /// into the rpc system IF the implementor wants the handler to be listed as ATS's handler.
 extern RPCRegistryInfo core_ats_rpc_service_provider_handle;
 // -----------------------------------------------------------------------------
@@ -33,17 +33,17 @@ extern RPCRegistryInfo core_ats_rpc_service_provider_handle;
 /// @see JsonRPCManager::add_method_handler for details
 template <typename Func>
 inline bool
-add_method_handler(std::string_view name, Func &&call, const RPCRegistryInfo *info = nullptr)
+add_method_handler(std::string_view name, Func &&call, const RPCRegistryInfo *info, TSRPCHandlerOptions const &opt)
 {
-  return JsonRPCManager::instance().add_method_handler(name, std::forward<Func>(call), info);
+  return JsonRPCManager::instance().add_method_handler(name, std::forward<Func>(call), info, opt);
 }
 
 /// @see JsonRPCManager::add_notification_handler for details
 template <typename Func>
 inline bool
-add_notification_handler(std::string_view name, Func &&call, const RPCRegistryInfo *info = nullptr)
+add_notification_handler(std::string_view name, Func &&call, const RPCRegistryInfo *info, TSRPCHandlerOptions const &opt)
 {
-  return JsonRPCManager::instance().add_notification_handler(name, std::forward<Func>(call), info);
+  return JsonRPCManager::instance().add_notification_handler(name, std::forward<Func>(call), info, opt);
 }
 
 } // namespace rpc
diff --git a/mgmt2/rpc/jsonrpc/JsonRPCManager.cc b/mgmt2/rpc/jsonrpc/JsonRPCManager.cc
index f84c7fc98..050f5a443 100644
--- a/mgmt2/rpc/jsonrpc/JsonRPCManager.cc
+++ b/mgmt2/rpc/jsonrpc/JsonRPCManager.cc
@@ -39,7 +39,12 @@ const std::string RPC_SERVICE_PROVIDER_KEY{"provider"};
 const std::string RPC_SERVICE_SCHEMA_KEY{"schema"};
 const std::string RPC_SERVICE_METHODS_KEY{"methods"};
 const std::string RPC_SERVICE_NOTIFICATIONS_KEY{"notifications"};
+const std::string RPC_SERVICE_PRIVILEGED_KEY{"privileged"};
 const std::string RPC_SERVICE_N_A_STR{"N/A"};
+
+// jsonrpc log tag.
+constexpr auto logTag    = "rpc";
+constexpr auto logTagMsg = "rpc.msg";
 } // namespace
 
 namespace rpc
@@ -54,9 +59,15 @@ std::condition_variable g_rpcHandlingCompletion;
 ts::Rv<YAML::Node> g_rpcHandlerResponseData;
 bool g_rpcHandlerProcessingCompleted{false};
 
-// jsonrpc log tag.
-static constexpr auto logTag    = "rpc";
-static constexpr auto logTagMsg = "rpc.msg";
+// --- Helpers
+std::pair<ts::Errata, error::RPCErrorCode>
+check_for_blockers(Context const &ctx, TSRPCHandlerOptions const &options)
+{
+  if (auto err = ctx.get_auth().is_blocked(options); !err.isOK()) {
+    return {err, error::RPCErrorCode::Unauthorized};
+  }
+  return {};
+}
 
 // --- Dispatcher
 JsonRPCManager::Dispatcher::Dispatcher()
@@ -66,32 +77,41 @@ JsonRPCManager::Dispatcher::Dispatcher()
 void
 JsonRPCManager::Dispatcher::register_service_descriptor_handler()
 {
-  // TODO: revisit this.
   if (!this->add_handler<Dispatcher::Method, MethodHandlerSignature>(
         "show_registered_handlers",
         [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> {
           return show_registered_handlers(id, req);
         },
-        &core_ats_rpc_service_provider_handle)) {
+        &core_ats_rpc_service_provider_handle, {{NON_RESTRICTED_API}})) {
     Warning("Handler already registered.");
   }
 
   if (!this->add_handler<Dispatcher::Method, MethodHandlerSignature>(
         "get_service_descriptor",
         [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> { return get_service_descriptor(id, req); },
-        &core_ats_rpc_service_provider_handle)) {
+        &core_ats_rpc_service_provider_handle, {{NON_RESTRICTED_API}})) {
     Warning("Handler already registered.");
   }
 }
 
 JsonRPCManager::Dispatcher::response_type
-JsonRPCManager::Dispatcher::dispatch(specs::RPCRequestInfo const &request) const
+JsonRPCManager::Dispatcher::dispatch(Context const &ctx, specs::RPCRequestInfo const &request) const
 {
   std::error_code ec;
   auto const &handler = find_handler(request, ec);
 
   if (ec) {
-    return {std::nullopt, ec};
+    specs::RPCResponseInfo resp{request.id};
+    resp.error.ec = ec;
+    return resp;
+  }
+
+  // We have got a valid handler, we will now check if the context holds any restriction for this handler to be called.
+  if (auto &&[errata, ec] = check_for_blockers(ctx, handler.get_options()); !errata.isOK()) {
+    specs::RPCResponseInfo resp{request.id};
+    resp.error.ec   = ec;
+    resp.error.data = errata;
+    return resp;
   }
 
   if (request.is_notification()) {
@@ -117,7 +137,7 @@ JsonRPCManager::Dispatcher::find_handler(specs::RPCRequestInfo const &request, s
     return no_handler;
   }
 
-  // we need to make sure we the request is valid against the internal handler.
+  // Handler's method type should match the requested method type.
   if ((request.is_method() && search->second.is_method()) || (request.is_notification() && !search->second.is_method())) {
     return search->second;
   }
@@ -143,10 +163,10 @@ JsonRPCManager::Dispatcher::invoke_method_handler(JsonRPCManager::Dispatcher::In
     }
   } catch (std::exception const &e) {
     Debug(logTag, "Oops, something happened during the callback invocation: %s", e.what());
-    return {std::nullopt, error::RPCErrorCode::ExecutionError};
+    response.error.ec = error::RPCErrorCode::ExecutionError;
   }
 
-  return {response, {}};
+  return response;
 }
 
 JsonRPCManager::Dispatcher::response_type
@@ -160,7 +180,7 @@ JsonRPCManager::Dispatcher::invoke_notification_handler(JsonRPCManager::Dispatch
     // it's a notification so we do not care much.
   }
 
-  return response_type{};
+  return {std::nullopt};
 }
 
 bool
@@ -182,32 +202,8 @@ JsonRPCManager::remove_handler(std::string_view name)
   return _dispatcher.remove_handler(name);
 }
 
-static inline specs::RPCResponseInfo
-make_error_response(specs::RPCRequestInfo const &req, std::error_code const &ec)
-{
-  specs::RPCResponseInfo resp;
-
-  // we may have been able to collect the id, if so, use it.
-  if (req.id) {
-    resp.id = req.id;
-  }
-
-  resp.rpcError = ec;
-
-  return resp;
-}
-
-static inline specs::RPCResponseInfo
-make_error_response(std::error_code const &ec)
-{
-  specs::RPCResponseInfo resp;
-
-  resp.rpcError = ec;
-  return resp;
-}
-
 std::optional<std::string>
-JsonRPCManager::handle_call(std::string const &request)
+JsonRPCManager::handle_call(Context const &ctx, std::string const &request)
 {
   Debug(logTagMsg, "--> JSONRPC request\n'%s'", request.c_str());
 
@@ -219,8 +215,9 @@ JsonRPCManager::handle_call(std::string const &request)
     // If any error happened within the request, they will be kept inside each
     // particular request, as they would need to be converted back in a proper error response.
     if (ec) {
-      auto response = make_error_response(ec);
-      return Encoder::encode(response);
+      specs::RPCResponseInfo resp;
+      resp.error.ec = ec;
+      return Encoder::encode(resp);
     }
 
     specs::RPCResponse response{msg.is_batch()};
@@ -231,23 +228,19 @@ JsonRPCManager::handle_call(std::string const &request)
       if (!decode_error) {
         // request seems ok and ready to be dispatched. The dispatcher will tell us if the method exist and if so, it will dispatch
         // the call and gives us back the response.
-        auto &&[encodedResponse, ec] = _dispatcher.dispatch(req);
-
-        // On any error, ec will have a value
-        if (!ec) {
-          // we only get valid responses if it was a method request, not
-          // for notifications.
-          if (encodedResponse) {
-            response.add_message(*encodedResponse);
-          }
-        } else {
-          // get an error response, we may have the id, so let's try to use it.
-          response.add_message(make_error_response(req, ec));
-        }
+        auto encodedResponse = _dispatcher.dispatch(ctx, req);
+
+        if (encodedResponse) {
+          // if any error was detected during invocation or before, the response will have the error field set, so this will
+          // internally be converted to the right response type.
+          response.add_message(std::move(*encodedResponse));
+        } // else it's a notification and no error.
 
       } else {
         // If the request was marked as an error(decode error), we still need to send the error back, so we save it.
-        response.add_message(make_error_response(req, decode_error));
+        specs::RPCResponseInfo resp{req.id};
+        resp.error.ec = decode_error;
+        response.add_message(std::move(resp));
       }
     }
 
@@ -262,8 +255,9 @@ JsonRPCManager::handle_call(std::string const &request)
   } catch (std::exception const &ex) {
     ec = error::RPCErrorCode::INTERNAL_ERROR;
   }
-
-  return {Encoder::encode(make_error_response(ec))};
+  specs::RPCResponseInfo resp;
+  resp.error.ec = ec;
+  return {Encoder::encode(resp)};
 }
 
 // ---------------------------- InternalHandler ---------------------------------
@@ -281,13 +275,13 @@ JsonRPCManager::Dispatcher::InternalHandler::invoke(specs::RPCRequestInfo const
                                   [&ret, &request](Method const &handler) -> void {
                                     // Regular Method Handler call, No cond variable check here, this should have not be created by
                                     // a plugin.
-                                    ret = handler.cb(*request.id, request.params);
+                                    ret = handler.cb(request.id, request.params);
                                   },
                                   [&ret, &request](PluginMethod const &handler) -> void {
                                     // We call the method handler, we'll lock and wait till the condition_variable
                                     // gets set on the other side. The handler may return immediately with no response being set.
                                     // cond var will give us green to proceed.
-                                    handler.cb(*request.id, request.params);
+                                    handler.cb(request.id, request.params);
                                     std::unique_lock<std::mutex> lock(g_rpcHandlingMutex);
                                     g_rpcHandlingCompletion.wait(lock, []() { return g_rpcHandlerProcessingCompleted; });
                                     g_rpcHandlerProcessingCompleted = false;
@@ -349,7 +343,8 @@ JsonRPCManager::Dispatcher::get_service_descriptor(std::string_view const &, con
     } else {
       provider = RPC_SERVICE_N_A_STR;
     }
-    method[RPC_SERVICE_PROVIDER_KEY] = provider;
+    method[RPC_SERVICE_PROVIDER_KEY]   = provider;
+    method[RPC_SERVICE_PRIVILEGED_KEY] = handler.get_options().auth.restricted;
     YAML::Node schema{YAML::NodeType::Map}; // no schema for now, but we have a placeholder for it. Schema should provide
                                             // description and all the details about the call
     method[RPC_SERVICE_SCHEMA_KEY] = std::move(schema);
diff --git a/mgmt2/rpc/jsonrpc/JsonRPCManager.h b/mgmt2/rpc/jsonrpc/JsonRPCManager.h
index e00b57f5b..88f297060 100644
--- a/mgmt2/rpc/jsonrpc/JsonRPCManager.h
+++ b/mgmt2/rpc/jsonrpc/JsonRPCManager.h
@@ -34,6 +34,7 @@
 #include "ts/apidefs.h"
 
 #include "Defs.h"
+#include "Context.h"
 
 namespace rpc
 {
@@ -44,9 +45,14 @@ namespace json_codecs
   class yamlcpp_json_encoder;
 } // namespace json_codecs
 
+///
+/// @brief This class keeps all relevant @c RPC provider's info.
+///
 struct RPCRegistryInfo {
-  std::string_view provider;
+  std::string_view provider; ///< Who's the rpc endpoint provider, could be ATS or a plugins. When requesting the service info from
+                             ///< the rpc node, this will be part of the service info.
 };
+
 ///
 /// @brief JSONRPC registration and JSONRPC invocation logic  https://www.jsonrpc.org/specification
 /// doc TBC
@@ -74,9 +80,11 @@ public:
   ///             'get_stats'...} .
   /// @param call The function handler.
   /// @param info RPCRegistryInfo pointer.
+  /// @param opt  Handler options, used to pass information about the registered handler.
   /// @return bool Boolean flag. true if the callback was successfully added, false otherwise
   ///
-  template <typename Func> bool add_method_handler(std::string_view name, Func &&call, const RPCRegistryInfo *info);
+  template <typename Func>
+  bool add_method_handler(std::string_view name, Func &&call, const RPCRegistryInfo *info, TSRPCHandlerOptions const &opt);
 
   ///
   /// @brief Add new registered notification handler to the JSON RPC engine.
@@ -85,18 +93,21 @@ public:
   /// @param name Name to be exposed by the RPC Engine.
   /// @param call The callback function that needs handler.
   /// @param info RPCRegistryInfo pointer.
+  /// @param opt  Handler options, used to pass information about the registered handler.
   /// @return bool Boolean flag. true if the callback was successfully added, false otherwise
   ///
-  template <typename Func> bool add_notification_handler(std::string_view name, Func &&call, const RPCRegistryInfo *info);
+  template <typename Func>
+  bool add_notification_handler(std::string_view name, Func &&call, const RPCRegistryInfo *info, TSRPCHandlerOptions const &opt);
 
   ///
   /// @brief This function handles the incoming jsonrpc request and dispatch the associated registered handler.
   ///
+  /// @param ctx @c Context object used pass information between rpc layers.
   /// @param jsonString The incoming jsonrpc 2.0 message. \link https://www.jsonrpc.org/specification
   /// @return std::optional<std::string> For methods, a valid jsonrpc 2.0 json string will be passed back. Notifications will not
   ///         contain any json back.
   ///
-  std::optional<std::string> handle_call(std::string const &jsonString);
+  std::optional<std::string> handle_call(Context const &ctx, std::string const &jsonString);
 
   ///
   /// @brief Get the instance of the whole RPC engine.
@@ -144,9 +155,9 @@ private:
   /// signatures inside a @c std::variant
   class Dispatcher
   {
-    using response_type = std::pair<
-      std::optional<specs::RPCResponseInfo>,
-      std::error_code>; ///< The response type used internally, notifications won't fill in the optional response. @c ec will be set
+    /// The response type used internally, notifications won't fill in the optional response.  Internal response's @ ec will be set
+    /// in case of any error.
+    using response_type = std::optional<specs::RPCResponseInfo>;
 
     ///
     /// @brief Class that wraps the actual std::function<T>.
@@ -166,11 +177,11 @@ private:
     /// Add a method handler to the internal container
     /// @return True if was successfully added, False otherwise.
     template <typename FunctionWrapperType, typename Handler>
-    bool add_handler(std::string_view name, Handler &&handler, const RPCRegistryInfo *info);
+    bool add_handler(std::string_view name, Handler &&handler, const RPCRegistryInfo *info, TSRPCHandlerOptions const &opt);
 
     /// Find and call the request's callback. If any error occurs, the return type will have the specific error.
     /// For notifications the @c RPCResponseInfo will not be set as part of the response. @c response_type
-    response_type dispatch(specs::RPCRequestInfo const &request) const;
+    response_type dispatch(Context const &ctx, specs::RPCRequestInfo const &request) const;
 
     /// Find a particular registered handler(method) by its associated name.
     /// @return A pair. The handler itself and a boolean flag indicating that the handler was found. If not found, second will
@@ -206,7 +217,7 @@ private:
     /// simplify the logic to insert and fetch callable objects from our container.
     struct InternalHandler {
       InternalHandler() = default;
-      InternalHandler(const RPCRegistryInfo *info) : _regInfo(info) {}
+      InternalHandler(const RPCRegistryInfo *info, TSRPCHandlerOptions const &opt) : _regInfo(info), _options(opt) {}
       /// Sets the handler.
       template <class T, class F> void set_callback(F &&t);
       explicit operator bool() const;
@@ -223,6 +234,13 @@ private:
         return _regInfo;
       }
 
+      /// Returns the configured options associated with this particular handler.
+      TSRPCHandlerOptions const &
+      get_options() const
+      {
+        return _options;
+      }
+
     private:
       // We need to keep this match with the order of types in the _func variant. This will help us to identify the holding type.
       enum class VariantTypeIndexId : std::size_t { NOTIFICATION = 1, METHOD = 2, METHOD_FROM_PLUGIN = 3 };
@@ -231,6 +249,7 @@ private:
       std::variant<std::monostate, Notification, Method, PluginMethod> _func;
       const RPCRegistryInfo *_regInfo; ///< Can hold internal information about the handler, this could be null as it is optional.
                                        ///< This pointer can eventually holds important information about the call.
+      TSRPCHandlerOptions _options;
     };
     // We will keep all the handlers wrapped inside the InternalHandler class, this will help us
     // to have a single container for all the types(method, notification & plugin method(cond var)).
@@ -244,19 +263,21 @@ private:
 // ------------------------------ JsonRPCManager -------------------------------
 template <typename Handler>
 bool
-JsonRPCManager::add_method_handler(std::string_view name, Handler &&call, const RPCRegistryInfo *info)
+JsonRPCManager::add_method_handler(std::string_view name, Handler &&call, const RPCRegistryInfo *info,
+                                   TSRPCHandlerOptions const &opt)
 {
-  return _dispatcher.add_handler<Dispatcher::Method, Handler>(name, std::forward<Handler>(call), info);
+  return _dispatcher.add_handler<Dispatcher::Method, Handler>(name, std::forward<Handler>(call), info, opt);
 }
 
 template <typename Handler>
 bool
-JsonRPCManager::add_notification_handler(std::string_view name, Handler &&call, const RPCRegistryInfo *info)
+JsonRPCManager::add_notification_handler(std::string_view name, Handler &&call, const RPCRegistryInfo *info,
+                                         TSRPCHandlerOptions const &opt)
 {
-  return _dispatcher.add_handler<Dispatcher::Notification, Handler>(name, std::forward<Handler>(call), info);
+  return _dispatcher.add_handler<Dispatcher::Notification, Handler>(name, std::forward<Handler>(call), info, opt);
 }
 
-// ----------------------------- InternalHandler ------------------------------------
+// ----------------------------- InternalHandler -------------------------------
 template <class T, class F>
 void
 JsonRPCManager::Dispatcher::InternalHandler::set_callback(F &&f)
@@ -276,10 +297,11 @@ bool inline JsonRPCManager::Dispatcher::InternalHandler::operator!() const
 // ----------------------------- Dispatcher ------------------------------------
 template <typename FunctionWrapperType, typename Handler>
 bool
-JsonRPCManager::Dispatcher::add_handler(std::string_view name, Handler &&handler, const RPCRegistryInfo *info)
+JsonRPCManager::Dispatcher::add_handler(std::string_view name, Handler &&handler, const RPCRegistryInfo *info,
+                                        TSRPCHandlerOptions const &opt)
 {
   std::lock_guard<std::mutex> lock(_mutex);
-  InternalHandler call{info};
+  InternalHandler call{info, opt};
   call.set_callback<FunctionWrapperType>(std::forward<Handler>(handler));
   return _handlers.emplace(name, std::move(call)).second;
 }
diff --git a/mgmt2/rpc/jsonrpc/error/RPCError.cc b/mgmt2/rpc/jsonrpc/error/RPCError.cc
index 6cbb10b87..03b8f6a66 100644
--- a/mgmt2/rpc/jsonrpc/error/RPCError.cc
+++ b/mgmt2/rpc/jsonrpc/error/RPCError.cc
@@ -74,6 +74,8 @@ RPCErrorCategory::message(int ev) const
     return {"Use of null as id is discouraged"};
   case RPCErrorCode::ExecutionError:
     return {"Error during execution"};
+  case RPCErrorCode::Unauthorized:
+    return {"Unauthorized action"};
   default:
     return "Rpc error " + std::to_string(ev);
   }
diff --git a/mgmt2/rpc/jsonrpc/error/RPCError.h b/mgmt2/rpc/jsonrpc/error/RPCError.h
index b10c8b917..f945c62bf 100644
--- a/mgmt2/rpc/jsonrpc/error/RPCError.h
+++ b/mgmt2/rpc/jsonrpc/error/RPCError.h
@@ -59,10 +59,13 @@ enum class RPCErrorCode {
   // execution errors
 
   // Internal rpc error when executing the method.
-  ExecutionError
+  //
+  ExecutionError, //!< Handler's general error.
+  Unauthorized    //!< In case we want to block the call based on privileges, access permissions, etc.
 };
 // TODO: force non 0 check
 std::error_code make_error_code(rpc::error::RPCErrorCode e);
+
 } // namespace rpc::error
 
 namespace std
diff --git a/mgmt2/rpc/jsonrpc/json/YAMLCodec.h b/mgmt2/rpc/jsonrpc/json/YAMLCodec.h
index 2998caf24..b00919f79 100644
--- a/mgmt2/rpc/jsonrpc/json/YAMLCodec.h
+++ b/mgmt2/rpc/jsonrpc/json/YAMLCodec.h
@@ -169,21 +169,6 @@ public:
 ///
 class yamlcpp_json_encoder
 {
-  ///
-  /// @brief Encode the ID if present.
-  /// If the id is not present which could be interpret as null(should not happen), it will not be set into the emitter, it will be
-  /// ignored. This is due the way that yamlcpp deals with the null, which instead of the literal null, it uses ~
-  static void
-  encode_id(const std::optional<std::string> &id, YAML::Emitter &json)
-  {
-    // workaround, we should find a better way, we should be able to use literal null if needed
-    if (id) {
-      json << YAML::Key << "id" << YAML::Value << *id;
-    }
-    // We do not insert null as it will break the json, we need literal null and not ~ (as per yaml)
-    // json << YAML::Null;
-  }
-
   ///
   /// @brief Function to encode an error.
   /// Error could be from two sources, presence of @c std::error_code means a high level and the @c ts::Errata a callee . Both will
@@ -214,13 +199,6 @@ class yamlcpp_json_encoder
     json << YAML::EndMap;
   }
 
-  /// Convenience functions to call encode_error.
-  static void
-  encode_error(std::error_code error, YAML::Emitter &json)
-  {
-    ts::Errata errata{};
-    encode_error(error, errata, json);
-  }
   /// Convenience functions to call encode_error.
   static void
   encode_error(ts::Errata const &errata, YAML::Emitter &json)
@@ -228,21 +206,6 @@ class yamlcpp_json_encoder
     encode_error({error::RPCErrorCode::ExecutionError}, errata, json);
   }
 
-  static void
-  encode_error_from_callee(ts::Errata const &errata, YAML::Emitter &json)
-  {
-    if (!errata.isOK()) {
-      json << YAML::Key << "errors";
-      json << YAML::BeginSeq;
-      for (auto const &err : errata) {
-        json << YAML::BeginMap;
-        json << YAML::Key << "code" << YAML::Value << err.getCode();
-        json << YAML::Key << "message" << YAML::Value << err.text();
-        json << YAML::EndMap;
-      }
-      json << YAML::EndSeq;
-    }
-  }
   ///
   /// @brief Function to encode a single response(no batch) into an emitter.
   ///
@@ -257,9 +220,9 @@ class yamlcpp_json_encoder
 
     // Important! As per specs, errors have preference over the result, we ignore result if error was set.
 
-    if (resp.rpcError) {
+    if (resp.error.ec) {
       // internal library detected error: Decoding, etc.
-      encode_error(resp.rpcError, json);
+      encode_error(resp.error.ec, resp.error.data, json);
     }
     // Registered handler error: They have set the error on the response from the registered handler. This uses ExecutionError as
     // top error.
@@ -280,8 +243,13 @@ class yamlcpp_json_encoder
       }
     }
 
-    // insert the id.
-    encode_id(resp.id, json);
+    // ID. Only if present.
+    if (!resp.id.empty()) {
+      json << YAML::Key << "id" << YAML::Value << resp.id;
+    }
+    // else: We do not insert null as it will break the json, we need literal null and not ~ (as per yaml)
+    // json << YAML::Null;
+
     json << YAML::EndMap;
   }
 
diff --git a/mgmt2/rpc/jsonrpc/unit_tests/test_basic_protocol.cc b/mgmt2/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
index ffe272a2d..0732a252b 100644
--- a/mgmt2/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
+++ b/mgmt2/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
@@ -37,19 +37,25 @@ struct JsonRpcUnitTest : rpc::JsonRPCManager {
   bool
   remove_handler(std::string const &name)
   {
-    return rpc::JsonRPCManager::remove_handler(name);
+    return base::remove_handler(name);
   }
   template <typename Func>
   bool
   add_notification_handler(const std::string &name, Func &&call)
   {
-    return base::add_notification_handler(name, std::forward<Func>(call), nullptr);
+    return base::add_notification_handler(name, std::forward<Func>(call), nullptr, {});
   }
   template <typename Func>
   bool
   add_method_handler(const std::string &name, Func &&call)
   {
-    return base::add_method_handler(name, std::forward<Func>(call), nullptr);
+    return base::add_method_handler(name, std::forward<Func>(call), nullptr, {});
+  }
+
+  std::optional<std::string>
+  handle_call(std::string const &jsonString)
+  {
+    return base::handle_call(rpc::Context{}, jsonString);
   }
 };
 
@@ -63,8 +69,6 @@ test_callback_ok_or_error(std::string_view const &id, YAML::Node const &params)
   if (YAML::Node n = params["return_error"]) {
     auto yesOrNo = n.as<std::string>();
     if (yesOrNo == "yes") {
-      // Can we just have a helper for this?
-      // resp.errata.push(static_cast<int>(TestErrors::ERR1), "Just an error message to add more meaning to the failure");
       resp.errata().push(ErratId, static_cast<int>(TestErrors::ERR1), "Just an error message to add more meaning to the failure");
     } else {
       resp.result()["ran"] = "ok";
diff --git a/mgmt2/rpc/server/IPCSocketServer.cc b/mgmt2/rpc/server/IPCSocketServer.cc
index ffabea9ff..6176d3a7f 100644
--- a/mgmt2/rpc/server/IPCSocketServer.cc
+++ b/mgmt2/rpc/server/IPCSocketServer.cc
@@ -37,6 +37,8 @@
 #include "tscore/Diags.h"
 #include "tscore/bwf_std_format.h"
 #include "records/I_RecProcess.h"
+#include "tscore/ink_sock.h"
+#include "utils/MgmtSocket.h"
 
 #include <ts/ts.h>
 
@@ -46,6 +48,7 @@
 namespace
 {
 constexpr size_t MAX_REQUEST_BUFFER_SIZE{32000};
+constexpr auto logTag = "rpc.net";
 
 // Quick check for errors(base on the errno);
 bool check_for_transient_errors();
@@ -72,8 +75,6 @@ poll_on_socket(Func &&check_poll_return, std::chrono::milliseconds timeout, int
 
 namespace rpc::comm
 {
-static constexpr auto logTag = "rpc.net";
-
 IPCSocketServer::~IPCSocketServer()
 {
   unlink(_conf.sockPathName.c_str());
@@ -172,7 +173,12 @@ IPCSocketServer::run()
 
       if (auto [ok, errStr] = client.read_all(bw); ok) {
         const auto json = std::string{bw.data(), bw.size()};
-        if (auto response = rpc::JsonRPCManager::instance().handle_call(json); response) {
+        rpc::Context ctx;
+        // we want to make sure the peer's credentials are ok.
+        ctx.get_auth().add_checker(
+          [&](TSRPCHandlerOptions const &opt, ts::Errata &errata) -> void { return late_check_peer_credentials(fd, opt, errata); });
+
+        if (auto response = rpc::JsonRPCManager::instance().handle_call(ctx, json); response) {
           // seems a valid response.
           if (client.write(*response, ec); ec) {
             Debug(logTag, "Error sending the response: %s", ec.message().c_str());
@@ -260,7 +266,14 @@ IPCSocketServer::bind(std::error_code &ec)
     return;
   }
 
-  mode_t mode = _conf.restrictedAccessApi ? 00700 : 00777;
+  // If the socket is not administratively restricted, check whether we have platform
+  // support. Otherwise, default to making it restricted.
+  bool restricted{true};
+  if (!_conf.restrictedAccessApi) {
+    restricted = !mgmt_has_peereid();
+  }
+
+  mode_t mode = restricted ? 00700 : 00777;
   if (chmod(_conf.sockPathName.c_str(), mode) < 0) {
     ec = std::make_error_code(static_cast<std::errc>(errno));
     return;
@@ -381,6 +394,25 @@ IPCSocketServer::Config::Config()
   lockPathName = Layout::relative_to(rundir, "jsonrpc20.lock");
   sockPathName = Layout::relative_to(rundir, "jsonrpc20.sock");
 }
+
+void
+IPCSocketServer::late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, ts::Errata &errata) const
+{
+  ts::LocalBufferWriter<256> w;
+  // For privileged calls, ensure we have caller credentials and that the caller is privileged.
+  if (mgmt_has_peereid() && options.auth.restricted) {
+    uid_t euid = -1;
+    gid_t egid = -1;
+    if (mgmt_get_peereid(peedFd, &euid, &egid) == -1) {
+      errata.push(1, static_cast<int>(UnauthorizedErrorCode::PEER_CREDENTIALS_ERROR),
+                  w.print("Error getting peer credentials: {}\0", ts::bwf::Errno{}).data());
+    } else if (euid != 0 && euid != geteuid()) {
+      errata.push(1, static_cast<int>(UnauthorizedErrorCode::PERMISSION_DENIED),
+                  w.print("Denied privileged API access for uid={} gid={}\0", euid, egid).data());
+    }
+  }
+}
+
 } // namespace rpc::comm
 
 namespace YAML
@@ -440,4 +472,4 @@ check_for_transient_errors()
     return false;
   }
 }
-} // namespace
\ No newline at end of file
+} // namespace
diff --git a/mgmt2/rpc/server/IPCSocketServer.h b/mgmt2/rpc/server/IPCSocketServer.h
index 2817c95f3..1df85704d 100644
--- a/mgmt2/rpc/server/IPCSocketServer.h
+++ b/mgmt2/rpc/server/IPCSocketServer.h
@@ -46,6 +46,11 @@ namespace rpc::comm
 ///       Buffer size = 32k
 class IPCSocketServer : public BaseCommInterface
 {
+  // Error codes to track any unauthorized call to a rpc handler.
+  enum class UnauthorizedErrorCode {
+    PEER_CREDENTIALS_ERROR = 1, ///< Error while trying to read the peer credentials from the unix socket.
+    PERMISSION_DENIED      = 2  ///< Client's socket credential didn't wasn't sufficient to execute the method.
+  };
   ///
   /// @brief Connection abstraction class that deals with sending and receiving data from the connected peer.
   ///
@@ -129,6 +134,7 @@ private:
   void bind(std::error_code &ec);
   void listen(std::error_code &ec);
   void close();
+  void late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, ts::Errata &errata) const;
 
   std::atomic_bool _running;
 
diff --git a/mgmt2/rpc/server/unit_tests/test_rpcserver.cc b/mgmt2/rpc/server/unit_tests/test_rpcserver.cc
index ee00df856..7649b3b41 100644
--- a/mgmt2/rpc/server/unit_tests/test_rpcserver.cc
+++ b/mgmt2/rpc/server/unit_tests/test_rpcserver.cc
@@ -55,6 +55,13 @@ test_remove_handler(std::string_view name)
 {
   return rpc::JsonRPCManager::instance().remove_handler(name);
 }
+
+template <typename Func>
+inline bool
+add_method_handler(const std::string &name, Func &&call)
+{
+  return rpc::JsonRPCManager::instance().add_method_handler(name, std::forward<Func>(call), nullptr, {});
+}
 } // namespace rpc
 static const std::string sockPath{"/tmp/jsonrpc20_test.sock"};
 static const std::string lockPath{"/tmp/jsonrpc20_test.lock"};
diff --git a/src/traffic_server/HostStatus.cc b/src/traffic_server/HostStatus.cc
index 240f32ade..7579a96f5 100644
--- a/src/traffic_server/HostStatus.cc
+++ b/src/traffic_server/HostStatus.cc
@@ -139,8 +139,10 @@ HostStatus::HostStatus()
   ink_rwlock_init(&host_status_rwlock);
 
   // register JSON-RPC methods.
-  rpc::add_method_handler("admin_host_set_status", &server_set_status, &rpc::core_ats_rpc_service_provider_handle);
-  rpc::add_method_handler("admin_host_get_status", &server_get_status, &rpc::core_ats_rpc_service_provider_handle);
+  rpc::add_method_handler("admin_host_set_status", &server_set_status, &rpc::core_ats_rpc_service_provider_handle,
+                          {{rpc::RESTRICTED_API}});
+  rpc::add_method_handler("admin_host_get_status", &server_get_status, &rpc::core_ats_rpc_service_provider_handle,
+                          {{rpc::NON_RESTRICTED_API}});
 }
 
 HostStatus::~HostStatus()
diff --git a/src/traffic_server/RpcAdminPubHandlers.cc b/src/traffic_server/RpcAdminPubHandlers.cc
index d97d668aa..8ca8b9d70 100644
--- a/src/traffic_server/RpcAdminPubHandlers.cc
+++ b/src/traffic_server/RpcAdminPubHandlers.cc
@@ -35,29 +35,40 @@ register_admin_jsonrpc_handlers()
 {
   // Config
   using namespace rpc::handlers::config;
-  rpc::add_method_handler("admin_config_set_records", &set_config_records, &core_ats_rpc_service_provider_handle);
-  rpc::add_method_handler("admin_config_reload", &reload_config, &core_ats_rpc_service_provider_handle);
+  rpc::add_method_handler("admin_config_set_records", &set_config_records, &core_ats_rpc_service_provider_handle,
+                          {{rpc::RESTRICTED_API}});
+  rpc::add_method_handler("admin_config_reload", &reload_config, &core_ats_rpc_service_provider_handle, {{rpc::RESTRICTED_API}});
 
   // Records
   using namespace rpc::handlers::records;
-  rpc::add_method_handler("admin_lookup_records", &lookup_records, &core_ats_rpc_service_provider_handle);
-  rpc::add_method_handler("admin_clear_all_metrics_records", &clear_all_metrics_records, &core_ats_rpc_service_provider_handle);
-  rpc::add_method_handler("admin_clear_metrics_records", &clear_metrics_records, &core_ats_rpc_service_provider_handle);
+  rpc::add_method_handler("admin_lookup_records", &lookup_records, &core_ats_rpc_service_provider_handle,
+                          {{rpc::NON_RESTRICTED_API}});
+  rpc::add_method_handler("admin_clear_all_metrics_records", &clear_all_metrics_records, &core_ats_rpc_service_provider_handle,
+                          {{rpc::RESTRICTED_API}});
+  rpc::add_method_handler("admin_clear_metrics_records", &clear_metrics_records, &core_ats_rpc_service_provider_handle,
+                          {{rpc::RESTRICTED_API}});
 
   // plugin
   using namespace rpc::handlers::plugins;
-  rpc::add_method_handler("admin_plugin_send_basic_msg", &plugin_send_basic_msg, &core_ats_rpc_service_provider_handle);
+  rpc::add_method_handler("admin_plugin_send_basic_msg", &plugin_send_basic_msg, &core_ats_rpc_service_provider_handle,
+                          {{rpc::RESTRICTED_API}});
 
   // server
   using namespace rpc::handlers::server;
-  rpc::add_method_handler("admin_server_start_drain", &server_start_drain, &core_ats_rpc_service_provider_handle);
-  rpc::add_method_handler("admin_server_stop_drain", &server_stop_drain, &core_ats_rpc_service_provider_handle);
-  rpc::add_notification_handler("admin_server_shutdown", &server_shutdown, &core_ats_rpc_service_provider_handle);
-  rpc::add_notification_handler("admin_server_restart", &server_shutdown, &core_ats_rpc_service_provider_handle);
+  rpc::add_method_handler("admin_server_start_drain", &server_start_drain, &core_ats_rpc_service_provider_handle,
+                          {{rpc::RESTRICTED_API}});
+  rpc::add_method_handler("admin_server_stop_drain", &server_stop_drain, &core_ats_rpc_service_provider_handle,
+                          {{rpc::RESTRICTED_API}});
+  rpc::add_notification_handler("admin_server_shutdown", &server_shutdown, &core_ats_rpc_service_provider_handle,
+                                {{rpc::RESTRICTED_API}});
+  rpc::add_notification_handler("admin_server_restart", &server_shutdown, &core_ats_rpc_service_provider_handle,
+                                {{rpc::RESTRICTED_API}});
 
   // storage
   using namespace rpc::handlers::storage;
-  rpc::add_method_handler("admin_storage_set_device_offline", &set_storage_offline, &core_ats_rpc_service_provider_handle);
-  rpc::add_method_handler("admin_storage_get_device_status", &get_storage_status, &core_ats_rpc_service_provider_handle);
+  rpc::add_method_handler("admin_storage_set_device_offline", &set_storage_offline, &core_ats_rpc_service_provider_handle,
+                          {{rpc::RESTRICTED_API}});
+  rpc::add_method_handler("admin_storage_get_device_status", &get_storage_status, &core_ats_rpc_service_provider_handle,
+                          {{rpc::NON_RESTRICTED_API}});
 }
 } // namespace rpc::admin