veyron/services/mgmt/binary/impl: provide useful GetACL default

Calling GetACL with a default nil authorizer return an error until an
ACL has been set with SetACL and the command line ACL setting tool
always calls GetACL before SetACL. Break this dependency problem by
returning a default ACL set.

Change-Id: I390a469a73a6e079448a3b3f5509406e4c0b5776
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 {