extargs

package
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 8, 2026 License: Apache-2.0, MIT Imports: 13 Imported by: 0

README

Motivations

UCAN is normally a pure RPC construct, when the entirety of the request's parameters is part of the invocation, in the form of args. Those args are evaluated against the delegation's policy to determine if the request is allowed or not, then the request handling happens purely based on those args and the command. In that setup, the service would have a single entry point.

Unfortunately, we live in a world of REST APIs, or JSON-RPC. Some adaptations or concessions need to be made.

In this package, we cross the chasm of the pure UCAN world into our practical needs. This can, however, be done in a reasonable way.

Example

Below is an example of args in Dag-Json format, where the values are recomposed server-side from the HTTP request:

{
  "http": {
    "scheme": "https",
    "method": "POST",
    "host": "example.com",
    "path": ""
  },
  "custom": {
    "foo": "bar"
  }
}

Those args can be evaluated against a delegation's policy, for example:

{
  "cmd": "/foo/bar",
  "pol": [
    ["==", ".http.host", "example.com"],
    ["like", ".custom.foo", "ba*"]
  ]
}

Security implications

UCAN essentially aims for perfect security. By having external args, we break that security perimeter, and we now need to arbitrate between security and practicality.

First, what are we breaking exactly? Normally, the invocation has all the parameters and is signed by the invoker. This means that an attacker cannot intercept (MITM) a request and change the parameters when relaying it to the server. As they are signed, that would make the request invalid.

If we have external args, now an attacker can intercept the request, change it, and pretend to be that person doing other things than intended. That may of may not be an actual problem, depending on the situation.

There is a way to get around that, and have the best of both worlds, but it comes with a client side complexity: we can hash the external values and put them into the invocation's args. For example:

{
  "http": "zQmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D",
  "custom": "zQmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9"
}

When the server receives the request, it can now reconstruct the values from the HTTP request, verify the hash and replace it with the real values for evaluation against the policies. We are now back to the better security model, but at the price of client-side complexity.

API design

Therefore, the server-side logic is made to have this hashing optional:

  • if present, the server honors the hash and enforces the security
  • the client can opt out of passing that hash, and won't benefit from the enforced security

The particular hash selected is SHA2-256 of the DAG-CBOR encoded argument, expressed in the form of a Multihash in raw bytes. The arguments being hashed are the complete map of values, including the root key being replaced (for example http or custom here).

Documentation

Overview

Package extargs adds external arguments to the invocation's arguments before the policy is evaluated.

Index

Examples

Constants

View Source
const HttpArgsKey = "http"

HttpArgsKey is the key in the args, used for: - if it exists in the invocation, holds a hash of the args derived from the HTTP request - in the final args to be evaluated against the policies, holds the args derived from the HTTP request

Variables

This section is empty.

Functions

func MakeHttpHash

func MakeHttpHash(req *http.Request) (invocation.Option, error)

MakeHttpHash compute the hash of the derived arguments from the HTTP request. If that hash is inserted at the HttpArgsKey key in the invocation arguments, this increases the security as the UCAN token cannot be used with a different HTTP request. For convenience, the hash is returned as a ready-to-use invocation argument.

Types

type CustomExtArgs

type CustomExtArgs struct {
	// contains filtered or unexported fields
}
Example
// Note: this is an example for how to build arguments, but you likely want to use CustomExtArgs
// through UcanCtx.

pol := policy.Policy{} // policies from the delegations

// We will construct the following args:
// "key": {
//  "ntwk":"eth-mainnet",
//  "quota":{
//    "ur":1234,
//    "udc":1234,
//    "arch":1234,
//    "down":1234,
//    "store":1234,
//    "up":1234
//  }
// }
customArgs := NewCustomExtArgs("key", pol, func(ma datamodel.MapAssembler) {
	qp.MapEntry(ma, "ntwk", qp.String("eth-mainnet"))
	qp.MapEntry(ma, "quota", qp.Map(6, func(ma datamodel.MapAssembler) {
		qp.MapEntry(ma, "ur", qp.Int(1234))
		qp.MapEntry(ma, "udc", qp.Int(1234))
		qp.MapEntry(ma, "arch", qp.Int(1234))
		qp.MapEntry(ma, "down", qp.Int(1234))
		qp.MapEntry(ma, "store", qp.Int(1234))
		qp.MapEntry(ma, "up", qp.Int(1234))
	}))
})

err := customArgs.Verify()
fmt.Println(err)
Output:

<nil>

func NewCustomExtArgs

func NewCustomExtArgs(key string, pol policy.Policy, assembler func(ma datamodel.MapAssembler)) *CustomExtArgs

func (*CustomExtArgs) Args

func (cea *CustomExtArgs) Args() (*args.Args, error)

func (*CustomExtArgs) Verify

func (cea *CustomExtArgs) Verify() error

type HttpExtArgs

type HttpExtArgs struct {
	// contains filtered or unexported fields
}

func NewHttpExtArgs

func NewHttpExtArgs(pol policy.Policy, originalArgs args.ReadOnly, req *http.Request) *HttpExtArgs

func (*HttpExtArgs) Args

func (hea *HttpExtArgs) Args() (*args.Args, error)

func (*HttpExtArgs) Verify

func (hea *HttpExtArgs) Verify() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL