services/mgmt/lib/acls: additional hierarchical authorizer changes

Further extend hierarchical authorizer to support Admin overriding
missing permissions on the root permission list.

Change-Id: I6001a46d5791a7661b7b77f457fbac105dc56bdc
diff --git a/services/mgmt/lib/acls/hierarchical_authorizer.go b/services/mgmt/lib/acls/hierarchical_authorizer.go
index 5b5e921..689844a 100644
--- a/services/mgmt/lib/acls/hierarchical_authorizer.go
+++ b/services/mgmt/lib/acls/hierarchical_authorizer.go
@@ -66,7 +66,7 @@
 		if err != nil {
 			return err
 		}
-		return a.Authorize(ctx)
+		return adminCheckAuth(ctx, a, rootPerms)
 	}
 
 	// This is not fatal: the childDir may not exist if we are invoking
@@ -79,7 +79,7 @@
 		if err != nil {
 			return err
 		}
-		return a.Authorize(ctx)
+		return adminCheckAuth(ctx, a, rootPerms)
 	}
 
 	childAuth, err := access.PermissionsAuthorizer(childPerms, access.TypicalTagType())
@@ -87,20 +87,23 @@
 		vlog.Errorf("Successfully obtained a Permissions from the filesystem but PermissionsAuthorizer couldn't use it: %v", err)
 		return err
 	}
+	return adminCheckAuth(ctx, childAuth, rootPerms)
+}
 
-	childErr := childAuth.Authorize(ctx)
-	if childErr == nil {
+func adminCheckAuth(ctx *context.T, auth security.Authorizer, perms access.Permissions) error {
+	err := auth.Authorize(ctx)
+	if err == nil {
 		return nil
 	}
 
 	// Maybe the invoking principal can invoke this method because
-	// it has root permissions.
+	// it has Admin permissions.
 	names, _ := security.RemoteBlessingNames(ctx)
-	if len(names) > 0 && rootPerms[string(access.Admin)].Includes(names...) {
+	if len(names) > 0 && perms[string(access.Admin)].Includes(names...) {
 		return nil
 	}
 
-	return childErr
+	return err
 }
 
 // defaultAuthorizer implements an authorization policy that requires one end