blob: fd535d897d5bf672dd06d287f0720c5f7cc0c4e0 [file] [log] [blame]
Asim Shankarae8d4c52014-10-08 13:03:31 -07001package security
2
3import (
4 "fmt"
5 "io/ioutil"
6 "os"
7 "reflect"
8 "testing"
9
10 "veyron.io/veyron/veyron2/security"
11)
12
13type storeTester struct {
14 forAll, forFoo, forBar, def security.Blessings
15 other security.Blessings // Blessings bound to a different principal.
16}
17
18func (t *storeTester) testSet(s security.BlessingStore) error {
19 testdata := []struct {
20 blessings security.Blessings
21 pattern security.BlessingPattern
22 wantErr string
23 }{
24 {t.forAll, "...", ""},
25 {t.forFoo, "foo/...", ""},
26 {t.forBar, "bar", ""},
27 {t.other, "...", "public key does not match"},
28 {t.forAll, "", "invalid BlessingPattern"},
29 {t.forAll, "foo...", "invalid BlessingPattern"},
30 {t.forAll, "...foo", "invalid BlessingPattern"},
31 {t.forAll, "foo/.../bar", "invalid BlessingPattern"},
32 }
33 for _, d := range testdata {
34 _, err := s.Set(d.blessings, d.pattern)
35 if merr := matchesError(err, d.wantErr); merr != nil {
36 return fmt.Errorf("Set(%v, %q): %v", d.blessings, d.pattern, merr)
37 }
38 }
39 return nil
40}
41
42func (t *storeTester) testSetDefault(s security.BlessingStore, currentDefault security.Blessings) error {
43 if got := s.Default(); !reflect.DeepEqual(got, currentDefault) {
44 return fmt.Errorf("Default(): got: %v, want: %v", got, currentDefault)
45 }
46 if err := s.SetDefault(t.def); err != nil {
47 return fmt.Errorf("SetDefault(%v): %v", t.def, err)
48 }
49 if got, want := s.Default(), t.def; !reflect.DeepEqual(got, want) {
50 return fmt.Errorf("Default returned %v, want %v", got, want)
51 }
52 // Changing default to an invalid blessing should not affect the existing default.
53 if err := matchesError(s.SetDefault(t.other), "public key does not match"); err != nil {
54 return err
55 }
56 if got, want := s.Default(), t.def; !reflect.DeepEqual(got, want) {
57 return fmt.Errorf("Default returned %v, want %v", got, want)
58 }
59 return nil
60}
61
62func (t *storeTester) testForPeer(s security.BlessingStore) error {
63 testdata := []struct {
64 peers []string
65 blessings security.Blessings
66 }{
67 {nil, t.forAll},
68 {[]string{"baz"}, t.forAll},
69 {[]string{"foo"}, unionOfBlessings(t.forAll, t.forFoo)},
70 {[]string{"bar"}, unionOfBlessings(t.forAll, t.forBar)},
71 {[]string{"foo/foo"}, unionOfBlessings(t.forAll, t.forFoo)},
72 {[]string{"bar/baz"}, t.forAll},
73 {[]string{"foo/foo/bar"}, unionOfBlessings(t.forAll, t.forFoo)},
74 {[]string{"bar/foo", "foo"}, unionOfBlessings(t.forAll, t.forFoo)},
75 {[]string{"bar", "foo"}, unionOfBlessings(t.forAll, t.forFoo, t.forBar)},
76 }
77 for _, d := range testdata {
78 if got, want := s.ForPeer(d.peers...), d.blessings; !reflect.DeepEqual(got, want) {
79 return fmt.Errorf("ForPeer(%v): got: %v, want: %v", d.peers, got, want)
80 }
81 }
82 return nil
83}
84
85func newStoreTester(blessed security.Principal) *storeTester {
86 var (
87 blessing = func(root, extension string) security.Blessings {
88 blesser, err := NewPrincipal()
89 if err != nil {
90 panic(err)
91 }
92 blessing, err := blesser.Bless(blessed.PublicKey(), blessSelf(blesser, root), extension, security.UnconstrainedUse())
93 if err != nil {
94 panic(err)
95 }
96 return blessing
97 }
98 )
99 pother, err := NewPrincipal()
100 if err != nil {
101 panic(err)
102 }
103
104 s := &storeTester{}
105 s.forAll = blessing("bar", "alice")
106 s.forFoo = blessing("foo", "alice")
107 s.forBar = unionOfBlessings(s.forAll, s.forFoo)
108 s.def = blessing("default", "alice")
109 s.other = blessSelf(pother, "other")
110 return s
111}
112
113func TestBlessingStore(t *testing.T) {
114 p, err := NewPrincipal()
115 if err != nil {
116 t.Fatal(err)
117 }
118 tester := newStoreTester(p)
119 s := p.BlessingStore()
120 if err := tester.testSet(s); err != nil {
121 t.Error(err)
122 }
123 if err := tester.testForPeer(s); err != nil {
124 t.Error(err)
125 }
126 if err := tester.testSetDefault(s, tester.forAll); err != nil {
127 t.Error(err)
128 }
129}
130
131func TestBlessingStorePersistence(t *testing.T) {
132 dir, err := ioutil.TempDir("", "TestPersistingBlessingStore")
133 if err != nil {
134 t.Fatal(err)
135 }
136 defer os.RemoveAll(dir)
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700137 p, err := CreatePersistentPrincipal(dir, nil)
Asim Shankarae8d4c52014-10-08 13:03:31 -0700138 if err != nil {
139 t.Fatal(err)
140 }
Asim Shankarae8d4c52014-10-08 13:03:31 -0700141 tester := newStoreTester(p)
142 s := p.BlessingStore()
143
144 if err := tester.testSet(s); err != nil {
145 t.Error(err)
146 }
147 if err := tester.testForPeer(s); err != nil {
148 t.Error(err)
149 }
150 if err := tester.testSetDefault(s, tester.forAll); err != nil {
151 t.Error(err)
152 }
153
154 // Recreate the BlessingStore from the directory.
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700155 p2, err := LoadPersistentPrincipal(dir, nil)
Asim Shankarae8d4c52014-10-08 13:03:31 -0700156 if err != nil {
157 t.Fatal(err)
158 }
159 s = p2.BlessingStore()
160 if err := tester.testForPeer(s); err != nil {
161 t.Error(err)
162 }
163 if got, want := s.Default(), tester.def; !reflect.DeepEqual(got, want) {
164 t.Fatalf("Default(): got: %v, want: %v", got, want)
165 }
166}
167
168func TestBlessingStoreSetOverridesOldSetting(t *testing.T) {
169 p, err := NewPrincipal()
170 if err != nil {
171 t.Fatal(err)
172 }
173 var (
174 alice = blessSelf(p, "alice")
175 bob = blessSelf(p, "bob")
176 s = p.BlessingStore()
177 )
178 // Set(alice, "alice")
179 // Set(bob, "alice/...")
180 // So, {alice, bob} is shared with "alice", whilst {bob} is shared with "alice/tv"
181 if _, err := s.Set(alice, "alice"); err != nil {
182 t.Fatal(err)
183 }
184 if _, err := s.Set(bob, "alice/..."); err != nil {
185 t.Fatal(err)
186 }
187 if got, want := s.ForPeer("alice"), unionOfBlessings(alice, bob); !reflect.DeepEqual(got, want) {
188 t.Errorf("Got %v, want %v", got, want)
189 }
190 if got, want := s.ForPeer("alice/friend"), bob; !reflect.DeepEqual(got, want) {
191 t.Errorf("Got %v, want %v", got, want)
192 }
193
194 // Clear out the blessing associated with "alice".
195 // Now, bob should be shared with both alice and alice/friend.
196 if _, err := s.Set(nil, "alice"); err != nil {
197 t.Fatal(err)
198 }
199 if got, want := s.ForPeer("alice"), bob; !reflect.DeepEqual(got, want) {
200 t.Errorf("Got %v, want %v", got, want)
201 }
202 if got, want := s.ForPeer("alice/friend"), bob; !reflect.DeepEqual(got, want) {
203 t.Errorf("Got %v, want %v", got, want)
204 }
205
206 // Clearing out an association that doesn't exist should have no effect.
207 if _, err := s.Set(nil, "alice/enemy"); err != nil {
208 t.Fatal(err)
209 }
210 if got, want := s.ForPeer("alice"), bob; !reflect.DeepEqual(got, want) {
211 t.Errorf("Got %v, want %v", got, want)
212 }
213 if got, want := s.ForPeer("alice/friend"), bob; !reflect.DeepEqual(got, want) {
214 t.Errorf("Got %v, want %v", got, want)
215 }
216
217 // Clear everything
218 if _, err := s.Set(nil, "alice/..."); err != nil {
219 t.Fatal(err)
220 }
221 if got := s.ForPeer("alice"); got != nil {
222 t.Errorf("Got %v, want nil", got)
223 }
224 if got := s.ForPeer("alice/friend"); got != nil {
225 t.Errorf("Got %v, want nil", got)
226 }
227}
228
229func TestBlessingStoreSetReturnsOldValue(t *testing.T) {
230 p, err := NewPrincipal()
231 if err != nil {
232 t.Fatal(err)
233 }
234 var (
235 alice = blessSelf(p, "alice")
236 bob = blessSelf(p, "bob")
237 s = p.BlessingStore()
238 )
239
240 if old, err := s.Set(alice, "..."); old != nil || err != nil {
241 t.Errorf("Got (%v, %v)", old, err)
242 }
243 if old, err := s.Set(alice, "..."); !reflect.DeepEqual(old, alice) || err != nil {
244 t.Errorf("Got (%v, %v) want (%v, nil)", old, err, alice)
245 }
246 if old, err := s.Set(bob, "..."); !reflect.DeepEqual(old, alice) || err != nil {
247 t.Errorf("Got (%v, %v) want (%v, nil)", old, err, alice)
248 }
249 if old, err := s.Set(nil, "..."); !reflect.DeepEqual(old, bob) || err != nil {
250 t.Errorf("Got (%v, %v) want (%v, nil)", old, err, bob)
251 }
252}