MatrixAI / Polykey

Polykey Core Library
https://polykey.com
GNU General Public License v3.0
29 stars 4 forks source link

Network Segregation/Authentication Token Logic #779

Open amydevs opened 1 month ago

amydevs commented 1 month ago

Specification

In order to form a network securely, we need some way to verify cryptographically whether a node should be able to access a network. To do this we need to make use of tokens as a portable, scale-able and secure method for proving access to a network. To do this the tokens need to encode details about the network authority, the subject node and provide a signature.

For out needs, we need a single network authority that defines the network itself. The details of this can be decided but all we require is a secure key pair to act as the trust anchor for the network authority. But we need to be able to issue access tokens in a decentralized way. Ideally using seed nodes issues for network access tokens.

We are going to be doing this with 2 types of tokens:

  1. ClaimNetworkAuthority - This is a token issued by the network authority authorizing the ability for nodes to mint ClaimnetworkAccess tokens.
  2. ClaimNetworkAccess - This token is minted for a specific node to prove access to a network.

Both tokens are required to be provided as a token chain to prove access to a network. They need to encode the following facts to prove this. Note that the ids for all purposes will just be NodeIds of nodes in the network as a way to identify a node and key interchangeably.

  1. The id/publicKey for the network authority. Its use to verify and identify the network
  2. The id/publicKey of the minter for the network access token.
  3. The id/publicKey of the node that gains access to the network.
  4. Signature from the network authority.
  5. Signature from the minter node.

Minting tokens

The ClaimNetworkAuthority token exists to prove that a node can mint tokens on the authority of the network. This means minters can be dynamic and not know ahead of time so long as they hold the authority token and the authority is known. This is important for dynamic scaling of minter nodes.

In the most basic form this ClaimNetworkAuthority needs to encode the following information.

  1. type=ClaimNetworkAuthority - indicating that the claim is a ClainNetworkAuthority.
  2. iss: The id/publicKey of the network authority.
  3. sub: the id/publicKey of the minter node.
  4. signature created with the privateKey of the network authority (iss).

Succinctly this proves that the subject (sub) has the authority of the network authority (iss) to mint access tokens for that network. This is verified with the signature. This for fills the facts 1, 2 and 4 above.

The ClaimNetworkAccess token exists to prove that a node has access to the network. This can be issued by any node that has a valid ClaimNetworkAuthority token.

In its most basic form the ClaimNetworkAccess token needs to encode the following information.

  1. type=ClaimNetworkAccess - indicating that the claim is a ClaimNetworkAccess.
  2. iss: The id/publicKey of the minter node.
  3. sub: the id/publicKey of the authorised node.
  4. signature created with the privateKey of the minter node (iss).

Succinctly this proves that the subject (sub) has access to the network under the authority of the network authority. This is verified with the signature. This for fills the facts 2, 3 and 5. Note that the fact 2 is common between the two claims and helps verify the chain.

The ClaimNetworkAccess needs to include extra metadata refers the ClaimNetworkAuthority in some way. While this data isn't strictly required to verify the chain. It should provide a way to find all the required information needed to verify the chain. This can take two forms.

  1. Embed the ClaimNetworkAuthority claim within the ClaimNetworkAccess claim. Simple but bloats the information.
  2. Include the claimId of the ClaimNetworkAuthority, The NodeId of the node we can get the token from. And optionally a hash of the token.

So long as the verify-er has the contents of both tokens then it can verify it.

Verifying tokens

Much like a certificate chain in TLS, the tokens form a token chain. Where verifying the tokens in order can prove a chain of trust that verifies access to a network. To verify all of the following facts.

  1. Check the TLS certificate of the node connecting and asking for access to extract the NodeId.
  2. Check the sub of the ClaimNetworkAccess token matches the connected node.
  3. Check the signature of the ClaimNetworkAccess token is signed buy it's iss.
  4. Check that the iss of the ClaimNetworkAccess token matches the sub of the ClaimNetworkAuthority token.
  5. Check that the iss of the ClaimNetworkAccess token matches the network we are authorised under.
  6. Check that the signature of the claimNetworkAccess token is signed bu the iss.

If all these facts are true and the network matches one we allow then we allow the connection. Otherwise we reject and kill the connection.

To expand on this we may want to enforce a strict mode where we only allow the node to access a single network. To do this we can can requests the access tokens as part of their sigchain. If we only see one network access token within their chain then that meets the strict condition.

Additional context

Parent: https://github.com/MatrixAI/Polykey/issues/770

Tasks

  1. Create a structure for ClaimNetworkAuthority and ClaimNetworkAccess claims within the claims domain.
  2. Add logic for minting these claims.
  3. Add a utility for verifying these claims.
linear[bot] commented 1 month ago

ENG-370 Network Segregation/Authentication Token Logic

tegefaulkes commented 1 month ago

Open to discussion. One thing I still need to nail down is if we want to embed the NetworkClaimAuthority token within theNetworkClaimAccess token. Or if we want to hold a reference between the two and send them separately.

Both function identically but the reference method enables us to reduce the amount of data sent and even lets us cache parent claims for verification. For example, the authority claims will be very common across all of the access claims, so if we can send much less extra data overall if we only send it if an verifying node hasn't seen it before.

Under this current spec its not really required. But I think its definitely something to explore when working on the smarter generic version of these tokens for our capability system.

tegefaulkes commented 1 month ago

You've already started on this @amydevs with trying to add the claims to the claims domain. Be sure to link a PR to the linear issue.

tegefaulkes commented 1 month ago

Ok, based on further design discussion. The implementation of this needs to be further generalised. While yes, we do need to have a network authority claim and a network access claim. It needs to be pivoted to a org authority claim where we can refine the kind of authority we want to give out. We need to convert the network access claim to something like a org group claim. But that may come later?

The network access claim needs to specify the hostname of the network. That seems to be a new requirement for this. But the org also falls under that host name. So it may not be a network specific label but an org label.

In any case, the main point I'm trying to make here is we have the need for different kinds of claims. Not just claims for access to a network but claims that allow…

The possibilities are endless!

CMCDragonkai commented 3 weeks ago

Let's separate any discussion on further sigchain claim expansion in https://github.com/MatrixAI/Polykey/discussions/791.

This should focus solely on being able to have segregated networks, and the ability to authenticate to PKE orgs. Other delegated authorities should wait until consider CVP 4. and decentralized trust infrastructure.

Also I prefer not using the word "tokens" to describe this. If you're talking about sigchain claims, use the word "claim". Token is too generic, as it can be confused as a shared secret token.

CMCDragonkai commented 1 week ago

Is this issue actually completed by #775? I thought this would also end up having to deal with the private network. If you need to, you need a new issue for ClaimNetworkAuthority.

tegefaulkes commented 1 week ago

Yeah, technically this isn't fully completed without handling the private networks. I'm going to re-open this issue.

CMCDragonkai commented 1 week ago

Can we update the scope - indicating what's left @amydevs ?

CMCDragonkai commented 5 days ago

So basically, the actual logic itself for mainnet and testnet can be done super simply by simply doing a string equality comparison with the designated --network option (see https://github.com/MatrixAI/Polykey/pull/775#issuecomment-2323546099). Although this does affect "multi network" connections. @tegefaulkes Currently the spec seems unclear to me with respect to the "logic" part of the authentication process.

Especially in terms of matching:

  1. Check that the iss of the ClaimNetworkAccess token matches the network we are authorised under.

With the --network option, how these all interact. I think we need a flow chart to make this clearer.