blob: a8251377796ecb398c7b841d8e746ba3aaa507e1 [file] [log] [blame]
package impl
import (
"path/filepath"
"v.io/core/veyron2/naming"
"v.io/core/veyron2/security"
"v.io/core/veyron2/services/security/access"
"v.io/core/veyron2/verror"
"v.io/core/veyron2/vlog"
"v.io/core/veyron/security/flag"
"v.io/core/veyron/services/mgmt/lib/fs"
"v.io/core/veyron/services/mgmt/repository"
)
// dispatcher holds the state of the application repository dispatcher.
type dispatcher struct {
store *fs.Memstore
storeRoot string
}
// NewDispatcher is the dispatcher factory. storeDir is a path to a directory in which to
// serialize the applicationd state.
func NewDispatcher(storeDir string) (*dispatcher, error) {
store, err := fs.NewMemstore(filepath.Join(storeDir, "applicationdstate.db"))
if err != nil {
return nil, err
}
acls, err := flag.TaggedACLMapFromFlag()
if err != nil {
return nil, err
}
if acls != nil {
store.Lock()
defer store.Unlock()
// (Re)set the root ACLs.
path := naming.Join("/acls", "data")
_, tag, err := getACL(store, path)
if !verror.Is(err, ErrNotFound.ID) {
return nil, err
}
if err := setACL(store, path, acls, tag); err != nil {
return nil, err
}
}
return &dispatcher{store: store, storeRoot: storeDir}, nil
}
// DISPATCHER INTERFACE IMPLEMENTATION
// getAuthorizer searches the provided list of paths in the Memstore hierarchy
// for an TaggedACLMap and uses it to produce an authorizer or returns nil
// to get a nil Authorizer.
func getAuthorizer(store *fs.Memstore, paths []string) (security.Authorizer, error) {
for _, p := range paths {
if tam, _, err := getACL(store, p); err == nil {
auth, err := access.TaggedACLAuthorizer(tam, access.TypicalTagType())
if err != nil {
vlog.Errorf("Successfully obtained an ACL from Memstore but TaggedACLAuthorizer couldn't use it: %v", err)
return nil, err
}
return auth, nil
} else if !verror.Is(err, ErrNotFound.ID) {
vlog.Errorf("Internal error obtaining ACL from Memstore: %v", err)
}
}
return nil, nil
}
func (d *dispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
app, version, _ := parse(nil, suffix)
// TODO(rjkroege@google.com): Implement ACL inheritance.
// Construct the search hierarchy for ACLs.
sp := []string{
naming.Join("/acls", app, version, "data"),
naming.Join("/acls", app, "data"),
naming.Join("/acls", "data"),
}
auth, err := getAuthorizer(d.store, sp)
if err != nil {
return nil, nil, err
}
return repository.ApplicationServer(NewApplicationService(d.store, d.storeRoot, suffix)), auth, nil
}