Most of the information about designing access control to RESTful API revolves around users (i.e. different users have different levels of access, etc).
Imagine a system where there is no notion of users as such. There is a bunch of servers communicating with each other via RESTful API. There are no clients - I mean, for every interaction between two servers one of them can be considered "a client", but my point is that all the servers are more or less "equal" and each server can send a request to many other servers (and vice versa).
This is very different from the traditional web/mobile client-server architecture.
Now, imagine that not all of those servers are actually 100% equal. Some should have access to some APIs, but not all. How to ensure such level of access control?
CodePudding user response:
Let's view the servers you have as nodes in your network to avoid confusion. When node1 sends a request to node2, then in that interaction, node2 is the server and node1 is the client (akin to a "user").
So, from the perspective of node2, if you have to differentiate between client1 and client2 (two possible nodes that can send requests) in terms of what each of them may or may not access, then it is highly advisable to define a role map for node2.
This would mean that you would have key-value pairs where the keys would be methods and values would be roles.
Whenever a method would be requested by client1 or client2, then you would somehow determine what roles are necessary for that method and whether client1 and client2 has all the roles necessary.
This means that for the API at node2, whenever a request is being received, the following algorithm needs to be performed:
- a central method would be invoked (let's call it
APIWrapper
for the time being) APIWrapper
finds out what the roles of the client areAPIWrapper
finds out what roles are necessary to invokefunction1
, the function the client requested- if any of the roles that are needed for
function1
is not fulfilled by the client, then respond with an unauthorized error and stop the process - if this stage has been reached successfully without an unauthorized error, then execute
method1
and transmit its response to the client
You may have a role forest, that is, you would have trees of roles, depending on the level of access (i.e. you may have a separate role to upload xlsx files and you may have a role to upload any file, so, in this case you may have a requirement for xlsx upload, while the client would have a role to upload any file, in which case the client should still be allowed to perform the given action).
If you have such requirements for subcategories of roles, then it is highly recommendable to
- In the roles map at the value section you would specify which role tree the role is part of (i.e. file upload) and the level of that role (i.e. xlsx)
- In each role tree if there is a parent P and a child C, then it would mean that P => C, that is, C would be more specific than P, so if role P exists that implies that role C also exists for the client
- Each role needs to have a signature that would uniquely identify its path in the tree, so reaching it would have an O(log(N)) complexity rather than O(N)
It goes without saying that the way roles are assigned or revoked needs to be secure and consistent.
So, this is how we thought from the perspective of node2. Yet, node2 itself may be a client of other nodes as well. The issue is similar then.
However, if server1 gains/loses a role at node1, would that trigger that server1 gains/loses that role for some other servers? If so, then you also need some way to synchronize roles, maybe periodically via a cron job.
Finally, it would be great if the way roles are defined, assigned and revoked could be standardized. Because then, the configuration for each server, however different it may be in content could be maintained with the same software, that would largely simplify the administrative burden.