-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Specification
In order to keep nodes from networks connecting to other networks that they are not supposed to, we need to implement some mechanism during the connection establishment process that will reject connections if say, a mainnet node tries to connect to the testnet network.
After talking with @tegefaulkes, we have come up with 2 solutions:
Using JWTs/Tokens with Verification Metadata
In order to show proof of access into a network, nodes should need to show some token to the seednodes, and peer nodes of that network in order to verify they are apart of that network.
These JWT tokens should contain information about:
From the point of view of proving that a node has access to a network we need the following.
- Some way to show proof of access. Ideally this will be a token, dumb (JWT) or otherwise (biscuits and capabilities) proving the following facts. This will provide verifiable proof of access without needing to ask anyone.
a. The subject of the token, Who has access. This is the public key of the node asking for access
b. The issuer of the token, Who gave access. This is the public key central issuer of the network.
c. The network they have access to. This can be the public key of the network issuer. Really just the same as the issuer
d. The signature of the above facts, signed by the issuers private key. - An access list. Essentially a list of all the networks the current node allows connections to. In it's barest form its just a list of public keys of the networks. Can include extra metadata since a public key without context can be hard to audit. This will be checked against when verifying the network tokens.
- A mechanism for providing the token to prove access after connection establishment. To do this, we will need to rework add middleware to our node-to-node rpc calls to limit calls until a node is authenticated. Similarly, the NodeGraph needs to be modified to only add nodes after authentication as to not add out-of-network nodes. The NodeGraph may also need to have network metadata as to filter out what node connection information to give to a peer. Finally, RPC handlers will have to be made to allow for the request and distribution of authentication tokens from seednodes, as well as allow for authentication between nodes.
We have decided, much like the ACL logic of our nodes, the authentication procedure should be carried out within the application layer. This parallels with the separation of authorization and TLS verification seen in the web. Separation of concerns is good here as the certchain is an immutable and inflexible structure that is purely meant to represent the flow of identity.
As for a node having access to multiple networks. It should be possible with this. It just means a node provides multiple network tokens when connecting and the connected node can decide to accept the connection based on it's access list. The only problem I can see with this is that one network might want to be strict and only allow nodes that use that one network. It would be possible to enforce this by rejecting nodes that provide multiple network tokens. but there's not way to force a node to provide all network tokens it has.
Bootstrapping
In order to bootstrap into a network, a node will make an RPC call to a seecnode in order to request a token to be signed in order to prove that the node is a part of the network. Connections to other nodes must not be made before the signed token is returned.
There should be separate RPC calls for requesting the token and receiving the token. The reason for this is so that a node can attempt to join a network and get the signed claim much later even if the node restarts or stops. This allows for nodes to be potentially individually accepted into the network by a human operator. If the node is offline when the seednode attempts to send it the fully signed token, the seednode can schedule a task to attempt to resend the token whenever a connection with the node is established again.
Trust Anchors
In order for the bootstrapping to work, there needs to be some anchor where trust is derived from.
To solve this, we present Trust Anchor entities that simply hold a public-private key. A token can be generated from the public private keypair that grants authority for seednodes to distribute tokens that prove that nodes are in the network.
An entity can be a node, a person, or some autonomous system. All that matters is that it is able to give the token to seednodes during bootstrapping so that they have a way to distribute network membership tokens.
Network membership tokens should contain the trust anchor's token embedded within. By comparing the facts between the network membership tokens and the trust anchor tokens, we can determine if a peer node is apart of a network.
Connection Procedure
When a node joins a network, it receives a token with rules and facts that represent its permissions and memberships.
An example what it could look like would be
{
"rules": [
"can_connect_to_network($N, $Network) :- node($N), has_membership($N, $Network)."
],
"facts": [
"node(\"N1\").",
"has_membership(\"N1\", \"mainnet.polykey.com\").",
"has_membership(\"N1\", \"testnet.polykey.com\")."
]
}- When Node A attempts to connect to Node B, it presents its JWT token.
- Node B verifies the token's signature and evaluates its rules and facts against its own policies.
- The security policies are evaluated using a Datalog engine or a similar logic programming interpreter.
- The connection is allowed or denied based on the evaluation results.
There needs to be a way to bootstrap seednodes of a network with a same private key to use to sign tokens to allow this.
Additional context
https://github.com/MatrixAI/Polykey-Enterprise/issues/11
Related: #779
Related: #780
Related: #781
Related: #782
Related: #783
Tasks
- Token request from seednodes RPC handler
- Token response from seednodes RPC handler
- Authentication RPC handler between seednodes
- Modify NodeGraph to only add nodes after authentication
- Limit RPC calls whilst peer node is unauthenticated
