blob: 98b0e2a1e355e004e026bef4ada47c23a2e045ae [file] [log] [blame]
Tilak Sharma3ed30242014-08-11 11:45:55 -07001package security
2
3import (
4 "io/ioutil"
5 "os"
6 "runtime"
7 "testing"
Tilak Sharma3ed30242014-08-11 11:45:55 -07008
Jiri Simsa519c5072014-09-17 21:37:57 -07009 "veyron.io/veyron/veyron2/security"
Tilak Sharma3ed30242014-08-11 11:45:55 -070010)
11
Tilak Sharma3ed30242014-08-11 11:45:55 -070012func saveACLToTempFile(acl security.ACL) string {
13 f, err := ioutil.TempFile("", "saved_acl")
14 if err != nil {
15 panic(err)
16 }
17 defer f.Close()
Tilak Sharmad6ade0e2014-08-20 16:28:32 -070018 if err := SaveACL(f, acl); err != nil {
Tilak Sharma3ed30242014-08-11 11:45:55 -070019 defer os.Remove(f.Name())
20 panic(err)
21 }
22 return f.Name()
23}
24
25func updateACLInFile(fileName string, acl security.ACL) {
26 f, err := os.OpenFile(fileName, os.O_WRONLY, 0600)
27 if err != nil {
28 panic(err)
29 }
30 defer f.Close()
Tilak Sharmad6ade0e2014-08-20 16:28:32 -070031 if err := SaveACL(f, acl); err != nil {
Tilak Sharma3ed30242014-08-11 11:45:55 -070032 panic(err)
33 }
34}
35
Tilak Sharma3ed30242014-08-11 11:45:55 -070036func testSelfRPCs(t *testing.T, authorizer security.Authorizer) {
37 _, file, line, _ := runtime.Caller(1)
38 var (
Asim Shankarbf6263f2014-10-01 12:32:30 -070039 pserver, server = newPrincipal("server")
40 _, imposter = newPrincipal("server")
41 palice, alice = newPrincipal("alice")
Asim Shankar2519cc12014-11-10 21:16:53 -080042 aliceServer = bless(palice, pserver, alice, "server")
Tilak Sharma3ed30242014-08-11 11:45:55 -070043
Asim Shankar2519cc12014-11-10 21:16:53 -080044 ctxp = &security.ContextParams{LocalPrincipal: pserver, LocalBlessings: server}
Asim Shankarbf6263f2014-10-01 12:32:30 -070045 tests = []struct {
46 remote security.Blessings
47 isAuthorized bool
48 }{
49 {server, true},
50 {imposter, false},
Asim Shankarbf6263f2014-10-01 12:32:30 -070051 // A principal talking to itself (even if with a different blessing) is authorized.
52 // TODO(ashankar,ataly): Is this a desired property?
53 {aliceServer, true},
54 }
55 )
56 for _, test := range tests {
Asim Shankar2519cc12014-11-10 21:16:53 -080057 ctxp.RemoteBlessings = test.remote
58 ctx := security.NewContext(ctxp)
Asim Shankarbf6263f2014-10-01 12:32:30 -070059 if got, want := authorizer.Authorize(ctx), test.isAuthorized; (got == nil) != want {
Asim Shankar2519cc12014-11-10 21:16:53 -080060 t.Errorf("%s:%d: %+v.Authorize(%v) returned error: %v, want error: %v", file, line, authorizer, ctx, got, !want)
Tilak Sharma3ed30242014-08-11 11:45:55 -070061 }
62 }
63}
64
65func testNothingPermitted(t *testing.T, authorizer security.Authorizer) {
66 _, file, line, _ := runtime.Caller(1)
67 var (
Asim Shankarbf6263f2014-10-01 12:32:30 -070068 pserver, server = newPrincipal("server")
69 palice, alice = newPrincipal("alice")
70 pbob, bob = newPrincipal("random")
Tilak Sharma3ed30242014-08-11 11:45:55 -070071
Asim Shankarbf6263f2014-10-01 12:32:30 -070072 serverAlice = bless(pserver, palice, server, "alice")
73 serverAliceFriend = bless(palice, pbob, serverAlice, "friend")
74 serverBob = bless(pserver, pbob, server, "bob")
75
76 users = []security.Blessings{
77 // blessings not recognized by "server" (since they are rooted at public
78 // keys not recognized as roots by pserver)
79 alice,
80 bob,
81 // blessings recognized by "server" (since they are its delegates)
82 serverAlice,
83 serverAliceFriend,
84 serverBob,
85 }
86
87 invalidLabel = security.Label(3)
88 )
89 // No principal (other than the server itself - self-RPCs are allowed) should have access to any
90 // valid or invalid label.
Tilak Sharma3ed30242014-08-11 11:45:55 -070091 for _, u := range users {
92 for _, l := range security.ValidLabels {
Asim Shankar2519cc12014-11-10 21:16:53 -080093 ctx := security.NewContext(&security.ContextParams{
94 LocalPrincipal: pserver,
95 LocalBlessings: server,
96 RemoteBlessings: u,
97 MethodTags: []interface{}{l},
98 })
Tilak Sharma3ed30242014-08-11 11:45:55 -070099 if got := authorizer.Authorize(ctx); got == nil {
100 t.Errorf("%s:%d: %+v.Authorize(%v) returns nil, want error", file, line, authorizer, ctx)
101 }
102 }
Asim Shankarbf6263f2014-10-01 12:32:30 -0700103
Asim Shankar2519cc12014-11-10 21:16:53 -0800104 ctx := security.NewContext(&security.ContextParams{
105 LocalPrincipal: pserver,
106 LocalBlessings: server,
107 RemoteBlessings: u,
108 MethodTags: []interface{}{invalidLabel},
109 })
Tilak Sharma3ed30242014-08-11 11:45:55 -0700110 if got := authorizer.Authorize(ctx); got == nil {
111 t.Errorf("%s:%d: %+v.Authorize(%v) returns nil, want error", file, line, authorizer, ctx)
112 }
113 }
114}
115
116func TestACLAuthorizer(t *testing.T) {
117 const (
118 // Shorthands
119 R = security.ReadLabel
120 W = security.WriteLabel
121 A = security.AdminLabel
122 D = security.DebugLabel
123 M = security.MonitoringLabel
Asim Shankarbf6263f2014-10-01 12:32:30 -0700124 X = security.ResolveLabel
Tilak Sharma3ed30242014-08-11 11:45:55 -0700125 )
Asim Shankarbf6263f2014-10-01 12:32:30 -0700126 type Expectations map[security.Blessings]security.LabelSet
Tilak Sharma3ed30242014-08-11 11:45:55 -0700127 // Principals to test
128 var (
Asim Shankarbf6263f2014-10-01 12:32:30 -0700129 // Principals
130 pserver, server = newPrincipal("server")
131 palice, alice = newPrincipal("alice")
132 pbob, bob = newPrincipal("bob")
133 pche, che = newPrincipal("che")
Tilak Sharma3ed30242014-08-11 11:45:55 -0700134
Asim Shankarbf6263f2014-10-01 12:32:30 -0700135 // Blessings from the server
136 serverAlice = bless(pserver, palice, server, "alice")
137 serverBob = bless(pserver, pbob, server, "bob")
138 serverChe = bless(pserver, pche, server, "che")
139 serverAliceFriend = bless(palice, pbob, serverAlice, "friend")
140 serverCheFriend = bless(pche, pbob, serverChe, "friend")
141
142 authorizer security.Authorizer // the authorizer to test.
143
144 runTests = func(expectations Expectations) {
145 _, file, line, _ := runtime.Caller(1)
146 for user, labels := range expectations {
147 for _, l := range security.ValidLabels {
Asim Shankar2519cc12014-11-10 21:16:53 -0800148 ctx := security.NewContext(&security.ContextParams{
149 LocalPrincipal: pserver,
150 LocalBlessings: server,
151 RemoteBlessings: user,
152 MethodTags: []interface{}{l},
153 })
Asim Shankarbf6263f2014-10-01 12:32:30 -0700154 if got, want := authorizer.Authorize(ctx), labels.HasLabel(l); (got == nil) != want {
Asim Shankar2519cc12014-11-10 21:16:53 -0800155 t.Errorf("%s:%d: %+v.Authorize(%v) returned error: %v, want error: %v", file, line, authorizer, ctx, got, !want)
Asim Shankarbf6263f2014-10-01 12:32:30 -0700156 }
157 }
158 }
159 }
Tilak Sharma3ed30242014-08-11 11:45:55 -0700160 )
161 // Convenience function for combining Labels into a LabelSet.
162 LS := func(labels ...security.Label) security.LabelSet {
163 var ret security.LabelSet
164 for _, l := range labels {
165 ret = ret | security.LabelSet(l)
166 }
167 return ret
168 }
169
170 // ACL for testing
Asim Shankarbf6263f2014-10-01 12:32:30 -0700171 acl := security.ACL{
172 In: map[security.BlessingPattern]security.LabelSet{
173 "...": LS(R),
174 "server/alice/...": LS(W, R),
175 "server/alice": LS(A, D, M),
176 "server/bob": LS(D, M),
177 "server/che/...": LS(W, R),
178 "server/che": LS(W, R),
179 },
180 NotIn: map[string]security.LabelSet{
181 "server/che/friend": LS(W),
182 },
Tilak Sharma3ed30242014-08-11 11:45:55 -0700183 }
184
185 // Authorizations for the above ACL.
Asim Shankarbf6263f2014-10-01 12:32:30 -0700186 expectations := Expectations{
187 alice: LS(R), // "..." ACL entry.
188 bob: LS(R), // "..." ACL entry.
189 che: LS(R), // "..." ACL entry.
190 server: security.AllLabels, // self RPC
191 serverAlice: LS(R, W, A, D, M), // "server/alice/..." ACL entry
192 serverBob: LS(R, D, M), // "..." and "server/bob" ACL entries
193 serverAliceFriend: LS(W, R), // "server/alice/..." ACL entry.
194 serverChe: LS(W, R), // "server/che" ACL entry.
195 serverCheFriend: LS(R), // "server/che/..." ACL entry, with the "server/che/friend" NotIn exception.
196 nil: LS(R), // No blessings presented, same authorizations as "..." ACL entry.
Tilak Sharma3ed30242014-08-11 11:45:55 -0700197 }
198 // Create an aclAuthorizer based on the ACL and verify the authorizations.
Asim Shankarbf6263f2014-10-01 12:32:30 -0700199 authorizer = NewACLAuthorizer(acl)
200 runTests(expectations)
Tilak Sharma3ed30242014-08-11 11:45:55 -0700201 testSelfRPCs(t, authorizer)
202
203 // Create a fileACLAuthorizer by saving the ACL in a file, and verify the
204 // authorizations.
205 fileName := saveACLToTempFile(acl)
206 defer os.Remove(fileName)
Asim Shankarbf6263f2014-10-01 12:32:30 -0700207 authorizer = NewFileACLAuthorizer(fileName)
208 runTests(expectations)
209 testSelfRPCs(t, authorizer)
Tilak Sharma3ed30242014-08-11 11:45:55 -0700210
211 // Modify the ACL stored in the file and verify that the authorizations appropriately
212 // change for the fileACLAuthorizer.
Asim Shankarbf6263f2014-10-01 12:32:30 -0700213 acl.In["server/bob"] = LS(R, W, A, D, M)
214 expectations[serverBob] = LS(R, W, A, D, M)
Tilak Sharma3ed30242014-08-11 11:45:55 -0700215 updateACLInFile(fileName, acl)
Asim Shankarbf6263f2014-10-01 12:32:30 -0700216 runTests(expectations)
217 testSelfRPCs(t, authorizer)
Tilak Sharma3ed30242014-08-11 11:45:55 -0700218
219 // Update the ACL file with invalid contents and verify that no requests are
220 // authorized.
221 f, err := os.OpenFile(fileName, os.O_WRONLY, 0600)
222 if err != nil {
223 panic(err)
224 }
225 f.Write([]byte("invalid ACL"))
226 f.Close()
Asim Shankarbf6263f2014-10-01 12:32:30 -0700227 testNothingPermitted(t, authorizer)
228}
Tilak Sharma3ed30242014-08-11 11:45:55 -0700229
Asim Shankarbf6263f2014-10-01 12:32:30 -0700230func TestFileACLAuthorizerOnNonExistentFile(t *testing.T) {
231 testNothingPermitted(t, NewFileACLAuthorizer("fileDoesNotExist"))
Tilak Sharma3ed30242014-08-11 11:45:55 -0700232}
233
234func TestNilACLAuthorizer(t *testing.T) {
Tilak Sharmab88a1112014-08-15 17:17:12 -0700235 authorizer := NewACLAuthorizer(nullACL)
Tilak Sharma3ed30242014-08-11 11:45:55 -0700236 testNothingPermitted(t, authorizer)
237 testSelfRPCs(t, authorizer)
238}