wasmCloud/wascc-host

Message Bus should support anti-forgery

autodidaddict opened this issue · 2 comments

With the new lattice feature, invocations will be sent across the wire other hosts. While TLS can be used on the endpoints and authentication can be used to limit access, we should still be able to prove that an invocation came from the host from which it claims to have originated.

Bad Actor Scenario

In keeping with defence-in-depth, you can't assume all of your layers of protection are working, so you need to defend everywhere you can. In this case, assume someone has managed to gain access to a NATS server or a NATS leaf node being used by the lattice distributed bus, and has stolen enough credentials so that they can legitimately publish messages to the lattice RPC prefix (wasmbus.*). They could then generate an invocation that might allow data exfiltration, corruption, or perform DDoS attacks. If every recipient in the lattice verifies that the invocation was signed by the host identity in the payload, we can at least verify that the sender has lattice credentials and is using our key system. Put another way, we would force the impersonated waSCC host to uniquely identify itself in order to send seemingly legitimate invocations.

These safeguards squarely put this bad actor scenario in the "far too much effort to be worth it" category.

Finally, if the above scenario were to take place, we would then gain the ability to place an offending impersonated host on a deny list. If we become aware of a forger on the lattice, we can block it immediately.

The way to create an anti-forgery token is to sign some bit of information with a private key and on the other side, they verify that signed payload using your public key. This is how the destination knows that the signed information came from the place it claims to have come from. What we want to ensure has not been tampered with is the "routing information" for the invocation request as well as the payload. We can get all of this cryptography, signing, and validation capability from the wascap library we already use for anti-forgery checks on our actor modules.

For the "routing" information, we can create a custom URL scheme for destinations within the wasmbus:

  • Actor destinations: wasmbus://{actor public key}/{operation}
  • Capability destinations: wasmbus://{capability id}/{binding name}/{operation}

We can concatenate the bytes of the routing URL with a hash of the payload bytes, sign it with the private key of the host, and then create an anti-forgery token containing the host's public key (the origin) and the signature. The receiving side would then decrypt that signature with the host's public key, and ensure that the signed anti-forgery token is valid. This would involve ensuring that the declared hash of the invocation payload bytes is the actual hash of the invocation payload bytes, and that the URL in the anti-forgery token is the same as the URL derived from the invocation.

If all of this validation turns out positive, then we have a reasonable assurance that no forgery has taken place.

We could potentially implement this by adding a new type of claims in the wascap crate, an Invocation claim. This would re-use all of the existing JWT infrastructure (we would get subject, issuer, iat, and expires for free), including all the code we use to create signatures, marshal and unmarshal JWTS, etc. 🤔