mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
macaroons: add BakeFromRootKey function
This commit is contained in:
parent
fd37c6f90a
commit
6e932c6bc8
68
macaroons/bake.go
Normal file
68
macaroons/bake.go
Normal file
@ -0,0 +1,68 @@
|
||||
package macaroons
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
"gopkg.in/macaroon.v2"
|
||||
)
|
||||
|
||||
// inMemoryRootKeyStore is a simple implementation of bakery.RootKeyStore that
|
||||
// stores a single root key in memory.
|
||||
type inMemoryRootKeyStore struct {
|
||||
rootKey []byte
|
||||
}
|
||||
|
||||
// A compile-time check to ensure that inMemoryRootKeyStore implements
|
||||
// bakery.RootKeyStore.
|
||||
var _ bakery.RootKeyStore = (*inMemoryRootKeyStore)(nil)
|
||||
|
||||
// Get returns the root key for the given id. If the item is not there, it
|
||||
// returns ErrNotFound.
|
||||
func (s *inMemoryRootKeyStore) Get(_ context.Context, id []byte) ([]byte,
|
||||
error) {
|
||||
|
||||
if !bytes.Equal(id, DefaultRootKeyID) {
|
||||
return nil, bakery.ErrNotFound
|
||||
}
|
||||
|
||||
return s.rootKey, nil
|
||||
}
|
||||
|
||||
// RootKey returns the root key to be used for making a new macaroon, and an id
|
||||
// that can be used to look it up later with the Get method.
|
||||
func (s *inMemoryRootKeyStore) RootKey(context.Context) ([]byte, []byte,
|
||||
error) {
|
||||
|
||||
return s.rootKey, DefaultRootKeyID, nil
|
||||
}
|
||||
|
||||
// BakeFromRootKey creates a new macaroon that is derived from the given root
|
||||
// key and permissions.
|
||||
func BakeFromRootKey(rootKey []byte,
|
||||
permissions []bakery.Op) (*macaroon.Macaroon, error) {
|
||||
|
||||
if len(rootKey) != RootKeyLen {
|
||||
return nil, fmt.Errorf("root key must be %d bytes, is %d",
|
||||
RootKeyLen, len(rootKey))
|
||||
}
|
||||
|
||||
rootKeyStore := &inMemoryRootKeyStore{
|
||||
rootKey: rootKey,
|
||||
}
|
||||
|
||||
service, err := NewService(rootKeyStore, "lnd", false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create service: %w", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
mac, err := service.NewMacaroon(ctx, DefaultRootKeyID, permissions...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create macaroon: %w", err)
|
||||
}
|
||||
|
||||
return mac.M(), nil
|
||||
}
|
58
macaroons/bake_test.go
Normal file
58
macaroons/bake_test.go
Normal file
@ -0,0 +1,58 @@
|
||||
package macaroons_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
)
|
||||
|
||||
// TestBakeFromRootKey tests that a macaroon can be baked from a root key
|
||||
// directly without needing to create a store or service first.
|
||||
func TestBakeFromRootKey(t *testing.T) {
|
||||
// Create a test store and unlock it.
|
||||
_, store := newTestStore(t)
|
||||
|
||||
pw := []byte("weks")
|
||||
err := store.CreateUnlock(&pw)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Force the store to create a new random root key.
|
||||
key, id, err := store.RootKey(defaultRootKeyIDContext)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, key, 32)
|
||||
|
||||
tmpKey, err := store.Get(defaultRootKeyIDContext, id)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, key, tmpKey)
|
||||
|
||||
// Create a service that uses the root key store.
|
||||
service, err := macaroons.NewService(store, "lnd", false)
|
||||
require.NoError(t, err, "Error creating new service")
|
||||
defer func() {
|
||||
require.NoError(t, service.Close())
|
||||
}()
|
||||
|
||||
// Call the BakeFromRootKey function that derives a macaroon directly
|
||||
// from the root key.
|
||||
perms := []bakery.Op{{Entity: "foo", Action: "bar"}}
|
||||
mac, err := macaroons.BakeFromRootKey(key, perms)
|
||||
require.NoError(t, err)
|
||||
|
||||
macaroonBytes, err := mac.MarshalBinary()
|
||||
require.NoError(t, err)
|
||||
|
||||
md := metadata.New(map[string]string{
|
||||
"macaroon": hex.EncodeToString(macaroonBytes),
|
||||
})
|
||||
macCtx := metadata.NewIncomingContext(context.Background(), md)
|
||||
|
||||
// The macaroon should be valid for the service, since the root key was
|
||||
// the same.
|
||||
err = service.ValidateMacaroon(macCtx, nil, "baz")
|
||||
require.NoError(t, err)
|
||||
}
|
Loading…
Reference in New Issue
Block a user