Remove the old security model.
This change removes all the implementation and a bulk of the interfaces
for the old veyron security model.
The PublicID type is still left in veyron2/security/model.go, it will be
removed once I remove a few unnecessary usage of it in the store and
wspr repositories.
Change-Id: I639047c4dc6ca70d3f4019f6556ba93bb9a9dced
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index b2bd087..25f67ea 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -11,7 +11,6 @@
"veyron.io/veyron/veyron/runtimes/google/ipc/version"
inaming "veyron.io/veyron/veyron/runtimes/google/naming"
- isecurity "veyron.io/veyron/veyron/runtimes/google/security"
"veyron.io/veyron/veyron/runtimes/google/vtrace"
"veyron.io/veyron/veyron2/context"
@@ -251,8 +250,7 @@
// LocalPrincipal is nil means that the client wanted to avoid authentication,
// and thus wanted to skip authorization as well.
- // TODO(suharshs,ataly,ashankar): Remove flow.LocalID() after the old security model is dead.
- if flow.LocalPrincipal() != nil || flow.LocalID() != nil {
+ if flow.LocalPrincipal() != nil {
// Validate caveats on the server's identity for the context associated with this call.
if serverB, grantedB, err = c.authorizeServer(flow, name, suffix, method, opts); err != nil {
lastErr = verror.NoAccessf("ipc: client unwilling to invoke %q.%q on server %v: %v", name, method, flow.RemoteBlessings(), err)
@@ -303,35 +301,10 @@
// server that are authorized for this purpose and any blessings that are to be granted to
// the server (via ipc.Granter implementations in opts.)
func (c *client) authorizeServer(flow stream.Flow, name, suffix, method string, opts []ipc.CallOpt) (serverBlessings []string, grantedBlessings security.Blessings, err error) {
- if flow.RemoteID() == nil && flow.RemoteBlessings() == nil {
+ if flow.RemoteBlessings() == nil {
return nil, nil, fmt.Errorf("server has not presented any blessings")
}
- authctx := isecurity.NewContext(isecurity.ContextArgs{
- LocalID: flow.LocalID(),
- RemoteID: flow.RemoteID(),
- Debug: "ClientAuthorizingServer",
- LocalPrincipal: flow.LocalPrincipal(),
- LocalBlessings: flow.LocalBlessings(),
- RemoteBlessings: flow.RemoteBlessings(),
- /* TODO(ashankar,ataly): Uncomment this! This is disabled till the hack to skip third-party caveat
- validation on a server's blessings are disabled. Commenting out the next three lines affects more
- than third-party caveats, so yeah, have to remove this soon!
- Method: method,
- Name: name,
- Suffix: suffix, */
- LocalEndpoint: flow.LocalEndpoint(),
- RemoteEndpoint: flow.RemoteEndpoint(),
- })
- if serverID := flow.RemoteID(); flow.RemoteBlessings() == nil && serverID != nil {
- serverID, err = serverID.Authorize(authctx)
- if err != nil {
- return nil, nil, err
- }
- serverBlessings = serverID.Names()
- }
- if server := flow.RemoteBlessings(); server != nil {
- serverBlessings = server.ForContext(authctx)
- }
+ serverBlessings = flow.RemoteBlessings().ForContext(serverAuthContext{flow})
for _, o := range opts {
switch v := o.(type) {
case options.RemoteID:
@@ -582,3 +555,19 @@
func (fc *flowClient) RemoteBlessings() ([]string, security.Blessings) {
return fc.server, fc.flow.RemoteBlessings()
}
+
+// serverAuthContext is the security.Context implementation used by a client to
+// authorize a server.
+type serverAuthContext struct {
+ stream.Flow
+}
+
+// TODO(ashankar,ataly): Set Method, Name, Suffix etc. once third-party caveat
+// validation for a server's blessings are eanbled.
+// Returning zero values affects more than third-party caveats, so yeah, have
+// to remove them soon!
+func (serverAuthContext) Method() string { return "" }
+func (serverAuthContext) Name() string { return "" }
+func (serverAuthContext) Suffix() string { return "" }
+func (serverAuthContext) Label() (l security.Label) { return l }
+func (serverAuthContext) Discharges() map[string]security.Discharge { return nil }
diff --git a/runtimes/google/ipc/flow_test.go b/runtimes/google/ipc/flow_test.go
index 183930b..b78a56f 100644
--- a/runtimes/google/ipc/flow_test.go
+++ b/runtimes/google/ipc/flow_test.go
@@ -40,8 +40,6 @@
func (f *testFlow) Write(b []byte) (int, error) { return f.w.Write(b) }
func (f *testFlow) LocalEndpoint() naming.Endpoint { return nil }
func (f *testFlow) RemoteEndpoint() naming.Endpoint { return nil }
-func (f *testFlow) LocalID() security.PublicID { return nil }
-func (f *testFlow) RemoteID() security.PublicID { return nil }
func (f *testFlow) LocalPrincipal() security.Principal { return f.p }
func (f *testFlow) LocalBlessings() security.Blessings { return f.lb }
func (f *testFlow) RemoteBlessings() security.Blessings { return f.rb }
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 0f0f3a9..3ffc9cb 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -674,14 +674,6 @@
pclient.BlessingStore().Set(nil, security.AllPrincipals)
type v []interface{}
- type testcase struct {
- clientID security.PrivateID
- name string
- method string
- args v
- results v
- finishErr string
- }
tests := []struct {
blessings security.Blessings // Blessings used by the client
name string // object name on which the method is invoked
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index 39e0649..002a233 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -27,7 +27,6 @@
"veyron.io/veyron/veyron/lib/netstate"
"veyron.io/veyron/veyron/runtimes/google/lib/publisher"
inaming "veyron.io/veyron/veyron/runtimes/google/naming"
- isecurity "veyron.io/veyron/veyron/runtimes/google/security"
ivtrace "veyron.io/veyron/veyron/runtimes/google/vtrace"
vsecurity "veyron.io/veyron/veyron/security"
"veyron.io/veyron/veyron/services/mgmt/debug"
@@ -630,18 +629,15 @@
enc *vom.Encoder // to encode responses and results to the client
flow stream.Flow // underlying flow
debugDisp ipc.Dispatcher // internal debug dispatcher
- // Fields filled in during the server invocation.
- // authorizedRemoteID is the PublicID obtained after authorizing the remoteID
- // of the underlying flow for the current request context.
- authorizedRemoteID security.PublicID
- blessings security.Blessings
- method, suffix string
- label security.Label
- discharges map[string]security.Discharge
- deadline time.Time
- endStreamArgs bool // are the stream args at EOF?
- allowDebug bool // true if the caller is permitted to view debug information.
+ // Fields filled in during the server invocation.
+ blessings security.Blessings
+ method, suffix string
+ label security.Label
+ discharges map[string]security.Discharge
+ deadline time.Time
+ endStreamArgs bool // are the stream args at EOF?
+ allowDebug bool // true if the caller is permitted to view debug information.
}
var _ ipc.Stream = (*flowServer)(nil)
@@ -693,12 +689,7 @@
}
func defaultAuthorizer(ctx security.Context) security.Authorizer {
- var blessings []string
- if ctx.LocalBlessings() == nil { // TODO(ashankar): This will go away once the old security model is removed
- blessings = ctx.LocalID().Names()
- } else {
- blessings = ctx.LocalBlessings().ForContext(ctx)
- }
+ blessings := ctx.LocalBlessings().ForContext(ctx)
acl := security.ACL{In: make(map[security.BlessingPattern]security.LabelSet)}
for _, b := range blessings {
acl.In[security.BlessingPattern(b).MakeGlob()] = security.AllLabels
@@ -851,26 +842,11 @@
return nil, verror.BadProtocolf("ipc: arg %d decoding failed: %v", ix, err)
}
}
- if remoteID := fs.flow.RemoteID(); remoteID != nil {
- // TODO(ashankar): This whole check goes away once the old security model is ripped out.
- if fs.authorizedRemoteID, err = remoteID.Authorize(isecurity.NewContext(isecurity.ContextArgs{
- LocalID: fs.flow.LocalID(),
- RemoteID: fs.flow.RemoteID(),
- Method: fs.method,
- Suffix: fs.suffix,
- Discharges: fs.discharges,
- Label: fs.label,
- })); err != nil {
- return nil, verror.NoAccessf("%v is not authorized to call %q.%q (%v)", fs.RemoteID(), fs.Name(), fs.Method(), err)
- }
- }
-
fs.allowDebug = fs.LocalPrincipal() == nil
// Check application's authorization policy and invoke the method.
// LocalPrincipal is nil means that the server wanted to avoid authentication,
// and thus wanted to skip authorization as well.
- // TODO(suharshs,ataly,ashankar): Remove fs.LocalID() after the old security model is dead.
- if fs.LocalPrincipal() != nil || fs.LocalID() != nil {
+ if fs.LocalPrincipal() != nil {
// Check if the caller is permitted to view debug information.
if err := fs.authorize(auth); err != nil {
return nil, err
@@ -1012,10 +988,7 @@
}
if err := auth.Authorize(fs); err != nil {
// TODO(ataly, ashankar): For privacy reasons, should we hide the authorizer error?
- if fs.RemoteBlessings() != nil {
- return verror.NoAccessf("ipc: %v not authorized to call %q.%q (%v)", fs.RemoteBlessings(), fs.Name(), fs.Method(), err)
- }
- return verror.NoAccessf("ipc: %v (deprecated security model) is not authorized to call %q.%q (%v)", fs.RemoteID(), fs.Name(), fs.Method(), err)
+ return verror.NoAccessf("ipc: %v not authorized to call %q.%q (%v)", fs.RemoteBlessings(), fs.Name(), fs.Method(), err)
}
return nil
}
@@ -1091,15 +1064,6 @@
//nologcall
return fs.label
}
-
-func (fs *flowServer) LocalID() security.PublicID {
- //nologcall
- return fs.flow.LocalID()
-}
-func (fs *flowServer) RemoteID() security.PublicID {
- //nologcall
- return fs.authorizedRemoteID
-}
func (fs *flowServer) LocalPrincipal() security.Principal {
//nologcall
return fs.flow.LocalPrincipal()
diff --git a/runtimes/google/ipc/stream/proxy/proxy.go b/runtimes/google/ipc/stream/proxy/proxy.go
index 683ea0c..8e9c509 100644
--- a/runtimes/google/ipc/stream/proxy/proxy.go
+++ b/runtimes/google/ipc/stream/proxy/proxy.go
@@ -77,7 +77,7 @@
}
}
func (s *server) String() string {
- return fmt.Sprintf("RoutingID %v on process %v (VCI:%v ID:%v)", s.RoutingID(), s.Process, s.VC.VCI(), s.VC.RemoteID())
+ return fmt.Sprintf("RoutingID %v on process %v (VCI:%v Blessings:%v)", s.RoutingID(), s.Process, s.VC.VCI(), s.VC.RemoteBlessings())
}
// servermap is a concurrent-access safe map from the RoutingID of a server exporting itself
diff --git a/runtimes/google/ipc/stream/vc/auth.go b/runtimes/google/ipc/stream/vc/auth.go
index 5746a99..af2be25 100644
--- a/runtimes/google/ipc/stream/vc/auth.go
+++ b/runtimes/google/ipc/stream/vc/auth.go
@@ -15,213 +15,19 @@
"veyron.io/veyron/veyron2/vom"
)
-const (
- clientChannelEnd = "client"
- serverChannelEnd = "server"
-)
-
var (
authServerContextTag = []byte("VCauthS\x00")
authClientContextTag = []byte("VCauthC\x00")
)
-// authenticateAsServer executes the authentication protocol at the server and
-// returns the identity of the client and server.
-func authenticateAsServerOld(conn io.ReadWriteCloser, localID LocalID, crypter crypto.Crypter, v version.IPCVersion) (clientID, serverID security.PublicID, err error) {
- // The authentication protocol has the server doing the final read, so
- // it is the one that closes the connection.
- defer conn.Close()
- if serverID, err = localID.AsServer(); err != nil {
- return
- }
- if err = writeIdentity(conn, serverChannelEnd, authServerContextTag, crypter, localID, serverID, v); err != nil {
- return
- }
- clientID, err = readIdentity(conn, clientChannelEnd, authClientContextTag, crypter, v)
- return
-}
-
-// authenticateAsClient executes the authentication protocol at the client and
-// returns the identity of the server.
-//
-// If serverName is non-nil, the authentication protocol will be considered
-// successfull iff the server identity matches the provided regular expression.
-func authenticateAsClientOld(conn io.ReadWriteCloser, localID LocalID, crypter crypto.Crypter, v version.IPCVersion) (serverID, clientID security.PublicID, err error) {
- defer conn.Close()
- if serverID, err = readIdentity(conn, serverChannelEnd, authServerContextTag, crypter, v); err != nil {
- return
- }
- if clientID, err = localID.AsClient(serverID); err != nil {
- return
- }
- err = writeIdentity(conn, clientChannelEnd, authClientContextTag, crypter, localID, clientID, v)
- return
-}
-
-// identityMessage encapsulates information sent across the wire by a principal
-// to introduce itself.
-//
-// Each field in the message is encrypted by the sender.
-type identityMessage struct {
- ChannelID []byte
- ID []byte // VOM-encoded
- SignR []byte
- SignS []byte
- Signature []byte // VOM-encoded
-}
-
var (
errSameChannelPublicKey = errors.New("same public keys for both ends of the channel")
errChannelIDMismatch = errors.New("channel id does not match expectation")
- errInvalidIdentityInMessage = errors.New("invalid identity in authentication message")
errInvalidSignatureInMessage = errors.New("signature does not verify in authentication handshake message")
errNoCertificatesReceived = errors.New("no certificates received")
errSingleCertificateRequired = errors.New("exactly one X.509 certificate chain with exactly one certificate is required")
)
-func writeIdentity(w io.Writer, chEnd string, contextTag []byte, crypter crypto.Crypter, id LocalID, pub security.PublicID, v version.IPCVersion) error {
- // TODO(ashankar): Remove references to protocol V1 and V2 before release
- if v != version.UnknownIPCVersion && v < version.IPCVersion2 {
- return fmt.Errorf("cannot authenticate with deprecated RPC protocol version(%v)", v)
- }
- if v == version.IPCVersion2 {
- // Compute channel id - encrypted chEnd string
- chid, err := crypter.Encrypt(iobuf.NewSlice([]byte(chEnd)))
- if err != nil {
- return err
- }
- defer chid.Release()
-
- // VOM-encode and encrypt the (public) identity.
- var buf bytes.Buffer
- if err := vom.NewEncoder(&buf).Encode(pub); err != nil {
- return err
- }
- eid, err := crypter.Encrypt(iobuf.NewSlice(buf.Bytes()))
- if err != nil {
- return err
- }
- defer eid.Release()
-
- // Sign the channel ID
- signature, err := id.Sign(chid.Contents)
- if err != nil {
- return err
- }
- msg := identityMessage{
- ID: eid.Contents,
- ChannelID: chid.Contents,
- }
- buf = bytes.Buffer{}
- if err := vom.NewEncoder(&buf).Encode(signature); err != nil {
- return err
- }
- esig, err := crypter.Encrypt(iobuf.NewSlice(buf.Bytes()))
- if err != nil {
- return err
- }
- defer esig.Release()
- msg.Signature = esig.Contents
- // Write the message out.
- return vom.NewEncoder(w).Encode(msg)
- }
- // v == version.IPCVersion3
- signature, err := id.Sign(append(contextTag, crypter.ChannelBinding()...))
- if err != nil {
- return err
- }
- var buf bytes.Buffer
- ve := vom.NewEncoder(&buf)
- if err := ve.Encode(pub); err != nil {
- return err
- }
- if err := ve.Encode(signature); err != nil {
- return err
- }
- msg, err := crypter.Encrypt(iobuf.NewSlice(buf.Bytes()))
- if err != nil {
- return err
- }
- defer msg.Release()
- return vom.NewEncoder(w).Encode(msg.Contents)
-}
-
-func readIdentity(reader io.Reader, expectedChEnd string, contextTag []byte, crypter crypto.Crypter, v version.IPCVersion) (security.PublicID, error) {
- if v != version.UnknownIPCVersion && v < version.IPCVersion2 {
- return nil, fmt.Errorf("cannot authenticate with deprecated RPC protocol version(%v)", v)
- }
- if v == version.IPCVersion2 {
- // Read the message.
- var msg identityMessage
- if err := vom.NewDecoder(reader).Decode(&msg); err != nil {
- return nil, fmt.Errorf("failed to decode identityMessage: %v", err)
- }
-
- // Decrypt and authenticate the channel id
- chEnd, err := crypter.Decrypt(iobuf.NewSlice(msg.ChannelID))
- if err != nil {
- return nil, fmt.Errorf("failed to decrypt ChannelID: %v", err)
- }
- defer chEnd.Release()
- if bytes.Compare([]byte(expectedChEnd), chEnd.Contents) != 0 {
- return nil, errChannelIDMismatch
- }
-
- // Decrypt and VOM-decode the identity
- idbytes, err := crypter.Decrypt(iobuf.NewSlice(msg.ID))
- if err != nil {
- return nil, fmt.Errorf("failed to decrypt security.PublicID: %v", err)
- }
- defer idbytes.Release()
- var id security.PublicID
- if err := vom.NewDecoder(bytes.NewBuffer(idbytes.Contents)).Decode(&id); err != nil {
- return nil, fmt.Errorf("failed to decode security.PublicID: %v", err)
- }
- if id == nil || id.PublicKey() == nil {
- return nil, errInvalidIdentityInMessage
- }
-
- // Decrypt the signature
- sigbytes, err := crypter.Decrypt(iobuf.NewSlice(msg.Signature))
- if err != nil {
- return nil, fmt.Errorf("failed to decrypt Signature: %v", err)
- }
- defer sigbytes.Release()
- var sig security.Signature
- if err = vom.NewDecoder(bytes.NewBuffer(sigbytes.Contents)).Decode(&sig); err != nil {
- return nil, fmt.Errorf("failed to decode security.Signature: %v", err)
- }
- // Validate the signature
- if !sig.Verify(id.PublicKey(), msg.ChannelID) {
- return nil, errInvalidSignatureInMessage
- }
- return id, nil
- }
- // v == version.IPCVersion3
- var encryptedHandshake []byte
- if err := vom.NewDecoder(reader).Decode(&encryptedHandshake); err != nil {
- return nil, fmt.Errorf("failed to read handshake: %v", err)
- }
- handshake, err := crypter.Decrypt(iobuf.NewSlice(encryptedHandshake))
- if err != nil {
- return nil, fmt.Errorf("failed to decrypt handshake: %v", err)
- }
- defer handshake.Release()
- vd := vom.NewDecoder(bytes.NewBuffer(handshake.Contents))
- var id security.PublicID
- if err := vd.Decode(&id); err != nil {
- return nil, fmt.Errorf("failed to decode security.PublicID: %v", err)
- }
- var signature security.Signature
- if err := vd.Decode(&signature); err != nil {
- return nil, fmt.Errorf("failed to decode security.Signature: %v", err)
- }
- if !signature.Verify(id.PublicKey(), append(contextTag, crypter.ChannelBinding()...)) {
- return nil, errInvalidSignatureInMessage
- }
- return id, nil
-}
-
// authenticateAsServer executes the authentication protocol at the server and
// returns the blessings used to authenticate both ends.
func authenticateAsServer(conn io.ReadWriteCloser, principal security.Principal, crypter crypto.Crypter, v version.IPCVersion) (client, server security.Blessings, err error) {
@@ -336,12 +142,10 @@
func (*serverAuthContext) Method() string { return "" }
func (*serverAuthContext) Name() string { return "" }
func (*serverAuthContext) Suffix() string { return "" }
-func (*serverAuthContext) Label() security.Label { return security.ReadLabel }
+func (*serverAuthContext) Label() (l security.Label) { return l }
func (c *serverAuthContext) Discharges() map[string]security.Discharge { return nil }
func (c *serverAuthContext) LocalPrincipal() security.Principal { return c.self }
func (c *serverAuthContext) LocalBlessings() security.Blessings { return nil }
func (c *serverAuthContext) RemoteBlessings() security.Blessings { return c.remote }
-func (c *serverAuthContext) LocalID() security.PublicID { return nil }
-func (c *serverAuthContext) RemoteID() security.PublicID { return nil }
func (c *serverAuthContext) LocalEndpoint() naming.Endpoint { return nil }
func (c *serverAuthContext) RemoteEndpoint() naming.Endpoint { return nil }
diff --git a/runtimes/google/ipc/stream/vc/flow.go b/runtimes/google/ipc/stream/vc/flow.go
index 1523736..e3ca561 100644
--- a/runtimes/google/ipc/stream/vc/flow.go
+++ b/runtimes/google/ipc/stream/vc/flow.go
@@ -1,25 +1,18 @@
package vc
import (
- "net"
-
- "veyron.io/veyron/veyron2/ipc/stream"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/security"
)
type flow struct {
- idHolder
+ authN // authentication information.
*reader
*writer
localEndpoint, remoteEndpoint naming.Endpoint
}
-var _ stream.Flow = (*flow)(nil)
-
-type idHolder interface {
- LocalID() security.PublicID
- RemoteID() security.PublicID
+type authN interface {
LocalPrincipal() security.Principal
LocalBlessings() security.Blessings
RemoteBlessings() security.Blessings
@@ -28,9 +21,6 @@
func (f *flow) LocalEndpoint() naming.Endpoint { return f.localEndpoint }
func (f *flow) RemoteEndpoint() naming.Endpoint { return f.remoteEndpoint }
-// implement net.Conn
-func (f *flow) LocalAddr() net.Addr { return f.localEndpoint }
-func (f *flow) RemoteAddr() net.Addr { return f.remoteEndpoint }
func (f *flow) Close() error {
f.reader.Close()
f.writer.Close()
diff --git a/runtimes/google/ipc/stream/vc/init.go b/runtimes/google/ipc/stream/vc/init.go
index 96c21bd..ee13672 100644
--- a/runtimes/google/ipc/stream/vc/init.go
+++ b/runtimes/google/ipc/stream/vc/init.go
@@ -6,13 +6,10 @@
"crypto/rand"
"fmt"
- isecurity "veyron.io/veyron/veyron/runtimes/google/security"
-
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/vlog"
)
-var anonymousID security.PrivateID
var anonymousPrincipal security.Principal
func init() {
@@ -27,9 +24,6 @@
if store.b, err = anonymousPrincipal.BlessSelf("anonymous"); err != nil {
vlog.Fatalf("failed to generate the one blessing to be used by the anonymous principal: %v", err)
}
- if anonymousID, err = isecurity.NewPrivateID("anonymous", nil); err != nil {
- vlog.Fatalf("could not create anonymousID for IPCs: %v", err)
- }
}
// TODO(ashankar,ataly): Figure out what to do with this!
diff --git a/runtimes/google/ipc/stream/vc/listener_test.go b/runtimes/google/ipc/stream/vc/listener_test.go
index e8931f7..90a3143 100644
--- a/runtimes/google/ipc/stream/vc/listener_test.go
+++ b/runtimes/google/ipc/stream/vc/listener_test.go
@@ -24,8 +24,6 @@
func (*noopFlow) LocalBlessings() security.Blessings { return nil }
func (*noopFlow) RemoteBlessings() security.Blessings { return nil }
func (*noopFlow) SetDeadline(<-chan struct{}) {}
-func (*noopFlow) LocalID() security.PublicID { return nil }
-func (*noopFlow) RemoteID() security.PublicID { return nil }
func TestListener(t *testing.T) {
ln := newListener()
diff --git a/runtimes/google/ipc/stream/vc/vc.go b/runtimes/google/ipc/stream/vc/vc.go
index d7b79ca..58ff157 100644
--- a/runtimes/google/ipc/stream/vc/vc.go
+++ b/runtimes/google/ipc/stream/vc/vc.go
@@ -40,7 +40,6 @@
type VC struct {
vci id.VC
localEP, remoteEP naming.Endpoint
- localID, remoteID security.PublicID
localPrincipal security.Principal
localBlessings, remoteBlessings security.Blessings
@@ -96,44 +95,6 @@
Version version.IPCVersion
}
-// DEPRECATED: TODO(ashankar,ataly): Remove when switch to LocalPrincipal is complete.
-type LocalID interface {
- stream.ListenerOpt
- stream.VCOpt
- Sign(message []byte) (security.Signature, error)
- AsClient(server security.PublicID) (security.PublicID, error)
- AsServer() (security.PublicID, error)
- IPCClientOpt()
- IPCServerOpt()
-}
-
-// DEPRECATED: TODO(ashankar,ataly): Remove when LocalID is removed.
-type fixedLocalID struct {
- security.PrivateID
-}
-
-func (f fixedLocalID) AsClient(security.PublicID) (security.PublicID, error) {
- return f.PrivateID.PublicID(), nil
-}
-
-func (f fixedLocalID) AsServer() (security.PublicID, error) {
- return f.PrivateID.PublicID(), nil
-}
-
-func (fixedLocalID) IPCStreamListenerOpt() {}
-func (fixedLocalID) IPCStreamVCOpt() {}
-func (fixedLocalID) IPCClientOpt() {
- //nologcall
-}
-func (fixedLocalID) IPCServerOpt() {
- //nologcall
-}
-
-// DEPRECATED: TODO(ashankar,ataly): Remove when LocalID is removed.
-func FixedLocalID(id security.PrivateID) LocalID {
- return fixedLocalID{id}
-}
-
// LocalPrincipal wraps a security.Principal so that it can be provided
// as an option to various methods in order to provide authentication information
// when establishing virtual circuits.
@@ -186,7 +147,7 @@
return nil, fmt.Errorf("failed to create writer for Flow: %v", err)
}
f := &flow{
- idHolder: vc,
+ authN: vc,
reader: newReader(readHandlerImpl{vc, fid}),
writer: writer,
localEndpoint: vc.localEP,
@@ -289,7 +250,7 @@
return fmt.Errorf("failed to create writer for new flow(%d): %v", fid, err)
}
f := &flow{
- idHolder: vc,
+ authN: vc,
reader: newReader(readHandlerImpl{vc, fid}),
writer: writer,
localEndpoint: vc.localEP,
@@ -379,14 +340,11 @@
// authentication etc.) under the assumption that the VC was initiated by the
// local process (i.e., the local process "Dial"ed to create the VC).
func (vc *VC) HandshakeDialedVC(opts ...stream.VCOpt) error {
- var localID LocalID
var principal security.Principal
var tlsSessionCache crypto.TLSClientSessionCache
var securityLevel options.VCSecurityLevel
for _, o := range opts {
switch v := o.(type) {
- case LocalID:
- localID = v
case LocalPrincipal:
principal = v.Principal
case options.VCSecurityLevel:
@@ -397,9 +355,6 @@
}
switch securityLevel {
case options.VCSecurityConfidential:
- if localID == nil {
- localID = FixedLocalID(anonymousID)
- }
if principal == nil {
principal = anonymousPrincipal
}
@@ -434,39 +389,21 @@
if err != nil {
return vc.err(fmt.Errorf("failed to create a Flow for authentication: %v", err))
}
- var (
- rID, lID security.PublicID
- rBlessings, lBlessings security.Blessings
- )
- if vc.useOldSecurityModel() {
- if rID, lID, err = authenticateAsClientOld(authConn, localID, crypter, vc.version); err != nil {
- return vc.err(fmt.Errorf("authentication (using the deprecated PublicID objects) failed: %v", err))
- }
- } else {
- if rBlessings, lBlessings, err = authenticateAsClient(authConn, principal, crypter, vc.version); err != nil {
- return vc.err(fmt.Errorf("authentication failed: %v", err))
- }
+ rBlessings, lBlessings, err := authenticateAsClient(authConn, principal, crypter, vc.version)
+ if err != nil {
+ return vc.err(fmt.Errorf("authentication failed: %v", err))
}
vc.mu.Lock()
vc.handshakeFID = handshakeFID
vc.authFID = authFID
vc.crypter = crypter
- if vc.useOldSecurityModel() {
- vc.localID = lID
- vc.remoteID = rID
- } else {
- vc.localPrincipal = principal
- vc.remoteBlessings = rBlessings
- vc.localBlessings = lBlessings
- }
+ vc.localPrincipal = principal
+ vc.remoteBlessings = rBlessings
+ vc.localBlessings = lBlessings
vc.mu.Unlock()
- if !vc.useOldSecurityModel() {
- vlog.VI(1).Infof("Client VC %v authenticated. RemoteBlessings:%v, LocalBlessings:%v", vc, rBlessings, lBlessings)
- } else {
- vlog.VI(1).Infof("Client VC %v authenticated using about-to-be-deleted protocol. RemoteID:%v LocalID:%v", vc, rID, lID)
- }
+ vlog.VI(1).Infof("Client VC %v authenticated. RemoteBlessings:%v, LocalBlessings:%v", vc, rBlessings, lBlessings)
return nil
}
@@ -489,13 +426,10 @@
result <- HandshakeResult{ln, err}
return result
}
- var localID LocalID
var principal security.Principal
var securityLevel options.VCSecurityLevel
for _, o := range opts {
switch v := o.(type) {
- case LocalID:
- localID = v
case LocalPrincipal:
principal = v.Principal
case options.VCSecurityLevel:
@@ -512,9 +446,6 @@
vc.helper.AddReceiveBuffers(vc.VCI(), SharedFlowID, DefaultBytesBufferedPerFlow)
switch securityLevel {
case options.VCSecurityConfidential:
- if localID == nil {
- localID = FixedLocalID(anonymousID)
- }
if principal == nil {
principal = anonymousPrincipal
}
@@ -560,40 +491,21 @@
vc.mu.Lock()
vc.authFID = vc.findFlowLocked(authConn)
vc.mu.Unlock()
- var (
- rID, lID security.PublicID
- rBlessings, lBlessings security.Blessings
- )
- if vc.useOldSecurityModel() {
- if rID, lID, err = authenticateAsServerOld(authConn, localID, crypter, vc.version); err != nil {
- sendErr(fmt.Errorf("Authentication failed (with soon-to-be-removed protocol): %v", err))
- return
- }
- } else {
- if rBlessings, lBlessings, err = authenticateAsServer(authConn, principal, crypter, vc.version); err != nil {
- sendErr(fmt.Errorf("authentication failed %v", err))
- return
- }
+ rBlessings, lBlessings, err := authenticateAsServer(authConn, principal, crypter, vc.version)
+ if err != nil {
+ sendErr(fmt.Errorf("authentication failed %v", err))
+ return
}
vc.mu.Lock()
vc.crypter = crypter
- if vc.useOldSecurityModel() {
- vc.localID = lID
- vc.remoteID = rID
- } else {
- vc.localPrincipal = principal
- vc.localBlessings = lBlessings
- vc.remoteBlessings = rBlessings
- }
+ vc.localPrincipal = principal
+ vc.localBlessings = lBlessings
+ vc.remoteBlessings = rBlessings
close(vc.acceptHandshakeDone)
vc.acceptHandshakeDone = nil
vc.mu.Unlock()
- if !vc.useOldSecurityModel() {
- vlog.VI(1).Infof("Server VC %v authenticated. RemoteBlessings:%v, LocalBlessings:%v", vc, rBlessings, lBlessings)
- } else {
- vlog.VI(1).Infof("Server VC %v authenticated using about-to-be-deleted protocol. RemoteID:%v LocalID:%v", vc, rID, lID)
- }
+ vlog.VI(1).Infof("Server VC %v authenticated. RemoteBlessings:%v, LocalBlessings:%v", vc, rBlessings, lBlessings)
result <- HandshakeResult{ln, nil}
}()
return result
@@ -676,28 +588,6 @@
return vc.remoteBlessings
}
-// LocalID returns the identity of the local end of the VC.
-func (vc *VC) LocalID() security.PublicID {
- vc.mu.Lock()
- defer vc.mu.Unlock()
- vc.waitForHandshakeLocked()
- if vc.useOldSecurityModel() {
- return anonymousIfNilPublicID(vc.localID)
- }
- return nil
-}
-
-// RemoteID returns the identity of the remote end of the VC.
-func (vc *VC) RemoteID() security.PublicID {
- vc.mu.Lock()
- defer vc.mu.Unlock()
- vc.waitForHandshakeLocked()
- if vc.useOldSecurityModel() {
- return anonymousIfNilPublicID(vc.remoteID)
- }
- return nil
-}
-
// waitForHandshakeLocked blocks until an in-progress handshake (encryption
// setup and authentication) completes.
// REQUIRES: vc.mu is held.
@@ -733,7 +623,6 @@
if vc.localPrincipal != nil {
l = append(l, fmt.Sprintf("LocalPrincipal:%v LocalBlessings:%v RemoteBlessings:%v", vc.localPrincipal.PublicKey(), vc.localBlessings, vc.remoteBlessings))
}
- l = append(l, fmt.Sprintf("LocalID:%q RemoteID:%q", anonymousIfNilPublicID(vc.localID), anonymousIfNilPublicID(vc.remoteID)))
}
for fid, f := range vc.flowMap {
l = append(l, fmt.Sprintf(" Flow:%3d BytesRead:%7d BytesWritten:%7d", fid, f.BytesRead(), f.BytesWritten()))
@@ -743,9 +632,6 @@
return strings.Join(l, "\n")
}
-// TODO(ashankar,ataly): Remove once the old security model is ripped out.
-func (vc *VC) useOldSecurityModel() bool { return vc.version < version.IPCVersion4 }
-
// readHandlerImpl is an adapter for the readHandler interface required by
// the reader type.
type readHandlerImpl struct {
@@ -756,10 +642,3 @@
func (r readHandlerImpl) HandleRead(bytes uint) {
r.vc.helper.AddReceiveBuffers(r.vc.vci, r.fid, bytes)
}
-
-func anonymousIfNilPublicID(id security.PublicID) security.PublicID {
- if id != nil {
- return id
- }
- return anonymousID.PublicID()
-}
diff --git a/runtimes/google/ipc/stream/vc/vc_test.go b/runtimes/google/ipc/stream/vc/vc_test.go
index d20ad5a..2d6cf09 100644
--- a/runtimes/google/ipc/stream/vc/vc_test.go
+++ b/runtimes/google/ipc/stream/vc/vc_test.go
@@ -74,22 +74,6 @@
}
}
-func matchID(got, want security.PublicID) error {
- if want == nil {
- if got.Names() != nil {
- return fmt.Errorf("got identity with names: %v, want one with names: nil", got.Names())
- }
- return nil
- }
- if g, w := got.Names(), want.Names(); !reflect.DeepEqual(got.Names(), want.Names()) {
- return fmt.Errorf("got identity with names: %v, want one with names: %v", g, w)
- }
- if g, w := got.PublicKey(), want.PublicKey(); !reflect.DeepEqual(got.PublicKey(), want.PublicKey()) {
- return fmt.Errorf("got identity with public key: %v, want one with public key: %v", g, w)
- }
- return nil
-}
-
func TestHandshake(t *testing.T) {
// When SecurityNone is used, the blessings should not be sent over the wire.
var (
@@ -183,8 +167,8 @@
func TestConnect(t *testing.T) { testConnect(t, SecurityNone) }
func TestConnectTLS(t *testing.T) { testConnect(t, SecurityTLS) }
-func testConnect_Version3(t *testing.T, security options.VCSecurityLevel) {
- h, vc := New(security, version.IPCVersion3, sectest.NewPrincipal("client"), sectest.NewPrincipal("server"))
+func testConnect_Version4(t *testing.T, security options.VCSecurityLevel) {
+ h, vc := New(security, version.IPCVersion4, sectest.NewPrincipal("client"), sectest.NewPrincipal("server"))
defer h.Close()
flow, err := vc.Connect()
if err != nil {
@@ -192,8 +176,8 @@
}
testFlowEcho(t, flow, 10)
}
-func TestConnect_Version3(t *testing.T) { testConnect_Version3(t, SecurityNone) }
-func TestConnect_Version3TLS(t *testing.T) { testConnect_Version3(t, SecurityTLS) }
+func TestConnect_Version4(t *testing.T) { testConnect_Version4(t, SecurityNone) }
+func TestConnect_Version4TLS(t *testing.T) { testConnect_Version4(t, SecurityTLS) }
// helper function for testing concurrent operations on multiple flows over the
// same VC. Such tests are most useful when running the race detector.
diff --git a/runtimes/google/ipc/version/version.go b/runtimes/google/ipc/version/version.go
index 131e40a..449dd30 100644
--- a/runtimes/google/ipc/version/version.go
+++ b/runtimes/google/ipc/version/version.go
@@ -21,7 +21,7 @@
// change that's not both forward and backward compatible.
// Min should be incremented whenever we want to remove
// support for old protocol versions.
- supportedRange = &Range{Min: version.IPCVersion2, Max: version.IPCVersion4}
+ supportedRange = &Range{Min: version.IPCVersion4, Max: version.IPCVersion4}
// Export the methods on supportedRange.
Endpoint = supportedRange.Endpoint
diff --git a/runtimes/google/rt/ipc.go b/runtimes/google/rt/ipc.go
index 53ab84f..293657a 100644
--- a/runtimes/google/rt/ipc.go
+++ b/runtimes/google/rt/ipc.go
@@ -1,7 +1,6 @@
package rt
import (
- "errors"
"fmt"
iipc "veyron.io/veyron/veyron/runtimes/google/ipc"
@@ -15,79 +14,15 @@
"veyron.io/veyron/veyron2/ipc/stream"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/options"
- "veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vtrace"
)
-// fixedPublicIDStore implements security.PublicIDStore. It embeds a (fixed) PublicID that
-// is both the default and the PublicID to be used for any peer. Adding a new PublicID
-// to the store is disallowed, and setting the default principal-pattern is a no-op.
-type fixedPublicIDStore struct {
- id security.PublicID
-}
-
-func (fixedPublicIDStore) Add(id security.PublicID, peerPattern security.BlessingPattern) error {
- return errors.New("adding new PublicIDs is disallowed for this PublicIDStore")
-}
-
-func (s fixedPublicIDStore) ForPeer(peer security.PublicID) (security.PublicID, error) {
- return s.id, nil
-}
-
-func (s fixedPublicIDStore) DefaultPublicID() (security.PublicID, error) {
- return s.id, nil
-}
-
-func (fixedPublicIDStore) SetDefaultBlessingPattern(pattern security.BlessingPattern) error {
- return errors.New("SetDefaultBlessingPattern is disallowed on a fixed PublicIDStore")
-}
-
-// localID is an option for passing a PrivateID and PublicIDStore
-// to a server or client.
-type localID struct {
- id security.PrivateID
- store security.PublicIDStore
-}
-
-func (lID *localID) Sign(message []byte) (security.Signature, error) {
- return lID.id.Sign(message)
-}
-
-func (lID *localID) AsClient(server security.PublicID) (security.PublicID, error) {
- return lID.store.ForPeer(server)
-}
-
-func (lID *localID) AsServer() (security.PublicID, error) {
- return lID.store.DefaultPublicID()
-}
-
-func (*localID) IPCClientOpt() {
- //nologcall
-}
-func (*localID) IPCStreamVCOpt() {}
-func (*localID) IPCServerOpt() {
- //nologcall
-}
-func (*localID) IPCStreamListenerOpt() {}
-
-// newLocalID returns a localID embedding the runtime's PrivateID and a fixed
-// PublicIDStore constructed from the provided PublicID or the runtiume's PublicIDStore
-// if the provided PublicID is nil.
-func (rt *vrt) newLocalID(id security.PublicID) vc.LocalID {
- lID := &localID{id: rt.id, store: rt.store}
- if id != nil {
- lID.store = fixedPublicIDStore{id}
- }
- return lID
-}
-
func (rt *vrt) NewClient(opts ...ipc.ClientOpt) (ipc.Client, error) {
rt.mu.Lock()
sm := rt.sm[0]
rt.mu.Unlock()
ns := rt.ns
- var id security.PublicID
var otherOpts []ipc.ClientOpt
for _, opt := range opts {
switch topt := opt.(type) {
@@ -95,14 +30,12 @@
sm = topt.Manager
case options.Namespace:
ns = topt.Namespace
- case options.LocalID:
- id = topt.PublicID
default:
otherOpts = append(otherOpts, opt)
}
}
- // Add the option that provides the local identity to the client.
- otherOpts = append(otherOpts, rt.newLocalID(id), vc.LocalPrincipal{rt.principal})
+ // Add the option that provides the runtime's principal to the client.
+ otherOpts = append(otherOpts, vc.LocalPrincipal{rt.principal})
return iipc.InternalNewClient(sm, ns, otherOpts...)
}
@@ -149,22 +82,18 @@
}
}
ns := rt.ns
- var id security.PublicID
var otherOpts []ipc.ServerOpt
for _, opt := range opts {
switch topt := opt.(type) {
case options.Namespace:
ns = topt
- case options.LocalID:
- id = topt.PublicID
default:
otherOpts = append(otherOpts, opt)
}
}
- // Add the option that provides the local identity to the server.
- otherOpts = append(otherOpts, rt.newLocalID(id), vc.LocalPrincipal{rt.principal})
+ // Add the option that provides the principal to the server.
+ otherOpts = append(otherOpts, vc.LocalPrincipal{rt.principal})
ctx := rt.NewContext()
-
return iipc.InternalNewServer(ctx, sm, ns, otherOpts...)
}
diff --git a/runtimes/google/rt/rt.go b/runtimes/google/rt/rt.go
index 6de8860..24cacf3 100644
--- a/runtimes/google/rt/rt.go
+++ b/runtimes/google/rt/rt.go
@@ -35,9 +35,7 @@
sm []stream.Manager // GUARDED_BY(mu)
ns naming.Namespace
signals chan os.Signal
- id security.PrivateID
principal security.Principal
- store security.PublicIDStore
client ipc.Client
mgmt *mgmtImpl
flags flags.RuntimeFlags
@@ -70,16 +68,12 @@
switch v := o.(type) {
case options.RuntimePrincipal:
rt.principal = v.Principal
- case options.RuntimeID:
- rt.id = v.PrivateID
case options.Profile:
rt.profile = v.Profile
case options.RuntimeName:
if v != "google" && v != "" {
return nil, fmt.Errorf("%q is the wrong name for this runtime", v)
}
- case options.ForceNewSecurityModel:
- // noop
default:
return nil, fmt.Errorf("option has wrong type %T", o)
}
diff --git a/runtimes/google/rt/rt_test.go b/runtimes/google/rt/rt_test.go
index 44b28fe..07bf6fd 100644
--- a/runtimes/google/rt/rt_test.go
+++ b/runtimes/google/rt/rt_test.go
@@ -35,8 +35,6 @@
func (*context) Suffix() string { return "" }
func (*context) Label() (l security.Label) { return }
func (*context) Discharges() map[string]security.Discharge { return nil }
-func (*context) LocalID() security.PublicID { return nil }
-func (*context) RemoteID() security.PublicID { return nil }
func (c *context) LocalPrincipal() security.Principal { return c.local }
func (*context) LocalBlessings() security.Blessings { return nil }
func (*context) RemoteBlessings() security.Blessings { return nil }
@@ -66,8 +64,18 @@
if !expected.MatchString(args) {
t.Errorf("unexpected default args: %q", args)
}
- if id := r.Identity().PublicID(); id == nil || len(id.Names()) == 0 || len(id.Names()[0]) == 0 {
- t.Errorf("New should have created an identity. Created %v", id)
+ p := r.Principal()
+ if p == nil {
+ t.Fatalf("A new principal should have been created")
+ }
+ if p.BlessingStore() == nil {
+ t.Fatalf("The principal must have a BlessingStore")
+ }
+ if p.BlessingStore().Default() == nil {
+ t.Errorf("Principal().BlessingStore().Default() should not be nil")
+ }
+ if p.BlessingStore().ForPeer() == nil {
+ t.Errorf("Principal().BlessingStore().ForPeer() should not be nil")
}
}
diff --git a/runtimes/google/rt/security.go b/runtimes/google/rt/security.go
index aa673d4..67814f1 100644
--- a/runtimes/google/rt/security.go
+++ b/runtimes/google/rt/security.go
@@ -6,42 +6,18 @@
"os/user"
"strconv"
- isecurity "veyron.io/veyron/veyron/runtimes/google/security"
vsecurity "veyron.io/veyron/veyron/security"
"veyron.io/veyron/veyron/security/agent"
"veyron.io/veyron/veyron2/options"
"veyron.io/veyron/veyron2/security"
- "veyron.io/veyron/veyron2/vlog"
)
func (rt *vrt) Principal() security.Principal {
return rt.principal
}
-func (rt *vrt) NewIdentity(name string) (security.PrivateID, error) {
- return isecurity.NewPrivateID(name, nil)
-}
-
-func (rt *vrt) Identity() security.PrivateID {
- return rt.id
-}
-
-func (rt *vrt) PublicIDStore() security.PublicIDStore {
- return rt.store
-}
-
func (rt *vrt) initSecurity(credentials string) error {
- if err := rt.initOldSecurity(); err != nil {
- return err
- }
- if err := rt.initPrincipal(credentials); err != nil {
- return fmt.Errorf("principal initialization failed: %v", err)
- }
- return nil
-}
-
-func (rt *vrt) initPrincipal(credentials string) error {
if rt.principal != nil {
return nil
}
@@ -72,59 +48,6 @@
return vsecurity.InitDefaultBlessings(rt.principal, defaultBlessingName())
}
-// TODO(ataly, ashankar): Get rid of this method once we get rid of
-// PrivateID and PublicIDStore.
-func (rt *vrt) initOldSecurity() error {
- if err := rt.initIdentity(); err != nil {
- return err
- }
- if err := rt.initPublicIDStore(); err != nil {
- return err
- }
- if err := rt.store.Add(rt.id.PublicID(), security.AllPrincipals); err != nil {
- return fmt.Errorf("could not initialize a PublicIDStore for the runtime: %s", err)
- }
- trustIdentityProviders(rt.id)
- return nil
-}
-
-func (rt *vrt) initIdentity() error {
- if rt.id != nil {
- return nil
- }
- var err error
- if file := os.Getenv("VEYRON_IDENTITY"); len(file) > 0 {
- if rt.id, err = loadIdentityFromFile(file); err != nil || rt.id == nil {
- return fmt.Errorf("Could not load identity from the VEYRON_IDENTITY environment variable (%q): %v", file, err)
- }
- } else {
- name := defaultBlessingName()
- vlog.VI(2).Infof("No identity provided to the runtime, minting one for %q", name)
- if rt.id, err = rt.NewIdentity(name); err != nil || rt.id == nil {
- return fmt.Errorf("Could not create new identity: %v", err)
- }
- }
- return nil
-}
-
-func (rt *vrt) initPublicIDStore() error {
- if rt.store != nil {
- return nil
- }
-
- var backup *isecurity.PublicIDStoreParams
- // TODO(ataly): Get rid of this environment variable and have a single variable for
- // all security related initialization.
- if dir := os.Getenv("VEYRON_PUBLICID_STORE"); len(dir) > 0 {
- backup = &isecurity.PublicIDStoreParams{dir, rt.id}
- }
- var err error
- if rt.store, err = isecurity.NewPublicIDStore(backup); err != nil {
- return fmt.Errorf("Could not create PublicIDStore for runtime: %v", err)
- }
- return nil
-}
-
func defaultBlessingName() string {
var name string
if user, _ := user.Current(); user != nil && len(user.Username) > 0 {
@@ -138,22 +61,6 @@
return fmt.Sprintf("%s-%d", name, os.Getpid())
}
-func trustIdentityProviders(id security.PrivateID) { isecurity.TrustIdentityProviders(id) }
-
-func loadIdentityFromFile(filePath string) (security.PrivateID, error) {
- f, err := os.Open(filePath)
- if err != nil {
- return nil, err
- }
- defer f.Close()
- // TODO(ashankar): Hack. See comments in vsecurity.LoadIdentity.
- hack, err := isecurity.NewPrivateID("hack", nil)
- if err != nil {
- return nil, err
- }
- return vsecurity.LoadIdentity(f, hack)
-}
-
func (rt *vrt) connectToAgent() (security.Principal, error) {
client, err := rt.NewClient(options.VCSecurityNone)
if err != nil {
diff --git a/runtimes/google/security/identity.go b/runtimes/google/security/identity.go
deleted file mode 100644
index e9fb4e5..0000000
--- a/runtimes/google/security/identity.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package security
-
-import "veyron.io/veyron/veyron2/security"
-
-// NewPrivateID returns a new PrivateID that uses the provided Signer to generate
-// signatures. The returned PrivateID additionaly contains a single self-signed
-// certificate with the given name.
-//
-// If a nil signer is provided, this method will generate a new public/private key pair
-// and use a system-default signer, which stores the private key in the clear in the memory
-// of the running process.
-func NewPrivateID(name string, signer security.Signer) (security.PrivateID, error) {
- return newChainPrivateID(name, signer)
-}
diff --git a/runtimes/google/security/identity_chain.go b/runtimes/google/security/identity_chain.go
deleted file mode 100644
index e582278..0000000
--- a/runtimes/google/security/identity_chain.go
+++ /dev/null
@@ -1,293 +0,0 @@
-package security
-
-// This file describes a certificate chain based implementation of security.PublicID.
-
-import (
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "fmt"
- "math/big"
- "reflect"
- "time"
-
- "veyron.io/veyron/veyron/runtimes/google/security/keys"
- vsecurity "veyron.io/veyron/veyron/security"
-
- "veyron.io/veyron/veyron2/security"
- "veyron.io/veyron/veyron2/security/wire"
- "veyron.io/veyron/veyron2/vom"
-)
-
-const (
- // unknownIDProviderPrefix is the prefix added when stringifying
- // an identity for which there is no entry for the root certificate
- // in the trusted keys set.
- unknownIDProviderPrefix = "unknown/"
- // mistrustedIDProviderPrefix is the prefix added when stringifying
- // an identity whose root certificate has a public key that does
- // not exist in the (non-empty) set of trusted keys for that root.
- mistrustedIDProviderPrefix = "mistrusted/"
-)
-
-func errAuthorize(err error) error {
- return fmt.Errorf("not authorized because: %v", err)
-}
-
-// chainPublicID implements security.PublicID.
-type chainPublicID struct {
- certificates []wire.Certificate
-
- // Fields derived from certificates in VomDecode
- publicKey security.PublicKey
- rootKey security.PublicKey
- name string
-}
-
-func (id *chainPublicID) Names() []string {
- // Return a name only if the identity provider is trusted.
- if keys.LevelOfTrust(id.rootKey, id.certificates[0].Name) == keys.Trusted {
- return []string{id.name}
- }
- return nil
-}
-
-func (id *chainPublicID) PublicKey() security.PublicKey { return id.publicKey }
-
-func (id *chainPublicID) String() string {
- // Add a prefix if the identity provider is not trusted.
- switch keys.LevelOfTrust(id.rootKey, id.certificates[0].Name) {
- case keys.Trusted:
- return id.name
- case keys.Mistrusted:
- return mistrustedIDProviderPrefix + id.name
- default:
- return unknownIDProviderPrefix + id.name
- }
-}
-
-func (id *chainPublicID) VomEncode() (*wire.ChainPublicID, error) {
- return &wire.ChainPublicID{Certificates: id.certificates}, nil
-}
-
-func (id *chainPublicID) VomDecode(w *wire.ChainPublicID) error {
- if err := w.VerifyIntegrity(); err != nil {
- return err
- }
- firstKey, err := w.Certificates[0].PublicKey.Decode()
- if err != nil {
- return err
- }
- lastKey, err := w.Certificates[len(w.Certificates)-1].PublicKey.Decode()
- if err != nil {
- return err
- }
- id.name = w.Name()
- id.certificates = w.Certificates
- id.publicKey = lastKey
- id.rootKey = firstKey
- return err
-}
-
-func caveatsFromWire(bytes []wire.Caveat) []security.Caveat {
- caveats := make([]security.Caveat, len(bytes))
- for idx, b := range bytes {
- caveats[idx].ValidatorVOM = b.Bytes
- }
- return caveats
-}
-
-// Authorize checks if all caveats on the PublicID validate with respect to the
-// provided context and if so returns the original PublicID. This method assumes that
-// the existing PublicID was obtained after successfully decoding a serialized
-// PublicID and hence has integrity.
-func (id *chainPublicID) Authorize(context security.Context) (security.PublicID, error) {
- for _, c := range id.certificates {
- validators, err := vsecurity.CaveatValidators(caveatsFromWire(c.Caveats)...)
- if err != nil {
- return nil, errAuthorize(err)
- }
- for _, v := range validators {
- if err := v.Validate(context); err != nil {
- return nil, errAuthorize(err)
- }
- }
- }
- return id, nil
-}
-
-func (id *chainPublicID) ThirdPartyCaveats() []security.ThirdPartyCaveat {
- var tpCaveats []security.ThirdPartyCaveat
- for _, c := range id.certificates {
- tpCaveats = append(tpCaveats, vsecurity.ThirdPartyCaveats(caveatsFromWire(c.Caveats)...)...)
- }
- return tpCaveats
-}
-
-// chainPrivateID implements security.PrivateID
-type chainPrivateID struct {
- signer security.Signer
- publicID *chainPublicID
- privateKey *ecdsa.PrivateKey // can be nil
-}
-
-func (id *chainPrivateID) PublicID() security.PublicID { return id.publicID }
-
-func (id *chainPrivateID) String() string { return fmt.Sprintf("PrivateID:%v", id.publicID) }
-
-func (id *chainPrivateID) VomEncode() (*wire.ChainPrivateID, error) {
- if id.privateKey == nil {
- // TODO(ataly): Figure out a clean way to serialize Signers.
- return nil, fmt.Errorf("cannot vom-encode a chainPrivateID that doesn't have access to a private key")
- }
- pub, err := id.publicID.VomEncode()
- if err != nil {
- return nil, err
- }
- return &wire.ChainPrivateID{Secret: id.privateKey.D.Bytes(), PublicID: *pub}, nil
-}
-
-func (id *chainPrivateID) VomDecode(w *wire.ChainPrivateID) error {
- id.publicID = new(chainPublicID)
- if err := id.publicID.VomDecode(&w.PublicID); err != nil {
- return err
- }
- id.privateKey = &ecdsa.PrivateKey{
- PublicKey: *id.publicID.publicKey.DO_NOT_USE(),
- D: new(big.Int).SetBytes(w.Secret),
- }
- id.signer = security.NewInMemoryECDSASigner(id.privateKey)
- return nil
-}
-
-// Bless returns a new PublicID by extending the ceritificate chain of the PrivateID's
-// PublicID with a new certificate that has the provided blessingName, caveats, and an
-// additional expiry caveat for the given duration.
-func (id *chainPrivateID) Bless(blessee security.PublicID, blessingName string, duration time.Duration, caveats []security.Caveat) (security.PublicID, error) {
- // The integrity of the PublicID blessee is assumed to have been verified
- // (typically by a Vom decode).
- if err := wire.ValidateBlessingName(blessingName); err != nil {
- return nil, err
- }
-
- cert := wire.Certificate{Name: blessingName}
- if err := cert.PublicKey.Encode(blessee.PublicKey()); err != nil {
- return nil, err
- }
-
- expiryCaveat, err := security.ExpiryCaveat(time.Now().Add(duration))
- if err != nil {
- return nil, err
- }
- caveats = append(caveats, expiryCaveat)
-
- cert.Caveats = make([]wire.Caveat, len(caveats))
- for i, c := range caveats {
- cert.Caveats[i] = wire.Caveat{Bytes: c.ValidatorVOM}
- }
-
- vomPubID, err := id.publicID.VomEncode()
- if err != nil {
- return nil, err
- }
-
- if err := cert.Sign(id, vomPubID); err != nil {
- return nil, err
- }
- w := &wire.ChainPublicID{
- Certificates: append(id.publicID.certificates, cert),
- }
- return &chainPublicID{
- certificates: w.Certificates,
- publicKey: blessee.PublicKey(),
- rootKey: id.publicID.rootKey,
- name: w.Name(),
- }, nil
-}
-
-func (id *chainPrivateID) Derive(pub security.PublicID) (security.PrivateID, error) {
- if !reflect.DeepEqual(pub.PublicKey(), id.publicID.publicKey) {
- return nil, errDeriveMismatch
- }
- switch p := pub.(type) {
- case *chainPublicID:
- return &chainPrivateID{
- signer: id.signer,
- publicID: p,
- privateKey: id.privateKey,
- }, nil
- case *setPublicID:
- privs := make([]security.PrivateID, len(*p))
- var err error
- for ix, ip := range *p {
- if privs[ix], err = id.Derive(ip); err != nil {
- return nil, fmt.Errorf("Derive failed for public id %d of %d in set: %v", ix, len(*p), err)
- }
- }
- return setPrivateID(privs), nil
- default:
- return nil, fmt.Errorf("PrivateID of type %T cannot be used to Derive from PublicID of type %T", id, pub)
- }
-}
-
-func (id *chainPrivateID) MintDischarge(cav security.ThirdPartyCaveat, ctx security.Context, duration time.Duration, dischargeCaveats []security.Caveat) (security.Discharge, error) {
- // TODO(ashankar): HACK using new API to fit into old. This will go away anyway when we get rid of PrivateID and PublicID before release.
- return security.MintDischargeForPrivateID(id.signer, cav, ctx, duration, dischargeCaveats)
-}
-
-func (id *chainPrivateID) Sign(message []byte) (security.Signature, error) {
- return id.signer.Sign(nil, message)
-}
-
-func (id *chainPrivateID) PublicKey() security.PublicKey { return id.signer.PublicKey() }
-
-// newChainPrivateID returns a new PrivateID that uses the provided Signer to generate
-// signatures. The returned PrivateID additionaly contains a single self-signed
-// certificate with the given name.
-//
-// If a nil signer is provided, this method will generate a new public/private key pair
-// and use a system-default signer, which stores the private key in the clear in the memory
-// of the running process.
-func newChainPrivateID(name string, signer security.Signer) (security.PrivateID, error) {
- if err := wire.ValidateBlessingName(name); err != nil {
- return nil, err
- }
- var privKey *ecdsa.PrivateKey
- if signer == nil {
- var err error
- privKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- return nil, err
- }
- signer = security.NewInMemoryECDSASigner(privKey)
- }
-
- id := &chainPrivateID{
- signer: signer,
- publicID: &chainPublicID{
- certificates: []wire.Certificate{{Name: name}},
- name: name,
- publicKey: signer.PublicKey(),
- rootKey: signer.PublicKey(),
- },
- privateKey: privKey,
- }
- // Self-sign the (single) certificate.
- cert := &id.publicID.certificates[0]
- if err := cert.PublicKey.Encode(signer.PublicKey()); err != nil {
- return nil, err
- }
- vomPubID, err := id.publicID.VomEncode()
- if err != nil {
- return nil, err
- }
- if err := cert.Sign(id, vomPubID); err != nil {
- return nil, err
- }
- return id, nil
-}
-
-func init() {
- vom.Register(chainPublicID{})
- vom.Register(chainPrivateID{})
-}
diff --git a/runtimes/google/security/identity_set.go b/runtimes/google/security/identity_set.go
deleted file mode 100644
index c2828a0..0000000
--- a/runtimes/google/security/identity_set.go
+++ /dev/null
@@ -1,214 +0,0 @@
-package security
-
-import (
- "errors"
- "fmt"
- "reflect"
- "strings"
- "time"
-
- "veyron.io/veyron/veyron2/security"
- "veyron.io/veyron/veyron2/vom"
-)
-
-type setPublicID []security.PublicID
-
-var (
- errEmptySet = errors.New("suspected manipulation of identity: empty set")
- errSingleElementSet = errors.New("suspected manipulation of identity: single element set")
- errNoNilsInSet = errors.New("suspected manipulation of identity: nil element in set")
- errMismatchedKeys = errors.New("mismatched keys in elements of set")
-)
-
-// NewSetPublicID returns a security.PublicID containing the combined credentials of ids.
-// It requires that all elements of ids have the same public key.
-func NewSetPublicID(ids ...security.PublicID) (security.PublicID, error) {
- // All public keys must match
- switch len(ids) {
- case 0:
- return nil, nil
- case 1:
- return ids[0], nil
- default:
- for i := 1; i < len(ids); i++ {
- if !reflect.DeepEqual(ids[0].PublicKey(), ids[i].PublicKey()) {
- return nil, errMismatchedKeys
- }
- }
- set := setPublicID(ids)
- return &set, nil
- }
-}
-
-func (s *setPublicID) Names() []string {
- names := make([]string, 0, len(*s))
- for _, id := range *s {
- names = append(names, id.Names()...)
- }
- if len(names) == 0 {
- return nil
- }
- return names
-}
-
-func (s *setPublicID) PublicKey() security.PublicKey {
- return (*s)[0].PublicKey()
-}
-
-func (s *setPublicID) Authorize(context security.Context) (security.PublicID, error) {
- var authids []security.PublicID
- var errs []error
- for _, id := range *s {
- if aid, err := id.Authorize(context); err != nil && len(authids) == 0 {
- errs = append(errs, err)
- } else if aid != nil {
- authids = append(authids, aid)
- }
- }
- if len(authids) == 0 {
- return nil, joinerrs(errs)
- }
- return NewSetPublicID(authids...)
-}
-
-func (s *setPublicID) ThirdPartyCaveats() []security.ThirdPartyCaveat {
- set := make(map[string]security.ThirdPartyCaveat)
- for _, id := range *s {
- for _, tp := range id.ThirdPartyCaveats() {
- set[tp.ID()] = tp
- }
- }
- if len(set) == 0 {
- return nil
- }
- ret := make([]security.ThirdPartyCaveat, 0, len(set))
- for _, c := range set {
- ret = append(ret, c)
- }
- return ret
-}
-
-func (s *setPublicID) String() string {
- strs := make([]string, len(*s))
- for ix, id := range *s {
- strs[ix] = fmt.Sprintf("%v", id)
- }
- return strings.Join(strs, "#")
-}
-
-func (s *setPublicID) VomEncode() ([]security.PublicID, error) {
- return []security.PublicID(*s), nil
-}
-
-func (s *setPublicID) VomDecode(ids []security.PublicID) error {
- switch len(ids) {
- case 0:
- return errEmptySet
- case 1:
- return errSingleElementSet
- }
- if ids[0] == nil {
- return errNoNilsInSet
- }
- for i := 1; i < len(ids); i++ {
- if ids[i] == nil {
- return errNoNilsInSet
- }
- if !reflect.DeepEqual(ids[0].PublicKey(), ids[i].PublicKey()) {
- return errMismatchedKeys
- }
- }
- *s = setPublicID(ids)
- return nil
-}
-
-type setPrivateID []security.PrivateID
-
-// NewSetPrivateID returns a security.PrivateID contiaining the combined credentials of ids.
-// It requires that all ids have the same private key.
-func NewSetPrivateID(ids ...security.PrivateID) (security.PrivateID, error) {
- switch len(ids) {
- case 0:
- return nil, nil
- case 1:
- return ids[0], nil
- default:
- pub := ids[0].PublicID().PublicKey()
- for i := 1; i < len(ids); i++ {
- if !reflect.DeepEqual(pub, ids[i].PublicID().PublicKey()) {
- return nil, errMismatchedKeys
- }
- }
- return setPrivateID(ids), nil
- }
-}
-
-func (s setPrivateID) PublicID() security.PublicID {
- pubs := make([]security.PublicID, len(s))
- for ix, id := range s {
- pubs[ix] = id.PublicID()
- }
- set := setPublicID(pubs)
- return &set
-}
-
-func (s setPrivateID) Sign(message []byte) (security.Signature, error) { return s[0].Sign(message) }
-
-func (s setPrivateID) PublicKey() security.PublicKey { return s[0].PublicKey() }
-
-func (s setPrivateID) Bless(blessee security.PublicID, blessingName string, duration time.Duration, caveats []security.Caveat) (security.PublicID, error) {
- pubs := make([]security.PublicID, len(s))
- for ix, id := range s {
- var err error
- if pubs[ix], err = id.Bless(blessee, blessingName, duration, caveats); err != nil {
- return nil, err
- }
- }
- return NewSetPublicID(pubs...)
-}
-
-func (s setPrivateID) Derive(pub security.PublicID) (security.PrivateID, error) {
- switch p := pub.(type) {
- case *chainPublicID:
- return s[0].Derive(p)
- case *setPublicID:
- privs := make([]security.PrivateID, len(*p))
- var err error
- for ix, ip := range *p {
- if privs[ix], err = s.Derive(ip); err != nil {
- return nil, fmt.Errorf("Derive failed for %d of %d id in set", ix, len(*p))
- }
- }
- return setPrivateID(privs), nil
- default:
- return nil, fmt.Errorf("PrivateID of type %T cannot be used to Derive from PublicID of type %T", s, pub)
- }
-}
-
-func (s setPrivateID) MintDischarge(cav security.ThirdPartyCaveat, ctx security.Context, duration time.Duration, dischargeCaveats []security.Caveat) (security.Discharge, error) {
- for _, id := range s {
- if d, err := id.MintDischarge(cav, ctx, duration, dischargeCaveats); err == nil {
- return d, nil
- }
- }
- return nil, fmt.Errorf("discharge cannot be constructed for %T from %T", cav, s)
-}
-
-func joinerrs(errs []error) error {
- switch len(errs) {
- case 0:
- return nil
- case 1:
- return errs[0]
- }
- strs := make([]string, len(errs))
- for i, err := range errs {
- strs[i] = err.Error()
- }
- return fmt.Errorf("none of the blessings in the set are authorized: %v", strings.Join(strs, ", "))
-}
-
-func init() {
- vom.Register(setPrivateID(nil))
- vom.Register(setPublicID(nil))
-}
diff --git a/runtimes/google/security/identity_test.go b/runtimes/google/security/identity_test.go
deleted file mode 100644
index 1dae49c..0000000
--- a/runtimes/google/security/identity_test.go
+++ /dev/null
@@ -1,871 +0,0 @@
-package security
-
-import (
- "bytes"
- "crypto/elliptic"
- "fmt"
- "io"
- "math/big"
- "reflect"
- "sort"
- "testing"
- "time"
-
- "veyron.io/veyron/veyron2/security"
- "veyron.io/veyron/veyron2/security/wire"
- "veyron.io/veyron/veyron2/vlog"
- "veyron.io/veyron/veyron2/vom"
-
- "veyron.io/veyron/veyron/lib/expect"
- "veyron.io/veyron/veyron/lib/modules"
-)
-
-type S []string
-
-func TestNewPrivateID(t *testing.T) {
- testdata := []struct {
- name, err string
- }{
- {"alice", ""},
- {"alice#google", ""},
- {"alice@google", ""},
- {"bob.smith", ""},
- {"", "invalid blessing name"},
- {"/", "invalid blessing name"},
- {"/alice", "invalid blessing name"},
- {"alice/", "invalid blessing name"},
- {"google/alice", "invalid blessing name"},
- {"google/alice/bob", "invalid blessing name"},
- }
- for _, d := range testdata {
- if _, err := NewPrivateID(d.name, nil); !matchesErrorPattern(err, d.err) {
- t.Errorf("NewPrivateID(%q): got: %s, want to match: %s", d.name, err, d.err)
- }
- }
-}
-
-func TestNameAndAuth(t *testing.T) {
- var (
- cUnknownAlice = newChain("alice").PublicID()
- cTrustedAlice = bless(cUnknownAlice, veyronChain, "alice")
- cMistrustedAlice = bless(cUnknownAlice, newChain("veyron"), "alice")
- cGoogleAlice = bless(cUnknownAlice, googleChain, "alice")
-
- sAlice = newSetPublicID(cTrustedAlice, cGoogleAlice)
- sBadAlice = newSetPublicID(cUnknownAlice, cMistrustedAlice)
- sGoogleAlice = newSetPublicID(cMistrustedAlice, cGoogleAlice)
- )
- testdata := []struct {
- id security.PublicID
- names []string
- }{
- {id: cUnknownAlice},
- {id: cTrustedAlice, names: S{"veyron/alice"}},
- {id: cMistrustedAlice},
- {id: sAlice, names: S{"veyron/alice", "google/alice"}},
- {id: sBadAlice},
- {id: sGoogleAlice, names: S{"google/alice"}},
- }
- for _, d := range testdata {
- if got, want := d.id.Names(), d.names; !reflect.DeepEqual(got, want) {
- t.Errorf("%q(%T).Names(): got: %q, want: %q", d.id, d.id, got, want)
- }
- authID, err := d.id.Authorize(NewContext(ContextArgs{}))
- if (authID != nil) == (err != nil) {
- t.Errorf("%q.Authorize returned: (%v, %v), exactly one return value must be nil", d.id, authID, err)
- continue
- }
- if err := verifyAuthorizedID(d.id, authID, d.names); err != nil {
- t.Error(err)
- }
- }
-}
-
-func TestMatch(t *testing.T) {
- alice := newChain("alice")
- type matchInstance struct {
- pattern security.BlessingPattern
- want bool
- }
- testdata := []struct {
- id security.PublicID
- matchData []matchInstance
- }{
- {
- // self-signed alice chain, not a trusted identity provider so should only match "..."
- id: alice.PublicID(),
- matchData: []matchInstance{
- {pattern: "...", want: true},
- {pattern: "alice", want: false},
- {pattern: "alice/...", want: false},
- },
- },
- {
- // veyron/alice: rooted in the trusted "veyron" identity provider
- id: bless(newChain("immaterial").PublicID(), veyronChain, "alice"),
- matchData: []matchInstance{
- {pattern: "...", want: true},
- {pattern: "veyron/...", want: true},
- {pattern: "veyron/alice", want: true},
- {pattern: "veyron/alice/...", want: true},
- {pattern: "veyron/alice/TV", want: true},
- {pattern: "veyron", want: false},
- {pattern: "veyron/ali", want: false},
- {pattern: "veyron/aliced", want: false},
- {pattern: "veyron/bob", want: false},
- {pattern: "google/alice", want: false},
- },
- },
- {
- // alice#veyron/alice#google/alice: two trusted identity providers
- id: newSetPublicID(alice.PublicID(), bless(alice.PublicID(), veyronChain, "alice"), bless(alice.PublicID(), googleChain, "alice")),
- matchData: []matchInstance{
- {pattern: "...", want: true},
- // Since alice is not a trusted identity provider, the self-blessed identity
- // should not match "alice/..."
- {pattern: "alice", want: false},
- {pattern: "alice/...", want: false},
- {pattern: "veyron/...", want: true},
- {pattern: "veyron/alice", want: true},
- {pattern: "veyron/alice/TV", want: true},
- {pattern: "veyron/alice/...", want: true},
- {pattern: "ali", want: false},
- {pattern: "aliced", want: false},
- {pattern: "veyron", want: false},
- {pattern: "veyron/ali", want: false},
- {pattern: "veyron/aliced", want: false},
- {pattern: "veyron/bob", want: false},
- {pattern: "google/alice", want: true},
- {pattern: "google/alice/TV", want: true},
- {pattern: "google/alice/...", want: true},
- },
- },
- }
- for _, d := range testdata {
- for _, m := range d.matchData {
- if got := m.pattern.MatchedBy(d.id.Names()...); got != m.want {
- t.Errorf("%q.Match(%s), Got %t, want %t", d.id, m.pattern, got, m.want)
- }
- }
- }
-}
-
-func TestExpiredIdentityChain(t *testing.T) {
- id, err := veyronChain.Bless(newChain("immaterial").PublicID(), "alice", time.Millisecond, nil)
- if err != nil {
- t.Fatal(err)
- }
- time.Sleep(time.Millisecond)
- if authid, _ := id.Authorize(NewContext(ContextArgs{})); authid != nil && len(authid.Names()) != 0 {
- t.Errorf("%q.Authorize returned %v, wanted empty slice", id, authid)
- }
-}
-
-func TestExpiredIdentityInSet(t *testing.T) {
- var (
- alice = newChain("alice").PublicID()
- googleAlice = bless(alice, googleChain, "googler")
- )
- veyronAlice, err := veyronChain.Bless(alice, "veyroner", time.Millisecond, nil)
- if err != nil {
- t.Fatal(err)
- }
- time.Sleep(time.Millisecond)
- setid := newSetPublicID(alice, googleAlice, veyronAlice)
- authid, _ := setid.Authorize(NewContext(ContextArgs{}))
- if authid == nil {
- t.Fatalf("%q.Authorize returned nil, expected google/alice", setid)
- }
- if got, want := authid.Names(), "google/googler"; len(got) != 1 || got[0] != want {
- t.Errorf("Got %v want [%v]", got, want)
- }
-}
-
-func TestTamperedIdentityChain(t *testing.T) {
- alice := newChain("alice").PublicID().(*chainPublicID)
- nCerts := len(alice.certificates)
- // Tamper with alice's public key, in a way that it can be decoded into a valid key,
- // just different from what was originally encoded.
- xy := alice.certificates[nCerts-1].PublicKey.XY
- x, y := elliptic.Unmarshal(elliptic.P256(), xy)
- y = y.Add(y, big.NewInt(1))
- alice.certificates[nCerts-1].PublicKey.XY = elliptic.Marshal(elliptic.P256(), x, y)
- if _, err := alice.certificates[nCerts-1].PublicKey.Decode(); err != nil {
- t.Fatal(err)
- }
- if _, err := roundTrip(alice); err != wire.ErrNoIntegrity {
- t.Errorf("Got %v want %v from roundTrip(%v)", err, wire.ErrNoIntegrity, alice)
- }
-}
-
-func TestBless(t *testing.T) {
- var (
- cAlice = newChain("alice")
- cBob = newChain("bob").PublicID()
- cVeyronAlice = derive(bless(cAlice.PublicID(), veyronChain, "alice"), cAlice)
- cGoogleAlice = derive(bless(cAlice.PublicID(), googleChain, "alice"), cAlice)
- cVeyronBob = bless(cBob, veyronChain, "bob")
-
- sVeyronAlice = newSetPrivateID(cAlice, cVeyronAlice, cGoogleAlice)
- sVeyronBob = newSetPublicID(cBob, cVeyronBob)
- )
- testdata := []struct {
- blessor security.PrivateID
- blessee security.PublicID
- blessing string // name provided to security.PublicID.Bless
- blessed []string // names of the blessed identity. Empty if the Bless operation should have failed
- err string
- }{
- // Blessings from veyron/alice (chain implementation)
- {
- blessor: cVeyronAlice,
- blessee: cBob,
- err: `invalid blessing name:""`,
- },
- {
- blessor: cVeyronAlice,
- blessee: cBob,
- blessing: "alice/bob",
- err: `invalid blessing name:"alice/bob"`,
- },
- {
- blessor: cVeyronAlice,
- blessee: cBob,
- blessing: "friend_bob",
- blessed: S{"veyron/alice/friend_bob"},
- },
- {
- blessor: cVeyronAlice,
- blessee: sVeyronBob,
- blessing: "friend_bob",
- blessed: S{"veyron/alice/friend_bob"},
- },
- // Blessings from alice#google/alice#veyron/alice
- {
- blessor: sVeyronAlice,
- blessee: cBob,
- err: `invalid blessing name:""`,
- },
- {
- blessor: sVeyronAlice,
- blessee: cBob,
- blessing: "alice/bob",
- err: `invalid blessing name:"alice/bob"`,
- },
- {
- blessor: sVeyronAlice,
- blessee: cBob,
- blessing: "friend_bob",
- blessed: S{"veyron/alice/friend_bob", "google/alice/friend_bob"},
- },
- {
- blessor: sVeyronAlice,
- blessee: sVeyronBob,
- blessing: "friend_bob",
- blessed: S{"veyron/alice/friend_bob", "google/alice/friend_bob"},
- },
- }
-
- for _, d := range testdata {
- if (len(d.blessed) == 0) == (len(d.err) == 0) {
- t.Fatalf("Bad testdata. Exactly one of blessed and err must be non-empty: %+v", d)
- }
- blessed, err := d.blessor.Bless(d.blessee, d.blessing, 1*time.Minute, nil)
- // Exactly one of (blessed, err) should be nil
- if (blessed != nil) == (err != nil) {
- t.Errorf("%q.Bless(%q, %q, ...) returned: (%v, %v): exactly one return value should be nil", d.blessor, d.blessee, d.blessing, blessed, err)
- continue
- }
- // err should match d.err
- if !matchesErrorPattern(err, d.err) {
- t.Errorf("%q.Bless(%q, %q, ...) returned error: %v, want to match: %q", d.blessor, d.blessee, d.blessing, err, d.err)
- }
- if err != nil {
- continue
- }
- // Compare names
- if got, want := blessed.Names(), d.blessed; !reflect.DeepEqual(got, want) {
- t.Errorf("%q.Names(): got: %q, want: %q", blessed, got, want)
- }
- // Public keys should match for blessed and blessee
- if !reflect.DeepEqual(blessed.PublicKey(), d.blessee.PublicKey()) {
- t.Errorf("PublicKey mismatch in %q.Bless(%q, %q, ...)", d.blessor, d.blessee, d.blessing)
- }
- // Verify wire encoding of the blessed
- if _, err := roundTrip(blessed); err != nil {
- t.Errorf("roundTrip(%q) failed: %v (from %q.Bless(%q, %q, ...))", blessed, err, d.blessor, d.blessee, d.blessing)
- }
- }
-}
-
-type unregisteredCaveat struct {
- // TODO(ataly, ashankar): The int is embedded in order to
- // distinguish the signature of this type from other Caveat types
- // and therefore preventing VOM from decoding values of this type
- // into another type. This is still not foolproof, we need to figure
- // out a better way of preventing the accidental decoding into another
- // type.
- UniqueField int
-}
-
-func (unregisteredCaveat) Validate(security.Context) error {
- return nil
-}
-
-func encodeUnregisteredCaveat(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- cav, err := security.NewCaveat(unregisteredCaveat{1})
- if err != nil {
- vlog.Fatalf("security.NewCaveat failed: %s", err)
- }
- var buf bytes.Buffer
- if err := vom.NewEncoder(&buf).Encode(cav); err != nil {
- vlog.Fatalf("could not VOM-encode caveat: %s", err)
- }
- fmt.Fprintln(stdout, string(buf.Bytes()))
- modules.WaitForEOF(stdin)
- return nil
-}
-
-func TestHelperProcess(t *testing.T) {
- modules.DispatchInTest()
-}
-
-func TestAuthorizeWithCaveats(t *testing.T) {
- var (
- // alice
- pcAlice = newChain("alice")
- cAlice = pcAlice.PublicID().(*chainPublicID)
-
- // Some random server called bob
- bob = newChain("bob").PublicID()
-
- // Caveats
- // Can only call "Play" at the Google service
- cavOnlyPlay = mkCaveat(security.MethodCaveat("Play"))
- )
-
- // We create a Caveat from the CaveatValidator "unregisteredCaveat".
- // Since "unregisteredCaveat" is not registered with VOM, decoding
- // this caveat as part of a PublicID should fail.
- //
- // The Caveat is created within a child process as VOM automaitcally
- // registers all values encoded within the same process.
- sh := modules.NewShell(".*")
- defer sh.Cleanup(nil, nil)
- h, err := sh.Start("encodeUnregisteredCaveat", nil)
- if err != nil {
- t.Fatalf("unexpected error: %s", err)
- }
- s := expect.NewSession(t, h.Stdout(), time.Minute)
-
- encodedCaveat := s.ReadLine()
- if s.Failed() {
- t.Fatalf("ReadLineFromChild failed: %v", s.Error())
- }
- h.CloseStdin()
-
- var cavUnregistered security.Caveat
- if err := vom.NewDecoder(bytes.NewReader([]byte(encodedCaveat))).Decode(&cavUnregistered); err != nil {
- t.Fatalf("Failed to decode bytes obtained from ReadLineFromChild: %v", err)
- }
-
- type rpc struct {
- server security.PublicID
- method string
- // Expected output: exactly one should be non-empty
- authErr string
- authNames []string
- }
- testdata := []struct {
- client security.PublicID
- tests []rpc
- }{
- // client has a chain identity
- {
- client: bless(cAlice, veyronChain, "alice", cavOnlyPlay),
- tests: []rpc{
- {server: bob, method: "Play", authNames: S{"veyron/alice"}},
- {server: bob, method: "Hello", authErr: `security.methodCaveat=[Play] fails validation for method "Hello"`},
- {server: googleChain.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
- {server: googleChain.PublicID(), method: "Hello", authErr: `security.methodCaveat=[Play] fails validation for method "Hello"`},
- },
- },
- /* TODO(ashankar): Test case disabled since PeerBlessingsCaveat is disabled.
- {
- client: bless(cAlice, veyronChain, "alice", cavOnlyGoogle),
- tests: []rpc{
- {server: bob, method: "Hello", authErr: `security.peerBlessingsCaveat=[google] fails validation for peer with blessings []`},
- {server: googleChain.PublicID(), method: "Hello", authNames: S{"veyron/alice"}},
- {server: googleChain.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
- },
- },
- */
- {
- client: bless(cAlice, veyronChain, "alice", cavUnregistered),
- tests: []rpc{
- {server: bob, method: "Play", authErr: "caveat bytes could not be VOM-decoded"},
- {server: bob, method: "Hello", authErr: "caveat bytes could not be VOM-decoded"},
- {server: googleChain.PublicID(), method: "Play", authErr: "caveat bytes could not be VOM-decoded"},
- {server: googleChain.PublicID(), method: "Hello", authErr: "caveat bytes could not be VOM-decoded"},
- },
- },
- /* TODO(ashankar): Test case disabled since PeerBlessingsCaveat is disabled.
- {
- client: bless(cAlice, veyronChain, "alice", cavOnlyGoogle, cavOnlyPlay),
- tests: []rpc{
- {server: bob, method: "Hello", authErr: `security.peerBlessingsCaveat=[google] fails validation for peer with blessings []`},
- {server: bob, method: "Play", authErr: `security.peerBlessingsCaveat=[google] fails validation for peer with blessings []`},
- {server: googleChain.PublicID(), method: "Hello", authErr: `security.methodCaveat=[Play] fails validation for method "Hello"`},
- {server: googleChain.PublicID(), method: "Play", authNames: S{"veyron/alice"}},
- },
- },
- */
- {
- client: bless(cAlice, veyronChain, "alice", cavUnregistered),
- tests: []rpc{
- {server: googleChain.PublicID(), method: "Play", authErr: "caveat bytes could not be VOM-decoded"},
- {server: googleChain.PublicID(), method: "Hello", authErr: "caveat bytes could not be VOM-decoded"},
- },
- },
- /* TODO(ashankar): Test case disabled since PeerBlessingsCaveat is disabled.
- // client has multiple blessings
- {
- client: newSetPublicID(bless(cAlice, veyronChain, "valice", cavOnlyPlay, cavUnregistered), bless(cAlice, googleChain, "galice", cavOnlyGoogle)),
- tests: []rpc{
- {server: bob, method: "Hello", authErr: "none of the blessings in the set are authorized"},
- {server: bob, method: "Play", authErr: "none of the blessings in the set are authorized"},
- {server: googleChain.PublicID(), method: "Hello", authNames: S{"google/galice"}},
- {server: googleChain.PublicID(), method: "Play", authNames: S{"google/galice"}},
- },
- },
- */
- }
- for _, d := range testdata {
- // Validate that the client identity (with all its blessings) is valid for wire transmission.
- if _, err := roundTrip(d.client); err != nil {
- t.Errorf("roundTrip(%q): %v", d.client, err)
- continue
- }
- for _, test := range d.tests {
- if (len(test.authNames) == 0) == (len(test.authErr) == 0) {
- t.Errorf("Bad testdata. Exactly one of authNames and authErr must be non-empty: %+q/%+v", d.client, test)
- continue
- }
- ctx := NewContext(ContextArgs{LocalID: test.server, RemoteID: d.client, Method: test.method})
- authID, err := d.client.Authorize(ctx)
- if !matchesErrorPattern(err, test.authErr) {
- t.Errorf("%q.Authorize(%v) returned error: %v, want to match: %q", d.client, ctx, err, test.authErr)
- continue
- }
- if err := verifyAuthorizedID(d.client, authID, test.authNames); err != nil {
- t.Errorf("%q.Authorize(%v) returned identity: %v want identity with names: %q [%v]", d.client, ctx, authID, test.authNames, err)
- continue
- }
- }
- }
-}
-
-type alwaysValidCaveat struct{}
-
-func (alwaysValidCaveat) Validate(security.Context) error {
- return nil
-}
-
-// proximityCaveat abuses the Method field to store proximity info
-// TODO(andreser): create a context that can hold proximity data by design
-type proximityCaveat struct{}
-
-func (proximityCaveat) Validate(ctx security.Context) error {
- if ctx != nil && ctx.Method() == "proximity: close enough" {
- return nil
- } else {
- return fmt.Errorf("proximityCaveat: not close enough")
- }
-}
-
-func TestThirdPartyCaveatMinting(t *testing.T) {
- minter := newChain("minter")
- cav, err := security.NewPublicKeyCaveat(minter.PublicID().PublicKey(), "location", security.ThirdPartyRequirements{}, newCaveat(proximityCaveat{}))
- if err != nil {
- t.Fatalf("security.NewPublicKeyCaveat failed: %s", err)
- }
-
- discharge, err := minter.MintDischarge(cav, NewContext(ContextArgs{}), time.Hour, nil)
- if discharge != nil || !matchesErrorPattern(err, "not close enough") {
- t.Errorf("Discharge was minted while minting caveats were not met")
- }
-
- discharge, err = minter.MintDischarge(cav, NewContext(ContextArgs{Method: "proximity: close enough"}), time.Hour, nil)
- if err != nil {
- t.Errorf("Discharge was NOT minted even though minting caveats were met")
- }
-
- ctxValidateMinting := NewContext(ContextArgs{
- Discharges: dischargeMap{discharge.ID(): discharge},
- Debug: "ctxValidateMinting",
- })
- if err = cav.Validate(ctxValidateMinting); err != nil {
- t.Errorf("Failed %q.Validate(%q): %s", cav, ctxValidateMinting, err)
- }
-}
-
-/*
-TODO(ashankar): Test disabled because PeerBlessingCaveat has been disabled.
-In any case, we expect this whole package to be deleted (it is the "old" security
-model), so won't bother with trying to fix up the tests
-
-func TestAuthorizeWithThirdPartyCaveats(t *testing.T) {
- mkveyron := func(id security.PrivateID, name string) security.PrivateID {
- return derive(bless(id.PublicID(), veyronChain, name), id)
- }
- mkgoogle := func(id security.PrivateID, name string) security.PrivateID {
- return derive(bless(id.PublicID(), googleChain, name), id)
- }
- mkTPCaveat := func(id security.PrivateID) security.ThirdPartyCaveat {
- c, err := security.NewPublicKeyCaveat(id.PublicID().PublicKey(), fmt.Sprintf("%v location", id.PublicID()), security.ThirdPartyRequirements{}, newCaveat(alwaysValidCaveat{}))
- if err != nil {
- t.Fatalf("NewPublicKeyCaveat with PublicKey of: %v failed: %s", id, err)
- }
- return c
- }
- var (
- alice = newChain("alice")
- bob = newChain("bob")
- carol = newChain("carol").PublicID()
-
- // aliceProximityCaveat is a caveat whose discharge can only be minted by alice.
- aliceProximityCaveat = mkTPCaveat(alice)
- bobProximityCaveat = mkTPCaveat(bob)
- )
-
- mintDischarge := func(id security.PrivateID, duration time.Duration, caveats ...security.Caveat) security.Discharge {
- d, err := id.MintDischarge(aliceProximityCaveat.(security.ThirdPartyCaveat), nil, duration, caveats)
- if err != nil {
- t.Fatalf("%q.MintDischarge failed: %v", id, err)
- }
- return d
- }
- var (
- // Discharges
- dAlice = mintDischarge(alice, time.Minute)
- dGoogle = mintDischarge(alice, time.Minute, mkCaveat(security.PeerBlessingsCaveat("google")))
- dExpired = mintDischarge(alice, 0)
- dInvalid = mintDischarge(bob, time.Minute) // Invalid because bob cannot mint valid discharges for aliceProximityCaveat
-
- // Contexts
- ctxEmpty = NewContext(ContextArgs{Method: "Play", Debug: "ctxEmpty"})
- ctxAlice = NewContext(ContextArgs{
- Method: "Play",
- Discharges: dischargeMap{dAlice.ID(): dAlice},
- Debug: "ctxAlice",
- })
- // Context containing the discharge dGoogle but the server is not a Google server, so
- // the service caveat is not satisfied
- ctxGoogleAtOther = NewContext(ContextArgs{
- Method: "Play",
- Discharges: dischargeMap{dGoogle.ID(): dGoogle},
- Debug: "ctxGoogleAtOther",
- })
- // Context containing the discharge dGoogle at a google server.
- ctxGoogleAtGoogle = NewContext(ContextArgs{
- Method: "Play",
- Discharges: dischargeMap{dGoogle.ID(): dGoogle},
- LocalID: googleChain.PublicID(),
- Debug: "ctxGoogleAtGoogle",
- })
- ctxExpired = NewContext(ContextArgs{
- Method: "Play",
- Discharges: dischargeMap{dExpired.ID(): dExpired},
- Debug: "ctxExpired",
- })
- ctxInvalid = NewContext(ContextArgs{
- Method: "Play",
- Discharges: dischargeMap{dInvalid.ID(): dInvalid},
- Debug: "ctxInvalid",
- })
-
- // Contexts that should always end in authorization errors
- errtests = map[security.Context]string{
- ctxEmpty: "missing discharge",
- ctxGoogleAtOther: "security.peerBlessingsCaveat=[google] fails validation",
- ctxExpired: "security.unixTimeExpiryCaveat",
- ctxInvalid: "signature verification on discharge",
- }
- )
-
- testdata := []struct {
- id security.PublicID
- authNames S // For ctxAlice and ctxGoogleAtGoogle
- }{
- // carol blessed by bob with the third-party caveat should be authorized when the context contains a valid discharge
- {
- id: bless(carol, mkveyron(bob, "bob"), "friend", newCaveat(aliceProximityCaveat)),
- authNames: S{"veyron/bob/friend"},
- },
- // veyron/vbob/vfriend with bobProximityCaveat and google/gbob/gfriend with aliceProximityCaveat
- // Only google/gbob/gfriend should be authorized since the discharge for the former is missing
- {
- id: newSetPublicID(
- bless(carol, mkveyron(bob, "vbob"), "vfriend", newCaveat(bobProximityCaveat)),
- bless(carol, mkgoogle(bob, "gbob"), "gfriend", newCaveat(aliceProximityCaveat))),
- authNames: S{"google/gbob/gfriend"},
- },
- // veyron/vbob/friend#google/gbob/friend both have the same caveat and both are satisfied
- {
- id: bless(carol, newSetPrivateID(mkveyron(bob, "vbob"), mkgoogle(bob, "gbob")), "friend", newCaveat(aliceProximityCaveat)),
- authNames: S{"veyron/vbob/friend", "google/gbob/friend"},
- },
- }
- for _, test := range testdata {
- if _, err := roundTrip(test.id); err != nil {
- t.Errorf("%q is not round-trippable: %v", test.id, test.id, err)
- }
- for _, ctx := range []security.Context{ctxAlice, ctxGoogleAtGoogle} {
- authID, _ := test.id.Authorize(ctx)
- if err := verifyAuthorizedID(test.id, authID, test.authNames); err != nil {
- t.Errorf("%q.Authorize(%v): %v", test.id, ctx, err)
- }
- }
- for ctx, want := range errtests {
- authID, err := test.id.Authorize(ctx)
- if authID != nil {
- t.Errorf("%q.Authorize(%v) returned %v, should have returned nil", test.id, ctx, authID)
- }
- if !matchesErrorPattern(err, want) {
- t.Errorf("%q.Authorize(%v) returned error: %v, want to match: %q", test.id, ctx, err, want)
- }
- }
- }
-}
-*/
-type SortedThirdPartyCaveats []security.ThirdPartyCaveat
-
-func (s SortedThirdPartyCaveats) Len() int { return len(s) }
-func (s SortedThirdPartyCaveats) Less(i, j int) bool {
- return s[i].ID() < s[j].ID()
-}
-func (s SortedThirdPartyCaveats) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-
-func TestThirdPartyCaveatAccessors(t *testing.T) {
- mkTPCaveat := func(id security.PublicID) security.ThirdPartyCaveat {
- tpCav, err := security.NewPublicKeyCaveat(id.PublicKey(), "someLocation", security.ThirdPartyRequirements{}, newCaveat(alwaysValidCaveat{}))
- if err != nil {
- t.Fatalf("NewPublicKeyCaveat with PublicKey of: %v failed: %s", id, err)
- }
- return tpCav
- }
- mintDischarge := func(caveat security.ThirdPartyCaveat, id security.PrivateID, caveats ...security.Caveat) security.Discharge {
- d, err := id.MintDischarge(caveat, nil, time.Minute, caveats)
- if err != nil {
- t.Fatalf("%q.MintDischarge failed: %v", id, err)
- }
- return d
- }
- sortTPCaveats := func(caveats []security.ThirdPartyCaveat) []security.ThirdPartyCaveat {
- sort.Stable(SortedThirdPartyCaveats(caveats))
- return caveats
- }
-
- var (
- // Principals (type conversions just to protect against accidentally
- // calling the wrong factory function)
- alice = newChain("alice").(*chainPrivateID)
- cBob = newChain("bob").(*chainPrivateID)
- cBobBuilder = derive(bless(cBob.PublicID(), cBob, "builder"), cBob) // Bob also calls himself bob/builder
- sBob = newSetPrivateID(cBob, cBobBuilder).(setPrivateID)
-
- // Caveats
- tpCavAlice = mkTPCaveat(alice.PublicID())
- tpCavBob = mkTPCaveat(alice.PublicID())
- cav = mkCaveat(security.MethodCaveat(""))
- )
-
- caveats := []struct {
- firstparty *security.Caveat
- thirdparty []security.ThirdPartyCaveat
- }{
- {firstparty: nil, thirdparty: nil},
- {firstparty: &cav},
- {thirdparty: []security.ThirdPartyCaveat{tpCavAlice}},
- {thirdparty: []security.ThirdPartyCaveat{tpCavAlice, tpCavBob}},
- {firstparty: &cav, thirdparty: []security.ThirdPartyCaveat{tpCavAlice, tpCavBob}},
- }
- testdata := []struct {
- privID security.PrivateID
- pubID security.PublicID
- }{
- {privID: veyronChain, pubID: cBob.PublicID()}, // Chain blessing a chain
- {privID: veyronChain, pubID: sBob.PublicID()}, // Chain blessing a set
- {privID: sBob, pubID: cBob.PublicID()}, // Set blessing a chain
- //{privID: veyronTree, pubID: tBob.PublicID()},
- }
- for _, d := range testdata {
- for _, c := range caveats {
- var all []security.Caveat
- if c.firstparty != nil {
- all = append(all, *c.firstparty)
- }
- for _, tpc := range c.thirdparty {
- all = append(all, newCaveat(tpc))
- }
- // Test ThirdPartyCaveat accessors on security.PublicIDs.
- id := bless(d.pubID, d.privID, "irrelevant", all...)
- want := sortTPCaveats(c.thirdparty)
- if got := sortTPCaveats(id.ThirdPartyCaveats()); !reflect.DeepEqual(got, want) {
- t.Errorf("%q(%T) got ThirdPartyCaveats() = %+v, want %+v", id, id, got, want)
- }
- // Test ThirdPartyCaveat accessors on security.ThirdPartyCaveat discharges.
- dis := mintDischarge(mkTPCaveat(alice.PublicID()), d.privID, all...)
- if got := sortTPCaveats(dis.ThirdPartyCaveats()); !reflect.DeepEqual(got, want) {
- t.Errorf("%q got ThirdPartyCaveats() = %+v, want %+v", dis, got, want)
- }
- }
- }
-}
-
-func TestBlessingChainAmplification(t *testing.T) {
- var (
- // alice has blessings from trusted identity providers google and veyron
- alice = newChain("alice")
- googleAlice = derive(bless(alice.PublicID(), googleChain, "alice"), alice)
- veyronAlice = derive(bless(alice.PublicID(), veyronChain, "alice"), alice)
- bob = newChain("bob").PublicID()
- )
-
- // veyron/alice blesses bob for 5 minutes
- veyronAliceBob, err := veyronAlice.Bless(bob, "bob@veyron@alice", 5*time.Minute, nil)
- if err != nil {
- t.Fatal(err)
- }
- authID, _ := veyronAliceBob.Authorize(NewContext(ContextArgs{}))
- if err := verifyAuthorizedID(veyronAliceBob, authID, S{"veyron/alice/bob@veyron@alice"}); err != nil {
- t.Fatal(err)
- }
-
- // google/alice blesses bob for 1 millisecond
- googleAliceBob, err := googleAlice.Bless(bob, "bob@google@alice", 1*time.Millisecond, nil)
- if err != nil {
- t.Fatal(err)
- }
- // Wait for 1ms so that the blessing expires
- time.Sleep(time.Millisecond)
- authID, _ = googleAliceBob.Authorize(NewContext(ContextArgs{}))
- if authID != nil {
- t.Fatal("%q.Authorized returned: %q, want nil", authID)
- }
-
- // At this point, Bob has a valid blessing from veyron/alice and an
- // expired blessing from google/alice. Bob should not be able to
- // construct a valid blessing from google/alice by combining certificates.
- veyronBob := veyronAliceBob.(*chainPublicID)
- googleBob := googleAliceBob.(*chainPublicID)
- // googleBob should be a valid identity before any modifications
- if _, err := roundTrip(googleBob); err != nil {
- t.Fatal(err)
- }
- // Keep the "google/alice" certificate and replace "alice/bob" from
- // "google/alice/bob" with the one from "veyron/alice/bob"
- cert := googleBob.certificates[2]
- googleBob.certificates[2] = veyronBob.certificates[2]
- // This hacked up identity should fail integrity tests
- if _, err := roundTrip(googleBob); err != wire.ErrNoIntegrity {
- t.Fatalf("roundTrip(%q) returned: %v want %v", googleBob, err, wire.ErrNoIntegrity)
- }
-
- // Restoring the certificate should restore validity.
- googleBob.certificates[2] = cert
- if _, err := roundTrip(googleBob); err != nil {
- t.Fatal(err)
- }
-
- // Replacing the "google/alice" certificate with the "veyron/alice"
- // certificate should also cause the identity to be invalid.
- googleBob.certificates[1] = veyronBob.certificates[1]
- if _, err := roundTrip(googleBob); err != wire.ErrNoIntegrity {
- t.Fatalf("roundTrip(%q) returned: %v want %v", googleBob, err, wire.ErrNoIntegrity)
- }
-}
-
-func TestDerive(t *testing.T) {
- var (
- cAlice = newChain("alice")
- cVeyronAlice = bless(cAlice.PublicID(), veyronChain, "alice")
- cBob = newChain("bob").PublicID()
- sVeyronAlice = newSetPrivateID(cAlice, derive(cVeyronAlice, cAlice))
-
- tChain = reflect.TypeOf(cAlice)
- tSet = reflect.TypeOf(sVeyronAlice)
- tErr = reflect.TypeOf(nil)
- )
- testdata := []struct {
- priv security.PrivateID
- pub security.PublicID
- typ reflect.Type
- }{
- {priv: cAlice, pub: cVeyronAlice, typ: tChain}, // chain.Derive(chain) = chain
- {priv: cAlice, pub: sVeyronAlice.PublicID(), typ: tSet}, // chain.Derive(set) = set
- {priv: cAlice, pub: cBob, typ: tErr},
- {priv: sVeyronAlice, pub: cAlice.PublicID(), typ: tChain}, // set.Derive(chain) = chain
- {priv: sVeyronAlice, pub: sVeyronAlice.PublicID(), typ: tSet}, // set.Derive(set) = set
- {priv: sVeyronAlice, pub: cBob, typ: tErr},
- }
- for _, d := range testdata {
- derivedID, err := d.priv.Derive(d.pub)
- if reflect.TypeOf(derivedID) != d.typ {
- t.Errorf("%T=%q.Derive(%T=%q) yielded (%T, %v), want %v", d.priv, d.priv, d.pub, d.pub, derivedID, err, d.typ)
- continue
- }
- if err != nil {
- // If it was not supposed to be, the previous check
- // would have registered the error.
- continue
- }
- if !reflect.DeepEqual(derivedID.PublicID(), d.pub) {
- t.Errorf("%q.Derive(%q) returned: %q. PublicID mismatch", d.priv, d.pub, derivedID)
- }
- if _, err := roundTrip(derivedID.PublicID()); err != nil {
- t.Errorf("roundTrip(%q=%q.Derive(%q)) failed: %v", derivedID, d.priv, d.pub, err)
- }
- }
-}
-
-func TestNewSetFailures(t *testing.T) {
- var (
- alice = newChain("alice")
- bob = newChain("bob")
- )
- if s, err := NewSetPrivateID(alice, bob); err == nil {
- t.Errorf("Got %v, want error since PrivateKeys do not match", s)
- }
- if s, err := NewSetPublicID(alice.PublicID(), bob.PublicID()); err == nil {
- t.Errorf("Got %v, want error since PublicKeys do not match", s)
- }
-}
-
-func TestSetIdentityAmplification(t *testing.T) {
- var (
- alice = newChain("alice").PublicID()
- bob = newChain("bob").PublicID()
-
- sAlice = newSetPublicID(bless(alice, veyronChain, "valice"), bless(alice, googleChain, "galice"))
- )
-
- // Manipulate sAlice before writing it out to the wire so that it has Bob's authorizations.
- reflect.ValueOf(sAlice).Elem().Index(1).Set(reflect.ValueOf(bob))
- // Encode/decode the identity.
- var buf bytes.Buffer
- if err := vom.NewEncoder(&buf).Encode(sAlice); err != nil {
- t.Fatal(err)
- }
- var decoded security.PublicID
- if err := vom.NewDecoder(&buf).Decode(&decoded); err == nil || decoded != nil {
- t.Fatalf("Got (%v, %v), want wire decode of manipulated identity to fail", decoded, err)
- }
-}
-
-func init() {
- modules.RegisterChild("encodeUnregisteredCaveat", "", encodeUnregisteredCaveat)
-
- vom.Register(alwaysValidCaveat{})
- vom.Register(proximityCaveat{})
-}
diff --git a/runtimes/google/security/keys/trusted_keys.go b/runtimes/google/security/keys/trusted_keys.go
deleted file mode 100644
index d7bef82..0000000
--- a/runtimes/google/security/keys/trusted_keys.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Package keys provides methods for managing various (trusted) issuer public keys.
-package keys
-
-import (
- "reflect"
- "sync"
-
- "veyron.io/veyron/veyron2/security"
-)
-
-var (
- // trusted holds the set of trusted public keys for certificates with the
- // self-signed name matching the key of the map.
- trusted map[string][]security.PublicKey
- trustedMu sync.Mutex
-)
-
-// Trust adds a public key to the set of keys trusted for the named
-// identity provider.
-func Trust(key security.PublicKey, name string) {
- trustedMu.Lock()
- trusted[name] = append(trusted[name], key)
- trustedMu.Unlock()
- // TODO(ataly): Eventually, "trusted" must be persisted.
-}
-
-// TrustLevel denotes the level of trust in an identity provider.
-type TrustLevel int
-
-const (
- // Unknown is the TrustLevel when the identity provider is not known -
- // no keys have ever been registered as trusted.
- Unknown TrustLevel = iota
- // Mistrusted is the TrustLevel returned when keys have been registered
- // for a named identity provider, but the key provided to LevelOfTrust
- // is not one of those registered keys.
- Mistrusted
- // Trusted is the TrustLevel returned when a key has been explicitly
- // registered as trustworthy for an identity provider (via a call to
- // Trust).
- Trusted
-)
-
-func (l TrustLevel) String() string {
- switch l {
- case Unknown:
- return "Unknown"
- case Mistrusted:
- return "Mistrusted"
- case Trusted:
- return "Trusted"
- default:
- return "<invalid TrustLevel>"
- }
-}
-
-// LevelOfTrust returns the TrustLevel for the given (key, identity provider) pair.
-func LevelOfTrust(key security.PublicKey, name string) TrustLevel {
- trustedMu.Lock()
- defer trustedMu.Unlock()
- keys, exists := trusted[name]
- if !exists {
- return Unknown
- }
- for _, k := range keys {
- if reflect.DeepEqual(k, key) {
- return Trusted
- }
- }
- return Mistrusted
-}
-
-func init() {
- trusted = make(map[string][]security.PublicKey)
-}
diff --git a/runtimes/google/security/keys/trusted_keys_test.go b/runtimes/google/security/keys/trusted_keys_test.go
deleted file mode 100644
index a678190..0000000
--- a/runtimes/google/security/keys/trusted_keys_test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package keys
-
-import (
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "errors"
- "fmt"
- "strings"
- "testing"
-
- "veyron.io/veyron/veyron2/security"
-)
-
-func mkkey() security.PublicKey {
- s, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- panic(err)
- }
- return security.NewECDSAPublicKey(&s.PublicKey)
-}
-
-func TestTrustedKeys(t *testing.T) {
- k1 := mkkey()
- k2 := mkkey()
- test := func(name string, k1Trust, k2Trust TrustLevel) error {
- var errs []string
- t1 := LevelOfTrust(k1, name)
- t2 := LevelOfTrust(k2, name)
- if t1 != k1Trust {
- errs = append(errs, fmt.Sprintf("Got %v want %v for LevelOfTrust(k1, %v)", t1, k1Trust, name))
- }
- if t2 != k2Trust {
- errs = append(errs, fmt.Sprintf("Got %v want %v for LevelOfTrust(k2, %v)", t2, k2Trust, name))
- }
- switch len(errs) {
- case 0:
- return nil
- case 1:
- return errors.New(errs[0])
- default:
- return errors.New(strings.Join(errs, ". "))
- }
- }
-
- // Initially, everything is unregistered
- if err := test("foo", Unknown, Unknown); err != nil {
- t.Error(err)
- }
- // k1 will be trusted for "foo" after Trust is called.
- Trust(k1, "foo")
- if err := test("foo", Trusted, Mistrusted); err != nil {
- t.Error(err)
- }
- // multiple keys can be trusted for the same name
- Trust(k2, "foo")
- if err := test("foo", Trusted, Trusted); err != nil {
- t.Error(err)
- }
- // Trust so far is only for "foo", not "bar"
- if err := test("bar", Unknown, Unknown); err != nil {
- t.Error(err)
- }
- Trust(k2, "bar")
- if err := test("bar", Mistrusted, Trusted); err != nil {
- t.Error(err)
- }
-}
diff --git a/runtimes/google/security/performance_test.go b/runtimes/google/security/performance_test.go
deleted file mode 100644
index f22a9b0..0000000
--- a/runtimes/google/security/performance_test.go
+++ /dev/null
@@ -1,106 +0,0 @@
-package security
-
-// This is a performance benchmark that tests the performance of the
-// chain and tree Identity implementations.
-//
-// Below are the results obtained on running the benchmark tests on April 2, 2014
-// on a desktop machine with a 12 core Intel Xeon E5-1650 @ 3.20GHz processor,
-// clock speed of 1200Mhz, and 32GB RAM.
-//
-// -- chain implementation --
-//
-// BenchmarkNewChain 1337091 ns/op
-// BenchmarkBlessChain 773872 ns/op
-// BenchmarkEncode0BlessingChain 47661 ns/op
-// BenchmarkEncode1BlessingChain 52063 ns/op
-// BenchmarkDecode0BlessingChain 2594072 ns/op
-// BenchmarkDecode1BlessingChain 5092197 ns/op
-//
-// Wire size with 0 blessings: 676 bytes ("untrusted/X")
-// Wire size with 1 blessings: 976 bytes ("untrusted/X/X")
-// Wire size with 2 blessings: 1275 bytes ("untrusted/X/X/X")
-import (
- "testing"
- "time"
-
- "veyron.io/veyron/veyron2/security"
-)
-
-func benchmarkBless(b *testing.B, blesser security.PrivateID, blessee security.PublicID) {
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if _, err := blesser.Bless(blessee, "friend_bob", 1*time.Second, nil); err != nil {
- b.Fatal(err)
- }
- }
-
-}
-
-func benchmarkEncode(b *testing.B, id security.PublicID) {
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if _, err := encode(id); err != nil {
- b.Fatal(err)
- }
- }
-}
-
-func benchmarkDecode(b *testing.B, idBytes []byte) {
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if _, err := decode(idBytes); err != nil {
- b.Fatal(err)
- }
- }
-}
-
-// -- chain implementation benchmarks --
-
-func BenchmarkNewChain(b *testing.B) {
- for i := 0; i < b.N; i++ {
- if _, err := newChainPrivateID("X", nil); err != nil {
- b.Fatalf("Failed newChainPrivateID #%d: %v", i, err)
- }
-
- }
-}
-
-func BenchmarkBlessChain(b *testing.B) {
- benchmarkBless(b, newChain("alice"), newChain("bob").PublicID())
-}
-func BenchmarkEncode0BlessingChain(b *testing.B) {
- benchmarkEncode(b, newChain("alice").PublicID())
-}
-func BenchmarkEncode1BlessingChain(b *testing.B) {
- benchmarkEncode(b, bless(newChain("immaterial").PublicID(), veyronChain, "alice"))
-}
-
-func BenchmarkDecode0BlessingChain(b *testing.B) {
- idBytes, err := encode(newChain("alice").PublicID())
- if err != nil {
- b.Fatal(err)
- }
- benchmarkDecode(b, idBytes)
-}
-
-func BenchmarkDecode1BlessingChain(b *testing.B) {
- idBytes, err := encode(bless(newChain("immaterial").PublicID(), veyronChain, "alice"))
- if err != nil {
- b.Fatal(err)
- }
- benchmarkDecode(b, idBytes)
-}
-
-func TestChainWireSize(t *testing.T) {
- const N = 3
- priv := newChain("X")
- for i := 0; i < N; i++ {
- pub := priv.PublicID()
- buf, err := encode(pub)
- if err != nil {
- t.Fatalf("Failed to encode %q: %v", pub, err)
- }
- t.Logf("Wire size of %T with %d blessings: %d bytes (%q)", pub, i, len(buf), pub)
- priv = derive(bless(pub, priv, "X"), priv)
- }
-}
diff --git a/runtimes/google/security/publicid_store.go b/runtimes/google/security/publicid_store.go
deleted file mode 100644
index 5df9874..0000000
--- a/runtimes/google/security/publicid_store.go
+++ /dev/null
@@ -1,272 +0,0 @@
-package security
-
-import (
- "errors"
- "fmt"
- "os"
- "path"
- "reflect"
- "sync"
-
- "veyron.io/veyron/veyron/security/serialization"
-
- "veyron.io/veyron/veyron2/security"
- "veyron.io/veyron/veyron2/vom"
-)
-
-const (
- dataFile = "blessingstore.data"
- signatureFile = "blessingstore.sig"
-)
-
-var (
- errStoreAddMismatch = errors.New("public key does not match that of existing PublicIDs in the store")
- errNoMatchingIDs = errors.New("no matching PublicIDs")
-)
-
-func errCombine(err error) error {
- return fmt.Errorf("could not combine matching PublicIDs: %s", err)
-}
-
-func saveErr(err error) error {
- return fmt.Errorf("could not save PublicIDStore: %s", err)
-}
-
-type taggedIDStore map[security.PublicID][]security.BlessingPattern
-
-type persistentState struct {
- // Store contains a set of PublicIDs mapped to a set of (peer) patterns. The
- // patterns indicate the set of peers against whom the PublicID can be used.
- // All PublicIDs in the store must have the same public key.
- Store taggedIDStore
- // DefaultPattern is the default BlessingPattern to be used to select
- // PublicIDs from the store in absence of any other search criterea.
- DefaultPattern security.BlessingPattern
-}
-
-// publicIDStore implements security.PublicIDStore.
-type publicIDStore struct {
- state persistentState
- publicKey security.PublicKey
- params *PublicIDStoreParams
- mu sync.RWMutex
-}
-
-func (s *publicIDStore) addTaggedID(id security.PublicID, peerPattern security.BlessingPattern) ([]security.PublicID, error) {
- var updatedIDs []security.PublicID
- switch p := id.(type) {
- case *setPublicID:
- for _, ip := range *p {
- ids, err := s.addTaggedID(ip, peerPattern)
- if err != nil {
- return updatedIDs, err
- }
- updatedIDs = append(updatedIDs, ids...)
- }
- default:
- for _, pattern := range s.state.Store[id] {
- if pattern == peerPattern {
- return updatedIDs, nil
- }
- }
- s.state.Store[id] = append(s.state.Store[id], peerPattern)
- updatedIDs = append(updatedIDs, id)
- }
- return updatedIDs, nil
-}
-
-func (s *publicIDStore) revert(updatedIDs []security.PublicID) {
- for _, id := range updatedIDs {
- s.state.Store[id] = s.state.Store[id][:len(s.state.Store[id])-1]
- }
-}
-
-func (s *publicIDStore) Add(id security.PublicID, peerPattern security.BlessingPattern) error {
- s.mu.Lock()
- defer s.mu.Unlock()
-
- publicKeyIsNil := s.publicKey == nil
- if !publicKeyIsNil && !reflect.DeepEqual(id.PublicKey(), s.publicKey) {
- return errStoreAddMismatch
- }
- if publicKeyIsNil {
- s.publicKey = id.PublicKey()
- }
-
- updatedIDs, err := s.addTaggedID(id, peerPattern)
- if err != nil {
- s.revert(updatedIDs)
- return err
- }
-
- if err := s.save(); err != nil {
- s.revert(updatedIDs)
- if publicKeyIsNil {
- s.publicKey = nil
- }
- return saveErr(err)
- }
- return nil
-}
-
-func (s *publicIDStore) ForPeer(peer security.PublicID) (security.PublicID, error) {
- s.mu.RLock()
- defer s.mu.RUnlock()
- var matchingIDs []security.PublicID
- for id, peerPatterns := range s.state.Store {
- for _, peerPattern := range peerPatterns {
- if peerPattern.MatchedBy(peer.Names()...) {
- matchingIDs = append(matchingIDs, id)
- break
- }
- }
- }
- id, err := NewSetPublicID(matchingIDs...)
- if err != nil {
- return nil, errCombine(err)
- }
- if id == nil {
- return nil, errNoMatchingIDs
- }
- return id, nil
-}
-
-func (s *publicIDStore) DefaultPublicID() (security.PublicID, error) {
- s.mu.RLock()
- defer s.mu.RUnlock()
- var matchingIDs []security.PublicID
- for id, _ := range s.state.Store {
- if s.state.DefaultPattern.MatchedBy(id.Names()...) {
- matchingIDs = append(matchingIDs, id)
- }
- }
- id, err := NewSetPublicID(matchingIDs...)
- if err != nil {
- return nil, errCombine(err)
- }
- if id == nil {
- return nil, errNoMatchingIDs
- }
- return id, nil
-}
-
-func (s *publicIDStore) SetDefaultBlessingPattern(pattern security.BlessingPattern) error {
- if !pattern.IsValid() {
- return fmt.Errorf("%q is an invalid BlessingPattern", pattern)
- }
- s.mu.Lock()
- defer s.mu.Unlock()
-
- oldPattern := s.state.DefaultPattern
- s.state.DefaultPattern = pattern
-
- if err := s.save(); err != nil {
- s.state.DefaultPattern = oldPattern
- return saveErr(err)
- }
- return nil
-}
-
-func (s *publicIDStore) save() error {
- if s.params == nil {
- return nil
- }
-
- // Save the state to temporary data and signature files, and then move
- // those files to the actually data and signature file. This reduces the
- // risk of loosing all saved data on disk in the event of a Write failure.
- dataPath := path.Join(s.params.Dir, dataFile)
- tempDataPath := dataPath + "_tmp"
- sigPath := path.Join(s.params.Dir, signatureFile)
- tempSigPath := sigPath + "_tmp"
-
- data, err := os.OpenFile(tempDataPath, os.O_WRONLY|os.O_CREATE, 0600)
- if err != nil {
- return err
- }
- defer os.Remove(tempDataPath)
- sig, err := os.OpenFile(tempSigPath, os.O_WRONLY|os.O_CREATE, 0600)
- if err != nil {
- return err
- }
- defer os.Remove(tempSigPath)
-
- swc, err := serialization.NewSigningWriteCloser(data, sig, s.params.Signer, nil)
- if err != nil {
- return err
- }
- if err := vom.NewEncoder(swc).Encode(s.state); err != nil {
- defer swc.Close()
- return err
- }
- if err := swc.Close(); err != nil {
- return err
- }
-
- if err := os.Rename(tempDataPath, dataPath); err != nil {
- return err
- }
- return os.Rename(tempSigPath, sigPath)
-}
-
-func (s *publicIDStore) String() string {
- return fmt.Sprintf("{state: %v, params: %v}", s.state, s.params)
-}
-
-// PublicIDStoreParams specifies persistent storage where a PublicIDStore can be
-// saved and loaded.
-type PublicIDStoreParams struct {
- // Dir specifies a path to a directory in which a serialized PublicIDStore
- // can be saved and loaded.
- Dir string
- // Signer provides a mechanism to sign and verify the serialized bytes.
- Signer serialization.Signer
-}
-
-// NewPublicIDStore returns a security.PublicIDStore based on params.
-// * If params is nil, a new store with an empty set of PublicIDs and the default
-// pattern "..." (matched by all PublicIDs) is returned. The store only lives in
-// memory and is never persisted.
-// * If params is non-nil, then a store obtained from the serialized data present
-// in params.Dir is returned if the data exists, or else a new store with an
-// empty set of PublicIDs and the default pattern "..." is returned. Any subsequent
-// modifications to the returned store are always signed (using params.Signer)
-// and persisted in params.Dir.
-func NewPublicIDStore(params *PublicIDStoreParams) (security.PublicIDStore, error) {
- store := &publicIDStore{
- state: persistentState{make(taggedIDStore), security.AllPrincipals},
- params: params,
- }
- if store.params == nil {
- return store, nil
- }
-
- data, dataErr := os.Open(path.Join(store.params.Dir, dataFile))
- defer data.Close()
- sig, sigErr := os.Open(path.Join(store.params.Dir, signatureFile))
- defer sig.Close()
-
- switch {
- case os.IsNotExist(dataErr) && os.IsNotExist(sigErr):
- // No params exists, returning an empty PublicIDStore.
- return store, nil
- case dataErr != nil:
- return nil, dataErr
- case sigErr != nil:
- return nil, sigErr
- }
-
- vr, err := serialization.NewVerifyingReader(data, sig, store.params.Signer.PublicKey())
- if err != nil {
- return nil, err
- }
- if err := vom.NewDecoder(vr).Decode(&store.state); err != nil {
- return nil, err
- }
-
- for id, _ := range store.state.Store {
- store.publicKey = id.PublicKey()
- break
- }
- return store, nil
-}
diff --git a/runtimes/google/security/publicid_store_test.go b/runtimes/google/security/publicid_store_test.go
deleted file mode 100644
index 0101a12..0000000
--- a/runtimes/google/security/publicid_store_test.go
+++ /dev/null
@@ -1,243 +0,0 @@
-package security
-
-import (
- "io/ioutil"
- "os"
- "reflect"
- "testing"
-
- "veyron.io/veyron/veyron2/security"
-)
-
-// verifyNamesAndPublicKey checks that the provided id has exactly the provided
-// set of names and the provided public key. If the provided set is empty then
-// the provided error must be errNoMatchingIDs.
-func verifyNamesAndPublicKey(id security.PublicID, err error, names []string, pkey security.PublicKey) bool {
- if id == nil {
- return err == errNoMatchingIDs && len(names) == 0
- }
- idNamesMap := make(map[string]bool)
- namesMap := make(map[string]bool)
- for _, n := range id.Names() {
- idNamesMap[n] = true
- }
- for _, n := range names {
- namesMap[n] = true
- }
- return reflect.DeepEqual(idNamesMap, namesMap) && reflect.DeepEqual(id.PublicKey(), pkey)
-}
-
-func TestStoreAdd(t *testing.T) {
- var (
- // test principals
- cAlice = newChain("alice")
- cBob = newChain("bob")
- cVeyronAlice = derive(bless(cAlice.PublicID(), veyronChain, "alice"), cAlice)
- sAlice = newSetPublicID(cAlice.PublicID(), cVeyronAlice.PublicID())
- )
- s, err := NewPublicIDStore(nil)
- if err != nil {
- t.Fatalf("NewPublicIDStore failed: %s", err)
- }
- // First Add should succeed for any PublicID (cAlice.PublicID() below)
- if err := s.Add(cAlice.PublicID(), "alice/..."); err != nil {
- t.Fatalf("%s.Add(%q, ...) failed unexpectedly: %s", s, cAlice.PublicID(), err)
- }
- // Subsequent Adds must succeed only for PublicIDs with cAlice's public key.
- if err := s.Add(cVeyronAlice.PublicID(), "..."); err != nil {
- t.Fatalf("%s.Add(%q, ...) failed unexpectedly: %s", s, cVeyronAlice.PublicID(), err)
- }
- if err := s.Add(sAlice, "alice/..."); err != nil {
- t.Fatalf("%s.Add(%q, ...) failed unexpectedly: %s", s, sAlice, err)
- }
- if got, want := s.Add(cBob.PublicID(), "bob/..."), errStoreAddMismatch; got != want {
- t.Fatalf("%s.Add(%q, ...): got: %s, want: %s", s, cBob, got, want)
- }
-}
-
-func TestSetDefaultPattern(t *testing.T) {
- s, err := NewPublicIDStore(nil)
- if err != nil {
- t.Fatalf("NewPublicIDStore failed: %s", err)
- }
- defaultPatterns := []struct {
- pattern security.BlessingPattern
- success bool
- }{
- {"veyron", true},
- {"veyron/alice@google", true},
- {"veyron/alice@google/bob", true},
- {"veyron/alice@google/...", true},
- {"", false},
- {"veyron...", false},
- {"...veyron", false},
- {"/veyron", false},
- {"veyron/", false},
- {"veyron/.../alice", false},
- }
- for _, d := range defaultPatterns {
- if got := s.SetDefaultBlessingPattern(d.pattern); d.success != (got == nil) {
- t.Errorf("%s.SetDefaultPattern(%q) returned: %v, expected it to succeed: %v", s, d.pattern, got, d.success)
- }
- }
-}
-
-func TestStoreGetters(t *testing.T) {
- add := func(s security.PublicIDStore, id security.PublicID, peers security.BlessingPattern) {
- if err := s.Add(id, peers); err != nil {
- t.Fatalf("%s.Add(%q, %q) failed unexpectedly: %s", s, id, peers, err)
- }
- }
- var (
- // test principals
- cAlice = newChain("alice")
- cBob = newChain("bob")
- cVService = newChain("vservice")
- cGService = newChain("gservice")
- cApp = newChain("app")
- cVeyronService = derive(bless(cVService.PublicID(), veyronChain, "service"), cVService)
- cGoogleService = derive(bless(cGService.PublicID(), googleChain, "service"), cGService)
- cGoogleServiceApp = derive(bless(cApp.PublicID(), cGoogleService, "app"), cApp)
- // PublicIDs for Alice's PublicIDStore
- cGoogleAlice = bless(cAlice.PublicID(), googleChain, "alice")
- cVeyronAlice = bless(cAlice.PublicID(), veyronChain, "alice")
- cGoogleServiceAlice = bless(cAlice.PublicID(), cGoogleService, "user-42")
- cVeyronServiceAlice = bless(cAlice.PublicID(), cVeyronService, "user-24")
-
- sGoogleAlice = newSetPublicID(cGoogleServiceAlice, cGoogleAlice)
- sAllAlice = newSetPublicID(sGoogleAlice, cVeyronAlice, cVeyronServiceAlice)
- // TODO(ataly): Test with SetPublicIDs as well.
- )
-
- // Create a new PublicIDStore and add Add Alice's PublicIDs to the store.
- s, err := NewPublicIDStore(nil)
- if err != nil {
- t.Fatalf("NewPublicIDStore failed: %s", err)
- }
- add(s, cGoogleAlice, "google") // use cGoogleAlice against all peers matching "google/..."
- add(s, cGoogleAlice, "veyron") // use cGoogleAlice against all peers matching "veyron/..." as well
- add(s, cVeyronAlice, "veyron/...") // use cVeyronAlice against peers matching "veyron/..."
- add(s, cVeyronAlice, "google") // use cVeyronAlice against peers matching "veyron/..."
- add(s, cVeyronServiceAlice, "veyron/service/...") // use cVeyronAlice against peers matching "veyron/service/..."
- add(s, cGoogleServiceAlice, "google/service/...") // use cGoogleServiceAlice against peers matching "google/service/..."
- add(s, sGoogleAlice, "google/service") // use any PublicID from sGoogleAlice against peers matching "google/service"
- add(s, sAllAlice, "veyron") // use any PublicID from sAllAlice against peers matching "veyron"
-
- pkey := cAlice.PublicID().PublicKey()
-
- // Test ForPeer.
- testDataForPeer := []struct {
- peer security.PublicID
- names []string
- }{
- {veyronChain.PublicID(), []string{"google/alice", "veyron/alice", "veyron/service/user-24", "google/service/user-42"}},
- {cVeyronService.PublicID(), []string{"veyron/alice", "veyron/service/user-24"}},
- {googleChain.PublicID(), []string{"veyron/alice", "google/alice", "google/service/user-42"}},
- {cGoogleService.PublicID(), []string{"google/alice", "google/service/user-42"}},
- {cGoogleServiceApp.PublicID(), []string{"google/service/user-42"}},
- {cBob.PublicID(), nil},
- }
- for _, d := range testDataForPeer {
- if got, err := s.ForPeer(d.peer); !verifyNamesAndPublicKey(got, err, d.names, pkey) {
- t.Errorf("%s.ForPeer(%s): got: %q, want PublicID with the exact set of names %q", s, d.peer, got, d.names)
- }
- }
-
- // Test initial DefaultPublicID -- we expect a PublicID with the union of the sets of names of all
- // PublicIDs in the store.
- defaultNames := []string{"google/alice", "veyron/alice", "veyron/service/user-24", "google/service/user-42"}
- if got, err := s.DefaultPublicID(); !verifyNamesAndPublicKey(got, err, defaultNames, pkey) {
- t.Errorf("%s.DefaultPublicID(): got: %s, want PublicID with the exact set of names: %s", s, got, defaultNames)
- }
-
- // Test SetDefaultBlessingPattern.
- testDataByBlessingPattern := []struct {
- defaultPattern security.BlessingPattern
- defaultNames []string
- }{
- {"veyron", nil},
- {"veyron/...", []string{"veyron/alice", "veyron/service/user-24"}},
- {"veyron/alice", []string{"veyron/alice"}},
- {"veyron/service/...", []string{"veyron/service/user-24"}},
- {"google", nil},
- {"google/...", []string{"google/alice", "google/service/user-42"}},
- {"google/alice", []string{"google/alice"}},
- {"google/service/...", []string{"google/service/user-42"}},
- {"bob", nil},
- }
- for _, d := range testDataByBlessingPattern {
- s.SetDefaultBlessingPattern(d.defaultPattern)
- if got, err := s.DefaultPublicID(); !verifyNamesAndPublicKey(got, err, d.defaultNames, pkey) {
- t.Errorf("%s.DefaultPublicID(): got: %s, want PublicID with the exact set of names: %s", s, got, d.defaultNames)
- }
- }
-}
-
-func TestPublicIDStorePersistence(t *testing.T) {
- newTempDir := func(name string) string {
- dir, err := ioutil.TempDir("", name)
- if err != nil {
- t.Fatal(err)
- }
- return dir
- }
-
- var (
- signer = newChain("signer")
-
- cAlice = newChain("alice")
- cBob = newChain("bob")
- cVeyronAlice = bless(cAlice.PublicID(), veyronChain, "alice")
- cGoogleAlice = bless(cAlice.PublicID(), googleChain, "alice")
- sAllAlice = newSetPublicID(cGoogleAlice, cVeyronAlice)
-
- pkey = cAlice.PublicID().PublicKey()
- )
-
- // Create a new PublicIDStore that saves all mutations to the provided directory.
- dir := newTempDir("publicid_store")
- defer os.RemoveAll(dir)
-
- s, err := NewPublicIDStore(&PublicIDStoreParams{dir, signer})
- if err != nil {
- t.Fatalf("NewPublicIDStore failed: %s", err)
- }
- if err := s.Add(sAllAlice, "google/..."); err != nil {
- t.Fatalf("%s.Add(%q, ...) failed unexpectedly: %s", s, sAllAlice, err)
- }
- if err := s.SetDefaultBlessingPattern("veyron/..."); err != nil {
- t.Fatalf("%s.SetDefaultBlessingPattern failed: %s", s, err)
- }
-
- // Test that all mutations are appropriately reflected in a PublicIDStore read from
- // the directory.
- s, err = NewPublicIDStore(&PublicIDStoreParams{dir, signer})
- if err != nil {
- t.Fatalf("NewPublicIDStore failed: %s", err)
- }
-
- testDataForPeer := []struct {
- peer security.PublicID
- names []string
- }{
- {googleChain.PublicID(), []string{"veyron/alice", "google/alice"}},
- {veyronChain.PublicID(), nil},
- {cBob.PublicID(), nil},
- }
- for _, d := range testDataForPeer {
- if got, err := s.ForPeer(d.peer); !verifyNamesAndPublicKey(got, err, d.names, pkey) {
- t.Errorf("%s.ForPeer(%s): got: %q, want PublicID with the exact set of names %q", s, d.peer, got, d.names)
- }
- }
-
- wantDefaultNames := []string{"veyron/alice"}
- if got, err := s.DefaultPublicID(); !verifyNamesAndPublicKey(got, err, wantDefaultNames, pkey) {
- t.Errorf("%s.DefaultPublicID(): got: %s, want PublicID with the exact set of names: %s", s, got, wantDefaultNames)
- }
-
- diffPubKeyID := newChain("immaterial").PublicID()
- if got, want := s.Add(diffPubKeyID, security.AllPrincipals), errStoreAddMismatch; got != want {
- t.Fatalf("%s.Add(%q, ...): got: %v, want: %v", s, diffPubKeyID, got, want)
- }
-
-}
diff --git a/runtimes/google/security/util.go b/runtimes/google/security/util.go
deleted file mode 100644
index 2834bca..0000000
--- a/runtimes/google/security/util.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package security
-
-import (
- "bytes"
- "errors"
- "fmt"
-
- "veyron.io/veyron/veyron/runtimes/google/security/keys"
- "veyron.io/veyron/veyron2/naming"
- "veyron.io/veyron/veyron2/security"
-)
-
-var errDeriveMismatch = errors.New("public key does not match that of deriving identity")
-
-// TrustIdentityProviders registers the identity providers of "id" as trustworthy ones,
-// i.e., any identities created by those providers will be considered trustworthy.
-func TrustIdentityProviders(id security.PrivateID) {
- switch t := id.(type) {
- case *chainPrivateID:
- keys.Trust(t.publicID.rootKey, t.publicID.certificates[0].Name)
- case setPrivateID:
- for _, priv := range t {
- TrustIdentityProviders(priv)
- }
- default:
- // Silently ignore
- }
-}
-
-// ContextArgs holds the arguments for creating a new security.Context for an IPC.
-type ContextArgs struct {
- // LocalPrincipal is the principal at the local end of a request.
- LocalPrincipal security.Principal
- // LocalBlessings is the blessings presented to the remote end of a request.
- LocalBlessings security.Blessings
- // RemoteBlessings is the blessings presented by the remote end of a request.
- RemoteBlessings security.Blessings
- // LocalID, RemoteID are the identities at the local and remote ends of a request
- // respectively.
- LocalID, RemoteID security.PublicID
- // Discharges is the set of third-party caveat discharges for the identity at the remote end
- // of the request.
- Discharges map[string]security.Discharge
- // Debug describes the context for debugging purposes.
- Debug string
- // The following fields must be set only for contexts created at the server receiving the IPC.
- //
- // Method is the name of the method being invoked.
- Method string
- // Name is the undispatched name for the request.
- Name string
- // Suffix is the object name suffix for the request.
- Suffix string
- // Label is the security label of the method being invoked.
- Label security.Label
- // LocalEndpoint, RemoteEndpoint are the veyron endpoints of the local and remote ends of a request
- LocalEndpoint, RemoteEndpoint naming.Endpoint
-}
-
-// context implements security.Context. This implementation simply stores the
-// method, label, suffix, and the identities of the local and remote principals
-// associated with an IPC call in the context object.
-type context struct {
- ContextArgs
- Debug string
-}
-
-func (c *context) String() string {
- // fmt.Sprintf("%#v", c) doesn't work because it does not expand
- // localID, remoteID etc.
- if len(c.ContextArgs.Debug) > 0 {
- return c.Debug
- }
- var buf bytes.Buffer
- buf.WriteString("{")
- if c.ContextArgs.LocalID != nil {
- buf.WriteString(fmt.Sprintf(" LocalID:%q", c.LocalID()))
- }
- if c.ContextArgs.RemoteID != nil {
- buf.WriteString(fmt.Sprintf(" RemoteID:%q", c.RemoteID()))
- }
- if len(c.ContextArgs.Method) > 0 {
- buf.WriteString(fmt.Sprintf(" Method:%q", c.Method()))
- }
- if len(c.ContextArgs.Name) > 0 {
- buf.WriteString(fmt.Sprintf(" Name:%q", c.Name()))
- }
- if len(c.ContextArgs.Suffix) > 0 {
- buf.WriteString(fmt.Sprintf(" Suffix:%q", c.Suffix()))
- }
- if c.ContextArgs.Label != 0 {
- buf.WriteString(fmt.Sprintf(" Label:%v", c.Label()))
- }
- if len(c.ContextArgs.Discharges) > 0 {
- buf.WriteString(fmt.Sprintf(" #Discharges:%d", len(c.Discharges())))
- }
- buf.WriteString(" }")
- return buf.String()
-}
-
-func (c *context) Method() string { return c.ContextArgs.Method }
-func (c *context) Name() string { return c.ContextArgs.Name }
-func (c *context) Suffix() string { return c.ContextArgs.Suffix }
-func (c *context) Label() security.Label { return c.ContextArgs.Label }
-func (c *context) Discharges() map[string]security.Discharge { return c.ContextArgs.Discharges }
-func (c *context) LocalID() security.PublicID { return c.ContextArgs.LocalID }
-func (c *context) RemoteID() security.PublicID { return c.ContextArgs.RemoteID }
-func (c *context) LocalPrincipal() security.Principal { return c.ContextArgs.LocalPrincipal }
-func (c *context) LocalBlessings() security.Blessings { return c.ContextArgs.LocalBlessings }
-func (c *context) RemoteBlessings() security.Blessings { return c.ContextArgs.RemoteBlessings }
-func (c *context) LocalEndpoint() naming.Endpoint { return c.ContextArgs.LocalEndpoint }
-func (c *context) RemoteEndpoint() naming.Endpoint { return c.ContextArgs.RemoteEndpoint }
-
-// NewContext returns a new security.Context for the provided method, name,
-// suffix, discharges, label and identities of the local and remote principals
-// associated with an IPC invocation.
-func NewContext(args ContextArgs) security.Context {
- return &context{ContextArgs: args}
-}
diff --git a/runtimes/google/security/util_test.go b/runtimes/google/security/util_test.go
deleted file mode 100644
index 294c552..0000000
--- a/runtimes/google/security/util_test.go
+++ /dev/null
@@ -1,184 +0,0 @@
-package security
-
-import (
- "bytes"
- "fmt"
- "reflect"
- "strings"
- "testing"
- "time"
-
- "veyron.io/veyron/veyron/runtimes/google/security/keys"
-
- "veyron.io/veyron/veyron2/security"
- "veyron.io/veyron/veyron2/vom"
-)
-
-var (
- // Trusted identity providers
- // (type assertion just to ensure test sanity)
- veyronChain = newChain("veyron").(*chainPrivateID)
- googleChain = newChain("google").(*chainPrivateID)
-)
-
-type dischargeMap map[string]security.Discharge
-
-func matchesErrorPattern(err error, pattern string) bool {
- if (len(pattern) == 0) != (err == nil) {
- return false
- }
- return err == nil || strings.Index(err.Error(), pattern) >= 0
-}
-
-func encode(id security.PublicID) ([]byte, error) {
- var b bytes.Buffer
- err := vom.NewEncoder(&b).Encode(id)
- return b.Bytes(), err
-}
-
-func decode(b []byte) (security.PublicID, error) {
- dID := new(security.PublicID)
- err := vom.NewDecoder(bytes.NewReader(b)).Decode(dID)
- return *dID, err
-}
-
-func roundTrip(id security.PublicID) (security.PublicID, error) {
- b, err := encode(id)
- if err != nil {
- return nil, err
- }
- return decode(b)
-}
-
-func newChain(name string) security.PrivateID {
- id, err := newChainPrivateID(name, nil)
- if err != nil {
- panic(err)
- }
- return id
-}
-
-func newSetPublicID(ids ...security.PublicID) security.PublicID {
- id, err := NewSetPublicID(ids...)
- if err != nil {
- panic(err)
- }
- return id
-}
-
-func newSetPrivateID(ids ...security.PrivateID) security.PrivateID {
- id, err := NewSetPrivateID(ids...)
- if err != nil {
- panic(err)
- }
- return id
-}
-
-func bless(blessee security.PublicID, blessor security.PrivateID, name string, caveats ...security.Caveat) security.PublicID {
- blessed, err := blessor.Bless(blessee, name, 5*time.Minute, caveats)
- if err != nil {
- panic(err)
- }
- return blessed
-}
-
-func derive(pub security.PublicID, priv security.PrivateID) security.PrivateID {
- d, err := priv.Derive(pub)
- if err != nil {
- panic(err)
- }
- return d
-}
-
-func verifyAuthorizedID(origID, authID security.PublicID, authNames []string) error {
- if authID == nil {
- if len(authNames) != 0 {
- return fmt.Errorf("%q.Authorize is nil, want identity with names: %v", origID, authNames)
- }
- return nil
- }
- if got, want := authID.Names(), authNames; !reflect.DeepEqual(got, want) {
- return fmt.Errorf("%q(%T).Names(): got: %v, want: %v", authID, authID, got, want)
- }
-
- if !reflect.DeepEqual(origID.PublicKey(), authID.PublicKey()) {
- return fmt.Errorf("%q.Authorize returned %q with public key %v, should have had %v", origID, authID, authID.PublicKey(), origID.PublicKey())
- }
- if _, err := roundTrip(authID); err != nil {
- return fmt.Errorf("%q.Authorize returned %q, which failed roundTripping: %v", origID, authID, err)
- }
- return nil
-}
-
-func newCaveat(validator security.CaveatValidator) security.Caveat {
- cav, err := security.NewCaveat(validator)
- if err != nil {
- panic(err)
- }
- return cav
-}
-
-func mkCaveat(cav security.Caveat, err error) security.Caveat {
- if err != nil {
- panic(err)
- }
- return cav
-}
-
-func init() {
- // Mark "veyron" and "google" as trusted identity providers.
- keys.Trust(veyronChain.PublicID().PublicKey(), "veyron")
- keys.Trust(googleChain.PublicID().PublicKey(), "google")
-}
-
-func TestTrustIdentityProviders(t *testing.T) {
- var (
- cSelf = newChain("chainself")
- cProvider = newChain("provider")
- cBlessed = derive(bless(cSelf.PublicID(), cProvider, "somebody"), cSelf)
-
- cProvider1 = newChain("provider")
- cProvider2 = newChain("provider")
- cSomebody1 = derive(bless(cSelf.PublicID(), cProvider1, "somebody1"), cSelf)
- cSomebody2 = derive(bless(cSelf.PublicID(), cProvider2, "somebody2"), cSelf)
- setID = newSetPrivateID(cSomebody1, cSomebody2)
- )
- // Initially nobody is trusted
- m := map[security.PrivateID]bool{
- cSelf: false,
- cProvider: false,
- cBlessed: false,
- cProvider1: false,
- cProvider2: false,
- cSomebody1: false,
- cSomebody2: false,
- }
- test := func() {
- for priv, want := range m {
- id := priv.PublicID()
- switch tl := keys.LevelOfTrust(id.PublicKey(), "provider"); tl {
- case keys.Trusted:
- if !want {
- t.Errorf("%q is trusted, should not be", id)
- }
- case keys.Unknown, keys.Mistrusted:
- if want {
- t.Errorf("%q is %v, it should be trusted", id, tl)
- }
- default:
- t.Errorf("%q has an invalid trust level: %v", tl)
- }
- }
- }
- test()
- // Trusting cBlessed should cause cProvider to be trusted
- TrustIdentityProviders(cBlessed)
- m[cProvider] = true
- test()
- // Trusting setID should cause both cProvider1 and cProvider2
- // to be trusted.
- TrustIdentityProviders(setID)
- m[cProvider1] = true
- m[cProvider2] = true
- test()
-}
diff --git a/runtimes/google/testing/mocks/runtime/panic_runtime.go b/runtimes/google/testing/mocks/runtime/panic_runtime.go
index e0b1294..215fb5c 100644
--- a/runtimes/google/testing/mocks/runtime/panic_runtime.go
+++ b/runtimes/google/testing/mocks/runtime/panic_runtime.go
@@ -23,9 +23,6 @@
func (*PanicRuntime) Profile() veyron2.Profile { panic(badRuntime) }
func (*PanicRuntime) Publisher() *config.Publisher { panic(badRuntime) }
-func (*PanicRuntime) NewIdentity(name string) (security.PrivateID, error) { panic(badRuntime) }
-func (*PanicRuntime) PublicIDStore() security.PublicIDStore { panic(badRuntime) }
-func (*PanicRuntime) Identity() security.PrivateID { panic(badRuntime) }
func (*PanicRuntime) Principal() security.Principal { panic(badRuntime) }
func (*PanicRuntime) NewClient(opts ...ipc.ClientOpt) (ipc.Client, error) { panic(badRuntime) }
func (*PanicRuntime) NewServer(opts ...ipc.ServerOpt) (ipc.Server, error) { panic(badRuntime) }