blob: cd86c372fedc8f9295d52f38b0b2894485c297d6 [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
Asim Shankarae8d4c52014-10-08 13:03:31 -07005package security
6
7import (
8 "fmt"
9 "io/ioutil"
10 "os"
11 "reflect"
12 "testing"
13
Jiri Simsa6ac95222015-02-23 16:11:49 -080014 "v.io/v23/security"
Asim Shankarae8d4c52014-10-08 13:03:31 -070015)
16
17type storeTester struct {
18 forAll, forFoo, forBar, def security.Blessings
19 other security.Blessings // Blessings bound to a different principal.
20}
21
22func (t *storeTester) testSet(s security.BlessingStore) error {
23 testdata := []struct {
24 blessings security.Blessings
25 pattern security.BlessingPattern
26 wantErr string
27 }{
Ankur78b8b2a2015-02-04 20:16:28 -080028 {t.forAll, security.AllPrincipals, ""},
Ankur2b61d352015-01-27 14:59:37 -080029 {t.forAll, "$", ""},
Ankur78b8b2a2015-02-04 20:16:28 -080030 {t.forFoo, "foo", ""},
Ankur2b61d352015-01-27 14:59:37 -080031 {t.forBar, "bar/$", ""},
Ankur78b8b2a2015-02-04 20:16:28 -080032 {t.other, security.AllPrincipals, "public key does not match"},
Asim Shankarae8d4c52014-10-08 13:03:31 -070033 {t.forAll, "", "invalid BlessingPattern"},
Ankur2b61d352015-01-27 14:59:37 -080034 {t.forAll, "foo/$/bar", "invalid BlessingPattern"},
Asim Shankarae8d4c52014-10-08 13:03:31 -070035 }
gauthamtf8263932014-12-16 10:59:09 -080036 added := make(map[security.BlessingPattern]security.Blessings)
Asim Shankarae8d4c52014-10-08 13:03:31 -070037 for _, d := range testdata {
38 _, err := s.Set(d.blessings, d.pattern)
39 if merr := matchesError(err, d.wantErr); merr != nil {
40 return fmt.Errorf("Set(%v, %q): %v", d.blessings, d.pattern, merr)
41 }
gauthamtf8263932014-12-16 10:59:09 -080042 if err == nil {
43 added[d.pattern] = d.blessings
44 }
45 }
46 m := s.PeerBlessings()
47 if !reflect.DeepEqual(added, m) {
48 return fmt.Errorf("PeerBlessings(%v) != added(%v)", m, added)
Asim Shankarae8d4c52014-10-08 13:03:31 -070049 }
50 return nil
51}
52
53func (t *storeTester) testSetDefault(s security.BlessingStore, currentDefault security.Blessings) error {
54 if got := s.Default(); !reflect.DeepEqual(got, currentDefault) {
55 return fmt.Errorf("Default(): got: %v, want: %v", got, currentDefault)
56 }
Asim Shankar2bf7b1e2015-02-27 00:45:12 -080057 if err := s.SetDefault(security.Blessings{}); err != nil {
58 return fmt.Errorf("SetDefault({}): %v", err)
Asim Shankarb378e662015-01-16 10:50:48 -080059 }
Asim Shankar2bf7b1e2015-02-27 00:45:12 -080060 if got := s.Default(); !got.IsZero() {
61 return fmt.Errorf("Default returned %v, wanted empty", got)
Asim Shankarb378e662015-01-16 10:50:48 -080062 }
Asim Shankarae8d4c52014-10-08 13:03:31 -070063 if err := s.SetDefault(t.def); err != nil {
64 return fmt.Errorf("SetDefault(%v): %v", t.def, err)
65 }
66 if got, want := s.Default(), t.def; !reflect.DeepEqual(got, want) {
67 return fmt.Errorf("Default returned %v, want %v", got, want)
68 }
69 // Changing default to an invalid blessing should not affect the existing default.
70 if err := matchesError(s.SetDefault(t.other), "public key does not match"); err != nil {
71 return err
72 }
73 if got, want := s.Default(), t.def; !reflect.DeepEqual(got, want) {
74 return fmt.Errorf("Default returned %v, want %v", got, want)
75 }
76 return nil
77}
78
79func (t *storeTester) testForPeer(s security.BlessingStore) error {
80 testdata := []struct {
81 peers []string
82 blessings security.Blessings
83 }{
84 {nil, t.forAll},
85 {[]string{"baz"}, t.forAll},
86 {[]string{"foo"}, unionOfBlessings(t.forAll, t.forFoo)},
87 {[]string{"bar"}, unionOfBlessings(t.forAll, t.forBar)},
88 {[]string{"foo/foo"}, unionOfBlessings(t.forAll, t.forFoo)},
89 {[]string{"bar/baz"}, t.forAll},
90 {[]string{"foo/foo/bar"}, unionOfBlessings(t.forAll, t.forFoo)},
91 {[]string{"bar/foo", "foo"}, unionOfBlessings(t.forAll, t.forFoo)},
92 {[]string{"bar", "foo"}, unionOfBlessings(t.forAll, t.forFoo, t.forBar)},
93 }
94 for _, d := range testdata {
95 if got, want := s.ForPeer(d.peers...), d.blessings; !reflect.DeepEqual(got, want) {
96 return fmt.Errorf("ForPeer(%v): got: %v, want: %v", d.peers, got, want)
97 }
98 }
99 return nil
100}
101
102func newStoreTester(blessed security.Principal) *storeTester {
103 var (
104 blessing = func(root, extension string) security.Blessings {
105 blesser, err := NewPrincipal()
106 if err != nil {
107 panic(err)
108 }
109 blessing, err := blesser.Bless(blessed.PublicKey(), blessSelf(blesser, root), extension, security.UnconstrainedUse())
110 if err != nil {
111 panic(err)
112 }
113 return blessing
114 }
115 )
116 pother, err := NewPrincipal()
117 if err != nil {
118 panic(err)
119 }
120
121 s := &storeTester{}
122 s.forAll = blessing("bar", "alice")
123 s.forFoo = blessing("foo", "alice")
124 s.forBar = unionOfBlessings(s.forAll, s.forFoo)
125 s.def = blessing("default", "alice")
126 s.other = blessSelf(pother, "other")
127 return s
128}
129
130func TestBlessingStore(t *testing.T) {
131 p, err := NewPrincipal()
132 if err != nil {
133 t.Fatal(err)
134 }
135 tester := newStoreTester(p)
136 s := p.BlessingStore()
137 if err := tester.testSet(s); err != nil {
138 t.Error(err)
139 }
140 if err := tester.testForPeer(s); err != nil {
141 t.Error(err)
142 }
143 if err := tester.testSetDefault(s, tester.forAll); err != nil {
144 t.Error(err)
145 }
146}
147
148func TestBlessingStorePersistence(t *testing.T) {
149 dir, err := ioutil.TempDir("", "TestPersistingBlessingStore")
150 if err != nil {
151 t.Fatal(err)
152 }
153 defer os.RemoveAll(dir)
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700154 p, err := CreatePersistentPrincipal(dir, nil)
Asim Shankarae8d4c52014-10-08 13:03:31 -0700155 if err != nil {
156 t.Fatal(err)
157 }
Asim Shankarae8d4c52014-10-08 13:03:31 -0700158 tester := newStoreTester(p)
159 s := p.BlessingStore()
160
161 if err := tester.testSet(s); err != nil {
162 t.Error(err)
163 }
164 if err := tester.testForPeer(s); err != nil {
165 t.Error(err)
166 }
167 if err := tester.testSetDefault(s, tester.forAll); err != nil {
168 t.Error(err)
169 }
170
171 // Recreate the BlessingStore from the directory.
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700172 p2, err := LoadPersistentPrincipal(dir, nil)
Asim Shankarae8d4c52014-10-08 13:03:31 -0700173 if err != nil {
174 t.Fatal(err)
175 }
176 s = p2.BlessingStore()
177 if err := tester.testForPeer(s); err != nil {
178 t.Error(err)
179 }
180 if got, want := s.Default(), tester.def; !reflect.DeepEqual(got, want) {
181 t.Fatalf("Default(): got: %v, want: %v", got, want)
182 }
183}
184
185func TestBlessingStoreSetOverridesOldSetting(t *testing.T) {
186 p, err := NewPrincipal()
187 if err != nil {
188 t.Fatal(err)
189 }
190 var (
191 alice = blessSelf(p, "alice")
192 bob = blessSelf(p, "bob")
193 s = p.BlessingStore()
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800194 empty security.Blessings
Asim Shankarae8d4c52014-10-08 13:03:31 -0700195 )
Ankur78b8b2a2015-02-04 20:16:28 -0800196 // {alice, bob} is shared with "alice", whilst {bob} is shared with "alice/tv"
Ankur2b61d352015-01-27 14:59:37 -0800197 if _, err := s.Set(alice, "alice/$"); err != nil {
Asim Shankarae8d4c52014-10-08 13:03:31 -0700198 t.Fatal(err)
199 }
Ankur78b8b2a2015-02-04 20:16:28 -0800200 if _, err := s.Set(bob, "alice"); err != nil {
Asim Shankarae8d4c52014-10-08 13:03:31 -0700201 t.Fatal(err)
202 }
203 if got, want := s.ForPeer("alice"), unionOfBlessings(alice, bob); !reflect.DeepEqual(got, want) {
204 t.Errorf("Got %v, want %v", got, want)
205 }
206 if got, want := s.ForPeer("alice/friend"), bob; !reflect.DeepEqual(got, want) {
207 t.Errorf("Got %v, want %v", got, want)
208 }
209
210 // Clear out the blessing associated with "alice".
211 // Now, bob should be shared with both alice and alice/friend.
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800212 if _, err := s.Set(empty, "alice/$"); err != nil {
Asim Shankarae8d4c52014-10-08 13:03:31 -0700213 t.Fatal(err)
214 }
215 if got, want := s.ForPeer("alice"), bob; !reflect.DeepEqual(got, want) {
216 t.Errorf("Got %v, want %v", got, want)
217 }
218 if got, want := s.ForPeer("alice/friend"), bob; !reflect.DeepEqual(got, want) {
219 t.Errorf("Got %v, want %v", got, want)
220 }
221
222 // Clearing out an association that doesn't exist should have no effect.
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800223 if _, err := s.Set(empty, "alice/enemy/$"); err != nil {
Asim Shankarae8d4c52014-10-08 13:03:31 -0700224 t.Fatal(err)
225 }
226 if got, want := s.ForPeer("alice"), bob; !reflect.DeepEqual(got, want) {
227 t.Errorf("Got %v, want %v", got, want)
228 }
229 if got, want := s.ForPeer("alice/friend"), bob; !reflect.DeepEqual(got, want) {
230 t.Errorf("Got %v, want %v", got, want)
231 }
232
233 // Clear everything
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800234 if _, err := s.Set(empty, "alice"); err != nil {
Asim Shankarae8d4c52014-10-08 13:03:31 -0700235 t.Fatal(err)
236 }
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800237 if got := s.ForPeer("alice"); !got.IsZero() {
238 t.Errorf("Got %v, want empty", got)
Asim Shankarae8d4c52014-10-08 13:03:31 -0700239 }
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800240 if got := s.ForPeer("alice/friend"); !got.IsZero() {
241 t.Errorf("Got %v, want empty", got)
Asim Shankarae8d4c52014-10-08 13:03:31 -0700242 }
243}
244
245func TestBlessingStoreSetReturnsOldValue(t *testing.T) {
246 p, err := NewPrincipal()
247 if err != nil {
248 t.Fatal(err)
249 }
250 var (
251 alice = blessSelf(p, "alice")
252 bob = blessSelf(p, "bob")
253 s = p.BlessingStore()
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800254 empty security.Blessings
Asim Shankarae8d4c52014-10-08 13:03:31 -0700255 )
256
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800257 if old, err := s.Set(alice, security.AllPrincipals); !reflect.DeepEqual(old, empty) || err != nil {
258 t.Errorf("Got (%v, %v), want (%v, nil)", old, err)
Asim Shankarae8d4c52014-10-08 13:03:31 -0700259 }
Ankur78b8b2a2015-02-04 20:16:28 -0800260 if old, err := s.Set(alice, security.AllPrincipals); !reflect.DeepEqual(old, alice) || err != nil {
Asim Shankarae8d4c52014-10-08 13:03:31 -0700261 t.Errorf("Got (%v, %v) want (%v, nil)", old, err, alice)
262 }
Ankur78b8b2a2015-02-04 20:16:28 -0800263 if old, err := s.Set(bob, security.AllPrincipals); !reflect.DeepEqual(old, alice) || err != nil {
Asim Shankarae8d4c52014-10-08 13:03:31 -0700264 t.Errorf("Got (%v, %v) want (%v, nil)", old, err, alice)
265 }
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800266 if old, err := s.Set(empty, security.AllPrincipals); !reflect.DeepEqual(old, bob) || err != nil {
Asim Shankarae8d4c52014-10-08 13:03:31 -0700267 t.Errorf("Got (%v, %v) want (%v, nil)", old, err, bob)
268 }
269}