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/multiformats/go-multihash"
|
||||||
"github.com/ucan-wg/go-ucan/pkg/args"
|
"github.com/ucan-wg/go-ucan/pkg/args"
|
||||||
"github.com/ucan-wg/go-ucan/pkg/policy"
|
"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:
|
// 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,
|
// 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
|
// this increases the security as the UCAN token cannot be used with a different
|
||||||
// HTTP request.
|
// 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)
|
computedArgs, err := makeHttpArgs(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -132,7 +135,7 @@ func MakeHttpHash(req *http.Request) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum, nil
|
return invocation.WithArgument(HttpArgsKey, []byte(sum)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeHttpArgs(req *http.Request) (*args.Args, error) {
|
func makeHttpArgs(req *http.Request) (*args.Args, error) {
|
||||||
|
|||||||
@@ -7,9 +7,12 @@ import (
|
|||||||
|
|
||||||
"github.com/multiformats/go-multihash"
|
"github.com/multiformats/go-multihash"
|
||||||
"github.com/stretchr/testify/require"
|
"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/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"
|
||||||
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
||||||
|
"github.com/ucan-wg/go-ucan/token/invocation"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHttp(t *testing.T) {
|
func TestHttp(t *testing.T) {
|
||||||
@@ -131,6 +134,9 @@ func TestHttp(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHttpHash(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)
|
req, err := http.NewRequest(http.MethodGet, "http://example.com/foo", nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Add("User-Agent", "Chrome/51.0.2704.103 Safari/537.36")
|
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")),
|
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 {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
hash []byte
|
argOptions []invocation.Option
|
||||||
expected bool
|
expected bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "correct hash",
|
name: "correct hash",
|
||||||
hash: must(MakeHttpHash(req)),
|
argOptions: []invocation.Option{must(MakeHttpHash(req))},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "non-matching hash",
|
name: "non-matching hash",
|
||||||
hash: must(multihash.Sum([]byte{1, 2, 3, 4}, multihash.SHA2_256, -1)),
|
argOptions: []invocation.Option{makeArg([]byte{1, 2, 3, 4}, multihash.SHA2_256)},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "wrong type of hash",
|
name: "wrong type of hash",
|
||||||
hash: must(multihash.Sum([]byte{1, 2, 3, 4}, multihash.BLAKE3, -1)),
|
argOptions: []invocation.Option{makeArg([]byte{1, 2, 3, 4}, multihash.BLAKE3)},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no hash",
|
name: "no hash",
|
||||||
hash: nil,
|
argOptions: nil,
|
||||||
expected: false,
|
expected: true, // having a hash is not enforced
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
invArgs := args.New()
|
inv, err := invocation.New(
|
||||||
err := invArgs.Add(HttpArgsKey, tc.hash)
|
clientPersona.DID(),
|
||||||
|
command.MustParse("/foo"),
|
||||||
|
servicePersona.DID(),
|
||||||
|
nil,
|
||||||
|
tc.argOptions..., // inject hash argument, if any
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx := NewHttpExtArgs(pol, invArgs.ReadOnly(), req)
|
ctx := NewHttpExtArgs(pol, inv.Arguments(), req)
|
||||||
|
|
||||||
if tc.expected {
|
if tc.expected {
|
||||||
require.NoError(t, ctx.Verify())
|
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/args"
|
||||||
"github.com/ucan-wg/go-ucan/pkg/policy"
|
"github.com/ucan-wg/go-ucan/pkg/policy"
|
||||||
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
"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:
|
// 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,
|
// 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
|
// this increases the security as the UCAN token cannot be used with a different
|
||||||
// JsonRPC request.
|
// 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)
|
computedArgs, err := makeJsonRpcArgs(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -133,7 +136,7 @@ func MakeJsonRpcHash(req *jsonrpc.Request) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum, nil
|
return invocation.WithArgument(JsonRpcArgsKey, []byte(sum)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeJsonRpcArgs(req *jsonrpc.Request) (*args.Args, error) {
|
func makeJsonRpcArgs(req *jsonrpc.Request) (*args.Args, error) {
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ import (
|
|||||||
"github.com/INFURA/go-ethlibs/jsonrpc"
|
"github.com/INFURA/go-ethlibs/jsonrpc"
|
||||||
"github.com/multiformats/go-multihash"
|
"github.com/multiformats/go-multihash"
|
||||||
"github.com/stretchr/testify/require"
|
"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/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"
|
||||||
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
||||||
|
"github.com/ucan-wg/go-ucan/token/invocation"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestJsonRpc(t *testing.T) {
|
func TestJsonRpc(t *testing.T) {
|
||||||
@@ -112,6 +115,9 @@ func TestJsonRpc(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestJsonRpcHash(t *testing.T) {
|
func TestJsonRpcHash(t *testing.T) {
|
||||||
|
servicePersona := didtest.PersonaAlice
|
||||||
|
clientPersona := didtest.PersonaBob
|
||||||
|
|
||||||
req := jsonrpc.MustRequest(1839673506133526, "debug_traceCall",
|
req := jsonrpc.MustRequest(1839673506133526, "debug_traceCall",
|
||||||
true, false, 1234, "ho_no",
|
true, false, 1234, "ho_no",
|
||||||
)
|
)
|
||||||
@@ -119,40 +125,51 @@ func TestJsonRpcHash(t *testing.T) {
|
|||||||
policy.Equal(".jsonrpc.method", literal.String("debug_traceCall")),
|
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 {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
hash []byte
|
argOptions []invocation.Option
|
||||||
expected bool
|
expected bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "correct hash",
|
name: "correct hash",
|
||||||
hash: must(MakeJsonRpcHash(req)),
|
argOptions: []invocation.Option{must(MakeJsonRpcHash(req))},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "non-matching hash",
|
name: "non-matching hash",
|
||||||
hash: must(multihash.Sum([]byte{1, 2, 3, 4}, multihash.SHA2_256, -1)),
|
argOptions: []invocation.Option{makeArg([]byte{1, 2, 3, 4}, multihash.SHA2_256)},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "wrong type of hash",
|
name: "wrong type of hash",
|
||||||
hash: must(multihash.Sum([]byte{1, 2, 3, 4}, multihash.BLAKE3, -1)),
|
argOptions: []invocation.Option{makeArg([]byte{1, 2, 3, 4}, multihash.BLAKE3)},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no hash",
|
name: "no hash",
|
||||||
hash: nil,
|
argOptions: nil,
|
||||||
expected: false,
|
expected: true, // having a hash is not enforced
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
invArgs := args.New()
|
inv, err := invocation.New(
|
||||||
err := invArgs.Add(JsonRpcArgsKey, tc.hash)
|
clientPersona.DID(),
|
||||||
|
command.MustParse("/foo"),
|
||||||
|
servicePersona.DID(),
|
||||||
|
nil,
|
||||||
|
tc.argOptions..., // inject hash argument, if any
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx := NewJsonRpcExtArgs(pol, invArgs.ReadOnly(), req)
|
ctx := NewJsonRpcExtArgs(pol, inv.Arguments(), req)
|
||||||
|
|
||||||
if tc.expected {
|
if tc.expected {
|
||||||
require.NoError(t, ctx.Verify())
|
require.NoError(t, ctx.Verify())
|
||||||
|
|||||||
Reference in New Issue
Block a user