diff --git a/macaroons/auth.go b/macaroons/auth.go index 452b2a3b..d7232949 100644 --- a/macaroons/auth.go +++ b/macaroons/auth.go @@ -23,13 +23,18 @@ func (m MacaroonCredential) RequireTransportSecurity() bool { return true } -// GetRequestMetadata implements the PerRPCCredentials interface. +// GetRequestMetadata implements the PerRPCCredentials interface. This method +// is required in order to pass the wrapped macaroon into the gRPC context. +// With this, the macaroon will be available within the request handling scope +// of the ultimate gRPC server implementation. func (m MacaroonCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { + macBytes, err := m.MarshalBinary() if err != nil { return nil, err } + md := make(map[string]string) md["macaroon"] = hex.EncodeToString(macBytes) return md, nil @@ -43,10 +48,15 @@ func NewMacaroonCredential(m *macaroon.Macaroon) MacaroonCredential { return ms } -// ValidateMacaroon validates auth given a bakery service, context, and uri. +// ValidateMacaroon validates the capabilities of a given request given a +// bakery service, context, and uri. Within the passed context.Context, we +// expect a macaroon to be encoded as request metadata using the key +// "macaroon". func ValidateMacaroon(ctx context.Context, method string, svc *bakery.Service) error { + // Get macaroon bytes from context and unmarshal into macaroon. + // // TODO(aakselrod): use FromIncomingContext after grpc update in glide. md, ok := metadata.FromContext(ctx) if !ok { @@ -56,6 +66,10 @@ func ValidateMacaroon(ctx context.Context, method string, return fmt.Errorf("expected 1 macaroon, got %d", len(md["macaroon"])) } + + // With the macaroon obtained, we'll now decode the hex-string + // encoding, then unmarshal it from binary into its concrete struct + // representation. macBytes, err := hex.DecodeString(md["macaroon"][0]) if err != nil { return err @@ -66,8 +80,9 @@ func ValidateMacaroon(ctx context.Context, method string, return err } - // Check the method being called against the permitted operation and the - // expiration time and return the result. + // Check the method being called against the permitted operation and + // the expiration time and return the result. + // // TODO(aakselrod): Add more checks as required. return svc.Check(macaroon.Slice{mac}, checkers.New( checkers.OperationChecker(method), diff --git a/macaroons/service.go b/macaroons/service.go index b0fe7d91..d54c1027 100644 --- a/macaroons/service.go +++ b/macaroons/service.go @@ -17,12 +17,14 @@ var ( // NewService returns a service backed by the macaroon Bolt DB stored in the // passed directory. func NewService(dir string) (*bakery.Service, error) { - // Open the database. + // Open the database that we'll use to store the primary macaroon key, + // and all generated macaroons+caveats. macaroonDB, err := bolt.Open(path.Join(dir, dbFilename), 0600, bolt.DefaultOptions) if err != nil { return nil, err } + rootKeyStore, err := NewRootKeyStorage(macaroonDB) if err != nil { return nil, err @@ -31,6 +33,7 @@ func NewService(dir string) (*bakery.Service, error) { if err != nil { return nil, err } + macaroonParams := bakery.NewServiceParams{ Location: "lnd", Store: macaroonStore, diff --git a/macaroons/store.go b/macaroons/store.go index 2baebd39..d381854b 100644 --- a/macaroons/store.go +++ b/macaroons/store.go @@ -19,6 +19,7 @@ var ( // defaultRootKeyID is the ID of the default root key. The first is // just 0, to emulate the memory storage that comes with bakery. + // // TODO(aakselrod): Add support for key rotation. defaultRootKeyID = "0" @@ -42,6 +43,7 @@ func NewRootKeyStorage(db *bolt.DB) (*RootKeyStorage, error) { if err != nil { return nil, err } + // Return the DB wrapped in a RootKeyStorage object. return &RootKeyStorage{db}, nil } @@ -60,6 +62,7 @@ func (r *RootKeyStorage) Get(id string) ([]byte, error) { if err != nil { return nil, err } + return rootKey, nil } @@ -88,6 +91,7 @@ func (r *RootKeyStorage) RootKey() ([]byte, string, error) { if err != nil { return nil, "", err } + return rootKey, id, nil } @@ -97,6 +101,7 @@ type Storage struct { } // 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. @@ -107,6 +112,7 @@ func NewStorage(db *bolt.DB) (*Storage, error) { if err != nil { return nil, err } + // Return the DB wrapped in a Storage object. return &Storage{db}, nil } @@ -134,6 +140,7 @@ func (s *Storage) Get(location string) (string, error) { if err != nil { return "", err } + return item, nil }