Merge "veyron/services/mgmt/binary/impl: provide useful GetACL default"
diff --git a/services/mgmt/binary/impl/acl_test.go b/services/mgmt/binary/impl/acl_test.go
index 7f81a0f..e599972 100644
--- a/services/mgmt/binary/impl/acl_test.go
+++ b/services/mgmt/binary/impl/acl_test.go
@@ -308,3 +308,69 @@
 		t.Fatalf("Stat() should have failed but didn't: %v", err)
 	}
 }
+
+func TestBinaryRationalStartingValueForGetACL(t *testing.T) {
+	ctx, shutdown := testutil.InitForTest()
+	defer shutdown()
+	veyron2.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
+
+	selfPrincipal := tsecurity.NewPrincipal("self")
+	selfCtx, err := veyron2.SetPrincipal(ctx, selfPrincipal)
+	if err != nil {
+		t.Fatalf("SetPrincipal failed: %v", err)
+	}
+	sh, deferFn := mgmttest.CreateShellAndMountTable(t, selfCtx, veyron2.GetPrincipal(selfCtx))
+	defer deferFn()
+
+	// setup mock up directory to put state in
+	storedir, cleanup := mgmttest.SetupRootDir(t, "bindir")
+	defer cleanup()
+	prepDirectory(t, storedir)
+
+	otherPrincipal := tsecurity.NewPrincipal("other")
+	if err := otherPrincipal.AddToRoots(selfPrincipal.BlessingStore().Default()); err != nil {
+		t.Fatalf("otherPrincipal.AddToRoots() failed: %v", err)
+	}
+
+	_, nms := mgmttest.RunShellCommand(t, sh, nil, binaryCmd, "bini", storedir)
+	pid := mgmttest.ReadPID(t, nms)
+	defer syscall.Kill(pid, syscall.SIGINT)
+
+	binary := repository.BinaryClient("bini")
+	acl, tag, err := binary.GetACL(selfCtx)
+	if err != nil {
+		t.Fatalf("GetACL failed: %#v", err)
+	}
+	expected := access.TaggedACLMap{
+		"Admin":   access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{}},
+		"Read":    access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{}},
+		"Write":   access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{}},
+		"Debug":   access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{}},
+		"Resolve": access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{}},
+	}
+	if got, want := acl.Normalize(), expected.Normalize(); !reflect.DeepEqual(got, want) {
+		t.Errorf("got %#v, expected %#v ", got, want)
+	}
+
+	acl.Blacklist("self", string("Read"))
+	err = binary.SetACL(selfCtx, acl, tag)
+	if err != nil {
+		t.Fatalf("SetACL() failed: %v", err)
+	}
+
+	acl, tag, err = binary.GetACL(selfCtx)
+	if err != nil {
+		t.Fatalf("GetACL failed: %#v", err)
+	}
+	expected = access.TaggedACLMap{
+		"Admin":   access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{}},
+		"Read":    access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{"self"}},
+		"Write":   access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{}},
+		"Debug":   access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{}},
+		"Resolve": access.ACL{In: []security.BlessingPattern{"self/child"}, NotIn: []string{}},
+	}
+	if got, want := acl.Normalize(), expected.Normalize(); !reflect.DeepEqual(got, want) {
+		t.Errorf("got %#v, expected %#v ", got, want)
+	}
+
+}
diff --git a/services/mgmt/binary/impl/service.go b/services/mgmt/binary/impl/service.go
index 12b1e54..718e9e2 100644
--- a/services/mgmt/binary/impl/service.go
+++ b/services/mgmt/binary/impl/service.go
@@ -375,7 +375,22 @@
 }
 
 func (i *binaryService) GetACL(ctx ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
-	return i.locks.GetPathACL(ctx.LocalPrincipal(), aclPath(i.state.rootDir, i.suffix))
+
+	acl, etag, err = i.locks.GetPathACL(
+		ctx.LocalPrincipal(), aclPath(i.state.rootDir, i.suffix))
+
+	if os.IsNotExist(err) {
+		// No ACL file which implies a nil authorizer.
+		tam := make(access.TaggedACLMap)
+		lb := ctx.LocalBlessings().ForContext(ctx)
+		for _, b := range lb {
+			for _, tag := range access.AllTypicalTags() {
+				tam.Add(security.BlessingPattern(b), string(tag))
+			}
+		}
+		return tam, "", nil
+	}
+	return acl, etag, err
 }
 
 func (i *binaryService) SetACL(ctx ipc.ServerContext, acl access.TaggedACLMap, etag string) error {