extargs: make the hash more convenient to use by directly returning the invocation.Option
This commit is contained in:
committed by
Michael Muré
parent
cc661f3936
commit
41d679dfab
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/multiformats/go-multihash"
|
||||
"github.com/ucan-wg/go-ucan/pkg/args"
|
||||
"github.com/ucan-wg/go-ucan/pkg/policy"
|
||||
"github.com/ucan-wg/go-ucan/token/invocation"
|
||||
)
|
||||
|
||||
// HttpArgsKey is the key in the args, used for:
|
||||
@@ -111,7 +112,9 @@ func (hea *HttpExtArgs) verifyHash() error {
|
||||
// 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.
|
||||
func MakeHttpHash(req *http.Request) ([]byte, error) {
|
||||
// For convenience, the hash is returned as a read to use invocation argument.
|
||||
func MakeHttpHash(req *http.Request) (invocation.Option, error) {
|
||||
// Note: the hash is computed on the full IPLD args, including HttpArgsKey
|
||||
computedArgs, err := makeHttpArgs(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -132,7 +135,7 @@ func MakeHttpHash(req *http.Request) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sum, nil
|
||||
return invocation.WithArgument(HttpArgsKey, []byte(sum)), nil
|
||||
}
|
||||
|
||||
func makeHttpArgs(req *http.Request) (*args.Args, error) {
|
||||
|
||||
@@ -7,9 +7,12 @@ import (
|
||||
|
||||
"github.com/multiformats/go-multihash"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/ucan-wg/go-ucan/did/didtest"
|
||||
"github.com/ucan-wg/go-ucan/pkg/args"
|
||||
"github.com/ucan-wg/go-ucan/pkg/command"
|
||||
"github.com/ucan-wg/go-ucan/pkg/policy"
|
||||
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
||||
"github.com/ucan-wg/go-ucan/token/invocation"
|
||||
)
|
||||
|
||||
func TestHttp(t *testing.T) {
|
||||
@@ -131,6 +134,9 @@ func TestHttp(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHttpHash(t *testing.T) {
|
||||
servicePersona := didtest.PersonaAlice
|
||||
clientPersona := didtest.PersonaBob
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://example.com/foo", nil)
|
||||
require.NoError(t, err)
|
||||
req.Header.Add("User-Agent", "Chrome/51.0.2704.103 Safari/537.36")
|
||||
@@ -140,40 +146,51 @@ func TestHttpHash(t *testing.T) {
|
||||
policy.Equal(".http.scheme", literal.String("http")),
|
||||
)
|
||||
|
||||
makeArg := func(data []byte, code uint64) invocation.Option {
|
||||
mh, err := multihash.Sum(data, code, -1)
|
||||
require.NoError(t, err)
|
||||
return invocation.WithArgument(HttpArgsKey, []byte(mh))
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
hash []byte
|
||||
expected bool
|
||||
name string
|
||||
argOptions []invocation.Option
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "correct hash",
|
||||
hash: must(MakeHttpHash(req)),
|
||||
expected: true,
|
||||
name: "correct hash",
|
||||
argOptions: []invocation.Option{must(MakeHttpHash(req))},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "non-matching hash",
|
||||
hash: must(multihash.Sum([]byte{1, 2, 3, 4}, multihash.SHA2_256, -1)),
|
||||
expected: false,
|
||||
name: "non-matching hash",
|
||||
argOptions: []invocation.Option{makeArg([]byte{1, 2, 3, 4}, multihash.SHA2_256)},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "wrong type of hash",
|
||||
hash: must(multihash.Sum([]byte{1, 2, 3, 4}, multihash.BLAKE3, -1)),
|
||||
expected: false,
|
||||
name: "wrong type of hash",
|
||||
argOptions: []invocation.Option{makeArg([]byte{1, 2, 3, 4}, multihash.BLAKE3)},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "no hash",
|
||||
hash: nil,
|
||||
expected: false,
|
||||
name: "no hash",
|
||||
argOptions: nil,
|
||||
expected: true, // having a hash is not enforced
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
invArgs := args.New()
|
||||
err := invArgs.Add(HttpArgsKey, tc.hash)
|
||||
inv, err := invocation.New(
|
||||
clientPersona.DID(),
|
||||
command.MustParse("/foo"),
|
||||
servicePersona.DID(),
|
||||
nil,
|
||||
tc.argOptions..., // inject hash argument, if any
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := NewHttpExtArgs(pol, invArgs.ReadOnly(), req)
|
||||
ctx := NewHttpExtArgs(pol, inv.Arguments(), req)
|
||||
|
||||
if tc.expected {
|
||||
require.NoError(t, ctx.Verify())
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/ucan-wg/go-ucan/pkg/args"
|
||||
"github.com/ucan-wg/go-ucan/pkg/policy"
|
||||
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
||||
"github.com/ucan-wg/go-ucan/token/invocation"
|
||||
)
|
||||
|
||||
// JsonRpcArgsKey is the key in the args, used for:
|
||||
@@ -112,7 +113,9 @@ func (jrea *JsonRpcExtArgs) verifyHash() error {
|
||||
// If that hash is inserted at the JsonRpcArgsKey key in the invocation arguments,
|
||||
// this increases the security as the UCAN token cannot be used with a different
|
||||
// JsonRPC request.
|
||||
func MakeJsonRpcHash(req *jsonrpc.Request) ([]byte, error) {
|
||||
// For convenience, the hash is returned as a read to use invocation argument.
|
||||
func MakeJsonRpcHash(req *jsonrpc.Request) (invocation.Option, error) {
|
||||
// Note: the hash is computed on the full IPLD args, including JsonRpcArgsKey
|
||||
computedArgs, err := makeJsonRpcArgs(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -133,7 +136,7 @@ func MakeJsonRpcHash(req *jsonrpc.Request) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sum, nil
|
||||
return invocation.WithArgument(JsonRpcArgsKey, []byte(sum)), nil
|
||||
}
|
||||
|
||||
func makeJsonRpcArgs(req *jsonrpc.Request) (*args.Args, error) {
|
||||
|
||||
@@ -6,9 +6,12 @@ import (
|
||||
"github.com/INFURA/go-ethlibs/jsonrpc"
|
||||
"github.com/multiformats/go-multihash"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/ucan-wg/go-ucan/did/didtest"
|
||||
"github.com/ucan-wg/go-ucan/pkg/args"
|
||||
"github.com/ucan-wg/go-ucan/pkg/command"
|
||||
"github.com/ucan-wg/go-ucan/pkg/policy"
|
||||
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
||||
"github.com/ucan-wg/go-ucan/token/invocation"
|
||||
)
|
||||
|
||||
func TestJsonRpc(t *testing.T) {
|
||||
@@ -112,6 +115,9 @@ func TestJsonRpc(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestJsonRpcHash(t *testing.T) {
|
||||
servicePersona := didtest.PersonaAlice
|
||||
clientPersona := didtest.PersonaBob
|
||||
|
||||
req := jsonrpc.MustRequest(1839673506133526, "debug_traceCall",
|
||||
true, false, 1234, "ho_no",
|
||||
)
|
||||
@@ -119,40 +125,51 @@ func TestJsonRpcHash(t *testing.T) {
|
||||
policy.Equal(".jsonrpc.method", literal.String("debug_traceCall")),
|
||||
)
|
||||
|
||||
makeArg := func(data []byte, code uint64) invocation.Option {
|
||||
mh, err := multihash.Sum(data, code, -1)
|
||||
require.NoError(t, err)
|
||||
return invocation.WithArgument(JsonRpcArgsKey, []byte(mh))
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
hash []byte
|
||||
expected bool
|
||||
name string
|
||||
argOptions []invocation.Option
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "correct hash",
|
||||
hash: must(MakeJsonRpcHash(req)),
|
||||
expected: true,
|
||||
name: "correct hash",
|
||||
argOptions: []invocation.Option{must(MakeJsonRpcHash(req))},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "non-matching hash",
|
||||
hash: must(multihash.Sum([]byte{1, 2, 3, 4}, multihash.SHA2_256, -1)),
|
||||
expected: false,
|
||||
name: "non-matching hash",
|
||||
argOptions: []invocation.Option{makeArg([]byte{1, 2, 3, 4}, multihash.SHA2_256)},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "wrong type of hash",
|
||||
hash: must(multihash.Sum([]byte{1, 2, 3, 4}, multihash.BLAKE3, -1)),
|
||||
expected: false,
|
||||
name: "wrong type of hash",
|
||||
argOptions: []invocation.Option{makeArg([]byte{1, 2, 3, 4}, multihash.BLAKE3)},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "no hash",
|
||||
hash: nil,
|
||||
expected: false,
|
||||
name: "no hash",
|
||||
argOptions: nil,
|
||||
expected: true, // having a hash is not enforced
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
invArgs := args.New()
|
||||
err := invArgs.Add(JsonRpcArgsKey, tc.hash)
|
||||
inv, err := invocation.New(
|
||||
clientPersona.DID(),
|
||||
command.MustParse("/foo"),
|
||||
servicePersona.DID(),
|
||||
nil,
|
||||
tc.argOptions..., // inject hash argument, if any
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := NewJsonRpcExtArgs(pol, invArgs.ReadOnly(), req)
|
||||
ctx := NewJsonRpcExtArgs(pol, inv.Arguments(), req)
|
||||
|
||||
if tc.expected {
|
||||
require.NoError(t, ctx.Verify())
|
||||
|
||||
Reference in New Issue
Block a user