blob: a6593f6bddf2d45814e77ac9422b14871b339f92 [file] [log] [blame]
Ryan Brownfed691e2014-09-15 13:09:40 -07001package agent_test
2
3import (
4 "crypto/ecdsa"
5 "crypto/elliptic"
6 "crypto/rand"
Ryan Brownfed691e2014-09-15 13:09:40 -07007 "reflect"
8 "testing"
Cosmos Nicolaouf889c732014-10-16 20:46:54 -07009
Ankurf416ac52015-01-29 13:58:24 -080010 "v.io/core/veyron/lib/testutil"
Jiri Simsa764efb72014-12-25 20:57:03 -080011 _ "v.io/core/veyron/profiles"
12 "v.io/core/veyron/security/agent"
13 "v.io/core/veyron/security/agent/server"
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070014
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -080015 "v.io/core/veyron2"
Matt Rosencrantz6edab562015-01-12 11:07:55 -080016 "v.io/core/veyron2/context"
Jiri Simsa764efb72014-12-25 20:57:03 -080017 "v.io/core/veyron2/security"
18 "v.io/core/veyron2/verror2"
Ryan Brownfed691e2014-09-15 13:09:40 -070019)
20
Matt Rosencrantz6edab562015-01-12 11:07:55 -080021func setupAgent(t *testing.T, ctx *context.T, p security.Principal) security.Principal {
22 sock, err := server.RunAnonymousAgent(ctx, p)
Ryan Brownfed691e2014-09-15 13:09:40 -070023 if err != nil {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070024 t.Fatal(err)
Ryan Brownfed691e2014-09-15 13:09:40 -070025 }
26 defer sock.Close()
Matt Rosencrantz6edab562015-01-12 11:07:55 -080027
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070028 var agentP security.Principal
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -080029 if agentP, err = agent.NewAgentPrincipal(ctx, int(sock.Fd()), veyron2.GetClient(ctx)); err != nil {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070030 t.Fatal(err)
31 }
32 return agentP
33}
34
35type testInfo struct {
36 Method string
37 Args V
38 Result interface{} // Result returned by the Method call.
Todd Wang34ed4c62014-11-26 15:15:52 -080039 Error verror2.E // If Error is not nil will be compared to the last result.
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070040}
41
Jiri Simsa764efb72014-12-25 20:57:03 -080042const pkgPath = "v.io/core/veyron/security/agent/"
Todd Wang34ed4c62014-11-26 15:15:52 -080043
44var (
45 addToRootsErr = verror2.Register(pkgPath+".addToRoots", verror2.NoRetry, "")
46 storeSetDefaultErr = verror2.Register(pkgPath+".storeSetDefault", verror2.NoRetry, "")
47 rootsAddErr = verror2.Register(pkgPath+".rootsAdd", verror2.NoRetry, "")
48 rootsRecognizedErr = verror2.Register(pkgPath+".rootsRecognized", verror2.NoRetry, "")
49)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070050
51func TestAgent(t *testing.T) {
Ankurf416ac52015-01-29 13:58:24 -080052 ctx, shutdown := testutil.InitForTest()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -080053 defer shutdown()
Matt Rosencrantz0610a232014-12-04 10:26:39 -080054
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070055 var (
56 thirdPartyCaveat, discharge = newThirdPartyCaveatAndDischarge(t)
57 mockP = newMockPrincipal()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -080058 agent = setupAgent(t, ctx, mockP)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070059 )
60 tests := []testInfo{
61 {"BlessSelf", V{"self"}, newBlessing(t, "blessing"), nil},
62 {"Bless", V{newPrincipal(t).PublicKey(), newBlessing(t, "root"), "extension", security.UnconstrainedUse()}, newBlessing(t, "root/extension"), nil},
Robin Thellend3709c162014-12-10 15:37:59 -080063 {"Sign", V{make([]byte, 10)}, security.Signature{Purpose: []byte{}, R: []byte{1}, S: []byte{1}}, nil},
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070064 {"MintDischarge", V{thirdPartyCaveat, security.UnconstrainedUse()}, discharge, nil},
65 {"PublicKey", V{}, mockP.PublicKey(), nil},
gauthamtf8263932014-12-16 10:59:09 -080066 {"BlessingsByName", V{security.BlessingPattern("self")}, []security.Blessings{newBlessing(t, "blessing")}, nil},
gauthamt8dc9a182015-01-08 18:03:18 -080067 {"BlessingsInfo", V{newBlessing(t, "blessing")}, map[string][]security.Caveat{"blessing": nil}, nil},
Todd Wang34ed4c62014-11-26 15:15:52 -080068 {"AddToRoots", V{newBlessing(t, "blessing")}, nil, verror2.Make(addToRootsErr, nil)},
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070069 }
70 for _, test := range tests {
71 mockP.NextResult = test.Result
72 mockP.NextError = test.Error
73 runTest(t, agent, test)
74 }
75
76 store := agent.BlessingStore()
77 storeTests := []testInfo{
78 {"Set", V{newBlessing(t, "blessing"), security.BlessingPattern("test")}, newBlessing(t, "root/extension"), nil},
79 {"ForPeer", V{"test", "oink"}, newBlessing(t, "for/peer"), nil},
Todd Wang34ed4c62014-11-26 15:15:52 -080080 {"SetDefault", V{newBlessing(t, "blessing")}, nil, verror2.Make(storeSetDefaultErr, nil)},
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070081 {"Default", V{}, newBlessing(t, "root/extension"), nil},
82 {"PublicKey", V{}, mockP.PublicKey(), nil},
gauthamtf8263932014-12-16 10:59:09 -080083 {"PeerBlessings", V{}, map[security.BlessingPattern]security.Blessings{"test": newBlessing(t, "root/extension")}, nil},
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070084 {"DebugString", V{}, "StoreString", nil},
85 }
86 for _, test := range storeTests {
87 mockP.MockStore.NextResult = test.Result
88 mockP.MockStore.NextError = test.Error
89 runTest(t, store, test)
90 }
91
92 roots := agent.Roots()
93 rootTests := []testInfo{
Todd Wang34ed4c62014-11-26 15:15:52 -080094 {"Add", V{newPrincipal(t).PublicKey(), security.BlessingPattern("test")}, nil, verror2.Make(rootsAddErr, nil)},
95 {"Recognized", V{newPrincipal(t).PublicKey(), "blessing"}, nil, verror2.Make(rootsRecognizedErr, nil)},
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070096 {"DebugString", V{}, "RootsString", nil},
97 }
98 for _, test := range rootTests {
99 mockP.MockRoots.NextResult = test.Result
100 mockP.MockRoots.NextError = test.Error
101 runTest(t, roots, test)
Ryan Brownfed691e2014-09-15 13:09:40 -0700102 }
103}
104
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700105func runTest(t *testing.T, receiver interface{}, test testInfo) {
106 results, err := call(receiver, test.Method, test.Args)
Ryan Brownfed691e2014-09-15 13:09:40 -0700107 if err != nil {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700108 t.Errorf("failed to invoke p.%v(%#v): %v", test.Method, test.Args, err)
109 return
Ryan Brownfed691e2014-09-15 13:09:40 -0700110 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700111 // We only set the error value when error is the only output to ensure the real function gets called.
112 if test.Error != nil {
Todd Wang34ed4c62014-11-26 15:15:52 -0800113 if got := results[len(results)-1]; got == nil || !verror2.Is(got.(error), test.Error.ErrorID()) {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700114 t.Errorf("p.%v(%#v) returned an incorrect error: %v, expected %v", test.Method, test.Args, got, test.Error)
115 }
116 if len(results) == 1 {
117 return
118 }
119 }
120 if got := results[0]; !reflect.DeepEqual(got, test.Result) {
Todd Wang34ed4c62014-11-26 15:15:52 -0800121 t.Errorf("p.%v(%#v) returned %#v want %#v", test.Method, test.Args, got, test.Result)
Ryan Brownfed691e2014-09-15 13:09:40 -0700122 }
123}
124
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700125func newMockPrincipal() *mockPrincipal {
Ryan Brownfed691e2014-09-15 13:09:40 -0700126 key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
127 if err != nil {
128 panic(err)
129 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700130 pkey := security.NewECDSAPublicKey(&key.PublicKey)
131 return &mockPrincipal{
132 Key: pkey,
133 MockStore: &mockBlessingStore{Key: pkey},
134 MockRoots: &mockBlessingRoots{},
135 }
Ryan Brownfed691e2014-09-15 13:09:40 -0700136}
137
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700138type mockPrincipal struct {
139 NextError error
140 NextResult interface{}
141 Key security.PublicKey
142 MockStore *mockBlessingStore
143 MockRoots *mockBlessingRoots
Ryan Brownfed691e2014-09-15 13:09:40 -0700144}
145
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700146func (p *mockPrincipal) reset() {
147 p.NextError = nil
148 p.NextResult = nil
149}
150
151func (p *mockPrincipal) Bless(security.PublicKey, security.Blessings, string, security.Caveat, ...security.Caveat) (security.Blessings, error) {
152 defer p.reset()
153 b, _ := p.NextResult.(security.Blessings)
154 return b, p.NextError
155}
156
157func (p *mockPrincipal) BlessSelf(string, ...security.Caveat) (security.Blessings, error) {
158 defer p.reset()
159 b, _ := p.NextResult.(security.Blessings)
160 return b, p.NextError
161}
162
163func (p *mockPrincipal) Sign([]byte) (sig security.Signature, err error) {
164 defer p.reset()
165 sig, _ = p.NextResult.(security.Signature)
166 err = p.NextError
167 return
168}
169
170func (p *mockPrincipal) MintDischarge(security.ThirdPartyCaveat, security.Caveat, ...security.Caveat) (security.Discharge, error) {
171 defer p.reset()
172 d, _ := p.NextResult.(security.Discharge)
173 return d, p.NextError
174}
175
gauthamtf8263932014-12-16 10:59:09 -0800176func (p *mockPrincipal) BlessingsByName(name security.BlessingPattern) []security.Blessings {
177 defer p.reset()
178 b, _ := p.NextResult.([]security.Blessings)
179 return b
180}
181
gauthamt8dc9a182015-01-08 18:03:18 -0800182func (p *mockPrincipal) BlessingsInfo(blessings security.Blessings) map[string][]security.Caveat {
gauthamtf8263932014-12-16 10:59:09 -0800183 defer p.reset()
gauthamt8dc9a182015-01-08 18:03:18 -0800184 s, _ := p.NextResult.(map[string][]security.Caveat)
gauthamtf8263932014-12-16 10:59:09 -0800185 return s
186}
187
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700188func (p *mockPrincipal) PublicKey() security.PublicKey { return p.Key }
189func (p *mockPrincipal) Roots() security.BlessingRoots { return p.MockRoots }
190func (p *mockPrincipal) BlessingStore() security.BlessingStore { return p.MockStore }
191func (p *mockPrincipal) AddToRoots(b security.Blessings) error {
192 defer p.reset()
193 return p.NextError
194}
195
196type mockBlessingStore struct {
197 NextError error
198 NextResult interface{}
199 Key security.PublicKey
200}
201
202func (s *mockBlessingStore) reset() {
203 s.NextError = nil
204 s.NextResult = nil
205}
206
207func (s *mockBlessingStore) Set(security.Blessings, security.BlessingPattern) (security.Blessings, error) {
208 defer s.reset()
209 b, _ := s.NextResult.(security.Blessings)
210 return b, s.NextError
211}
212
213func (s *mockBlessingStore) ForPeer(...string) security.Blessings {
214 defer s.reset()
215 b, _ := s.NextResult.(security.Blessings)
216 return b
217}
218
219func (s *mockBlessingStore) SetDefault(security.Blessings) error {
220 defer s.reset()
221 return s.NextError
222}
223
224func (s *mockBlessingStore) Default() security.Blessings {
225 defer s.reset()
226 b, _ := s.NextResult.(security.Blessings)
227 return b
228}
229
230func (s *mockBlessingStore) PublicKey() security.PublicKey { return s.Key }
231
gauthamtf8263932014-12-16 10:59:09 -0800232func (s *mockBlessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
233 defer s.reset()
234 m, _ := s.NextResult.(map[security.BlessingPattern]security.Blessings)
235 return m
236}
237
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700238func (s *mockBlessingStore) DebugString() string {
239 defer s.reset()
240 return s.NextResult.(string)
241}
242
243type mockBlessingRoots struct {
244 NextError error
245 NextResult interface{}
246}
247
248func (r *mockBlessingRoots) reset() {
249 r.NextError = nil
250 r.NextResult = nil
251}
252
253func (r *mockBlessingRoots) Add(security.PublicKey, security.BlessingPattern) error {
254 defer r.reset()
255 return r.NextError
256}
257
258func (r *mockBlessingRoots) Recognized(security.PublicKey, string) error {
259 defer r.reset()
260 return r.NextError
261}
262
263func (r *mockBlessingRoots) DebugString() string {
264 defer r.reset()
265 return r.NextResult.(string)
266}
267
268type V []interface{}
269
270func call(receiver interface{}, method string, args V) (results []interface{}, err interface{}) {
271 defer func() {
272 err = recover()
273 }()
274 callargs := make([]reflect.Value, len(args))
275 for idx, arg := range args {
276 callargs[idx] = reflect.ValueOf(arg)
277 }
278 callresults := reflect.ValueOf(receiver).MethodByName(method).Call(callargs)
279 results = make([]interface{}, len(callresults))
280 for idx, res := range callresults {
281 results[idx] = res.Interface()
282 }
283 return
284}
285
286func newPrincipal(t *testing.T) security.Principal {
287 key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
288 if err != nil {
289 t.Fatal(err)
290 }
291 signer := security.NewInMemoryECDSASigner(key)
292 p, err := security.CreatePrincipal(signer, nil, nil)
293 if err != nil {
294 t.Fatal(err)
295 }
296 return p
297}
298
299func newCaveat(c security.Caveat, err error) security.Caveat {
300 if err != nil {
301 panic(err)
302 }
303 return c
304}
305
306func newBlessing(t *testing.T, name string) security.Blessings {
307 b, err := newPrincipal(t).BlessSelf(name)
308 if err != nil {
309 t.Fatal(err)
310 }
311 return b
312}
313
314func newThirdPartyCaveatAndDischarge(t *testing.T) (security.ThirdPartyCaveat, security.Discharge) {
315 p := newPrincipal(t)
316 c, err := security.NewPublicKeyCaveat(p.PublicKey(), "location", security.ThirdPartyRequirements{}, newCaveat(security.MethodCaveat("method")))
317 if err != nil {
318 t.Fatal(err)
319 }
320 d, err := p.MintDischarge(c, security.UnconstrainedUse())
321 if err != nil {
322 t.Fatal(err)
323 }
324 return c, d
Ryan Brownfed691e2014-09-15 13:09:40 -0700325}