Merge pull request #6509 from Roasbeef/macaroons-rks

macaroons: futher abstract NewService from root key store impl
This commit is contained in:
Olaoluwa Osuntokun authored and GitHub committed 2022-07-06 19:00:49 -07:00
commit dc35f78ebc
5 files changed
+91 -24

No files matched your search

+5 -1
View File
@@ -394,8 +394,12 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
var macaroonService *macaroons.Service
if !d.cfg.NoMacaroons {
// Create the macaroon authentication/authorization service.
rootKeyStore, err := macaroons.NewRootKeyStorage(dbs.MacaroonDB)
if err != nil {
return nil, nil, nil, err
}
macaroonService, err = macaroons.NewService(
dbs.MacaroonDB, "lnd", walletInitParams.StatelessInit,
rootKeyStore, "lnd", walletInitParams.StatelessInit,
macaroons.IPLockChecker,
macaroons.CustomChecker(interceptorChain),
)
+3 -1
View File
@@ -5,7 +5,9 @@
* [Fixed error typo](https://github.com/lightningnetwork/lnd/pull/6659).
* [The macaroon key store implementation was refactored to be more generally useable](https://github.com/lightningnetwork/lnd/pull/6509).
# Contributors (Alphabetical Order)
* Carla Kirk-Cohen
* ErikEk
* Olaoluwa Osuntokun
+65 -17
View File
@@ -5,7 +5,6 @@ import (
"encoding/hex"
"fmt"
"github.com/lightningnetwork/lnd/kvdb"
"google.golang.org/grpc/metadata"
"gopkg.in/macaroon-bakery.v2/bakery"
"gopkg.in/macaroon-bakery.v2/bakery/checkers"
@@ -41,13 +40,43 @@ type MacaroonValidator interface {
requiredPermissions []bakery.Op, fullMethod string) error
}
// ExtendedRootKeyStore is an interface augments the existing
// macaroons.RootKeyStorage interface by adding a number of additional utility
// methods such as encrypting and decrypting the root key given a password.
type ExtendedRootKeyStore interface {
bakery.RootKeyStore
// Close closes the RKS and zeros out any in-memory encryption keys.
Close() error
// CreateUnlock calls the underlying root key store's CreateUnlock and
// returns the result.
CreateUnlock(password *[]byte) error
// ListMacaroonIDs returns all the root key ID values except the value
// of encryptedKeyID.
ListMacaroonIDs(ctxt context.Context) ([][]byte, error)
// DeleteMacaroonID removes one specific root key ID. If the root key
// ID is found and deleted, it will be returned.
DeleteMacaroonID(ctxt context.Context, rootKeyID []byte) ([]byte, error)
// ChangePassword calls the underlying root key store's ChangePassword
// and returns the result.
ChangePassword(oldPw, newPw []byte) error
// GenerateNewRootKey calls the underlying root key store's
// GenerateNewRootKey and returns the result.
GenerateNewRootKey() error
}
// Service encapsulates bakery.Bakery and adds a Close() method that zeroes the
// root key service encryption keys, as well as utility methods to validate a
// macaroon against the bakery and gRPC middleware for macaroon-based auth.
type Service struct {
bakery.Bakery
rks *RootKeyStorage
rks bakery.RootKeyStore
// ExternalValidators is a map between an absolute gRPC URIs and the
// corresponding external macaroon validator to be used for that URI.
@@ -67,17 +96,12 @@ type Service struct {
// not harmful. Default checkers, such as those for `allow`, `time-before`,
// `declared`, and `error` caveats are registered automatically and don't need
// to be added.
func NewService(db kvdb.Backend, location string, statelessInit bool,
checks ...Checker) (*Service, error) {
rootKeyStore, err := NewRootKeyStorage(db)
if err != nil {
return nil, err
}
func NewService(keyStore bakery.RootKeyStore, location string,
statelessInit bool, checks ...Checker) (*Service, error) {
macaroonParams := bakery.BakeryParams{
Location: location,
RootKeyStore: rootKeyStore,
RootKeyStore: keyStore,
// No third-party caveat support for now.
// TODO(aakselrod): Add third-party caveat support.
Locator: nil,
@@ -98,7 +122,7 @@ func NewService(db kvdb.Backend, location string, statelessInit bool,
return &Service{
Bakery: *svc,
rks: rootKeyStore,
rks: keyStore,
ExternalValidators: make(map[string]MacaroonValidator),
StatelessInit: statelessInit,
}, nil
@@ -204,13 +228,21 @@ func (svc *Service) CheckMacAuth(ctx context.Context, macBytes []byte,
// Close closes the database that underlies the RootKeyStore and zeroes the
// encryption keys.
func (svc *Service) Close() error {
return svc.rks.Close()
if boltRKS, ok := svc.rks.(ExtendedRootKeyStore); ok {
return boltRKS.Close()
}
return nil
}
// CreateUnlock calls the underlying root key store's CreateUnlock and returns
// the result.
func (svc *Service) CreateUnlock(password *[]byte) error {
return svc.rks.CreateUnlock(password)
if boltRKS, ok := svc.rks.(ExtendedRootKeyStore); ok {
return boltRKS.CreateUnlock(password)
}
return nil
}
// NewMacaroon wraps around the function Oven.NewMacaroon with the defaults,
@@ -239,7 +271,11 @@ func (svc *Service) NewMacaroon(
// ListMacaroonIDs returns all the root key ID values except the value of
// encryptedKeyID.
func (svc *Service) ListMacaroonIDs(ctxt context.Context) ([][]byte, error) {
return svc.rks.ListMacaroonIDs(ctxt)
if boltRKS, ok := svc.rks.(ExtendedRootKeyStore); ok {
return boltRKS.ListMacaroonIDs(ctxt)
}
return nil, nil
}
// DeleteMacaroonID removes one specific root key ID. If the root key ID is
@@ -247,19 +283,31 @@ func (svc *Service) ListMacaroonIDs(ctxt context.Context) ([][]byte, error) {
func (svc *Service) DeleteMacaroonID(ctxt context.Context,
rootKeyID []byte) ([]byte, error) {
return svc.rks.DeleteMacaroonID(ctxt, rootKeyID)
if boltRKS, ok := svc.rks.(ExtendedRootKeyStore); ok {
return boltRKS.DeleteMacaroonID(ctxt, rootKeyID)
}
return nil, nil
}
// GenerateNewRootKey calls the underlying root key store's GenerateNewRootKey
// and returns the result.
func (svc *Service) GenerateNewRootKey() error {
return svc.rks.GenerateNewRootKey()
if boltRKS, ok := svc.rks.(ExtendedRootKeyStore); ok {
return boltRKS.GenerateNewRootKey()
}
return nil
}
// ChangePassword calls the underlying root key store's ChangePassword and
// returns the result.
func (svc *Service) ChangePassword(oldPw, newPw []byte) error {
return svc.rks.ChangePassword(oldPw, newPw)
if boltRKS, ok := svc.rks.(ExtendedRootKeyStore); ok {
return boltRKS.ChangePassword(oldPw, newPw)
}
return nil
}
// RawMacaroonFromContext is a helper function that extracts a raw macaroon
+13 -4
View File
@@ -59,10 +59,13 @@ func TestNewService(t *testing.T) {
tempDir, db := setupTestRootKeyStorage(t)
defer os.RemoveAll(tempDir)
rootKeyStore, err := macaroons.NewRootKeyStorage(db)
require.NoError(t, err)
// Second, create the new service instance, unlock it and pass in a
// checker that we expect it to add to the bakery.
service, err := macaroons.NewService(
db, "lnd", false, macaroons.IPLockChecker,
rootKeyStore, "lnd", false, macaroons.IPLockChecker,
)
require.NoError(t, err, "Error creating new service")
defer service.Close()
@@ -106,8 +109,10 @@ func TestValidateMacaroon(t *testing.T) {
// First, initialize the service and unlock it.
tempDir, db := setupTestRootKeyStorage(t)
defer os.RemoveAll(tempDir)
rootKeyStore, err := macaroons.NewRootKeyStorage(db)
require.NoError(t, err)
service, err := macaroons.NewService(
db, "lnd", false, macaroons.IPLockChecker,
rootKeyStore, "lnd", false, macaroons.IPLockChecker,
)
require.NoError(t, err, "Error creating new service")
defer service.Close()
@@ -154,8 +159,10 @@ func TestListMacaroonIDs(t *testing.T) {
// Second, create the new service instance, unlock it and pass in a
// checker that we expect it to add to the bakery.
rootKeyStore, err := macaroons.NewRootKeyStorage(db)
require.NoError(t, err)
service, err := macaroons.NewService(
db, "lnd", false, macaroons.IPLockChecker,
rootKeyStore, "lnd", false, macaroons.IPLockChecker,
)
require.NoError(t, err, "Error creating new service")
defer service.Close()
@@ -186,8 +193,10 @@ func TestDeleteMacaroonID(t *testing.T) {
// Second, create the new service instance, unlock it and pass in a
// checker that we expect it to add to the bakery.
rootKeyStore, err := macaroons.NewRootKeyStorage(db)
require.NoError(t, err)
service, err := macaroons.NewService(
db, "lnd", false, macaroons.IPLockChecker,
rootKeyStore, "lnd", false, macaroons.IPLockChecker,
)
require.NoError(t, err, "Error creating new service")
defer service.Close()
+5 -1
View File
@@ -807,8 +807,12 @@ func (u *UnlockerService) ChangePassword(ctx context.Context,
// then close it again.
// Attempt to open the macaroon DB, unlock it and then change
// the passphrase.
rootKeyStore, err := macaroons.NewRootKeyStorage(u.macaroonDB)
if err != nil {
return nil, err
}
macaroonService, err := macaroons.NewService(
u.macaroonDB, "lnd", in.StatelessInit,
rootKeyStore, "lnd", in.StatelessInit,
)
if err != nil {
return nil, err