tests: lots of small asjustement

This commit is contained in:
Michael Muré
2024-11-20 14:55:48 +01:00
parent 2fb5a3dc01
commit aea1880386
27 changed files with 376 additions and 396 deletions

View File

@@ -4,27 +4,28 @@
package didtest package didtest
import ( import (
"sync" "fmt"
"testing" "testing"
"github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/crypto"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ucan-wg/go-ucan/did" "github.com/ucan-wg/go-ucan/did"
) )
const ( const (
alicePrivKeyCfg = "CAESQHdNJLBBiuc1AdwPHBkubB2KS1p0cv2JEF7m8tfwtrcm5ajaYPm+XmVCmtcHOF2lGDlmaiDA7emfwD3IrcyES0M=" alicePrivKeyB64 = "CAESQHdNJLBBiuc1AdwPHBkubB2KS1p0cv2JEF7m8tfwtrcm5ajaYPm+XmVCmtcHOF2lGDlmaiDA7emfwD3IrcyES0M="
bobPrivKeyCfg = "CAESQHBz+AIop1g+9iBDj+ufUc/zm9/ry7c6kDFO8Wl/D0+H63V9hC6s9l4npf3pYEFCjBtlR0AMNWMoFQKSlYNKo20=" bobPrivKeyB64 = "CAESQHBz+AIop1g+9iBDj+ufUc/zm9/ry7c6kDFO8Wl/D0+H63V9hC6s9l4npf3pYEFCjBtlR0AMNWMoFQKSlYNKo20="
carolPrivKeyCfg = "CAESQPrCgkcHnYFXDT9AlAydhPECBEivEuuVx9dJxLjVvDTmJIVNivfzg6H4mAiPfYS+5ryVVUZTHZBzvMuvvvG/Ks0=" carolPrivKeyB64 = "CAESQPrCgkcHnYFXDT9AlAydhPECBEivEuuVx9dJxLjVvDTmJIVNivfzg6H4mAiPfYS+5ryVVUZTHZBzvMuvvvG/Ks0="
danPrivKeyCfg = "CAESQCgNhzofKhC+7hW6x+fNd7iMPtQHeEmKRhhlduf/I7/TeOEFYAEflbJ0sAhMeDJ/HQXaAvsWgHEbJ3ZLhP8q2B0=" danPrivKeyB64 = "CAESQCgNhzofKhC+7hW6x+fNd7iMPtQHeEmKRhhlduf/I7/TeOEFYAEflbJ0sAhMeDJ/HQXaAvsWgHEbJ3ZLhP8q2B0="
erinPrivKeyCfg = "CAESQKhCJo5UBpQcthko8DKMFsbdZ+qqQ5oc01CtLCqrE90dF2GfRlrMmot3WPHiHGCmEYi5ZMEHuiSI095e/6O4Bpw=" erinPrivKeyB64 = "CAESQKhCJo5UBpQcthko8DKMFsbdZ+qqQ5oc01CtLCqrE90dF2GfRlrMmot3WPHiHGCmEYi5ZMEHuiSI095e/6O4Bpw="
frankPrivKeyCfg = "CAESQDlXPKsy3jHh7OWTWQqyZF95Ueac5DKo7xD0NOBE5F2BNr1ZVxRmJ2dBELbOt8KP9sOACcO9qlCB7uMA1UQc7sk=" frankPrivKeyB64 = "CAESQDlXPKsy3jHh7OWTWQqyZF95Ueac5DKo7xD0NOBE5F2BNr1ZVxRmJ2dBELbOt8KP9sOACcO9qlCB7uMA1UQc7sk="
) )
// Persona is a generic participant used for cryptographic testing. // Persona is a generic participant used for cryptographic testing.
type Persona int type Persona int
// The provided Personas were selected from the first few generic // The provided Personas were selected from the first few generic
// participants listed in this [table]. // participants listed in this [table].
// //
// [table]: https://en.wikipedia.org/wiki/Alice_and_Bob#Cryptographic_systems // [table]: https://en.wikipedia.org/wiki/Alice_and_Bob#Cryptographic_systems
@@ -37,26 +38,36 @@ const (
PersonaFrank PersonaFrank
) )
var ( var privKeys map[Persona]crypto.PrivKey
once sync.Once
func init() {
privKeys = make(map[Persona]crypto.PrivKey, 6) privKeys = make(map[Persona]crypto.PrivKey, 6)
err error for persona, privKeyCfg := range privKeyB64() {
) privKeyMar, err := crypto.ConfigDecodeKey(privKeyCfg)
if err != nil {
return
}
privKey, err := crypto.UnmarshalPrivateKey(privKeyMar)
if err != nil {
return
}
privKeys[persona] = privKey
}
}
// DID returns a did.DID based on the Persona's Ed25519 public key. // DID returns a did.DID based on the Persona's Ed25519 public key.
func (p Persona) DID(t *testing.T) did.DID { func (p Persona) DID() did.DID {
t.Helper() d, err := did.FromPrivKey(p.PrivKey())
if err != nil {
did, err := did.FromPrivKey(p.PrivKey(t)) panic(err)
require.NoError(t, err) }
return d
return did
} }
// Name returns the username of the Persona. // Name returns the username of the Persona.
func (p Persona) Name(t *testing.T) string { func (p Persona) Name() string {
t.Helper()
name, ok := map[Persona]string{ name, ok := map[Persona]string{
PersonaAlice: "Alice", PersonaAlice: "Alice",
PersonaBob: "Bob", PersonaBob: "Bob",
@@ -66,78 +77,45 @@ func (p Persona) Name(t *testing.T) string {
PersonaFrank: "Frank", PersonaFrank: "Frank",
}[p] }[p]
if !ok { if !ok {
t.Fatal("Unknown persona:", p) panic(fmt.Sprintf("Unknown persona: %v", p))
} }
return name return name
} }
// PrivKey returns the Ed25519 private key for the Persona. // PrivKey returns the Ed25519 private key for the Persona.
func (p Persona) PrivKey(t *testing.T) crypto.PrivKey { func (p Persona) PrivKey() crypto.PrivKey {
t.Helper()
once.Do(func() {
for persona, privKeyCfg := range privKeyCfgs(t) {
privKeyMar, err := crypto.ConfigDecodeKey(privKeyCfg)
if err != nil {
return
}
privKey, err := crypto.UnmarshalPrivateKey(privKeyMar)
if err != nil {
return
}
privKeys[persona] = privKey
}
})
require.NoError(t, err)
return privKeys[p] return privKeys[p]
} }
// PrivKeyConfig returns the marshaled and encoded Ed25519 private key
// for the Persona.
func (p Persona) PrivKeyConfig(t *testing.T) string {
t.Helper()
return privKeyCfgs(t)[p]
}
// PubKey returns the Ed25519 public key for the Persona. // PubKey returns the Ed25519 public key for the Persona.
func (p Persona) PubKey(t *testing.T) crypto.PubKey { func (p Persona) PubKey() crypto.PubKey {
t.Helper() return p.PrivKey().GetPublic()
return p.PrivKey(t).GetPublic()
} }
// PubKeyConfig returns the marshaled and encoded Ed25519 public key // PubKeyConfig returns the marshaled and encoded Ed25519 public key
// for the Persona. // for the Persona.
func (p Persona) PubKeyConfig(t *testing.T) string { func (p Persona) PubKeyConfig(t *testing.T) string {
pubKeyMar, err := crypto.MarshalPublicKey(p.PrivKey(t).GetPublic()) pubKeyMar, err := crypto.MarshalPublicKey(p.PrivKey().GetPublic())
require.NoError(t, err) require.NoError(t, err)
return crypto.ConfigEncodeKey(pubKeyMar) return crypto.ConfigEncodeKey(pubKeyMar)
} }
func privKeyCfgs(t *testing.T) map[Persona]string { func privKeyB64() map[Persona]string {
t.Helper()
return map[Persona]string{ return map[Persona]string{
PersonaAlice: alicePrivKeyCfg, PersonaAlice: alicePrivKeyB64,
PersonaBob: bobPrivKeyCfg, PersonaBob: bobPrivKeyB64,
PersonaCarol: carolPrivKeyCfg, PersonaCarol: carolPrivKeyB64,
PersonaDan: danPrivKeyCfg, PersonaDan: danPrivKeyB64,
PersonaErin: erinPrivKeyCfg, PersonaErin: erinPrivKeyB64,
PersonaFrank: frankPrivKeyCfg, PersonaFrank: frankPrivKeyB64,
} }
} }
// Personas returns an (alphabetically) ordered list of the defined // Personas returns an (alphabetically) ordered list of the defined
// Persona values. // Persona values.
func Personas(t *testing.T) []Persona { func Personas() []Persona {
t.Helper()
return []Persona{ return []Persona{
PersonaAlice, PersonaAlice,
PersonaBob, PersonaBob,

View File

@@ -1,20 +0,0 @@
// Package policytest provides values and functions that are useful when
// testing code that relies on Policies.
package policytest
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/ucan-wg/go-ucan/pkg/policy"
)
// EmptyPolicy provides a policy with no statements for testing purposes.
func EmptyPolicy(t *testing.T) policy.Policy {
t.Helper()
pol, err := policy.FromDagJson("[]")
require.NoError(t, err)
return pol
}

View File

@@ -7,14 +7,14 @@
// //
// Delegation proof-chain names contain each didtest.Persona name in // Delegation proof-chain names contain each didtest.Persona name in
// order starting with the root delegation (which will always be generated // order starting with the root delegation (which will always be generated
// by Alice.) This is opposite of the list of cic.Cids that represent the // by Alice). This is the opposite of the list of cic.Cids that represent the
// proof chain. // proof chain.
// //
// For both the generated delegation tokens granted to Carol's Persona and // For both the generated delegation tokens granted to Carol's Persona and
// the proof chains containing Carol's delegations to Dan, if there is no // the proof chains containing Carol's delegations to Dan, if there is no
// suffix, the proof chain will be deemed valid. If there is a suffix, it // suffix, the proof chain will be deemed valid. If there is a suffix, it
// will consist of either the word "Valid" or "Invalid" and the name of the // will consist of either the word "Valid" or "Invalid" and the name of the
// field that has been altered. Only optional fields will generate proof // field that has been altered. Only optional fields will generate proof
// chains with Valid suffixes. // chains with Valid suffixes.
// //
// If changes are made to the list of Personas included in the chain, or // If changes are made to the list of Personas included in the chain, or
@@ -25,9 +25,9 @@
// go test . -update // go test . -update
// //
// Generated delegation Tokens are stored in the data/ directory and loaded // Generated delegation Tokens are stored in the data/ directory and loaded
// into the DelegationLoader on the first call to GetDelegationLoader. // into the delegation.Loader.
// Generated references to these tokens and the tokens themselves are // Generated references to these tokens and the tokens themselves are
// created in the token_gen.go file. See /token/invocation/invocation_test.go // created in the token_gen.go file. See /token/invocation/invocation_test.go
// for an example of how these delegation tokens and proof-chains can // for an example of how these delegation tokens and proof-chains can
// be used during testing. // be used during testing.
package delegationtest package delegationtest

View File

@@ -0,0 +1,227 @@
package delegationtest
import (
"os"
"path/filepath"
"slices"
"time"
"github.com/dave/jennifer/jen"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/ucan-wg/go-ucan/did"
"github.com/ucan-wg/go-ucan/did/didtest"
"github.com/ucan-wg/go-ucan/pkg/command"
"github.com/ucan-wg/go-ucan/pkg/policy"
"github.com/ucan-wg/go-ucan/token/delegation"
)
const (
tokenNamePrefix = "Token"
proorChainNamePrefix = "Proof"
)
var constantNonce = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b}
type newDelegationParams struct {
privKey crypto.PrivKey
aud did.DID
sub did.DID
cmd command.Command
pol policy.Policy
opts []delegation.Option
}
type token struct {
name string
id cid.Cid
}
type proof struct {
name string
prf []cid.Cid
}
type acc struct {
name string
chain []cid.Cid
}
type variant struct {
name string
variant func(*newDelegationParams)
}
func noopVariant() variant {
return variant{
name: "",
variant: func(_ *newDelegationParams) {},
}
}
type generator struct {
dlgs []token
chains []proof
}
func (g *generator) chainPersonas(personas []didtest.Persona, acc acc, vari variant) error {
acc.name += personas[0].Name()
proofName := acc.name
if len(vari.name) > 0 {
proofName += "_" + vari.name
}
g.createProofChain(proofName, acc.chain)
if len(personas) < 2 {
return nil
}
name := personas[0].Name() + personas[1].Name()
params := newDelegationParams{
privKey: personas[0].PrivKey(),
aud: personas[1].DID(),
cmd: NominalCommand,
pol: policy.Policy{},
opts: []delegation.Option{
delegation.WithSubject(didtest.PersonaAlice.DID()),
delegation.WithNonce(constantNonce),
},
}
// Create each nominal token and continue the chain
id, err := g.createDelegation(params, name, vari)
if err != nil {
return err
}
acc.chain = append(acc.chain, id)
err = g.chainPersonas(personas[1:], acc, vari)
if err != nil {
return err
}
// If the user is Carol, create variants for each invalid and/or optional
// parameter and also continue the chain
if personas[0] == didtest.PersonaCarol {
variants := []variant{
{name: "InvalidExpandedCommand", variant: func(p *newDelegationParams) {
p.cmd = ExpandedCommand
}},
{name: "ValidAttenuatedCommand", variant: func(p *newDelegationParams) {
p.cmd = AttenuatedCommand
}},
{name: "InvalidSubject", variant: func(p *newDelegationParams) {
p.opts = append(p.opts, delegation.WithSubject(didtest.PersonaBob.DID()))
}},
{name: "InvalidExpired", variant: func(p *newDelegationParams) {
// Note: this makes the generator not deterministic
p.opts = append(p.opts, delegation.WithExpiration(time.Now().Add(time.Second)))
}},
{name: "InvalidInactive", variant: func(p *newDelegationParams) {
nbf, err := time.Parse(time.RFC3339, "2070-01-01T00:00:00Z")
if err != nil {
panic(err)
}
p.opts = append(p.opts, delegation.WithNotBefore(nbf))
}},
}
// Start a branch in the recursion for each of the variants
for _, v := range variants {
id, err := g.createDelegation(params, name, v)
if err != nil {
return err
}
// replace the previous Carol token id with the one from the variant
acc.chain[len(acc.chain)-1] = id
err = g.chainPersonas(personas[1:], acc, v)
if err != nil {
return err
}
}
}
return nil
}
func (g *generator) createDelegation(params newDelegationParams, name string, vari variant) (cid.Cid, error) {
vari.variant(&params)
tkn, err := delegation.New(params.privKey, params.aud, params.cmd, params.pol, params.opts...)
if err != nil {
return cid.Undef, err
}
data, id, err := tkn.ToSealed(params.privKey)
if err != nil {
return cid.Undef, err
}
dlgName := tokenNamePrefix + name
if len(vari.name) > 0 {
dlgName += "_" + vari.name
}
err = os.WriteFile(filepath.Join(tokenDir, dlgName+tokenExt), data, 0o644)
if err != nil {
return cid.Undef, err
}
g.dlgs = append(g.dlgs, token{
name: dlgName,
id: id,
})
return id, nil
}
func (g *generator) createProofChain(name string, prf []cid.Cid) {
if len(prf) < 1 {
return
}
clone := make([]cid.Cid, len(prf))
copy(clone, prf)
g.chains = append(g.chains, proof{
name: proorChainNamePrefix + name,
prf: clone,
})
}
func (g *generator) writeGoFile() error {
file := jen.NewFile("delegationtest")
file.HeaderComment("Code generated by delegationtest - DO NOT EDIT.")
refs := map[cid.Cid]string{}
for _, d := range g.dlgs {
refs[d.id] = d.name + "CID"
file.Var().Defs(
jen.Id(d.name+"CID").Op("=").Qual("github.com/ipfs/go-cid", "MustParse").Call(jen.Lit(d.id.String())),
jen.Id(d.name).Op("=").Id("mustGetDelegation").Call(jen.Id(d.name+"CID")),
)
file.Line()
}
for _, c := range g.chains {
g := jen.CustomFunc(jen.Options{
Multi: true,
Separator: ",",
Close: "\n",
}, func(g *jen.Group) {
slices.Reverse(c.prf)
for _, p := range c.prf {
g.Id(refs[p])
}
})
file.Var().Id(c.name).Op("=").Index().Qual("github.com/ipfs/go-cid", "Cid").Values(g)
file.Line()
}
return file.Save("token_gen.go")
}

View File

@@ -1,32 +1,14 @@
package delegationtest package delegationtest
import ( import (
"os"
"path/filepath"
"slices"
"testing" "testing"
"time"
"github.com/dave/jennifer/jen"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ucan-wg/go-ucan/did"
"github.com/ucan-wg/go-ucan/did/didtest"
"github.com/ucan-wg/go-ucan/pkg/command"
"github.com/ucan-wg/go-ucan/pkg/policy"
"github.com/ucan-wg/go-ucan/pkg/policy/policytest"
"github.com/ucan-wg/go-ucan/token/delegation"
"gotest.tools/v3/golden" "gotest.tools/v3/golden"
)
const ( "github.com/ucan-wg/go-ucan/did/didtest"
tokenNamePrefix = "Token"
proorChainNamePrefix = "Proof"
) )
var constantNonce = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b}
// TestUpdate doesn't actually run a test but uses the Go testing library // TestUpdate doesn't actually run a test but uses the Go testing library
// to trigger generation of the delegation tokens and associated Go file. // to trigger generation of the delegation tokens and associated Go file.
func TestUpdate(t *testing.T) { func TestUpdate(t *testing.T) {
@@ -35,190 +17,10 @@ func TestUpdate(t *testing.T) {
} }
} }
type newDelegationParams struct {
privKey crypto.PrivKey
aud did.DID
sub did.DID
cmd command.Command
pol policy.Policy
opts []delegation.Option
}
type newDelegationParamsVariant func(*newDelegationParams)
type token struct {
name string
id cid.Cid
}
type proof struct {
name string
prf []cid.Cid
}
type generator struct {
dlgs []token
chains []proof
}
type acc struct {
name string
chain []cid.Cid
}
type variant struct {
name string
variant func(*newDelegationParams)
}
func noopVariant() variant {
return variant{
name: "",
variant: func(_ *newDelegationParams) {},
}
}
func update(t *testing.T) { func update(t *testing.T) {
t.Helper() t.Helper()
gen := &generator{} gen := &generator{}
gen.chainPersonas(t, didtest.Personas(t), acc{}, noopVariant()) require.NoError(t, gen.chainPersonas(didtest.Personas(), acc{}, noopVariant()))
gen.writeGoFile(t) require.NoError(t, gen.writeGoFile())
}
func (g *generator) chainPersonas(t *testing.T, personas []didtest.Persona, acc acc, vari variant) {
t.Helper()
acc.name += personas[0].Name(t)
g.createProofChain(t, acc.name+vari.name, acc.chain)
if len(personas) < 2 {
return
}
name := personas[0].Name(t) + personas[1].Name(t)
params := newDelegationParams{
privKey: personas[0].PrivKey(t),
aud: personas[1].DID(t),
cmd: NominalCommand,
pol: policytest.EmptyPolicy(t),
opts: []delegation.Option{
delegation.WithSubject(didtest.PersonaAlice.DID(t)),
delegation.WithNonce(constantNonce),
},
}
// Create each nominal token and continue the chain
id := g.createDelegation(t, params, name, vari)
acc.chain = append(acc.chain, id)
g.chainPersonas(t, personas[1:], acc, vari)
// If the user is Carol, create variants for each invalid and/or optional
// parameter and also continue the chain
if personas[0] == didtest.PersonaCarol {
variants := []variant{
{name: "InvalidExpandedCommand", variant: func(p *newDelegationParams) {
p.cmd = ExpandedCommand
}},
{name: "ValidAttenuatedCommand", variant: func(p *newDelegationParams) {
p.cmd = AttenuatedCommand
}},
{name: "InvalidSubject", variant: func(p *newDelegationParams) {
p.opts = append(p.opts, delegation.WithSubject(didtest.PersonaBob.DID(t)))
}},
{name: "InvalidExpired", variant: func(p *newDelegationParams) {
p.opts = append(p.opts, delegation.WithExpiration(time.Now().Add(time.Second)))
}},
{name: "InvalidInactive", variant: func(p *newDelegationParams) {
nbf, err := time.Parse(time.RFC3339, "2070-01-01T00:00:00Z")
require.NoError(t, err)
p.opts = append(p.opts, delegation.WithNotBefore(nbf))
}},
}
// Start a branch in the recursion for each of the variants
for _, v := range variants {
id := g.createDelegation(t, params, name, v)
// replace the previous Carol token id with the one from the variant
acc.chain[len(acc.chain)-1] = id
g.chainPersonas(t, personas[1:], acc, v)
}
}
}
func (g *generator) createDelegation(t *testing.T, params newDelegationParams, name string, vari variant) cid.Cid {
t.Helper()
vari.variant(&params)
tkn, err := delegation.New(params.privKey, params.aud, params.cmd, params.pol, params.opts...)
require.NoError(t, err)
data, id, err := tkn.ToSealed(params.privKey)
require.NoError(t, err)
require.NoError(t, os.WriteFile(filepath.Join(tokenDir, tokenNamePrefix+name+vari.name+tokenExt), data, 0o644))
g.dlgs = append(g.dlgs, token{
name: tokenNamePrefix + name + vari.name,
id: id,
})
return id
}
func (g *generator) createProofChain(t *testing.T, name string, prf []cid.Cid) {
t.Helper()
if len(prf) < 1 {
return
}
clone := make([]cid.Cid, len(prf))
copy(clone, prf)
g.chains = append(g.chains, proof{
name: proorChainNamePrefix + name,
prf: clone,
})
}
func (g *generator) writeGoFile(t *testing.T) {
t.Helper()
file := jen.NewFile("delegationtest")
file.HeaderComment("Code generated by delegationtest - DO NOT EDIT.")
refs := map[cid.Cid]string{}
for _, d := range g.dlgs {
refs[d.id] = d.name + "CID"
file.Var().Defs(
jen.Id(d.name+"CID").Op("=").Qual("github.com/ipfs/go-cid", "MustParse").Call(jen.Lit(d.id.String())),
jen.Id(d.name).Op("=").Id("mustGetDelegation").Call(jen.Id(d.name+"CID")),
)
file.Line()
}
for _, c := range g.chains {
g := jen.CustomFunc(jen.Options{
Multi: true,
Separator: ",",
Close: "\n",
}, func(g *jen.Group) {
slices.Reverse(c.prf)
for _, p := range c.prf {
g.Id(refs[p])
}
})
file.Var().Id(c.name).Op("=").Index().Qual("github.com/ipfs/go-cid", "Cid").Values(g)
file.Line()
}
require.NoError(t, file.Save("token_gen.go"))
} }

View File

@@ -38,27 +38,29 @@ var ProofEmpty = []cid.Cid{}
//go:embed data //go:embed data
var fs embed.FS var fs embed.FS
var (
once sync.Once
ldr delegation.Loader
err error
)
var _ delegation.Loader = (*delegationLoader)(nil) var _ delegation.Loader = (*delegationLoader)(nil)
type delegationLoader struct { type delegationLoader struct {
tokens map[cid.Cid]*delegation.Token tokens map[cid.Cid]*delegation.Token
} }
var (
once sync.Once
ldr delegation.Loader
)
// GetDelegationLoader returns a singleton instance of a test // GetDelegationLoader returns a singleton instance of a test
// DelegationLoader containing all the tokens present in the data/ // DelegationLoader containing all the tokens present in the data/
// directory. // directory.
func GetDelegationLoader() (delegation.Loader, error) { func GetDelegationLoader() delegation.Loader {
once.Do(func() { once.Do(func() {
var err error
ldr, err = loadDelegations() ldr, err = loadDelegations()
if err != nil {
panic(err)
}
}) })
return ldr
return ldr, err
} }
// GetDelegation implements invocation.DelegationLoader. // GetDelegation implements invocation.DelegationLoader.
@@ -101,12 +103,7 @@ func loadDelegations() (delegation.Loader, error) {
// GetDelegation is a shortcut that gets (or creates) the DelegationLoader // GetDelegation is a shortcut that gets (or creates) the DelegationLoader
// and attempts to return the token referenced by the provided CID. // and attempts to return the token referenced by the provided CID.
func GetDelegation(id cid.Cid) (*delegation.Token, error) { func GetDelegation(id cid.Cid) (*delegation.Token, error) {
ldr, err := GetDelegationLoader() return GetDelegationLoader().GetDelegation(id)
if err != nil {
return nil, err
}
return ldr.GetDelegation(id)
} }
func mustGetDelegation(id cid.Cid) *delegation.Token { func mustGetDelegation(id cid.Cid) *delegation.Token {
@@ -114,6 +111,5 @@ func mustGetDelegation(id cid.Cid) *delegation.Token {
if err != nil { if err != nil {
panic(err) panic(err)
} }
return tkn return tkn
} }

View File

@@ -30,78 +30,78 @@ var (
) )
var ( var (
TokenCarolDanInvalidExpandedCommandCID = gocid.MustParse("bafyreid3m3pk53gqgp5rlzqhvpedbwsqbidqlp4yz64vknwbzj7bxrmsr4") TokenCarolDan_InvalidExpandedCommandCID = gocid.MustParse("bafyreid3m3pk53gqgp5rlzqhvpedbwsqbidqlp4yz64vknwbzj7bxrmsr4")
TokenCarolDanInvalidExpandedCommand = mustGetDelegation(TokenCarolDanInvalidExpandedCommandCID) TokenCarolDan_InvalidExpandedCommand = mustGetDelegation(TokenCarolDan_InvalidExpandedCommandCID)
) )
var ( var (
TokenDanErinInvalidExpandedCommandCID = gocid.MustParse("bafyreifn4sy5onwajx3kqvot5mib6m6xarzrqjozqbzgmzpmc5ox3g2uzm") TokenDanErin_InvalidExpandedCommandCID = gocid.MustParse("bafyreifn4sy5onwajx3kqvot5mib6m6xarzrqjozqbzgmzpmc5ox3g2uzm")
TokenDanErinInvalidExpandedCommand = mustGetDelegation(TokenDanErinInvalidExpandedCommandCID) TokenDanErin_InvalidExpandedCommand = mustGetDelegation(TokenDanErin_InvalidExpandedCommandCID)
) )
var ( var (
TokenErinFrankInvalidExpandedCommandCID = gocid.MustParse("bafyreidmpgd36jznmq42bs34o4qi3fcbrsh4idkg6ejahudejzwb76fwxe") TokenErinFrank_InvalidExpandedCommandCID = gocid.MustParse("bafyreidmpgd36jznmq42bs34o4qi3fcbrsh4idkg6ejahudejzwb76fwxe")
TokenErinFrankInvalidExpandedCommand = mustGetDelegation(TokenErinFrankInvalidExpandedCommandCID) TokenErinFrank_InvalidExpandedCommand = mustGetDelegation(TokenErinFrank_InvalidExpandedCommandCID)
) )
var ( var (
TokenCarolDanValidAttenuatedCommandCID = gocid.MustParse("bafyreiekhtm237vyapk3c6voeb5lnz54crebqdqi3x4wn4u4cbrrhzsqfe") TokenCarolDan_ValidAttenuatedCommandCID = gocid.MustParse("bafyreiekhtm237vyapk3c6voeb5lnz54crebqdqi3x4wn4u4cbrrhzsqfe")
TokenCarolDanValidAttenuatedCommand = mustGetDelegation(TokenCarolDanValidAttenuatedCommandCID) TokenCarolDan_ValidAttenuatedCommand = mustGetDelegation(TokenCarolDan_ValidAttenuatedCommandCID)
) )
var ( var (
TokenDanErinValidAttenuatedCommandCID = gocid.MustParse("bafyreicrvzqferyy7rgo75l5rn6r2nl7zyeexxjmu3dm4ff7rn2coblj4y") TokenDanErin_ValidAttenuatedCommandCID = gocid.MustParse("bafyreicrvzqferyy7rgo75l5rn6r2nl7zyeexxjmu3dm4ff7rn2coblj4y")
TokenDanErinValidAttenuatedCommand = mustGetDelegation(TokenDanErinValidAttenuatedCommandCID) TokenDanErin_ValidAttenuatedCommand = mustGetDelegation(TokenDanErin_ValidAttenuatedCommandCID)
) )
var ( var (
TokenErinFrankValidAttenuatedCommandCID = gocid.MustParse("bafyreie6fhspk53kplcc2phla3e7z7fzldlbmmpuwk6nbow5q6s2zjmw2q") TokenErinFrank_ValidAttenuatedCommandCID = gocid.MustParse("bafyreie6fhspk53kplcc2phla3e7z7fzldlbmmpuwk6nbow5q6s2zjmw2q")
TokenErinFrankValidAttenuatedCommand = mustGetDelegation(TokenErinFrankValidAttenuatedCommandCID) TokenErinFrank_ValidAttenuatedCommand = mustGetDelegation(TokenErinFrank_ValidAttenuatedCommandCID)
) )
var ( var (
TokenCarolDanInvalidSubjectCID = gocid.MustParse("bafyreifgksz6756if42tnc6rqsnbaa2u3fdrveo7ek44lnj2d64d5sw26u") TokenCarolDan_InvalidSubjectCID = gocid.MustParse("bafyreifgksz6756if42tnc6rqsnbaa2u3fdrveo7ek44lnj2d64d5sw26u")
TokenCarolDanInvalidSubject = mustGetDelegation(TokenCarolDanInvalidSubjectCID) TokenCarolDan_InvalidSubject = mustGetDelegation(TokenCarolDan_InvalidSubjectCID)
) )
var ( var (
TokenDanErinInvalidSubjectCID = gocid.MustParse("bafyreibdwew5nypsxrm4fq73wu6hw3lgwwiolj3bi33xdrbgcf3ogm6fty") TokenDanErin_InvalidSubjectCID = gocid.MustParse("bafyreibdwew5nypsxrm4fq73wu6hw3lgwwiolj3bi33xdrbgcf3ogm6fty")
TokenDanErinInvalidSubject = mustGetDelegation(TokenDanErinInvalidSubjectCID) TokenDanErin_InvalidSubject = mustGetDelegation(TokenDanErin_InvalidSubjectCID)
) )
var ( var (
TokenErinFrankInvalidSubjectCID = gocid.MustParse("bafyreicr364mj3n7x4iyhcksxypelktcqkkw3ptg7ggxtqegw3p3mr6zc4") TokenErinFrank_InvalidSubjectCID = gocid.MustParse("bafyreicr364mj3n7x4iyhcksxypelktcqkkw3ptg7ggxtqegw3p3mr6zc4")
TokenErinFrankInvalidSubject = mustGetDelegation(TokenErinFrankInvalidSubjectCID) TokenErinFrank_InvalidSubject = mustGetDelegation(TokenErinFrank_InvalidSubjectCID)
) )
var ( var (
TokenCarolDanInvalidExpiredCID = gocid.MustParse("bafyreibgtlioorouqpwr6olk6boc3pprl5tx5xs6zpfnv3pvxtggueofii") TokenCarolDan_InvalidExpiredCID = gocid.MustParse("bafyreigenypixaxvhzlry5rjnywvjyl4xvzlzxz2ui74uzys7qdhos4bbu")
TokenCarolDanInvalidExpired = mustGetDelegation(TokenCarolDanInvalidExpiredCID) TokenCarolDan_InvalidExpired = mustGetDelegation(TokenCarolDan_InvalidExpiredCID)
) )
var ( var (
TokenDanErinInvalidExpiredCID = gocid.MustParse("bafyreidhq3hjsfrucbecgcjf2nkcgmq3sh3m5gjxz23vzcaynozs5p3uh4") TokenDanErin_InvalidExpiredCID = gocid.MustParse("bafyreifvnfb7zqocpdysedcvjkb4y7tqfuziuqjhbbdoay4zg33pwpbzqi")
TokenDanErinInvalidExpired = mustGetDelegation(TokenDanErinInvalidExpiredCID) TokenDanErin_InvalidExpired = mustGetDelegation(TokenDanErin_InvalidExpiredCID)
) )
var ( var (
TokenErinFrankInvalidExpiredCID = gocid.MustParse("bafyreido4om3y3ttkmp4c4gxm6pqug76vu3aekb666vdp6zewpvir5zs7u") TokenErinFrank_InvalidExpiredCID = gocid.MustParse("bafyreicvydzt3obkqx7krmoi3zu4tlirlksibxfks5jc7vlvjxjamv2764")
TokenErinFrankInvalidExpired = mustGetDelegation(TokenErinFrankInvalidExpiredCID) TokenErinFrank_InvalidExpired = mustGetDelegation(TokenErinFrank_InvalidExpiredCID)
) )
var ( var (
TokenCarolDanInvalidInactiveCID = gocid.MustParse("bafyreicea5y2nvlitvxijkupeavtg23i7ktjk3uejnaquguurzptiabk4u") TokenCarolDan_InvalidInactiveCID = gocid.MustParse("bafyreicea5y2nvlitvxijkupeavtg23i7ktjk3uejnaquguurzptiabk4u")
TokenCarolDanInvalidInactive = mustGetDelegation(TokenCarolDanInvalidInactiveCID) TokenCarolDan_InvalidInactive = mustGetDelegation(TokenCarolDan_InvalidInactiveCID)
) )
var ( var (
TokenDanErinInvalidInactiveCID = gocid.MustParse("bafyreifsgqzkmxj2vexuts3z766mwcjreiisjg2jykyzf7tbj5sclutpvq") TokenDanErin_InvalidInactiveCID = gocid.MustParse("bafyreifsgqzkmxj2vexuts3z766mwcjreiisjg2jykyzf7tbj5sclutpvq")
TokenDanErinInvalidInactive = mustGetDelegation(TokenDanErinInvalidInactiveCID) TokenDanErin_InvalidInactive = mustGetDelegation(TokenDanErin_InvalidInactiveCID)
) )
var ( var (
TokenErinFrankInvalidInactiveCID = gocid.MustParse("bafyreifbfegon24c6dndiqyktahzs65vhyasrygbw7nhsvojn6distsdre") TokenErinFrank_InvalidInactiveCID = gocid.MustParse("bafyreifbfegon24c6dndiqyktahzs65vhyasrygbw7nhsvojn6distsdre")
TokenErinFrankInvalidInactive = mustGetDelegation(TokenErinFrankInvalidInactiveCID) TokenErinFrank_InvalidInactive = mustGetDelegation(TokenErinFrank_InvalidInactiveCID)
) )
var ProofAliceBob = []gocid.Cid{ var ProofAliceBob = []gocid.Cid{
@@ -134,107 +134,107 @@ var ProofAliceBobCarolDanErinFrank = []gocid.Cid{
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanInvalidExpandedCommand = []gocid.Cid{ var ProofAliceBobCarolDan_InvalidExpandedCommand = []gocid.Cid{
TokenCarolDanInvalidExpandedCommandCID, TokenCarolDan_InvalidExpandedCommandCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinInvalidExpandedCommand = []gocid.Cid{ var ProofAliceBobCarolDanErin_InvalidExpandedCommand = []gocid.Cid{
TokenDanErinInvalidExpandedCommandCID, TokenDanErin_InvalidExpandedCommandCID,
TokenCarolDanInvalidExpandedCommandCID, TokenCarolDan_InvalidExpandedCommandCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinFrankInvalidExpandedCommand = []gocid.Cid{ var ProofAliceBobCarolDanErinFrank_InvalidExpandedCommand = []gocid.Cid{
TokenErinFrankInvalidExpandedCommandCID, TokenErinFrank_InvalidExpandedCommandCID,
TokenDanErinInvalidExpandedCommandCID, TokenDanErin_InvalidExpandedCommandCID,
TokenCarolDanInvalidExpandedCommandCID, TokenCarolDan_InvalidExpandedCommandCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanValidAttenuatedCommand = []gocid.Cid{ var ProofAliceBobCarolDan_ValidAttenuatedCommand = []gocid.Cid{
TokenCarolDanValidAttenuatedCommandCID, TokenCarolDan_ValidAttenuatedCommandCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinValidAttenuatedCommand = []gocid.Cid{ var ProofAliceBobCarolDanErin_ValidAttenuatedCommand = []gocid.Cid{
TokenDanErinValidAttenuatedCommandCID, TokenDanErin_ValidAttenuatedCommandCID,
TokenCarolDanValidAttenuatedCommandCID, TokenCarolDan_ValidAttenuatedCommandCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinFrankValidAttenuatedCommand = []gocid.Cid{ var ProofAliceBobCarolDanErinFrank_ValidAttenuatedCommand = []gocid.Cid{
TokenErinFrankValidAttenuatedCommandCID, TokenErinFrank_ValidAttenuatedCommandCID,
TokenDanErinValidAttenuatedCommandCID, TokenDanErin_ValidAttenuatedCommandCID,
TokenCarolDanValidAttenuatedCommandCID, TokenCarolDan_ValidAttenuatedCommandCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanInvalidSubject = []gocid.Cid{ var ProofAliceBobCarolDan_InvalidSubject = []gocid.Cid{
TokenCarolDanInvalidSubjectCID, TokenCarolDan_InvalidSubjectCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinInvalidSubject = []gocid.Cid{ var ProofAliceBobCarolDanErin_InvalidSubject = []gocid.Cid{
TokenDanErinInvalidSubjectCID, TokenDanErin_InvalidSubjectCID,
TokenCarolDanInvalidSubjectCID, TokenCarolDan_InvalidSubjectCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinFrankInvalidSubject = []gocid.Cid{ var ProofAliceBobCarolDanErinFrank_InvalidSubject = []gocid.Cid{
TokenErinFrankInvalidSubjectCID, TokenErinFrank_InvalidSubjectCID,
TokenDanErinInvalidSubjectCID, TokenDanErin_InvalidSubjectCID,
TokenCarolDanInvalidSubjectCID, TokenCarolDan_InvalidSubjectCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanInvalidExpired = []gocid.Cid{ var ProofAliceBobCarolDan_InvalidExpired = []gocid.Cid{
TokenCarolDanInvalidExpiredCID, TokenCarolDan_InvalidExpiredCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinInvalidExpired = []gocid.Cid{ var ProofAliceBobCarolDanErin_InvalidExpired = []gocid.Cid{
TokenDanErinInvalidExpiredCID, TokenDanErin_InvalidExpiredCID,
TokenCarolDanInvalidExpiredCID, TokenCarolDan_InvalidExpiredCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinFrankInvalidExpired = []gocid.Cid{ var ProofAliceBobCarolDanErinFrank_InvalidExpired = []gocid.Cid{
TokenErinFrankInvalidExpiredCID, TokenErinFrank_InvalidExpiredCID,
TokenDanErinInvalidExpiredCID, TokenDanErin_InvalidExpiredCID,
TokenCarolDanInvalidExpiredCID, TokenCarolDan_InvalidExpiredCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanInvalidInactive = []gocid.Cid{ var ProofAliceBobCarolDan_InvalidInactive = []gocid.Cid{
TokenCarolDanInvalidInactiveCID, TokenCarolDan_InvalidInactiveCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinInvalidInactive = []gocid.Cid{ var ProofAliceBobCarolDanErin_InvalidInactive = []gocid.Cid{
TokenDanErinInvalidInactiveCID, TokenDanErin_InvalidInactiveCID,
TokenCarolDanInvalidInactiveCID, TokenCarolDan_InvalidInactiveCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }
var ProofAliceBobCarolDanErinFrankInvalidInactive = []gocid.Cid{ var ProofAliceBobCarolDanErinFrank_InvalidInactive = []gocid.Cid{
TokenErinFrankInvalidInactiveCID, TokenErinFrank_InvalidInactiveCID,
TokenDanErinInvalidInactiveCID, TokenDanErin_InvalidInactiveCID,
TokenCarolDanInvalidInactiveCID, TokenCarolDan_InvalidInactiveCID,
TokenBobCarolCID, TokenBobCarolCID,
TokenAliceBobCID, TokenAliceBobCID,
} }

View File

@@ -12,8 +12,6 @@ import (
) )
func TestGetDelegation(t *testing.T) { func TestGetDelegation(t *testing.T) {
t.Parallel()
t.Run("passes with valid CID", func(t *testing.T) { t.Run("passes with valid CID", func(t *testing.T) {
t.Parallel() t.Parallel()

View File

@@ -39,7 +39,7 @@ func TestToken_ExecutionAllowed(t *testing.T) {
t.Run("passes - proof chain attenuates command", func(t *testing.T) { t.Run("passes - proof chain attenuates command", func(t *testing.T) {
t.Parallel() t.Parallel()
testPasses(t, didtest.PersonaFrank, delegationtest.AttenuatedCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrankValidAttenuatedCommand) testPasses(t, didtest.PersonaFrank, delegationtest.AttenuatedCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrank_ValidAttenuatedCommand)
}) })
t.Run("passes - invocation attenuates command", func(t *testing.T) { t.Run("passes - invocation attenuates command", func(t *testing.T) {
@@ -67,14 +67,14 @@ func TestToken_ExecutionAllowed(t *testing.T) {
t.Run("fails - referenced delegation expired", func(t *testing.T) { t.Run("fails - referenced delegation expired", func(t *testing.T) {
t.Parallel() t.Parallel()
testFails(t, invocation.ErrTokenInvalidNow, didtest.PersonaFrank, delegationtest.NominalCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrankInvalidExpired) testFails(t, invocation.ErrTokenInvalidNow, didtest.PersonaFrank, delegationtest.NominalCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrank_InvalidExpired)
}) })
t.Run("fails - referenced delegation inactive", func(t *testing.T) { t.Run("fails - referenced delegation inactive", func(t *testing.T) {
t.Parallel() t.Parallel()
testFails(t, invocation.ErrTokenInvalidNow, didtest.PersonaFrank, delegationtest.NominalCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrankInvalidInactive) testFails(t, invocation.ErrTokenInvalidNow, didtest.PersonaFrank, delegationtest.NominalCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrank_InvalidInactive)
}) })
t.Run("fails - last (or only) delegation not root", func(t *testing.T) { t.Run("fails - last (or only) delegation not root", func(t *testing.T) {
@@ -101,7 +101,7 @@ func TestToken_ExecutionAllowed(t *testing.T) {
t.Run("fails - proof chain expands command", func(t *testing.T) { t.Run("fails - proof chain expands command", func(t *testing.T) {
t.Parallel() t.Parallel()
testFails(t, invocation.ErrCommandNotCovered, didtest.PersonaFrank, delegationtest.NominalCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrankInvalidExpandedCommand) testFails(t, invocation.ErrCommandNotCovered, didtest.PersonaFrank, delegationtest.NominalCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrank_InvalidExpandedCommand)
}) })
t.Run("fails - invocation expands command", func(t *testing.T) { t.Run("fails - invocation expands command", func(t *testing.T) {
@@ -113,20 +113,19 @@ func TestToken_ExecutionAllowed(t *testing.T) {
t.Run("fails - inconsistent subject", func(t *testing.T) { t.Run("fails - inconsistent subject", func(t *testing.T) {
t.Parallel() t.Parallel()
testFails(t, invocation.ErrWrongSub, didtest.PersonaFrank, delegationtest.ExpandedCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrankInvalidSubject) testFails(t, invocation.ErrWrongSub, didtest.PersonaFrank, delegationtest.ExpandedCommand, emptyArguments, delegationtest.ProofAliceBobCarolDanErinFrank_InvalidSubject)
}) })
} }
func test(t *testing.T, persona didtest.Persona, cmd command.Command, args *args.Args, prf []cid.Cid, opts ...invocation.Option) error { func test(t *testing.T, persona didtest.Persona, cmd command.Command, args *args.Args, prf []cid.Cid, opts ...invocation.Option) error {
t.Helper() t.Helper()
tkn, err := invocation.New(persona.DID(t), didtest.PersonaAlice.DID(t), cmd, prf, opts...) // TODO: use the args and add minimal test to check that they are verified against the policy
tkn, err := invocation.New(persona.DID(), didtest.PersonaAlice.DID(), cmd, prf, opts...)
require.NoError(t, err) require.NoError(t, err)
ldr, err := delegationtest.GetDelegationLoader() return tkn.ExecutionAllowed(delegationtest.GetDelegationLoader())
require.NoError(t, err)
return tkn.ExecutionAllowed(ldr)
} }
func testFails(t *testing.T, expErr error, persona didtest.Persona, cmd command.Command, args *args.Args, prf []cid.Cid, opts ...invocation.Option) { func testFails(t *testing.T, expErr error, persona didtest.Persona, cmd command.Command, args *args.Args, prf []cid.Cid, opts ...invocation.Option) {