blob: db9376f55ff2895ba8d474e9adcc58cf56f2266a [file] [log] [blame]
// 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.
//go:generate jiri test generate
package main_test
import (
"bytes"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"
"v.io/v23/security"
"v.io/x/ref"
"v.io/x/ref/test/modules"
"v.io/x/ref/test/v23tests"
)
func V23TestClusterAgentD(t *v23tests.T) {
workdir, err := ioutil.TempDir("", "cluster-agentd-test-")
if err != nil {
t.Fatalf("ioutil.TempDir failed: %v", err)
}
defer os.RemoveAll(workdir)
agentCreds, err := t.Shell().NewChildCredentials("agent")
if err != nil {
t.Fatalf("Failed to create agent credentials: %v", err)
}
aliceCreds, err := t.Shell().NewChildCredentials("alice")
if err != nil {
t.Fatalf("Failed to create alice credentials: %v", err)
}
// Create a blessing (root/alice/prod) that alice will use to talk to
// the cluster agent.
alicePrincipal := aliceCreds.Principal()
if prodBlessing, err := alicePrincipal.Bless(alicePrincipal.PublicKey(), alicePrincipal.BlessingStore().Default(), "prod", security.UnconstrainedUse()); err != nil {
t.Fatalf("Failed to create alice/prod blessing: %v", err)
} else if _, err := alicePrincipal.BlessingStore().Set(prodBlessing, security.BlessingPattern("root/agent")); err != nil {
t.Fatalf("Failed to set alice/prod for root/agent: %v", err)
}
var (
agentBin = t.BuildV23Pkg("v.io/x/ref/services/cluster/cluster_agentd")
clientBin = t.BuildV23Pkg("v.io/x/ref/services/cluster/cluster_agent")
podAgentBin = t.BuildV23Pkg("v.io/x/ref/services/agent/pod_agentd")
principalBin = t.BuildV23Pkg("v.io/x/ref/cmd/principal")
)
// Start the cluster agent.
addr := agentBin.WithStartOpts(agentBin.StartOpts().WithCustomCredentials(agentCreds)).Start(
"--v23.tcp.address=127.0.0.1:0",
"--v23.permissions.literal={\"Admin\":{\"In\":[\"root/alice/prod\"]}}",
"--root-dir="+workdir,
).ExpectVar("NAME")
// Create a new secret.
secret := strings.TrimSpace(clientBin.WithStartOpts(clientBin.StartOpts().WithCustomCredentials(aliceCreds)).Start(
"--agent="+addr,
"new",
"foo",
).Output())
secretPath := filepath.Join(workdir, "secret")
if err := ioutil.WriteFile(secretPath, []byte(secret), 0600); err != nil {
t.Fatalf("Unexpected WriteFile error: %v", err)
}
// Start the pod agent.
sockPath := filepath.Join(workdir, "agent.sock")
podAgentBin.Start(
"--agent="+addr,
"--socket-path="+sockPath,
"--secret-key-file="+secretPath,
"--root-blessings="+rootBlessings(t, agentCreds),
)
// Wait for the socket to show up.
// TODO(rthellend): This should be fixed in agentlib.
for c := 0; ; c++ {
if _, err := os.Stat(sockPath); err == nil {
break
}
if c < 10 {
time.Sleep(time.Second)
continue
}
t.Fatalf("%q still doesn't exist after 10 sec", sockPath)
}
principalBin = principalBin.WithEnv(ref.EnvAgentPath + "=" + sockPath)
opts := principalBin.StartOpts()
// With ExecProtocol true, the v23_test library overrides the principal
// in such a way that EnvAgentPath is not used.
opts.ExecProtocol = false
principalBin = principalBin.WithStartOpts(opts)
// The principal served by the pod agent should have a blessing name
// that starts with root/alice/foo/.
if got, expected := principalBin.Start("dump", "-s").Output(), "root/alice/foo/"; !strings.HasPrefix(got, expected) {
t.Errorf("Unexpected output. Got %q, expected %q", got, expected)
}
// Bob should not be able to call NewSecret.
bobCreds, err := t.Shell().NewChildCredentials("bob")
if err != nil {
t.Fatalf("Failed to create bob credentials: %v", err)
}
clientBin = clientBin.WithStartOpts(clientBin.StartOpts().WithCustomCredentials(bobCreds))
if err := clientBin.Start("--agent="+addr, "new", "foo").Wait(nil, nil); err == nil {
t.Error("Unexpected success. Bob should not be able to call NewSecret")
}
// After Alice calls ForgetSecret, SeekBlessings no longer works.
clientBin = clientBin.WithStartOpts(clientBin.StartOpts().WithCustomCredentials(aliceCreds))
if err := clientBin.Start("--agent="+addr, "forget", secret).Wait(nil, nil); err != nil {
t.Errorf("Unexpected forget error: %v", err)
}
if err := clientBin.Start("--agent="+addr, "seekblessings", secret).Wait(nil, nil); err == nil {
t.Error("Unexpected success. This secret should not exist anymore.")
}
// The pod agent should be unaffected.
if got, expected := principalBin.Start("dump", "-s").Output(), "root/alice/foo/"; !strings.HasPrefix(got, expected) {
t.Errorf("Unexpected output. Got %q, expected %q", got, expected)
}
}
func rootBlessings(t *v23tests.T, creds *modules.CustomCredentials) string {
principalBin := t.BuildV23Pkg("v.io/x/ref/cmd/principal")
opts := principalBin.StartOpts().WithCustomCredentials(creds)
principalBin = principalBin.WithStartOpts(opts)
blessings := strings.TrimSpace(principalBin.Start("get", "default").Output())
opts.Stdin = bytes.NewBufferString(blessings)
opts.ExecProtocol = false
opts.Credentials = nil
principalBin = principalBin.WithStartOpts(opts)
out := strings.TrimSpace(principalBin.Start("dumproots", "-").Output())
return strings.Replace(out, "\n", ",", -1)
}