mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-03 18:22:25 +02:00
macaroons: add tests for service and constraints
This commit is contained in:
committed by
Oliver Gugger
parent
04f4dbe639
commit
8e4e2bd889
@@ -1,109 +1,108 @@
|
||||
package macaroons
|
||||
package macaroons_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"gopkg.in/macaroon.v2"
|
||||
"time"
|
||||
|
||||
"gopkg.in/macaroon-bakery.v1/bakery"
|
||||
"gopkg.in/macaroon-bakery.v1/bakery/checkers"
|
||||
macaroon "gopkg.in/macaroon.v1"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type macError struct {
|
||||
message string
|
||||
}
|
||||
var (
|
||||
testRootKey = []byte("dummyRootKey")
|
||||
testId = []byte("dummyId")
|
||||
testLocation = "lnd"
|
||||
testVersion = macaroon.LatestVersion
|
||||
expectedTimeCaveatSubstring = "time-before " + string(time.Now().Year())
|
||||
)
|
||||
|
||||
func (err macError) Error() string {
|
||||
return err.message
|
||||
}
|
||||
|
||||
func testConstraint(constraint Constraint, ok checkers.Checker,
|
||||
failFn func() checkers.Checker) error {
|
||||
macParams := bakery.NewServiceParams{}
|
||||
svc, err := bakery.NewService(macParams)
|
||||
func createDummyMacaroon(t *testing.T) *macaroon.Macaroon {
|
||||
dummyMacaroon, err := macaroon.New(testRootKey, testId,
|
||||
testLocation, testVersion)
|
||||
if err != nil {
|
||||
return errors.New("Failed to create a new service")
|
||||
t.Fatalf("Error creating initial macaroon: %v", err)
|
||||
}
|
||||
mac, err := svc.NewMacaroon("", nil, nil)
|
||||
if err != nil {
|
||||
return errors.New("Failed to create a new macaroon")
|
||||
}
|
||||
|
||||
mac, err = AddConstraints(mac, constraint)
|
||||
if err != nil {
|
||||
return errors.New("Failed to add macaroon constraint")
|
||||
}
|
||||
|
||||
okChecker := checkers.New(ok)
|
||||
if err := svc.Check(macaroon.Slice{mac}, okChecker); err != nil {
|
||||
msg := "Correct checker failed: %v"
|
||||
return macError{fmt.Sprintf(msg, ok)}
|
||||
}
|
||||
|
||||
fail := failFn()
|
||||
failChecker := checkers.New(fail)
|
||||
if err := svc.Check(macaroon.Slice{mac}, failChecker); err == nil {
|
||||
msg := "Incorrect checker succeeded: %v"
|
||||
return macError{fmt.Sprintf(msg, fail)}
|
||||
}
|
||||
return nil
|
||||
return dummyMacaroon
|
||||
}
|
||||
|
||||
func TestAllowConstraint(t *testing.T) {
|
||||
if err := testConstraint(
|
||||
AllowConstraint("op1", "op2", "op4"),
|
||||
AllowChecker("op1"),
|
||||
func() checkers.Checker {
|
||||
return AllowChecker("op3")
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
// TestAddConstraints tests that constraints can be added to an existing
|
||||
// macaroon and therefore tighten its restrictions.
|
||||
func TestAddConstraints(t *testing.T) {
|
||||
// We need a dummy macaroon to start with. Create one without
|
||||
// a bakery, because we mock everything anyway.
|
||||
initialMac := createDummyMacaroon(t)
|
||||
|
||||
// Now add a constraint and make sure we have a cloned macaroon
|
||||
// with the constraint applied instead of a mutated initial one.
|
||||
newMac, err := macaroons.AddConstraints(initialMac,
|
||||
macaroons.TimeoutConstraint(1))
|
||||
if err != nil {
|
||||
t.Fatalf("Error adding constraint: %v", err)
|
||||
}
|
||||
if &newMac == &initialMac {
|
||||
t.Fatalf("Initial macaroon has been changed, something " +
|
||||
"went wrong!")
|
||||
}
|
||||
|
||||
// Finally, test that the constraint has been added.
|
||||
if len(initialMac.Caveats()) == len(newMac.Caveats()) {
|
||||
t.Fatalf("No caveat has been added to the macaroon when " +
|
||||
"constraint was applied")
|
||||
}
|
||||
}
|
||||
|
||||
// TestTimeoutConstraint tests that a caveat for the lifetime of
|
||||
// a macaroon is created.
|
||||
func TestTimeoutConstraint(t *testing.T) {
|
||||
if err := testConstraint(
|
||||
TimeoutConstraint(1),
|
||||
TimeoutChecker(),
|
||||
func() checkers.Checker {
|
||||
time.Sleep(time.Second)
|
||||
return TimeoutChecker()
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
// Get a configured version of the constraint function.
|
||||
constraintFunc := macaroons.TimeoutConstraint(3)
|
||||
|
||||
// Now we need a dummy macaroon that we can apply the constraint
|
||||
// function to.
|
||||
testMacaroon := createDummyMacaroon(t)
|
||||
err := constraintFunc(testMacaroon)
|
||||
if err != nil {
|
||||
t.Fatalf("Error applying timeout constraint: %v", err)
|
||||
}
|
||||
|
||||
// Finally, check that the created caveat has an
|
||||
// acceptable value
|
||||
if strings.HasPrefix(string(testMacaroon.Caveats()[0].Id),
|
||||
expectedTimeCaveatSubstring) {
|
||||
t.Fatalf("Added caveat '%s' does not meet the expectations!",
|
||||
testMacaroon.Caveats()[0].Id)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPLockConstraint(t *testing.T) {
|
||||
if err := testConstraint(
|
||||
IPLockConstraint("127.0.0.1"),
|
||||
IPLockChecker("127.0.0.1"),
|
||||
func() checkers.Checker {
|
||||
return IPLockChecker("0.0.0.0")
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPLockEmptyIP(t *testing.T) {
|
||||
if err := testConstraint(
|
||||
IPLockConstraint(""),
|
||||
IPLockChecker("127.0.0.1"),
|
||||
func() checkers.Checker {
|
||||
return IPLockChecker("0.0.0.0")
|
||||
},
|
||||
); err != nil {
|
||||
if _, ok := err.(macError); !ok {
|
||||
t.Fatalf("IPLock with an empty IP should always pass")
|
||||
}
|
||||
// TestTimeoutConstraint tests that a caveat for the lifetime of
|
||||
// a macaroon is created.
|
||||
func TestIpLockConstraint(t *testing.T) {
|
||||
// Get a configured version of the constraint function.
|
||||
constraintFunc := macaroons.IPLockConstraint("127.0.0.1")
|
||||
|
||||
// Now we need a dummy macaroon that we can apply the constraint
|
||||
// function to.
|
||||
testMacaroon := createDummyMacaroon(t)
|
||||
err := constraintFunc(testMacaroon)
|
||||
if err != nil {
|
||||
t.Fatalf("Error applying timeout constraint: %v", err)
|
||||
}
|
||||
|
||||
// Finally, check that the created caveat has an
|
||||
// acceptable value
|
||||
if string(testMacaroon.Caveats()[0].Id) != "ipaddr 127.0.0.1" {
|
||||
t.Fatalf("Added caveat '%s' does not meet the expectations!",
|
||||
testMacaroon.Caveats()[0].Id)
|
||||
}
|
||||
}
|
||||
|
||||
// TestIPLockBadIP tests that an IP constraint cannot be added if the
|
||||
// provided string is not a valid IP address.
|
||||
func TestIPLockBadIP(t *testing.T) {
|
||||
if err := IPLockConstraint("127.0.0/800"); err == nil {
|
||||
t.Fatalf("IPLockConstraint with bad IP should fail")
|
||||
constraintFunc := macaroons.IPLockConstraint("127.0.0/800");
|
||||
testMacaroon := createDummyMacaroon(t)
|
||||
err := constraintFunc(testMacaroon)
|
||||
if err == nil {
|
||||
t.Fatalf("IPLockConstraint with bad IP should fail.")
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user