blob: e4f7c200321fa9482d0c6685617dd84360f7efff [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Jiri Simsa5293dcb2014-05-10 09:56:38 -07005package rt_test
6
7import (
8 "fmt"
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -07009 "io"
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -080010 "io/ioutil"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070011 "os"
12 "regexp"
13 "testing"
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -070014 "time"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070015
Jiri Simsa337af232015-02-27 14:36:46 -080016 "v.io/x/lib/vlog"
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -070017
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070018 "v.io/v23"
Matt Rosencrantz250558f2015-03-17 11:37:31 -070019 "v.io/v23/context"
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070020 "v.io/v23/security"
21
Asim Shankar59b8b692015-03-30 01:23:36 -070022 "v.io/x/ref/envvar"
Jiri Simsaffceefa2015-02-28 11:03:34 -080023 vsecurity "v.io/x/ref/security"
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070024 "v.io/x/ref/test"
25 "v.io/x/ref/test/expect"
26 "v.io/x/ref/test/modules"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070027)
28
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080029//go:generate v23 test generate
Jiri Simsa5293dcb2014-05-10 09:56:38 -070030
31func TestInit(t *testing.T) {
Asim Shankar59b8b692015-03-30 01:23:36 -070032 envvar.ClearCredentials()
Jiri Simsa6ac95222015-02-23 16:11:49 -080033 ctx, shutdown := v23.Init()
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -080034 defer shutdown()
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -080035
Matt Rosencrantz97d67a92015-01-27 21:03:12 -080036 l := vlog.Log
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -080037 fmt.Println(l)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070038 args := fmt.Sprintf("%s", l)
Suharsh Sivakumar8646ba62015-03-18 15:22:28 -070039 expected := regexp.MustCompile("name=vanadium logdirs=\\[/tmp\\] logtostderr=true|false alsologtostderr=false|true max_stack_buf_size=4292608 v=[0-9] stderrthreshold=2 vmodule= log_backtrace_at=:0")
Jiri Simsa5293dcb2014-05-10 09:56:38 -070040 if !expected.MatchString(args) {
Cosmos Nicolaoud83b90b2014-11-30 15:01:31 -080041 t.Errorf("unexpected default args: %s", args)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070042 }
Jiri Simsa6ac95222015-02-23 16:11:49 -080043 p := v23.GetPrincipal(ctx)
Asim Shankar220a0152014-10-30 21:21:09 -070044 if p == nil {
45 t.Fatalf("A new principal should have been created")
46 }
47 if p.BlessingStore() == nil {
48 t.Fatalf("The principal must have a BlessingStore")
49 }
Asim Shankar2bf7b1e2015-02-27 00:45:12 -080050 if p.BlessingStore().Default().IsZero() {
51 t.Errorf("Principal().BlessingStore().Default() should not be the zero value")
Asim Shankar220a0152014-10-30 21:21:09 -070052 }
Asim Shankar2bf7b1e2015-02-27 00:45:12 -080053 if p.BlessingStore().ForPeer().IsZero() {
54 t.Errorf("Principal().BlessingStore().ForPeer() should not be the zero value")
Jiri Simsa5293dcb2014-05-10 09:56:38 -070055 }
56}
57
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -070058func child(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
Cosmos Nicolaoua18a1eb2015-03-12 13:15:01 -070059 _, shutdown := test.InitForTest()
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -080060 defer shutdown()
Matt Rosencrantz0610a232014-12-04 10:26:39 -080061
Matt Rosencrantz97d67a92015-01-27 21:03:12 -080062 logger := vlog.Log
Matt Rosencrantz97eb5402015-01-08 14:51:52 -080063 vlog.Infof("%s\n", logger)
64 fmt.Fprintf(stdout, "%s\n", logger)
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -070065 modules.WaitForEOF(stdin)
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -070066 fmt.Fprintf(stdout, "done\n")
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -070067 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -070068}
69
70func TestInitArgs(t *testing.T) {
Cosmos Nicolaou9e909842015-03-17 11:58:59 -070071 sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -080072 if err != nil {
73 t.Fatalf("unexpected error: %s", err)
74 }
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -070075 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaoud83b90b2014-11-30 15:01:31 -080076 h, err := sh.Start("child", nil, "--logtostderr=true", "--vmodule=*=3", "--", "foobar")
Jiri Simsa5293dcb2014-05-10 09:56:38 -070077 if err != nil {
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -070078 t.Fatalf("unexpected error: %s", err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070079 }
Suharsh Sivakumar8646ba62015-03-18 15:22:28 -070080 h.Expect(fmt.Sprintf("name=vanadium "+
Jiri Simsa5293dcb2014-05-10 09:56:38 -070081 "logdirs=[%s] "+
82 "logtostderr=true "+
83 "alsologtostderr=true "+
84 "max_stack_buf_size=4292608 "+
Cosmos Nicolaoud83b90b2014-11-30 15:01:31 -080085 "v=0 "+
Jiri Simsa5293dcb2014-05-10 09:56:38 -070086 "stderrthreshold=2 "+
Cosmos Nicolaoud83b90b2014-11-30 15:01:31 -080087 "vmodule=*=3 "+
Jiri Simsa5293dcb2014-05-10 09:56:38 -070088 "log_backtrace_at=:0",
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -070089 os.TempDir()))
90 h.CloseStdin()
Cosmos Nicolaou9e909842015-03-17 11:58:59 -070091 h.Expect("done")
92 h.ExpectEOF()
Cosmos Nicolaou59496fe2014-10-14 11:21:05 -070093 h.Shutdown(os.Stderr, os.Stderr)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070094}
Ankur7c890592014-10-02 11:36:28 -070095
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -080096func validatePrincipal(p security.Principal) error {
97 if p == nil {
98 return fmt.Errorf("nil principal")
Matt Rosencrantz0610a232014-12-04 10:26:39 -080099 }
Ankurd8646812015-03-12 10:48:41 -0700100 call := security.NewCall(&security.CallParams{LocalPrincipal: p, RemoteBlessings: p.BlessingStore().Default()})
Matt Rosencrantz250558f2015-03-17 11:37:31 -0700101 ctx, cancel := context.RootContext()
102 defer cancel()
103 ctx = security.SetCall(ctx, call)
Ankur9e75e7f2015-03-18 18:48:41 -0700104 blessings, rejected := security.RemoteBlessingNames(ctx)
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800105 if n := len(blessings); n != 1 {
106 return fmt.Errorf("rt.Principal().BlessingStore().Default() return blessings:%v (rejected:%v), want exactly one recognized blessing", blessings, rejected)
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -0800107 }
108 return nil
109}
110
111func defaultBlessing(p security.Principal) string {
Ankurd8646812015-03-12 10:48:41 -0700112 call := security.NewCall(&security.CallParams{LocalPrincipal: p, RemoteBlessings: p.BlessingStore().Default()})
Matt Rosencrantz250558f2015-03-17 11:37:31 -0700113 ctx, cancel := context.RootContext()
114 defer cancel()
115 ctx = security.SetCall(ctx, call)
Ankur9e75e7f2015-03-18 18:48:41 -0700116 b, _ := security.RemoteBlessingNames(ctx)
Ryan Brown41093a92015-02-10 10:59:14 -0800117 return b[0]
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -0800118}
119
120func tmpDir(t *testing.T) string {
121 dir, err := ioutil.TempDir("", "rt_test_dir")
122 if err != nil {
123 t.Fatalf("unexpected error: %s", err)
124 }
125 return dir
126}
127
128func principal(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
Cosmos Nicolaoua18a1eb2015-03-12 13:15:01 -0700129 ctx, shutdown := test.InitForTest()
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -0800130 defer shutdown()
Matt Rosencrantz0610a232014-12-04 10:26:39 -0800131
Jiri Simsa6ac95222015-02-23 16:11:49 -0800132 p := v23.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800133 if err := validatePrincipal(p); err != nil {
Ankur9f957942014-11-24 16:34:18 -0800134 return err
135 }
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800136 fmt.Fprintf(stdout, "DEFAULT_BLESSING=%s\n", defaultBlessing(p))
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700137 return nil
138}
139
140// Runner runs a principal as a subprocess and reports back with its
141// own security info and it's childs.
142func runner(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
Cosmos Nicolaoua18a1eb2015-03-12 13:15:01 -0700143 ctx, shutdown := test.InitForTest()
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -0800144 defer shutdown()
145
Jiri Simsa6ac95222015-02-23 16:11:49 -0800146 p := v23.GetPrincipal(ctx)
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800147 if err := validatePrincipal(p); err != nil {
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700148 return err
Ankur7c890592014-10-02 11:36:28 -0700149 }
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800150 fmt.Fprintf(stdout, "RUNNER_DEFAULT_BLESSING=%v\n", defaultBlessing(p))
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700151 sh, err := modules.NewShell(ctx, p, false, nil)
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800152 if err != nil {
153 return err
154 }
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -0800155 if _, err := sh.Start("principal", nil, args...); err != nil {
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700156 return err
157 }
Suharsh Sivakumard02ac222014-11-18 14:02:15 -0800158 // Cleanup copies the output of sh to these Writers.
159 sh.Cleanup(stdout, stderr)
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700160 return nil
161}
162
Suharsh Sivakumar4d36f812015-01-15 13:58:00 -0800163func createCredentialsInDir(t *testing.T, dir string, blessing string) {
164 principal, err := vsecurity.CreatePersistentPrincipal(dir, nil)
165 if err != nil {
166 t.Fatalf("unexpected error: %s", err)
167 }
168 if err := vsecurity.InitDefaultBlessings(principal, blessing); err != nil {
169 t.Fatalf("unexpected error: %s", err)
170 }
171}
172
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700173func TestPrincipalInheritance(t *testing.T) {
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700174 sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800175 if err != nil {
176 t.Fatalf("unexpected error: %s", err)
177 }
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700178 defer func() {
179 sh.Cleanup(os.Stdout, os.Stderr)
180 }()
181
Ankur9f957942014-11-24 16:34:18 -0800182 // Test that the child inherits from the parent's credentials correctly.
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700183 // The running test process may or may not have a credentials directory set
184 // up so we have to use a 'runner' process to ensure the correct setup.
185 cdir := tmpDir(t)
186 defer os.RemoveAll(cdir)
187
Ankur9f957942014-11-24 16:34:18 -0800188 createCredentialsInDir(t, cdir, "test")
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700189
190 // directory supplied by the environment.
Asim Shankar59b8b692015-03-30 01:23:36 -0700191 credEnv := []string{envvar.Credentials + "=" + cdir}
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700192
193 h, err := sh.Start("runner", credEnv)
194 if err != nil {
195 t.Fatalf("unexpected error: %s", err)
196 }
Ankur9f957942014-11-24 16:34:18 -0800197
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700198 runnerBlessing := h.ExpectVar("RUNNER_DEFAULT_BLESSING")
199 principalBlessing := h.ExpectVar("DEFAULT_BLESSING")
200 if err := h.Error(); err != nil {
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700201 t.Fatalf("failed to read input from children: %s", err)
202 }
203 h.Shutdown(os.Stdout, os.Stderr)
Ankur9f957942014-11-24 16:34:18 -0800204
205 wantRunnerBlessing := "test"
206 wantPrincipalBlessing := "test/child"
207 if runnerBlessing != wantRunnerBlessing || principalBlessing != wantPrincipalBlessing {
208 t.Fatalf("unexpected default blessing: got runner %s, principal %s, want runner %s, principal %s", runnerBlessing, principalBlessing, wantRunnerBlessing, wantPrincipalBlessing)
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700209 }
210
211}
212
213func TestPrincipalInit(t *testing.T) {
Ankur9f957942014-11-24 16:34:18 -0800214 // Collect the process' public key and error status
215 collect := func(sh *modules.Shell, env []string, args ...string) string {
216 h, err := sh.Start("principal", env, args...)
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700217 if err != nil {
218 t.Fatalf("unexpected error: %s", err)
219 }
220 s := expect.NewSession(t, h.Stdout(), time.Minute)
221 s.SetVerbosity(testing.Verbose())
Ankur9f957942014-11-24 16:34:18 -0800222 return s.ExpectVar("DEFAULT_BLESSING")
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700223 }
224
225 // A credentials directory may, or may, not have been already specified.
226 // Either way, we want to use our own, so we set it aside and use our own.
Asim Shankar59b8b692015-03-30 01:23:36 -0700227 origCredentialsDir := os.Getenv(envvar.Credentials)
228 defer os.Setenv(envvar.Credentials, origCredentialsDir)
229 if err := os.Setenv(envvar.Credentials, ""); err != nil {
Ankur7c890592014-10-02 11:36:28 -0700230 t.Fatal(err)
231 }
232
Ankura4b7c4a2015-02-02 11:41:24 -0800233 // We create two shells -- one initializing the principal for a child process
234 // via a credentials directory and the other via an agent.
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700235 sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800236 if err != nil {
237 t.Fatalf("unexpected error: %s", err)
238 }
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700239 defer sh.Cleanup(os.Stderr, os.Stderr)
240
Cosmos Nicolaoua18a1eb2015-03-12 13:15:01 -0700241 ctx, shutdown := test.InitForTest()
Ankura4b7c4a2015-02-02 11:41:24 -0800242 defer shutdown()
243
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700244 agentSh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx), testing.Verbose(), t)
Ankura4b7c4a2015-02-02 11:41:24 -0800245 if err != nil {
246 t.Fatalf("unexpected error: %s", err)
247 }
248 defer agentSh.Cleanup(os.Stderr, os.Stderr)
249
Asim Shankar59b8b692015-03-30 01:23:36 -0700250 // Test that with envvar.Credentials unset the runtime's Principal
Ankura4b7c4a2015-02-02 11:41:24 -0800251 // is correctly initialized for both shells.
252 if len(collect(sh, nil)) == 0 {
253 t.Fatalf("Without agent: child returned an empty default blessings set")
254 }
Cosmos Nicolaoua18a1eb2015-03-12 13:15:01 -0700255 if got, want := collect(agentSh, nil), test.TestBlessing+security.ChainSeparator+"child"; got != want {
Ankura4b7c4a2015-02-02 11:41:24 -0800256 t.Fatalf("With agent: got %q, want %q", got, want)
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700257 }
258
Asim Shankar59b8b692015-03-30 01:23:36 -0700259 // Test that credentials specified via the envvar.Credentials
260 // environment variable take precedence over an agent.
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700261 cdir1 := tmpDir(t)
262 defer os.RemoveAll(cdir1)
Ankur9f957942014-11-24 16:34:18 -0800263 createCredentialsInDir(t, cdir1, "test_env")
Asim Shankar59b8b692015-03-30 01:23:36 -0700264 credEnv := []string{envvar.Credentials + "=" + cdir1}
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700265
Ankura4b7c4a2015-02-02 11:41:24 -0800266 if got, want := collect(sh, credEnv), "test_env"; got != want {
267 t.Errorf("Without agent: got default blessings: %q, want %q", got, want)
268 }
269 if got, want := collect(agentSh, credEnv), "test_env"; got != want {
270 t.Errorf("With agent: got default blessings: %q, want %q", got, want)
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700271 }
272
Ankura4b7c4a2015-02-02 11:41:24 -0800273 // Test that credentials specified via the command line take precedence over the
Asim Shankar59b8b692015-03-30 01:23:36 -0700274 // envvar.Credentials environment variable and also the agent.
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700275 cdir2 := tmpDir(t)
276 defer os.RemoveAll(cdir2)
Ankur9f957942014-11-24 16:34:18 -0800277 createCredentialsInDir(t, cdir2, "test_cmd")
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700278
Ankura4b7c4a2015-02-02 11:41:24 -0800279 if got, want := collect(sh, credEnv, "--veyron.credentials="+cdir2), "test_cmd"; got != want {
280 t.Errorf("Without agent: got %q, want %q", got, want)
281 }
282 if got, want := collect(agentSh, credEnv, "--veyron.credentials="+cdir2), "test_cmd"; got != want {
283 t.Errorf("With agent: got %q, want %q", got, want)
Ankur7c890592014-10-02 11:36:28 -0700284 }
285}