"x/ref": VDL types for BlessingRoot and BlessingStore
This CL adds VDL types defining the wire formats
for BlessingStore and BlessingRoots.
Additionally, it changes that semantics of BlessingStore.Default()
according to CL: https://vanadium-review.googlesource.com/#/c/9846/
Closes veyron/release-issues#1232
Change-Id: I98545f13f2db695ce4fdeaef99fc40f12ff03d41
diff --git a/lib/security/blessingroots.go b/lib/security/blessingroots.go
index 6ecd0ba..43417b2 100644
--- a/lib/security/blessingroots.go
+++ b/lib/security/blessingroots.go
@@ -20,10 +20,10 @@
persistedData SerializerReaderWriter
signer serialization.Signer
mu sync.RWMutex
- store map[string][]security.BlessingPattern // GUARDED_BY(mu)
+ state blessingRootsState // GUARDED_BY(mu)
}
-func storeMapKey(root security.PublicKey) (string, error) {
+func stateMapKey(root security.PublicKey) (string, error) {
rootBytes, err := root.MarshalBinary()
if err != nil {
return "", err
@@ -32,37 +32,37 @@
}
func (br *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
- key, err := storeMapKey(root)
+ key, err := stateMapKey(root)
if err != nil {
return err
}
br.mu.Lock()
defer br.mu.Unlock()
- patterns := br.store[key]
+ patterns := br.state[key]
for _, p := range patterns {
if p == pattern {
return nil
}
}
- br.store[key] = append(patterns, pattern)
+ br.state[key] = append(patterns, pattern)
if err := br.save(); err != nil {
- br.store[key] = patterns[:len(patterns)-1]
+ br.state[key] = patterns[:len(patterns)-1]
return err
}
return nil
}
func (br *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
- key, err := storeMapKey(root)
+ key, err := stateMapKey(root)
if err != nil {
return err
}
br.mu.RLock()
defer br.mu.RUnlock()
- for _, p := range br.store[key] {
+ for _, p := range br.state[key] {
if p.MatchedBy(blessing) {
return nil
}
@@ -82,7 +82,7 @@
const format = "%-47s %s\n"
b := bytes.NewBufferString(fmt.Sprintf(format, "Public key", "Pattern"))
var s rootSorter
- for keyBytes, patterns := range br.store {
+ for keyBytes, patterns := range br.state {
key, err := security.UnmarshalPublicKey([]byte(keyBytes))
if err != nil {
return fmt.Sprintf("failed to decode public key: %v", err)
@@ -115,7 +115,7 @@
if err != nil {
return err
}
- return encodeAndStore(br.store, data, signature, br.signer)
+ return encodeAndStore(br.state, data, signature, br.signer)
}
// newInMemoryBlessingRoots returns an in-memory security.BlessingRoots.
@@ -123,7 +123,7 @@
// The returned BlessingRoots is initialized with an empty set of keys.
func newInMemoryBlessingRoots() security.BlessingRoots {
return &blessingRoots{
- store: make(map[string][]security.BlessingPattern),
+ state: make(blessingRootsState),
}
}
@@ -135,7 +135,7 @@
return nil, verror.New(errDataOrSignerUnspecified, nil)
}
br := &blessingRoots{
- store: make(map[string][]security.BlessingPattern),
+ state: make(blessingRootsState),
persistedData: persistedData,
signer: signer,
}
@@ -144,7 +144,7 @@
return nil, err
}
if (data != nil) && (signature != nil) {
- if err := decodeFromStorage(&br.store, data, signature, br.signer.PublicKey()); err != nil {
+ if err := decodeFromStorage(&br.state, data, signature, br.signer.PublicKey()); err != nil {
return nil, err
}
}
diff --git a/lib/security/blessingstore.go b/lib/security/blessingstore.go
index 381ec87..8397294 100644
--- a/lib/security/blessingstore.go
+++ b/lib/security/blessingstore.go
@@ -27,24 +27,14 @@
errDataOrSignerUnspecified = verror.Register(pkgPath+".errDataOrSignerUnspecified", verror.NoRetry, "{1:}{2:} persisted data or signer is not specified{:_}")
)
-// TODO(ashankar,ataly): The only reason that Value is encapsulated in a struct
-// is for backward compatibility. We should probably restore "oldState" and
-// get rid of this.
+// TODO(ataly, ashankar): Get rid of this struct once we have switched all
+// credentials directories to the new serialization format.
type blessings struct {
Value security.Blessings
}
-func (w *blessings) Blessings() security.Blessings {
- if w == nil {
- return security.Blessings{}
- }
- return w.Value
-}
-
-func newWireBlessings(b security.Blessings) *blessings {
- return &blessings{Value: b}
-}
-
+// TODO(ataly, ashankar): Get rid of this struct once we have switched all
+// credentials directories to the new serialization format.
type state struct {
// Store maps BlessingPatterns to the Blessings object that is to be shared
// with peers which present blessings of their own that match the pattern.
@@ -62,7 +52,7 @@
serializer SerializerReaderWriter
signer serialization.Signer
mu sync.RWMutex
- state state // GUARDED_BY(mu)
+ state blessingStoreState // GUARDED_BY(mu)
}
func (bs *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
@@ -74,21 +64,21 @@
}
bs.mu.Lock()
defer bs.mu.Unlock()
- old, hadold := bs.state.Store[forPeers]
+ old, hadold := bs.state.PeerBlessings[forPeers]
if !blessings.IsZero() {
- bs.state.Store[forPeers] = newWireBlessings(blessings)
+ bs.state.PeerBlessings[forPeers] = blessings
} else {
- delete(bs.state.Store, forPeers)
+ delete(bs.state.PeerBlessings, forPeers)
}
if err := bs.save(); err != nil {
if hadold {
- bs.state.Store[forPeers] = old
+ bs.state.PeerBlessings[forPeers] = old
} else {
- delete(bs.state.Store, forPeers)
+ delete(bs.state.PeerBlessings, forPeers)
}
return security.Blessings{}, err
}
- return old.Blessings(), nil
+ return old, nil
}
func (bs *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
@@ -96,9 +86,8 @@
defer bs.mu.RUnlock()
var ret security.Blessings
- for pattern, wb := range bs.state.Store {
+ for pattern, b := range bs.state.PeerBlessings {
if pattern.MatchedBy(peerBlessings...) {
- b := wb.Blessings()
if union, err := security.UnionOfBlessings(ret, b); err != nil {
vlog.Errorf("UnionOfBlessings(%v, %v) failed: %v, dropping the latter from BlessingStore.ForPeers(%v)", ret, b, err, peerBlessings)
} else {
@@ -112,10 +101,7 @@
func (bs *blessingStore) Default() security.Blessings {
bs.mu.RLock()
defer bs.mu.RUnlock()
- if bs.state.Default != nil {
- return bs.state.Default.Blessings()
- }
- return bs.ForPeer()
+ return bs.state.DefaultBlessings
}
func (bs *blessingStore) SetDefault(blessings security.Blessings) error {
@@ -124,10 +110,11 @@
if !blessings.IsZero() && !reflect.DeepEqual(blessings.PublicKey(), bs.publicKey) {
return verror.New(errStoreAddMismatch, nil)
}
- oldDefault := bs.state.Default
- bs.state.Default = newWireBlessings(blessings)
+ oldDefault := bs.state.DefaultBlessings
+ bs.state.DefaultBlessings = blessings
if err := bs.save(); err != nil {
- bs.state.Default = oldDefault
+ bs.state.DefaultBlessings = oldDefault
+ return err
}
return nil
}
@@ -142,8 +129,8 @@
func (bs *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
m := make(map[security.BlessingPattern]security.Blessings)
- for pattern, wb := range bs.state.Store {
- m[pattern] = wb.Blessings()
+ for pattern, b := range bs.state.PeerBlessings {
+ m[pattern] = b
}
return m
}
@@ -157,20 +144,19 @@
// <pattern> <blessings>
func (bs *blessingStore) DebugString() string {
const format = "%-30s %s\n"
- b := bytes.NewBufferString(fmt.Sprintf(format, "Default Blessings", bs.state.Default.Blessings()))
+ buff := bytes.NewBufferString(fmt.Sprintf(format, "Default Blessings", bs.state.DefaultBlessings))
- b.WriteString(fmt.Sprintf(format, "Peer pattern", "Blessings"))
+ buff.WriteString(fmt.Sprintf(format, "Peer pattern", "Blessings"))
- sorted := make([]string, 0, len(bs.state.Store))
- for k, _ := range bs.state.Store {
+ sorted := make([]string, 0, len(bs.state.PeerBlessings))
+ for k, _ := range bs.state.PeerBlessings {
sorted = append(sorted, string(k))
}
sort.Strings(sorted)
for _, pattern := range sorted {
- wb := bs.state.Store[security.BlessingPattern(pattern)]
- b.WriteString(fmt.Sprintf(format, pattern, wb.Blessings()))
+ buff.WriteString(fmt.Sprintf(format, pattern, bs.state.PeerBlessings[security.BlessingPattern(pattern)]))
}
- return b.String()
+ return buff.String()
}
func (bs *blessingStore) save() error {
@@ -191,50 +177,18 @@
func newInMemoryBlessingStore(publicKey security.PublicKey) security.BlessingStore {
return &blessingStore{
publicKey: publicKey,
- state: state{Store: make(map[security.BlessingPattern]*blessings)},
+ state: blessingStoreState{PeerBlessings: make(map[security.BlessingPattern]security.Blessings)},
}
}
-// TODO(ataly, ashankar): Get rid of this struct once we have switched all
-// credentials directories to the new serialization format. Or maybe we should
-// restore this and get rid of "type state". Probably should define the
-// serialization format in VDL!
-type oldState struct {
- Store map[security.BlessingPattern]security.Blessings
- Default security.Blessings
-}
-
-// TODO(ataly, ashankar): Get rid of this method once we have switched all
-// credentials directories to the new serialization format.
-func (bs *blessingStore) tryOldFormat() bool {
- var empty security.Blessings
- if len(bs.state.Store) == 0 {
- return bs.state.Default.Value.IsZero() || reflect.DeepEqual(bs.state.Default.Value, empty)
- }
- for _, wb := range bs.state.Store {
- if wb.Value.IsZero() {
- return true
- }
- }
- return false
-}
-
func (bs *blessingStore) verifyState() error {
- verifyBlessings := func(wb *blessings, key security.PublicKey) error {
- if b := wb.Blessings(); !reflect.DeepEqual(b.PublicKey(), key) {
- return verror.New(errBlessingsNotForKey, nil, b, key)
- }
- return nil
- }
- for _, wb := range bs.state.Store {
- if err := verifyBlessings(wb, bs.publicKey); err != nil {
- return err
+ for _, b := range bs.state.PeerBlessings {
+ if !reflect.DeepEqual(b.PublicKey(), bs.publicKey) {
+ return verror.New(errBlessingsNotForKey, nil, b, bs.publicKey)
}
}
- if bs.state.Default != nil {
- if err := verifyBlessings(bs.state.Default, bs.publicKey); err != nil {
- return err
- }
+ if !bs.state.DefaultBlessings.IsZero() && !reflect.DeepEqual(bs.state.DefaultBlessings.PublicKey(), bs.publicKey) {
+ return verror.New(errBlessingsNotForKey, nil, bs.state.DefaultBlessings, bs.publicKey)
}
return nil
}
@@ -249,24 +203,32 @@
if data == nil && signature == nil {
return nil
}
- var old oldState
+
+ var old state
if err := decodeFromStorage(&old, data, signature, bs.signer.PublicKey()); err != nil {
return err
}
- for p, wire := range old.Store {
- bs.state.Store[p] = &blessings{Value: wire}
+
+ for p, wb := range old.Store {
+ if wb != nil {
+ bs.state.PeerBlessings[p] = wb.Value
+ }
}
- bs.state.Default = &blessings{Value: old.Default}
+ if old.Default != nil {
+ bs.state.DefaultBlessings = old.Default.Value
+ }
if err := bs.verifyState(); err != nil {
return err
}
+
// Save the blessingstore in the new serialization format. This will ensure
// that all credentials directories in the old format will switch to the new
// format.
if err := bs.save(); err != nil {
return err
}
+
return nil
}
@@ -278,13 +240,10 @@
if data == nil && signature == nil {
return nil
}
- if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err == nil && !bs.tryOldFormat() {
- return bs.verifyState()
+ if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err != nil {
+ return bs.deserializeOld()
}
- if err := bs.deserializeOld(); err != nil {
- return err
- }
- return nil
+ return bs.verifyState()
}
// newPersistingBlessingStore returns a security.BlessingStore for a principal
@@ -296,7 +255,7 @@
}
bs := &blessingStore{
publicKey: signer.PublicKey(),
- state: state{Store: make(map[security.BlessingPattern]*blessings)},
+ state: blessingStoreState{PeerBlessings: make(map[security.BlessingPattern]security.Blessings)},
serializer: serializer,
signer: signer,
}
diff --git a/lib/security/blessingstore_test.go b/lib/security/blessingstore_test.go
index cd86c37..8177624 100644
--- a/lib/security/blessingstore_test.go
+++ b/lib/security/blessingstore_test.go
@@ -50,10 +50,7 @@
return nil
}
-func (t *storeTester) testSetDefault(s security.BlessingStore, currentDefault security.Blessings) error {
- if got := s.Default(); !reflect.DeepEqual(got, currentDefault) {
- return fmt.Errorf("Default(): got: %v, want: %v", got, currentDefault)
- }
+func (t *storeTester) testSetDefault(s security.BlessingStore) error {
if err := s.SetDefault(security.Blessings{}); err != nil {
return fmt.Errorf("SetDefault({}): %v", err)
}
@@ -140,7 +137,7 @@
if err := tester.testForPeer(s); err != nil {
t.Error(err)
}
- if err := tester.testSetDefault(s, tester.forAll); err != nil {
+ if err := tester.testSetDefault(s); err != nil {
t.Error(err)
}
}
@@ -164,7 +161,7 @@
if err := tester.testForPeer(s); err != nil {
t.Error(err)
}
- if err := tester.testSetDefault(s, tester.forAll); err != nil {
+ if err := tester.testSetDefault(s); err != nil {
t.Error(err)
}
diff --git a/lib/security/type.vdl b/lib/security/type.vdl
new file mode 100644
index 0000000..9d65571
--- /dev/null
+++ b/lib/security/type.vdl
@@ -0,0 +1,21 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package security
+
+import "v.io/v23/security"
+
+type blessingRootsState map[string][]security.BlessingPattern
+
+type blessingStoreState struct {
+ // PeerBlessings maps BlessingPatterns to the Blessings object that is to
+ // be shared with peers which present blessings of their own that match the
+ // pattern.
+ //
+ // All blessings bind to the same public key.
+ PeerBlessings map[security.BlessingPattern]security.WireBlessings
+ // DefaultBlessings is the default Blessings to be shared with peers for which
+ // no other information is available to select blessings.
+ DefaultBlessings security.WireBlessings
+}
diff --git a/lib/security/type.vdl.go b/lib/security/type.vdl.go
new file mode 100644
index 0000000..127698b
--- /dev/null
+++ b/lib/security/type.vdl.go
@@ -0,0 +1,45 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file was auto-generated by the vanadium vdl tool.
+// Source: type.vdl
+
+package security
+
+import (
+ // VDL system imports
+ "v.io/v23/vdl"
+
+ // VDL user imports
+ "v.io/v23/security"
+)
+
+type blessingRootsState map[string][]security.BlessingPattern
+
+func (blessingRootsState) __VDLReflect(struct {
+ Name string "v.io/x/ref/lib/security.blessingRootsState"
+}) {
+}
+
+type blessingStoreState struct {
+ // PeerBlessings maps BlessingPatterns to the Blessings object that is to
+ // be shared with peers which present blessings of their own that match the
+ // pattern.
+ //
+ // All blessings bind to the same public key.
+ PeerBlessings map[security.BlessingPattern]security.Blessings
+ // DefaultBlessings is the default Blessings to be shared with peers for which
+ // no other information is available to select blessings.
+ DefaultBlessings security.Blessings
+}
+
+func (blessingStoreState) __VDLReflect(struct {
+ Name string "v.io/x/ref/lib/security.blessingStoreState"
+}) {
+}
+
+func init() {
+ vdl.Register((*blessingRootsState)(nil))
+ vdl.Register((*blessingStoreState)(nil))
+}