multi: upgrade macaroons to v2, replace per-method auth with interceptors
This commit reworks the macaroon authentication framework to use the v2 macaroon format and bakery API. It also replaces the code in each RPC method which calls the macaroon verifier with interceptors which call the macaroon verifier instead. In addition, the operation permissions are reworked to fit the new format of "allow" commands (specifically, entity/operation permissions instead of method permissions).
This commit is contained in:
1 parent
20098e8cb3
commit
21c29c33d7
11 files changed
+427
-514
No files matched your search
+10
-66
@@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
)
|
||||
|
||||
@@ -21,7 +23,7 @@ var (
|
||||
// just 0, to emulate the memory storage that comes with bakery.
|
||||
//
|
||||
// TODO(aakselrod): Add support for key rotation.
|
||||
defaultRootKeyID = "0"
|
||||
defaultRootKeyID = []byte("0")
|
||||
|
||||
// macaroonBucketName is the name of the macaroon store bucket.
|
||||
macaroonBucketName = []byte("macaroons")
|
||||
@@ -49,13 +51,13 @@ func NewRootKeyStorage(db *bolt.DB) (*RootKeyStorage, error) {
|
||||
}
|
||||
|
||||
// Get implements the Get method for the bakery.RootKeyStorage interface.
|
||||
func (r *RootKeyStorage) Get(id string) ([]byte, error) {
|
||||
func (r *RootKeyStorage) Get(_ context.Context, id []byte) ([]byte, error) {
|
||||
var rootKey []byte
|
||||
err := r.View(func(tx *bolt.Tx) error {
|
||||
dbKey := tx.Bucket(rootKeyBucketName).Get([]byte(id))
|
||||
dbKey := tx.Bucket(rootKeyBucketName).Get(id)
|
||||
if len(dbKey) == 0 {
|
||||
return fmt.Errorf("root key with id %s doesn't exist",
|
||||
id)
|
||||
string(id))
|
||||
}
|
||||
|
||||
rootKey = make([]byte, len(dbKey))
|
||||
@@ -72,12 +74,12 @@ func (r *RootKeyStorage) Get(id string) ([]byte, error) {
|
||||
// RootKey implements the RootKey method for the bakery.RootKeyStorage
|
||||
// interface.
|
||||
// TODO(aakselrod): Add support for key rotation.
|
||||
func (r *RootKeyStorage) RootKey() ([]byte, string, error) {
|
||||
func (r *RootKeyStorage) RootKey(_ context.Context) ([]byte, []byte, error) {
|
||||
var rootKey []byte
|
||||
id := defaultRootKeyID
|
||||
err := r.Update(func(tx *bolt.Tx) error {
|
||||
ns := tx.Bucket(rootKeyBucketName)
|
||||
rootKey = ns.Get([]byte(id))
|
||||
rootKey = ns.Get(id)
|
||||
|
||||
// If there's no root key stored in the bucket yet, create one.
|
||||
if len(rootKey) != 0 {
|
||||
@@ -89,69 +91,11 @@ func (r *RootKeyStorage) RootKey() ([]byte, string, error) {
|
||||
if _, err := io.ReadFull(rand.Reader, rootKey[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return ns.Put([]byte(id), rootKey)
|
||||
return ns.Put(id, rootKey)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return rootKey, id, nil
|
||||
}
|
||||
|
||||
// Storage implements the bakery.Storage interface.
|
||||
type Storage struct {
|
||||
*bolt.DB
|
||||
}
|
||||
|
||||
// NewStorage creates a Storage instance.
|
||||
//
|
||||
// TODO(aakselrod): Add support for encryption of data with passphrase.
|
||||
func NewStorage(db *bolt.DB) (*Storage, error) {
|
||||
// If the store's bucket doesn't exist, create it.
|
||||
err := db.Update(func(tx *bolt.Tx) error {
|
||||
_, err := tx.CreateBucketIfNotExists(macaroonBucketName)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Return the DB wrapped in a Storage object.
|
||||
return &Storage{db}, nil
|
||||
}
|
||||
|
||||
// Put implements the Put method for the bakery.Storage interface.
|
||||
func (s *Storage) Put(location string, item string) error {
|
||||
return s.Update(func(tx *bolt.Tx) error {
|
||||
return tx.Bucket(macaroonBucketName).Put([]byte(location),
|
||||
[]byte(item))
|
||||
})
|
||||
}
|
||||
|
||||
// Get implements the Get method for the bakery.Storage interface.
|
||||
func (s *Storage) Get(location string) (string, error) {
|
||||
var item []byte
|
||||
err := s.View(func(tx *bolt.Tx) error {
|
||||
itemBytes := tx.Bucket(macaroonBucketName).Get([]byte(location))
|
||||
if len(itemBytes) == 0 {
|
||||
return fmt.Errorf("couldn't get item for location %s",
|
||||
location)
|
||||
}
|
||||
|
||||
item = make([]byte, len(itemBytes))
|
||||
copy(item, itemBytes)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(item), nil
|
||||
}
|
||||
|
||||
// Del implements the Del method for the bakery.Storage interface.
|
||||
func (s *Storage) Del(location string) error {
|
||||
return s.Update(func(tx *bolt.Tx) error {
|
||||
return tx.Bucket(macaroonBucketName).Delete([]byte(location))
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user