Merge "services/agent: Add a vbecome command to run with derived principals."
diff --git a/cmd/principal/bless.go b/cmd/principal/bless.go
index 3ed3ed9..80db361 100644
--- a/cmd/principal/bless.go
+++ b/cmd/principal/bless.go
@@ -59,7 +59,7 @@
return service, macaroon, root, nil
}
-func getMacaroonForBlessRPC(blessServerURL string, blessedChan <-chan string, browser bool) (<-chan string, error) {
+func getMacaroonForBlessRPC(key security.PublicKey, blessServerURL string, blessedChan <-chan string, browser bool) (<-chan string, error) {
// Setup a HTTP server to recieve a blessing macaroon from the identity server.
// Steps:
// 1. Generate a state token to be included in the HTTP request
@@ -118,7 +118,7 @@
go http.Serve(ln, nil)
// Print the link to start the flow.
- url, err := seekBlessingsURL(blessServerURL, redirectURL, state)
+ url, err := seekBlessingsURL(key, blessServerURL, redirectURL, state)
if err != nil {
return nil, fmt.Errorf("failed to create seekBlessingsURL: %s", err)
}
@@ -135,14 +135,19 @@
return result, nil
}
-func seekBlessingsURL(blessServerURL, redirectURL, state string) (string, error) {
+func seekBlessingsURL(key security.PublicKey, blessServerURL, redirectURL, state string) (string, error) {
baseURL, err := url.Parse(joinURL(blessServerURL, identity.SeekBlessingsRoute))
if err != nil {
return "", fmt.Errorf("failed to parse url: %v", err)
}
+ keyBytes, err := key.MarshalBinary()
+ if err != nil {
+ return "", fmt.Errorf("failed to marshal public key: %v", err)
+ }
params := url.Values{}
params.Add("redirect_url", redirectURL)
params.Add("state", state)
+ params.Add("public_key", base64.URLEncoding.EncodeToString(keyBytes))
baseURL.RawQuery = params.Encode()
return baseURL.String(), nil
}
diff --git a/cmd/principal/main.go b/cmd/principal/main.go
index 2c76e3a..dc95990 100644
--- a/cmd/principal/main.go
+++ b/cmd/principal/main.go
@@ -691,9 +691,11 @@
ctx, shutdown := v23.Init()
defer shutdown()
+ p := v23.GetPrincipal(ctx)
+
blessedChan := make(chan string)
defer close(blessedChan)
- macaroonChan, err := getMacaroonForBlessRPC(flagSeekBlessingsFrom, blessedChan, flagSeekBlessingsBrowser)
+ macaroonChan, err := getMacaroonForBlessRPC(p.PublicKey(), flagSeekBlessingsFrom, blessedChan, flagSeekBlessingsBrowser)
if err != nil {
return fmt.Errorf("failed to get macaroon from Vanadium blesser: %v", err)
}
@@ -706,8 +708,6 @@
// Wait for getTokenForBlessRPC to clean up:
<-macaroonChan
- p := v23.GetPrincipal(ctx)
-
if flagSeekBlessingsSetDefault {
if err := p.BlessingStore().SetDefault(blessings); err != nil {
return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
diff --git a/services/device/internal/impl/impl_test.go b/services/device/internal/impl/impl_test.go
index babe024..0a3bccd 100644
--- a/services/device/internal/impl/impl_test.go
+++ b/services/device/internal/impl/impl_test.go
@@ -9,10 +9,8 @@
package impl_test
import (
- "bytes"
"crypto/md5"
"encoding/base64"
- "encoding/hex"
"fmt"
"io/ioutil"
"os"
@@ -83,16 +81,6 @@
return path
}
-func initForTest() (*context.T, v23.Shutdown) {
- roots, _ := envvar.NamespaceRoots()
- for key, _ := range roots {
- os.Unsetenv(key)
- }
- ctx, shutdown := test.InitForTest()
- v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
- return ctx, shutdown
-}
-
// TestDeviceManagerUpdateAndRevert makes the device manager go through the
// motions of updating itself to newer versions (twice), and reverting itself
// back (twice). It also checks that update and revert fail when they're
@@ -100,7 +88,7 @@
// command. Further versions are running through the soft link that the device
// manager itself updates.
func TestDeviceManagerUpdateAndRevert(t *testing.T) {
- ctx, shutdown := initForTest()
+ ctx, shutdown := utiltest.InitForTest()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, v23.GetPrincipal(ctx))
@@ -324,7 +312,7 @@
// TestLifeOfAnApp installs an app, instantiates, runs, kills, and deletes
// several instances, and performs updates.
func TestLifeOfAnApp(t *testing.T) {
- ctx, shutdown := initForTest()
+ ctx, shutdown := utiltest.InitForTest()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -624,173 +612,6 @@
}
}
-// TestDeviceManagerClaim claims a devicemanager and tests AccessList permissions on
-// its methods.
-func TestDeviceManagerClaim(t *testing.T) {
- ctx, shutdown := initForTest()
- defer shutdown()
-
- // root blessing provider so that the principals of all the contexts
- // recognize each other.
- idp := testutil.NewIDProvider("root")
- if err := idp.Bless(v23.GetPrincipal(ctx), "ctx"); err != nil {
- t.Fatal(err)
- }
-
- sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
- defer deferFn()
-
- // Set up mock application and binary repositories.
- envelope, cleanup := utiltest.StartMockRepos(t, ctx)
- defer cleanup()
-
- root, cleanup := servicetest.SetupRootDir(t, "devicemanager")
- defer cleanup()
- if err := impl.SaveCreatorInfo(root); err != nil {
- t.Fatal(err)
- }
-
- // Create a script wrapping the test target that implements suidhelper.
- helperPath := utiltest.GenerateSuidHelperScript(t, root)
-
- // Set up the device manager. Since we won't do device manager updates,
- // don't worry about its application envelope and current link.
- pairingToken := "abcxyz"
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link", pairingToken)
- pid := servicetest.ReadPID(t, dmh)
- defer syscall.Kill(pid, syscall.SIGINT)
-
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", "trapp")
-
- claimantCtx := utiltest.CtxWithNewPrincipal(t, ctx, idp, "claimant")
- octx, err := v23.WithPrincipal(ctx, testutil.NewPrincipal("other"))
- if err != nil {
- t.Fatal(err)
- }
-
- // Unclaimed devices cannot do anything but be claimed.
- // TODO(ashankar,caprita): The line below will currently fail with
- // ErrUnclaimedDevice != NotTrusted. NotTrusted can be avoided by
- // passing options.SkipServerEndpointAuthorization{} to the "Install" RPC.
- // Refactor the helper function to make this possible.
- //installAppExpectError(t, octx, impl.ErrUnclaimedDevice.ID)
-
- // Claim the device with an incorrect pairing token should fail.
- utiltest.ClaimDeviceExpectError(t, claimantCtx, "claimable", "mydevice", "badtoken", impl.ErrInvalidPairingToken.ID)
- // But succeed with a valid pairing token
- utiltest.ClaimDevice(t, claimantCtx, "claimable", "dm", "mydevice", pairingToken)
-
- // Installation should succeed since claimantRT is now the "owner" of
- // the devicemanager.
- appID := utiltest.InstallApp(t, claimantCtx)
-
- // octx will not install the app now since it doesn't recognize the
- // device's blessings. The error returned will be ErrNoServers as that
- // is what the IPC stack does when there are no authorized servers.
- utiltest.InstallAppExpectError(t, octx, verror.ErrNoServers.ID)
- // Even if it does recognize the device (by virtue of recognizing the
- // claimant), the device will not allow it to install.
- if err := v23.GetPrincipal(octx).AddToRoots(v23.GetPrincipal(claimantCtx).BlessingStore().Default()); err != nil {
- t.Fatal(err)
- }
- utiltest.InstallAppExpectError(t, octx, verror.ErrNoAccess.ID)
-
- // Create the local server that the app uses to let us know it's ready.
- pingCh, cleanup := utiltest.SetupPingServer(t, claimantCtx)
- defer cleanup()
-
- // Start an instance of the app.
- instanceID := utiltest.LaunchApp(t, claimantCtx, appID)
-
- // Wait until the app pings us that it's ready.
- pingCh.WaitForPingArgs(t)
- utiltest.Resolve(t, ctx, "trapp", 1)
- utiltest.KillApp(t, claimantCtx, appID, instanceID)
-
- // TODO(gauthamt): Test that AccessLists persist across devicemanager restarts
-}
-
-func TestDeviceManagerUpdateAccessList(t *testing.T) {
- ctx, shutdown := initForTest()
- defer shutdown()
-
- // Identity provider to ensure that all processes recognize each
- // others' blessings.
- idp := testutil.NewIDProvider("root")
- ctx = utiltest.CtxWithNewPrincipal(t, ctx, idp, "self")
-
- sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
- defer deferFn()
-
- // Set up mock application and binary repositories.
- envelope, cleanup := utiltest.StartMockRepos(t, ctx)
- defer cleanup()
-
- root, cleanup := servicetest.SetupRootDir(t, "devicemanager")
- defer cleanup()
- if err := impl.SaveCreatorInfo(root); err != nil {
- t.Fatal(err)
- }
-
- selfCtx := ctx
- octx := utiltest.CtxWithNewPrincipal(t, selfCtx, idp, "other")
-
- // Set up the device manager. Since we won't do device manager updates,
- // don't worry about its application envelope and current link.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
- pid := servicetest.ReadPID(t, dmh)
- defer syscall.Kill(pid, syscall.SIGINT)
- defer utiltest.VerifyNoRunningProcesses(t)
-
- // Create an envelope for an app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps")
-
- // On an unclaimed device manager, there will be no AccessLists.
- if _, _, err := device.DeviceClient("claimable").GetPermissions(selfCtx); err == nil {
- t.Fatalf("GetPermissions should have failed but didn't.")
- }
-
- // Claim the devicemanager as "root/self/mydevice"
- utiltest.ClaimDevice(t, selfCtx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
- expectedAccessList := make(access.Permissions)
- for _, tag := range access.AllTypicalTags() {
- expectedAccessList[string(tag)] = access.AccessList{In: []security.BlessingPattern{"root/$", "root/self/$", "root/self/mydevice/$"}}
- }
- var b bytes.Buffer
- if err := expectedAccessList.WriteTo(&b); err != nil {
- t.Fatalf("Failed to save AccessList:%v", err)
- }
- // Note, "version" below refers to the Permissions version, not the device
- // manager version.
- md5hash := md5.Sum(b.Bytes())
- expectedVersion := hex.EncodeToString(md5hash[:])
- deviceStub := device.DeviceClient("dm/device")
- perms, version, err := deviceStub.GetPermissions(selfCtx)
- if err != nil {
- t.Fatal(err)
- }
- if version != expectedVersion {
- t.Fatalf("getAccessList expected:%v(%v), got:%v(%v)", expectedAccessList, expectedVersion, perms, version)
- }
- // Install from octx should fail, since it does not match the AccessList.
- utiltest.InstallAppExpectError(t, octx, verror.ErrNoAccess.ID)
-
- newAccessList := make(access.Permissions)
- for _, tag := range access.AllTypicalTags() {
- newAccessList.Add("root/other", string(tag))
- }
- if err := deviceStub.SetPermissions(selfCtx, newAccessList, "invalid"); err == nil {
- t.Fatalf("SetPermissions should have failed with invalid version")
- }
- if err := deviceStub.SetPermissions(selfCtx, newAccessList, version); err != nil {
- t.Fatal(err)
- }
- // Install should now fail with selfCtx, which no longer matches the
- // AccessLists but succeed with octx, which does.
- utiltest.InstallAppExpectError(t, selfCtx, verror.ErrNoAccess.ID)
- utiltest.InstallApp(t, octx)
-}
-
type simpleRW chan []byte
func (s simpleRW) Write(p []byte) (n int, err error) {
@@ -807,7 +628,7 @@
// This should bring up a functioning device manager. In the end it runs
// Uninstall and verifies that the installation is gone.
func TestDeviceManagerInstallation(t *testing.T) {
- ctx, shutdown := initForTest()
+ ctx, shutdown := utiltest.InitForTest()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -867,7 +688,7 @@
}
func TestDeviceManagerGlobAndDebug(t *testing.T) {
- ctx, shutdown := initForTest()
+ ctx, shutdown := utiltest.InitForTest()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -966,7 +787,7 @@
// TODO(caprita): We need better test coverage for how updating/reverting apps
// affects the package configured for the app.
func TestDeviceManagerPackages(t *testing.T) {
- ctx, shutdown := initForTest()
+ ctx, shutdown := utiltest.InitForTest()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -1106,7 +927,7 @@
// TODO(rjkroege): Verify that associations persist across restarts once
// permanent storage is added.
func TestAccountAssociation(t *testing.T) {
- ctx, shutdown := initForTest()
+ ctx, shutdown := utiltest.InitForTest()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -1192,7 +1013,7 @@
}
func TestAppWithSuidHelper(t *testing.T) {
- ctx, shutdown := initForTest()
+ ctx, shutdown := utiltest.InitForTest()
defer shutdown()
// Identity provider used to ensure that all processes recognize each
@@ -1357,7 +1178,7 @@
}
func TestDownloadSignatureMatch(t *testing.T) {
- ctx, shutdown := initForTest()
+ ctx, shutdown := utiltest.InitForTest()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
diff --git a/services/device/internal/impl/debug_perms_test.go b/services/device/internal/impl/perms/debug_perms_test.go
similarity index 96%
rename from services/device/internal/impl/debug_perms_test.go
rename to services/device/internal/impl/perms/debug_perms_test.go
index 306cebe..9c6e757 100644
--- a/services/device/internal/impl/debug_perms_test.go
+++ b/services/device/internal/impl/perms/debug_perms_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package impl_test
+package perms_test
import (
"io/ioutil"
@@ -226,15 +226,15 @@
[]string{
// STDERR and STDOUT are not handled through the log package so
// are not included here.
- "impl.test.INFO",
- "impl.test.<*>.INFO.<timestamp>",
+ "perms.test.INFO",
+ "perms.test.<*>.INFO.<timestamp>",
},
},
}
- res := utiltest.NewGlobTestRegexHelper(`impl\.test`)
+ res := utiltest.NewGlobTestRegexHelper(`perms\.test`)
// Bob claimed the DM so can access it.
- utiltest.VerifyGlob(t, bobCtx, "impl.test", dmGlobtests, res)
+ utiltest.VerifyGlob(t, bobCtx, "perms.test", dmGlobtests, res)
utiltest.VerifyStatsValues(t, bobCtx, "dm", "__debug", "stats/system/start-time*")
// Without permissions, hackerjoe can't access the device manager.
@@ -247,14 +247,14 @@
// Alice is an adminstrator and so can can access device manager __debug
// values.
- utiltest.VerifyGlob(t, aliceCtx, "impl.test", dmGlobtests, res)
+ utiltest.VerifyGlob(t, aliceCtx, "perms.test", dmGlobtests, res)
utiltest.VerifyStatsValues(t, aliceCtx, "dm", "__debug", "stats/system/start-time*")
// Bob gives debug access to the device manager to hackerjoe
updateAccessList(t, bobCtx, "root/hackerjoe/$", string(access.Debug), "dm", "device")
// hackerjoe can now access the device manager
- utiltest.VerifyGlob(t, hjCtx, "impl.test", dmGlobtests, res)
+ utiltest.VerifyGlob(t, hjCtx, "perms.test", dmGlobtests, res)
utiltest.VerifyStatsValues(t, hjCtx, "dm", "__debug", "stats/system/start-time*")
// Cleanly shut down the device manager.
diff --git a/services/device/internal/impl/perms/doc.go b/services/device/internal/impl/perms/doc.go
new file mode 100644
index 0000000..afd8566
--- /dev/null
+++ b/services/device/internal/impl/perms/doc.go
@@ -0,0 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package perms
+
+// Test code for claiming and permission list code in the device manager.
diff --git a/services/device/internal/impl/perms/impl_test.go b/services/device/internal/impl/perms/impl_test.go
new file mode 100644
index 0000000..37a5102
--- /dev/null
+++ b/services/device/internal/impl/perms/impl_test.go
@@ -0,0 +1,19 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package perms_test
+
+import (
+ "testing"
+
+ "v.io/x/ref/services/device/internal/impl/utiltest"
+)
+
+func TestMain(m *testing.M) {
+ utiltest.TestMainImpl(m)
+}
+
+func TestSuidHelper(t *testing.T) {
+ utiltest.TestSuidHelperImpl(t)
+}
diff --git a/services/device/internal/impl/perms/perms_test.go b/services/device/internal/impl/perms/perms_test.go
new file mode 100644
index 0000000..83bd086
--- /dev/null
+++ b/services/device/internal/impl/perms/perms_test.go
@@ -0,0 +1,191 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package perms_test
+
+import (
+ "bytes"
+ "crypto/md5"
+ "encoding/hex"
+ "syscall"
+ "testing"
+
+ "v.io/v23"
+ "v.io/v23/security"
+ "v.io/v23/security/access"
+ "v.io/v23/services/device"
+ "v.io/v23/verror"
+
+ "v.io/x/ref/services/device/internal/impl"
+ "v.io/x/ref/services/device/internal/impl/utiltest"
+ "v.io/x/ref/services/internal/servicetest"
+ "v.io/x/ref/test/testutil"
+)
+
+// TestDeviceManagerClaim claims a devicemanager and tests AccessList permissions on
+// its methods.
+func TestDeviceManagerClaim(t *testing.T) {
+ ctx, shutdown := utiltest.InitForTest()
+ defer shutdown()
+
+ // root blessing provider so that the principals of all the contexts
+ // recognize each other.
+ idp := testutil.NewIDProvider("root")
+ if err := idp.Bless(v23.GetPrincipal(ctx), "ctx"); err != nil {
+ t.Fatal(err)
+ }
+
+ sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
+ defer deferFn()
+
+ // Set up mock application and binary repositories.
+ envelope, cleanup := utiltest.StartMockRepos(t, ctx)
+ defer cleanup()
+
+ root, cleanup := servicetest.SetupRootDir(t, "devicemanager")
+ defer cleanup()
+ if err := impl.SaveCreatorInfo(root); err != nil {
+ t.Fatal(err)
+ }
+
+ // Create a script wrapping the test target that implements suidhelper.
+ helperPath := utiltest.GenerateSuidHelperScript(t, root)
+
+ // Set up the device manager. Since we won't do device manager updates,
+ // don't worry about its application envelope and current link.
+ pairingToken := "abcxyz"
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link", pairingToken)
+ pid := servicetest.ReadPID(t, dmh)
+ defer syscall.Kill(pid, syscall.SIGINT)
+
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", "trapp")
+
+ claimantCtx := utiltest.CtxWithNewPrincipal(t, ctx, idp, "claimant")
+ octx, err := v23.WithPrincipal(ctx, testutil.NewPrincipal("other"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Unclaimed devices cannot do anything but be claimed.
+ // TODO(ashankar,caprita): The line below will currently fail with
+ // ErrUnclaimedDevice != NotTrusted. NotTrusted can be avoided by
+ // passing options.SkipServerEndpointAuthorization{} to the "Install" RPC.
+ // Refactor the helper function to make this possible.
+ //installAppExpectError(t, octx, impl.ErrUnclaimedDevice.ID)
+
+ // Claim the device with an incorrect pairing token should fail.
+ utiltest.ClaimDeviceExpectError(t, claimantCtx, "claimable", "mydevice", "badtoken", impl.ErrInvalidPairingToken.ID)
+ // But succeed with a valid pairing token
+ utiltest.ClaimDevice(t, claimantCtx, "claimable", "dm", "mydevice", pairingToken)
+
+ // Installation should succeed since claimantRT is now the "owner" of
+ // the devicemanager.
+ appID := utiltest.InstallApp(t, claimantCtx)
+
+ // octx will not install the app now since it doesn't recognize the
+ // device's blessings. The error returned will be ErrNoServers as that
+ // is what the IPC stack does when there are no authorized servers.
+ utiltest.InstallAppExpectError(t, octx, verror.ErrNoServers.ID)
+ // Even if it does recognize the device (by virtue of recognizing the
+ // claimant), the device will not allow it to install.
+ if err := v23.GetPrincipal(octx).AddToRoots(v23.GetPrincipal(claimantCtx).BlessingStore().Default()); err != nil {
+ t.Fatal(err)
+ }
+ utiltest.InstallAppExpectError(t, octx, verror.ErrNoAccess.ID)
+
+ // Create the local server that the app uses to let us know it's ready.
+ pingCh, cleanup := utiltest.SetupPingServer(t, claimantCtx)
+ defer cleanup()
+
+ // Start an instance of the app.
+ instanceID := utiltest.LaunchApp(t, claimantCtx, appID)
+
+ // Wait until the app pings us that it's ready.
+ pingCh.WaitForPingArgs(t)
+ utiltest.Resolve(t, ctx, "trapp", 1)
+ utiltest.KillApp(t, claimantCtx, appID, instanceID)
+
+ // TODO(gauthamt): Test that AccessLists persist across devicemanager restarts
+}
+
+func TestDeviceManagerUpdateAccessList(t *testing.T) {
+ ctx, shutdown := utiltest.InitForTest()
+ defer shutdown()
+
+ // Identity provider to ensure that all processes recognize each
+ // others' blessings.
+ idp := testutil.NewIDProvider("root")
+ ctx = utiltest.CtxWithNewPrincipal(t, ctx, idp, "self")
+
+ sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
+ defer deferFn()
+
+ // Set up mock application and binary repositories.
+ envelope, cleanup := utiltest.StartMockRepos(t, ctx)
+ defer cleanup()
+
+ root, cleanup := servicetest.SetupRootDir(t, "devicemanager")
+ defer cleanup()
+ if err := impl.SaveCreatorInfo(root); err != nil {
+ t.Fatal(err)
+ }
+
+ selfCtx := ctx
+ octx := utiltest.CtxWithNewPrincipal(t, selfCtx, idp, "other")
+
+ // Set up the device manager. Since we won't do device manager updates,
+ // don't worry about its application envelope and current link.
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
+ pid := servicetest.ReadPID(t, dmh)
+ defer syscall.Kill(pid, syscall.SIGINT)
+ defer utiltest.VerifyNoRunningProcesses(t)
+
+ // Create an envelope for an app.
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps")
+
+ // On an unclaimed device manager, there will be no AccessLists.
+ if _, _, err := device.DeviceClient("claimable").GetPermissions(selfCtx); err == nil {
+ t.Fatalf("GetPermissions should have failed but didn't.")
+ }
+
+ // Claim the devicemanager as "root/self/mydevice"
+ utiltest.ClaimDevice(t, selfCtx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
+ expectedAccessList := make(access.Permissions)
+ for _, tag := range access.AllTypicalTags() {
+ expectedAccessList[string(tag)] = access.AccessList{In: []security.BlessingPattern{"root/$", "root/self/$", "root/self/mydevice/$"}}
+ }
+ var b bytes.Buffer
+ if err := expectedAccessList.WriteTo(&b); err != nil {
+ t.Fatalf("Failed to save AccessList:%v", err)
+ }
+ // Note, "version" below refers to the Permissions version, not the device
+ // manager version.
+ md5hash := md5.Sum(b.Bytes())
+ expectedVersion := hex.EncodeToString(md5hash[:])
+ deviceStub := device.DeviceClient("dm/device")
+ perms, version, err := deviceStub.GetPermissions(selfCtx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if version != expectedVersion {
+ t.Fatalf("getAccessList expected:%v(%v), got:%v(%v)", expectedAccessList, expectedVersion, perms, version)
+ }
+ // Install from octx should fail, since it does not match the AccessList.
+ utiltest.InstallAppExpectError(t, octx, verror.ErrNoAccess.ID)
+
+ newAccessList := make(access.Permissions)
+ for _, tag := range access.AllTypicalTags() {
+ newAccessList.Add("root/other", string(tag))
+ }
+ if err := deviceStub.SetPermissions(selfCtx, newAccessList, "invalid"); err == nil {
+ t.Fatalf("SetPermissions should have failed with invalid version")
+ }
+ if err := deviceStub.SetPermissions(selfCtx, newAccessList, version); err != nil {
+ t.Fatal(err)
+ }
+ // Install should now fail with selfCtx, which no longer matches the
+ // AccessLists but succeed with octx, which does.
+ utiltest.InstallAppExpectError(t, selfCtx, verror.ErrNoAccess.ID)
+ utiltest.InstallApp(t, octx)
+}
diff --git a/services/device/internal/impl/reaping/impl_test.go b/services/device/internal/impl/reaping/impl_test.go
index abc7f7a..66d1c4e 100644
--- a/services/device/internal/impl/reaping/impl_test.go
+++ b/services/device/internal/impl/reaping/impl_test.go
@@ -14,8 +14,6 @@
utiltest.TestMainImpl(m)
}
-// TestSuidHelper is testing boilerplate for suidhelper that does not
-// create a runtime because the suidhelper is not a Vanadium application.
func TestSuidHelper(t *testing.T) {
utiltest.TestSuidHelperImpl(t)
}
diff --git a/services/device/internal/impl/utiltest/helpers.go b/services/device/internal/impl/utiltest/helpers.go
index 5b753c0..4e82508 100644
--- a/services/device/internal/impl/utiltest/helpers.go
+++ b/services/device/internal/impl/utiltest/helpers.go
@@ -33,6 +33,7 @@
"v.io/v23/services/stats"
"v.io/v23/verror"
+ "v.io/x/ref/envvar"
_ "v.io/x/ref/profiles/roaming"
"v.io/x/ref/services/device/internal/impl"
"v.io/x/ref/services/internal/servicetest"
@@ -665,3 +666,13 @@
}
return u.Username
}
+
+func InitForTest() (*context.T, v23.Shutdown) {
+ roots, _ := envvar.NamespaceRoots()
+ for key, _ := range roots {
+ os.Unsetenv(key)
+ }
+ ctx, shutdown := test.InitForTest()
+ v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
+ return ctx, shutdown
+}
diff --git a/services/mounttable/mounttablelib/mounttable.go b/services/mounttable/mounttablelib/mounttable.go
index 7ba7f4e..3b87098 100644
--- a/services/mounttable/mounttablelib/mounttable.go
+++ b/services/mounttable/mounttablelib/mounttable.go
@@ -534,7 +534,7 @@
// removeUselessRecursive removes any useless nodes on the tail of the path.
func (mt *mountTable) removeUselessRecursive(elems []string) {
for i := len(elems); i > 0; i-- {
- n, nelems, _ := mt.traverse(nil, nil, elems[:i-1], false)
+ n, nelems, _ := mt.traverse(nil, nil, elems[:i], false)
if n == nil {
break
}
diff --git a/services/mounttable/mounttablelib/mounttable_test.go b/services/mounttable/mounttablelib/mounttable_test.go
index 5704ef1..5f0da6e 100644
--- a/services/mounttable/mounttablelib/mounttable_test.go
+++ b/services/mounttable/mounttablelib/mounttable_test.go
@@ -506,6 +506,7 @@
// After the unmount nothing should be left
doUnmount(t, rootCtx, estr, "one/bright/day", "", true)
+ checkMatch(t, nil, doGlob(t, rootCtx, estr, "", "one"))
checkMatch(t, nil, doGlob(t, rootCtx, estr, "", "*/..."))
// Set up a mount, then set the AccessList.