veyron2/security, veyron2/services/security/access: Update security.ACL to support the Access API.
- Move access.ACL to security.ACL and update services that use ACLs.
- Replace PublicID.Match(PrincipalPattern) with
Matches(PublicID, PrincipalPattern).
Change-Id: I59b6399a30089c48d97755e96e428e692c6551e0
diff --git a/examples/bank/pbankd/main.go b/examples/bank/pbankd/main.go
index d8a6dbc..e4fa5ef 100644
--- a/examples/bank/pbankd/main.go
+++ b/examples/bank/pbankd/main.go
@@ -442,7 +442,10 @@
// bankAccountServer := bank.NewServerBankAccount(pbankd)
// // Setup bank and account authorizers.
- // bankAuth := vsecurity.NewACLAuthorizer(security.ACL{security.AllPrincipals: security.LabelSet(security.ReadLabel | security.WriteLabel)})
+ // bankAuth := vsecurity.NewACLAuthorizer(security.NewWhitelistACL(
+ // map[security.PrincipalPattern]security.LabelSet{
+ // security.AllPrincipals: security.LabelSet(security.ReadLabel | security.WriteLabel),
+ // }))
// bankAccountAuth := AccountAuthorizer(runtime.Identity().PublicID().Names()[0] + SUFFIX_REGEXP)
// dispatcher := newBankDispatcher(bankServer, bankAccountServer, bankAuth, bankAccountAuth)
diff --git a/examples/boxes/android/src/boxesp2p/main.go b/examples/boxes/android/src/boxesp2p/main.go
index 0cc51e6..392710b 100644
--- a/examples/boxes/android/src/boxesp2p/main.go
+++ b/examples/boxes/android/src/boxesp2p/main.go
@@ -256,7 +256,10 @@
}
func (gs *goState) registerAsPeer() {
- auth := vsecurity.NewACLAuthorizer(security.ACL{security.AllPrincipals: security.LabelSet(security.AdminLabel)})
+ auth := vsecurity.NewACLAuthorizer(security.NewWhitelistACL(
+ map[security.PrincipalPattern]security.LabelSet{
+ security.AllPrincipals: security.LabelSet(security.AdminLabel),
+ }))
gs.disp.drawAuth = auth
gs.disp.drawServer = ipc.ReflectInvoker(boxes.NewServerDrawInterface(gs))
endPt, err := gs.ipc.Listen("tcp", gs.myIPAddr+drawServicePort)
diff --git a/lib/testutil/security/util_test.go b/lib/testutil/security/util_test.go
index 3aac88d..3f2a38e 100644
--- a/lib/testutil/security/util_test.go
+++ b/lib/testutil/security/util_test.go
@@ -49,9 +49,14 @@
t.Fatalf("rt.New failed: %v", err)
}
defer r.Cleanup()
- acl := security.ACL{
+ acl := security.ACL{}
+ acl.In.Principals = map[security.PrincipalPattern]security.LabelSet{
+ "veyron/*": security.LabelSet(security.ReadLabel),
"veyron/alice": security.LabelSet(security.ReadLabel | security.WriteLabel),
- "veyron/bob": security.LabelSet(security.ReadLabel),
+ "veyron/bob": security.LabelSet(security.AdminLabel),
+ }
+ acl.NotIn.Principals = map[security.PrincipalPattern]security.LabelSet{
+ "veyron/che": security.LabelSet(security.ReadLabel),
}
filePath := SaveACLToFile(acl)
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index bff3c70..4efe411 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -192,7 +192,7 @@
for _, o := range opts {
switch v := o.(type) {
case veyron2.RemoteID:
- if !authID.Match(security.PrincipalPattern(v)) {
+ if !security.Matches(authID, security.PrincipalPattern(v)) {
return nil, fmt.Errorf("server %q does not match the provided pattern %q", authID, v)
}
case ipc.Granter:
diff --git a/runtimes/google/ipc/discharges.go b/runtimes/google/ipc/discharges.go
index 8e390f5..4f2a665 100644
--- a/runtimes/google/ipc/discharges.go
+++ b/runtimes/google/ipc/discharges.go
@@ -25,7 +25,7 @@
var caveats []security.ThirdPartyCaveat
for _, cav := range blessing.ThirdPartyCaveats() {
- if server.Match(cav.Service) {
+ if security.Matches(server, cav.Service) {
caveats = append(caveats, cav.Caveat.(security.ThirdPartyCaveat))
}
}
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 5b87cbb..a495340 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -163,10 +163,11 @@
authorizer = nil
case "aclAuth":
// Only authorize clients matching patterns "client" or "server/*".
- authorizer = vsecurity.NewACLAuthorizer(security.ACL{
- "server/*": security.LabelSet(security.AdminLabel),
- "client": security.LabelSet(security.AdminLabel),
- })
+ authorizer = vsecurity.NewACLAuthorizer(security.NewWhitelistACL(
+ map[security.PrincipalPattern]security.LabelSet{
+ "server/*": security.LabelSet(security.AdminLabel),
+ "client": security.LabelSet(security.AdminLabel),
+ }))
default:
authorizer = testServerAuthorizer{}
}
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index 6ed86f0..84c66df 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -19,7 +19,6 @@
"veyron2/ipc/stream"
"veyron2/naming"
"veyron2/security"
- "veyron2/security/wire"
"veyron2/verror"
"veyron2/vlog"
"veyron2/vom"
@@ -380,13 +379,13 @@
func defaultACL(id security.PublicID) security.ACL {
if id == nil {
- return nil
+ return security.ACL{}
}
- acl := make(security.ACL)
+ in := map[security.PrincipalPattern]security.LabelSet{}
for _, n := range id.Names() {
- acl[security.PrincipalPattern(n+wire.ChainSeparator+security.AllPrincipals)] = security.AllLabels
+ in[security.PrincipalPattern(n+security.ChainSeparator+security.AllPrincipals)] = security.AllLabels
}
- return acl
+ return security.NewWhitelistACL(in)
}
func (fs *flowServer) serve() error {
diff --git a/runtimes/google/rt/ipc_test.go b/runtimes/google/rt/ipc_test.go
index 804e4fc..a8360a1 100644
--- a/runtimes/google/rt/ipc_test.go
+++ b/runtimes/google/rt/ipc_test.go
@@ -161,7 +161,11 @@
continue
}
defer stopServer(server)
- if err := server.Serve("", ipc.SoloDispatcher(&testService{}, vsecurity.NewACLAuthorizer(security.ACL{security.AllPrincipals: security.AllLabels}))); err != nil {
+ if err := server.Serve("", ipc.SoloDispatcher(&testService{},
+ vsecurity.NewACLAuthorizer(security.NewWhitelistACL(
+ map[security.PrincipalPattern]security.LabelSet{
+ security.AllPrincipals: security.AllLabels,
+ })))); err != nil {
t.Errorf("error serving service: ", err)
continue
}
diff --git a/runtimes/google/security/identity_chain.go b/runtimes/google/security/identity_chain.go
index 7351b41..a16447d 100644
--- a/runtimes/google/security/identity_chain.go
+++ b/runtimes/google/security/identity_chain.go
@@ -49,15 +49,6 @@
return nil
}
-// Match determines if the PublicID's chained name can be extended to match the
-// provided PrincipalPattern. An extension of a chained name is any name obtained
-// by joining additional strings to the name using wire.ChainSeparator. Ex: extensions
-// of the name "foo/bar" are the names "foo/bar", "foo/bar/baz", "foo/bar/baz/car", and
-// so on.
-func (id *chainPublicID) Match(pattern security.PrincipalPattern) bool {
- return matchPrincipalPattern(id.Names(), pattern)
-}
-
func (id *chainPublicID) PublicKey() *ecdsa.PublicKey { return id.publicKey }
func (id *chainPublicID) String() string {
diff --git a/runtimes/google/security/identity_set.go b/runtimes/google/security/identity_set.go
index 1c00e00..912536e 100644
--- a/runtimes/google/security/identity_set.go
+++ b/runtimes/google/security/identity_set.go
@@ -52,15 +52,6 @@
return names
}
-func (s *setPublicID) Match(pattern security.PrincipalPattern) bool {
- for _, id := range *s {
- if id.Match(pattern) {
- return true
- }
- }
- return false
-}
-
func (s *setPublicID) PublicKey() *ecdsa.PublicKey {
return (*s)[0].PublicKey()
}
diff --git a/runtimes/google/security/identity_test.go b/runtimes/google/security/identity_test.go
index 890325c..0ea92dc 100644
--- a/runtimes/google/security/identity_test.go
+++ b/runtimes/google/security/identity_test.go
@@ -137,7 +137,7 @@
}
for _, d := range testdata {
for _, m := range d.matchData {
- if got := d.id.Match(m.pattern); got != m.want {
+ if got := security.Matches(d.id, m.pattern); got != m.want {
t.Errorf("%q.Match(%s), Got %t, want %t", d.id, m.pattern, got, m.want)
}
}
diff --git a/runtimes/google/security/jni/publicid.go b/runtimes/google/security/jni/publicid.go
index 4b0dae7..07f855c 100644
--- a/runtimes/google/security/jni/publicid.go
+++ b/runtimes/google/security/jni/publicid.go
@@ -51,13 +51,6 @@
return util.CallStringArrayMethodOrCatch(env, id.jPublicID, "names", nil)
}
-func (id *publicID) Match(pattern security.PrincipalPattern) bool {
- envPtr, freeFunc := util.GetEnv(id.jVM)
- env := (*C.JNIEnv)(envPtr)
- defer freeFunc()
- return util.CallBooleanMethodOrCatch(env, id.jPublicID, "match", []util.Sign{util.StringSign})
-}
-
func (id *publicID) PublicKey() *ecdsa.PublicKey {
envPtr, freeFunc := util.GetEnv(id.jVM)
env := (*C.JNIEnv)(envPtr)
diff --git a/runtimes/google/security/publicid_store.go b/runtimes/google/security/publicid_store.go
index 4ce543c..7758762 100644
--- a/runtimes/google/security/publicid_store.go
+++ b/runtimes/google/security/publicid_store.go
@@ -119,7 +119,7 @@
var matchingIDs []security.PublicID
for id, peerPatterns := range s.state.Store {
for _, peerPattern := range peerPatterns {
- if peer.Match(peerPattern) {
+ if security.Matches(peer, peerPattern) {
matchingIDs = append(matchingIDs, id)
break
}
@@ -140,7 +140,7 @@
defer s.mu.RUnlock()
var matchingIDs []security.PublicID
for id, _ := range s.state.Store {
- if id.Match(s.state.DefaultPattern) {
+ if security.Matches(id, s.state.DefaultPattern) {
matchingIDs = append(matchingIDs, id)
}
}
diff --git a/runtimes/google/security/util.go b/runtimes/google/security/util.go
index 6c9f1aa..b4fb38d 100644
--- a/runtimes/google/security/util.go
+++ b/runtimes/google/security/util.go
@@ -4,12 +4,10 @@
"bytes"
"errors"
"fmt"
- "strings"
"veyron/runtimes/google/security/keys"
"veyron2/naming"
"veyron2/security"
- "veyron2/security/wire"
)
var errDeriveMismatch = errors.New("public key does not match that of deriving identity")
@@ -29,49 +27,6 @@
}
}
-// matchesPattern checks if the provided name conforms to the provided pattern.
-// This function assumes pattern to be one of the following forms:
-// - Pattern is a chained name of the form p_0/.../p_k; in this case the check
-// succeeds iff the provided name is of the form n_0/.../n_m such that m <= k
-// and for all i from 0 to m, p_i = n_i.
-// - Pattern is a chained name of the form p_0/.../p_k/*; in this case the check
-// succeeds iff the provided name is of the form n_0/.../n_m such that for all i
-// from 0 to min(m, k), p_i = n_i.
-func matchesPattern(name, pattern string) bool {
- patternParts := strings.Split(pattern, wire.ChainSeparator)
- patternLen := len(patternParts)
- nameParts := strings.Split(name, wire.ChainSeparator)
- nameLen := len(nameParts)
-
- if patternParts[patternLen-1] != security.AllPrincipals && nameLen > patternLen {
- return false
- }
-
- min := nameLen
- if patternParts[patternLen-1] == security.AllPrincipals && nameLen > patternLen-1 {
- min = patternLen - 1
- }
-
- for i := 0; i < min; i++ {
- if patternParts[i] != nameParts[i] {
- return false
- }
- }
- return true
-}
-
-func matchPrincipalPattern(names []string, pattern security.PrincipalPattern) bool {
- if pattern == security.AllPrincipals {
- return true
- }
- for _, n := range names {
- if matchesPattern(n, string(pattern)) {
- return true
- }
- }
- return false
-}
-
// ContextArgs holds the arguments for creating a new security.Context for an IPC.
type ContextArgs struct {
// LocalID, RemoteID are the identities at the local and remote ends of a request
diff --git a/security/acl_authorizer.go b/security/acl_authorizer.go
index 82b35d9..9d88e13 100644
--- a/security/acl_authorizer.go
+++ b/security/acl_authorizer.go
@@ -18,7 +18,6 @@
errACL = errors.New("no matching ACL entry found")
errInvalidLabel = errors.New("label is invalid")
errNilID = errors.New("identity being matched is nil")
- errNilACL = errors.New("ACL is nil")
nullACL security.ACL
)
@@ -82,13 +81,8 @@
if id == nil {
return errNilID
}
- if acl == nil {
- return errNilACL
- }
- for key, labels := range acl {
- if labels.HasLabel(label) && id.Match(key) {
- return nil
- }
+ if acl.Matches(id, label) {
+ return nil
}
return errACL
}
@@ -96,7 +90,7 @@
func loadACLFromFile(filePath string) (security.ACL, error) {
f, err := os.Open(filePath)
if err != nil {
- return nil, err
+ return nullACL, err
}
defer f.Close()
return security.LoadACL(f)
diff --git a/security/acl_authorizer_test.go b/security/acl_authorizer_test.go
index 6c54ca4..8e58b33 100644
--- a/security/acl_authorizer_test.go
+++ b/security/acl_authorizer_test.go
@@ -162,14 +162,19 @@
var (
veyronPrivateID = security.FakePrivateID("veyron")
alicePrivateID = security.FakePrivateID("alice")
+ bobPrivateID = security.FakePrivateID("bob")
+ chePrivateID = security.FakePrivateID("che")
veyron = veyronPrivateID.PublicID()
alice = alicePrivateID.PublicID()
- bob = security.FakePrivateID("bob").PublicID()
+ bob = bobPrivateID.PublicID()
+ che = chePrivateID.PublicID()
// Blessed principals
veyronAlice = bless(alice, veyronPrivateID, "alice")
veyronBob = bless(bob, veyronPrivateID, "bob")
+ veyronChe = bless(che, veyronPrivateID, "che")
veyronAliceFriend = bless(bob, derive(veyronAlice, alicePrivateID), "friend")
+ veyronCheFriend = bless(che, derive(veyronChe, chePrivateID), "friend")
)
// Convenience function for combining Labels into a LabelSet.
LS := func(labels ...security.Label) security.LabelSet {
@@ -181,11 +186,17 @@
}
// ACL for testing
- acl := security.ACL{
+ acl := security.ACL{}
+ acl.In.Principals = map[security.PrincipalPattern]security.LabelSet{
"*": LS(R),
"fake/veyron/alice/*": LS(W, R),
"fake/veyron/alice": LS(A, D, M),
"fake/veyron/bob": LS(D, M),
+ "fake/veyron/che/*": LS(W, R),
+ "fake/veyron/che": LS(W, R),
+ }
+ acl.NotIn.Principals = map[security.PrincipalPattern]security.LabelSet{
+ "fake/veyron/che/friend": LS(W),
}
// Authorizations for the above ACL.
@@ -193,6 +204,7 @@
// alice and bob have only what "*" has.
alice: LS(R),
bob: LS(R),
+ che: LS(R),
// veyron and veyronAlice have R, W, A, D, M from the "veyron/alice" and
// "veyron/alice/*" ACL entries.
veyron: LS(R, W, A, D, M),
@@ -201,6 +213,11 @@
veyronBob: LS(R, D, M),
// veyronAliceFriend has W, R from the "veyron/alice/*" ACL entry.
veyronAliceFriend: LS(W, R),
+ // veyronChe has W, R from the "veyron/che" entry.
+ veyronChe: LS(W, R),
+ // veyronCheFriend has W, R from the "veyron/che/*" entry, but loses W
+ // from the blacklist entry "veyron/che/friend".
+ veyronCheFriend: LS(R),
// nil PublicIDs are not authorized.
nil: LS(),
}
@@ -219,7 +236,7 @@
// Modify the ACL stored in the file and verify that the authorizations appropriately
// change for the fileACLAuthorizer.
- acl["fake/veyron/bob"] = LS(R, W, A, D, M)
+ acl.In.Principals["fake/veyron/bob"] = LS(R, W, A, D, M)
updateACLInFile(fileName, acl)
authorizations[veyronBob] = LS(R, W, A, D, M)
@@ -243,7 +260,7 @@
}
func TestNilACLAuthorizer(t *testing.T) {
- authorizer := NewACLAuthorizer(nil)
+ authorizer := NewACLAuthorizer(nullACL)
testNothingPermitted(t, authorizer)
testSelfRPCs(t, authorizer)
}
diff --git a/security/caveat/caveat.go b/security/caveat/caveat.go
index a0e0f11..d3da712 100644
--- a/security/caveat/caveat.go
+++ b/security/caveat/caveat.go
@@ -52,7 +52,7 @@
// identified by the PrincipalPatterns on the caveat.
func (c PeerIdentity) Validate(ctx security.Context) error {
for _, p := range c {
- if ctx.LocalID() != nil && ctx.LocalID().Match(p) {
+ if ctx.LocalID() != nil && security.Matches(ctx.LocalID(), p) {
return nil
}
}
diff --git a/security/flag/flag_test.go b/security/flag/flag_test.go
index 03ae915..0f7ff63 100644
--- a/security/flag/flag_test.go
+++ b/security/flag/flag_test.go
@@ -30,7 +30,10 @@
}
var (
acl1 = security.ACL{}
- acl2 = security.ACL{"veyron/alice": security.LabelSet(security.ReadLabel | security.WriteLabel), "veyron/bob": security.LabelSet(security.ReadLabel)}
+ acl2 = security.NewWhitelistACL(map[security.PrincipalPattern]security.LabelSet{
+ "veyron/alice": security.LabelSet(security.ReadLabel | security.WriteLabel),
+ "veyron/bob": security.LabelSet(security.ReadLabel),
+ })
)
acl2File := tsecurity.SaveACLToFile(acl2)
defer os.Remove(acl2File)
@@ -49,11 +52,11 @@
wantAuth: vsecurity.NewACLAuthorizer(acl1),
},
{
- flags: flagValue{"acl": "{\"veyron/alice\":\"RW\", \"veyron/bob\": \"R\"}"},
+ flags: flagValue{"acl": "{\"In\":{\"Principals\":{\"veyron/alice\":\"RW\", \"veyron/bob\": \"R\"}}}"},
wantAuth: vsecurity.NewACLAuthorizer(acl2),
},
{
- flags: flagValue{"acl": "{\"veyron/bob\":\"R\", \"veyron/alice\": \"WR\"}"},
+ flags: flagValue{"acl": "{\"In\":{\"Principals\":{\"veyron/bob\":\"R\", \"veyron/alice\": \"WR\"}}}"},
wantAuth: vsecurity.NewACLAuthorizer(acl2),
},
{
@@ -61,7 +64,7 @@
wantAuth: vsecurity.NewFileACLAuthorizer(acl2File),
},
{
- flags: flagValue{"acl_file": acl2File, "acl": "{\"veyron/alice\":\"RW\", \"veyron/bob\": \"R\"}"},
+ flags: flagValue{"acl_file": acl2File, "acl": "{\"In\":{\"Principals\":{\"veyron/alice\":\"RW\", \"veyron/bob\": \"R\"}}}"},
wantPanic: true,
},
}
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index 0a1d716..b3d8191 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -134,7 +134,9 @@
if err != nil {
return nil, nil, fmt.Errorf("server.Listen(%q, %q) failed: %v", "tcp", *address, err)
}
- allowEveryoneACL := security.ACL{security.AllPrincipals: security.AllLabels}
+ allowEveryoneACL := security.NewWhitelistACL(map[security.PrincipalPattern]security.LabelSet{
+ security.AllPrincipals: security.AllLabels,
+ })
objectname := fmt.Sprintf("identity/%s/google", r.Identity().PublicID().Names()[0])
if err := server.Serve(objectname, ipc.SoloDispatcher(blesser.NewGoogleOAuthBlesserServer(params), vsecurity.NewACLAuthorizer(allowEveryoneACL))); err != nil {
return nil, nil, fmt.Errorf("failed to start Veyron service: %v", err)
diff --git a/services/mounttable/lib/testdata/test.acl b/services/mounttable/lib/testdata/test.acl
index 1a3c98c..b65c35b 100644
--- a/services/mounttable/lib/testdata/test.acl
+++ b/services/mounttable/lib/testdata/test.acl
@@ -1,5 +1,5 @@
{
-"/": {"fake/root": "RW", "*": "R"},
-"/stuff": {"fake/root": "RW", "fake/bob": "R"},
-"/a": {"fake/root": "RW", "fake/alice": "R"}
+"/": {"In": {"Principals": {"fake/root": "RW", "*": "R"}}},
+"/stuff": {"In": {"Principals": {"fake/root": "RW", "fake/bob": "R"}}},
+"/a": {"In": {"Principals": {"fake/root": "RW", "fake/alice": "R"}}}
}
\ No newline at end of file
diff --git a/services/security/dischargerd/main.go b/services/security/dischargerd/main.go
index 2b5524e..6afb52b 100644
--- a/services/security/dischargerd/main.go
+++ b/services/security/dischargerd/main.go
@@ -30,7 +30,10 @@
func authorizer(file string) security.Authorizer {
if file == "" {
- return vsecurity.NewACLAuthorizer(security.ACL{security.AllPrincipals: security.AllLabels})
+ return vsecurity.NewACLAuthorizer(security.NewWhitelistACL(
+ map[security.PrincipalPattern]security.LabelSet{
+ security.AllPrincipals: security.AllLabels,
+ }))
}
return vsecurity.NewFileACLAuthorizer(file)
}
diff --git a/services/wsprd/identity/identity.go b/services/wsprd/identity/identity.go
index 51b8ec6..989be61 100644
--- a/services/wsprd/identity/identity.go
+++ b/services/wsprd/identity/identity.go
@@ -137,7 +137,7 @@
defer i.mu.Unlock()
result := []string{}
for name, id := range i.state.Accounts {
- if id.PublicID().Match(trustedRoot) {
+ if security.Matches(id.PublicID(), trustedRoot) {
result = append(result, name)
}
}
diff --git a/services/wsprd/ipc/server/server.go b/services/wsprd/ipc/server/server.go
index 6f9e601..5349086 100644
--- a/services/wsprd/ipc/server/server.go
+++ b/services/wsprd/ipc/server/server.go
@@ -176,9 +176,11 @@
}
if s.dispatcher == nil {
- s.dispatcher = newDispatcher(invoker, vsecurity.NewACLAuthorizer(
- security.ACL{security.AllPrincipals: security.AllLabels},
- ))
+ s.dispatcher = newDispatcher(invoker,
+ vsecurity.NewACLAuthorizer(security.NewWhitelistACL(
+ map[security.PrincipalPattern]security.LabelSet{
+ security.AllPrincipals: security.AllLabels,
+ })))
}
if s.endpoint == "" {