veyron/runtimes/google: Plumb the new security model all the way through.
This commit aims to enable a smooth transition to the new security
model for all client and server processes.
- ipc.Server implementations have both an old model identity
(PrivateID/PublicID) and new model credentials (Principal)
However, the IPC protocol version sent by the client determines
which model to use. IPCVersion4 implies authentication with
the new model, older versions use the older model
- The runtime sets up ipc.Client to use the new security model
only when explicitly asked to do so via the presense of the
VEYRON_CREDENTIALS environment variable.
The upgrade plan is to:
- Generate new-model credentials for all services and restart
those services
- After some time (once we've traced all remaining old code),
switch the default behavior to only use the old model if
explicitly asked to do so.
- And after that, remove the old model
Change-Id: Ifcaee44dbf12fa8bdbeec6e241f3f9d232668273
diff --git a/runtimes/google/ipc/stream/benchmark/throughput_flow.go b/runtimes/google/ipc/stream/benchmark/throughput_flow.go
index 01d925b..ff69e6f 100644
--- a/runtimes/google/ipc/stream/benchmark/throughput_flow.go
+++ b/runtimes/google/ipc/stream/benchmark/throughput_flow.go
@@ -5,8 +5,6 @@
"testing"
"veyron.io/veyron/veyron/runtimes/google/ipc/stream/manager"
- "veyron.io/veyron/veyron/runtimes/google/ipc/stream/sectest"
- "veyron.io/veyron/veyron/runtimes/google/ipc/stream/vc"
"veyron.io/veyron/veyron2"
"veyron.io/veyron/veyron2/ipc/stream"
"veyron.io/veyron/veyron2/naming"
@@ -27,11 +25,9 @@
// that calling stream.Manager.Dial to each of the endpoints will end up
// creating a new VIF.
func createListeners(mode veyron2.VCSecurityLevel, m stream.Manager, N int) (servers []listener, err error) {
- // TODO(ashankar): Remove once PublicIDs are gone since at that point, if no Principal is provided, an anonymous one should be gereated within vc.go
- serverP := vc.LocalPrincipal{sectest.NewPrincipal("server")}
for i := 0; i < N; i++ {
var l listener
- if l.ln, l.ep, err = m.Listen("tcp", "127.0.0.1:0", mode, serverP); err != nil {
+ if l.ln, l.ep, err = m.Listen("tcp", "127.0.0.1:0", mode); err != nil {
return
}
servers = append(servers, l)
@@ -52,14 +48,12 @@
rchan := make(chan io.ReadCloser, nFlows)
wchan := make(chan io.WriteCloser, nFlows)
- // TODO(ashankar): Remove once PublicIDs are gone since at that point, if no Principal is provided, an anonymous one should be gereated within vc.go
- clientP := vc.LocalPrincipal{sectest.NewPrincipal("client")}
go func() {
defer close(wchan)
for i := 0; i < nVIFs; i++ {
ep := lns[i].ep
for j := 0; j < nVCsPerVIF; j++ {
- vc, err := client.Dial(ep, mode, clientP)
+ vc, err := client.Dial(ep, mode)
if err != nil {
b.Error(err)
return
diff --git a/runtimes/google/ipc/stream/manager/manager_test.go b/runtimes/google/ipc/stream/manager/manager_test.go
index 5729c30..1130e2c 100644
--- a/runtimes/google/ipc/stream/manager/manager_test.go
+++ b/runtimes/google/ipc/stream/manager/manager_test.go
@@ -320,7 +320,7 @@
// Have the server read from each flow and write to rchan.
rchan := make(chan string)
- ln, ep, err := server.Listen("tcp", "127.0.0.1:0", newPrincipal("server"))
+ ln, ep, err := server.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
@@ -356,7 +356,7 @@
var vcs [nVCs]stream.VC
for i := 0; i < nVCs; i++ {
var err error
- vcs[i], err = client.Dial(ep, newPrincipal("client"))
+ vcs[i], err = client.Dial(ep)
if err != nil {
t.Fatal(err)
}
@@ -433,7 +433,6 @@
func TestServerRestartDuringClientLifetime(t *testing.T) {
client := InternalNew(naming.FixedRoutingID(0xcccccccc))
- clientP := newPrincipal("client") // TODO(ashankar): Remove. Once the PublicID code is gone anonymous principals should be generated within vc.go if one is not provided.
server := blackbox.HelperCommand(t, "runServer", "127.0.0.1:0")
server.Cmd.Start()
addr, err := server.ReadLineFromChild()
@@ -444,12 +443,12 @@
if err != nil {
t.Fatalf("inaming.NewEndpoint(%q): %v", addr, err)
}
- if _, err := client.Dial(ep, clientP); err != nil {
+ if _, err := client.Dial(ep); err != nil {
t.Fatal(err)
}
server.Cleanup()
// A new VC cannot be created since the server is dead
- if _, err := client.Dial(ep, clientP); err == nil {
+ if _, err := client.Dial(ep); err == nil {
t.Fatal("Expected client.Dial to fail since server is dead")
}
// Restarting the server, listening on the same address as before
@@ -459,7 +458,7 @@
if addr2, err := server.ReadLineFromChild(); addr2 != addr || err != nil {
t.Fatalf("Got (%q, %v) want (%q, nil)", addr2, err, addr)
}
- if _, err := client.Dial(ep, clientP); err != nil {
+ if _, err := client.Dial(ep); err != nil {
t.Fatal(err)
}
}
@@ -471,7 +470,7 @@
func runServer(argv []string) {
server := InternalNew(naming.FixedRoutingID(0x55555555))
- _, ep, err := server.Listen("tcp", argv[0], newPrincipal("server"))
+ _, ep, err := server.Listen("tcp", argv[0])
if err != nil {
fmt.Println(err)
return
diff --git a/runtimes/google/ipc/stream/proxy/proxy.go b/runtimes/google/ipc/stream/proxy/proxy.go
index 4099d71..683ea0c 100644
--- a/runtimes/google/ipc/stream/proxy/proxy.go
+++ b/runtimes/google/ipc/stream/proxy/proxy.go
@@ -127,14 +127,7 @@
// New creates a new Proxy that listens for network connections on the provided
// (network, address) pair and routes VC traffic between accepted connections.
-//
-// TODO(ashankar): Change principal to security.Principal once the old security model is ripped out.
-func New(rid naming.RoutingID, principal interface{}, network, address, pubAddress string) (*Proxy, error) {
- if _, ok := principal.(security.Principal); principal != nil && !ok {
- if _, ok := principal.(security.PrivateID); !ok {
- return nil, fmt.Errorf("principal argument must be either a security.Principal or a security.PrivateID, not a %T", principal)
- }
- }
+func New(rid naming.RoutingID, principal security.Principal, network, address, pubAddress string) (*Proxy, error) {
ln, err := net.Listen(network, address)
if err != nil {
return nil, fmt.Errorf("net.Listen(%q, %q) failed: %v", network, address, err)
@@ -148,11 +141,7 @@
servers: &servermap{m: make(map[naming.RoutingID]*server)},
processes: make(map[*process]struct{}),
pubAddress: pubAddress,
- }
- if p, ok := principal.(security.Principal); ok {
- proxy.principal = vc.LocalPrincipal{p}
- } else if principal != nil {
- proxy.principal = vc.FixedLocalID(principal.(security.PrivateID))
+ principal: vc.LocalPrincipal{principal},
}
go proxy.listenLoop()
return proxy, nil
@@ -518,6 +507,11 @@
vc.Close("duplicate OpenVC request")
return nil
}
+ version, err := version.CommonVersion(m.DstEndpoint, m.SrcEndpoint)
+ if err != nil {
+ p.SendCloseVC(m.VCI, fmt.Errorf("incompatible IPC protocol versions: %v", err))
+ return nil
+ }
vc := vc.InternalNew(vc.Params{
VCI: m.VCI,
LocalEP: m.DstEndpoint,
@@ -525,6 +519,7 @@
Pool: iobuf.NewPool(0),
ReserveBytes: message.HeaderSizeBytes,
Helper: p,
+ Version: version,
})
p.servers[m.VCI] = vc
proxyLog().Infof("Registered VC %v from server on process %v", vc, p)
diff --git a/runtimes/google/ipc/stream/proxy/proxy_test.go b/runtimes/google/ipc/stream/proxy/proxy_test.go
index 8803604..e705c6c 100644
--- a/runtimes/google/ipc/stream/proxy/proxy_test.go
+++ b/runtimes/google/ipc/stream/proxy/proxy_test.go
@@ -10,23 +10,14 @@
"veyron.io/veyron/veyron2/ipc/stream"
"veyron.io/veyron/veyron2/naming"
- "veyron.io/veyron/veyron2/security"
_ "veyron.io/veyron/veyron/lib/testutil"
"veyron.io/veyron/veyron/runtimes/google/ipc/stream/manager"
"veyron.io/veyron/veyron/runtimes/google/ipc/stream/proxy"
+ "veyron.io/veyron/veyron/runtimes/google/ipc/stream/sectest"
"veyron.io/veyron/veyron/runtimes/google/ipc/stream/vc"
- isecurity "veyron.io/veyron/veyron/runtimes/google/security"
)
-func newID(name string) security.PrivateID {
- id, err := isecurity.NewPrivateID(name, nil)
- if err != nil {
- panic(err)
- }
- return id
-}
-
func TestProxy(t *testing.T) {
proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), nil, "tcp", "127.0.0.1:0", "")
if err != nil {
@@ -114,9 +105,9 @@
}
}
-func TestProxyIdentity(t *testing.T) {
- proxyID := newID("proxy")
- proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), proxyID, "tcp", "127.0.0.1:0", "")
+func TestProxyAuthentication(t *testing.T) {
+ pproxy := sectest.NewPrincipal("proxy")
+ proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), pproxy, "tcp", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
}
@@ -134,12 +125,12 @@
if err != nil {
t.Fatal(err)
}
- if got, want := fmt.Sprintf("%v", flow.RemoteID()), fmt.Sprintf("%v", proxyID.PublicID()); got != want {
- t.Errorf("Proxy has identity %q want %q", flow.RemoteID(), want)
+ if got, want := flow.RemoteBlessings(), pproxy.BlessingStore().Default(); !reflect.DeepEqual(got, want) {
+ t.Errorf("Proxy authenticated as [%v], want [%v]", got, want)
}
}
-func TestServerIdentity(t *testing.T) {
+func TestServerBlessings(t *testing.T) {
proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), nil, "tcp", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
@@ -147,11 +138,8 @@
server := manager.InternalNew(naming.FixedRoutingID(0x5555555555555555))
defer server.Shutdown()
- serverID := newID("server")
- if err != nil {
- t.Fatal(err)
- }
- ln, ep, err := server.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String(), vc.FixedLocalID(serverID))
+ pserver := sectest.NewPrincipal("server")
+ ln, ep, err := server.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String(), vc.LocalPrincipal{pserver})
if err != nil {
t.Fatal(err)
}
@@ -174,8 +162,8 @@
if err != nil {
t.Fatal(err)
}
- if got, want := flow.RemoteID(), serverID.PublicID(); !reflect.DeepEqual(got, want) {
- t.Errorf("Got %q want %q", got, want)
+ if got, want := flow.RemoteBlessings(), pserver.BlessingStore().Default(); !reflect.DeepEqual(got, want) {
+ t.Errorf("Got [%v] want [%v]", got, want)
}
}
diff --git a/runtimes/google/ipc/stream/vc/auth.go b/runtimes/google/ipc/stream/vc/auth.go
index e3b06ec..5746a99 100644
--- a/runtimes/google/ipc/stream/vc/auth.go
+++ b/runtimes/google/ipc/stream/vc/auth.go
@@ -75,6 +75,7 @@
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")
)
@@ -316,6 +317,9 @@
if err != nil {
return nil, err
}
+ if b == nil {
+ return nil, errNoCertificatesReceived
+ }
if !sig.Verify(b.PublicKey(), append(tag, crypter.ChannelBinding()...)) {
return nil, errInvalidSignatureInMessage
}
diff --git a/runtimes/google/ipc/stream/vc/init.go b/runtimes/google/ipc/stream/vc/init.go
index 8ff0aa5..8b7dbaa 100644
--- a/runtimes/google/ipc/stream/vc/init.go
+++ b/runtimes/google/ipc/stream/vc/init.go
@@ -1,6 +1,11 @@
package vc
import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "fmt"
+
isecurity "veyron.io/veyron/veyron/runtimes/google/security"
"veyron.io/veyron/veyron2/security"
@@ -8,10 +13,49 @@
)
var anonymousID security.PrivateID
+var anonymousPrincipal security.Principal
func init() {
- var err error
- if anonymousID, err = isecurity.NewPrivateID("anonymous", nil); err != nil {
- vlog.Fatalf("could not create anonymousID for IPCs: %s", err)
+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ vlog.Fatalf("could not create private key for anonymous principal: %v", err)
}
+ store := &anonymousBlessingStore{k: security.NewECDSAPublicKey(&key.PublicKey)}
+ if anonymousPrincipal, err = security.CreatePrincipal(security.NewInMemoryECDSASigner(key), store, nil); err != nil {
+ vlog.Fatalf("could not create anonymous principal: %v", err)
+ }
+ 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!
+// (Most likely move the BlessingStore implementation from veyron/runtimes/google/rt to veyron/security
+// and use that?)
+type anonymousBlessingStore struct {
+ k security.PublicKey
+ b security.Blessings
+}
+
+func (s *anonymousBlessingStore) Set(security.Blessings, security.BlessingPattern) (security.Blessings, error) {
+ return nil, fmt.Errorf("cannot store blessings with an anonymous principal")
+}
+
+func (s *anonymousBlessingStore) ForPeer(...string) security.Blessings {
+ return s.b
+}
+
+func (s *anonymousBlessingStore) SetDefault(security.Blessings) error {
+ return fmt.Errorf("cannot change default blessing associated with the anonymous principal")
+}
+
+func (s *anonymousBlessingStore) Default() security.Blessings {
+ return s.b
+}
+
+func (s *anonymousBlessingStore) PublicKey() security.PublicKey {
+ return s.k
}
diff --git a/runtimes/google/ipc/stream/vc/vc.go b/runtimes/google/ipc/stream/vc/vc.go
index f0b4ad9..0093009 100644
--- a/runtimes/google/ipc/stream/vc/vc.go
+++ b/runtimes/google/ipc/stream/vc/vc.go
@@ -397,11 +397,12 @@
}
switch securityLevel {
case veyron2.VCSecurityConfidential:
- // TODO(ashankar): This should change to:
- // if principal == nil { either return error or principal = newAnonymousPrincipal }
- if localID == nil && principal == nil {
+ if localID == nil {
localID = FixedLocalID(anonymousID)
}
+ if principal == nil {
+ principal = anonymousPrincipal
+ }
case veyron2.VCSecurityNone:
return nil
default:
@@ -437,7 +438,7 @@
rID, lID security.PublicID
rBlessings, lBlessings security.Blessings
)
- if principal == nil {
+ 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))
}
@@ -451,14 +452,17 @@
vc.handshakeFID = handshakeFID
vc.authFID = authFID
vc.crypter = crypter
- vc.localID = lID
- vc.remoteID = rID
- vc.localPrincipal = principal
- vc.remoteBlessings = rBlessings
- vc.localBlessings = lBlessings
+ if vc.useOldSecurityModel() {
+ vc.localID = lID
+ vc.remoteID = rID
+ } else {
+ vc.localPrincipal = principal
+ vc.remoteBlessings = rBlessings
+ vc.localBlessings = lBlessings
+ }
vc.mu.Unlock()
- if principal != nil {
+ 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)
@@ -511,6 +515,9 @@
if localID == nil {
localID = FixedLocalID(anonymousID)
}
+ if principal == nil {
+ principal = anonymousPrincipal
+ }
case veyron2.VCSecurityNone:
return finish(ln, nil)
default:
@@ -557,7 +564,7 @@
rID, lID security.PublicID
rBlessings, lBlessings security.Blessings
)
- if principal == nil {
+ 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
@@ -571,18 +578,21 @@
vc.mu.Lock()
vc.crypter = crypter
- vc.localID = lID
- vc.remoteID = rID
- vc.localPrincipal = principal
- vc.localBlessings = lBlessings
- vc.remoteBlessings = rBlessings
+ if vc.useOldSecurityModel() {
+ vc.localID = lID
+ vc.remoteID = rID
+ } else {
+ vc.localPrincipal = principal
+ vc.localBlessings = lBlessings
+ vc.remoteBlessings = rBlessings
+ }
close(vc.acceptHandshakeDone)
vc.acceptHandshakeDone = nil
vc.mu.Unlock()
- if principal == nil {
- vlog.VI(1).Infof("Server VC %v authenticated using about-to-be-deleted protocol. RemoteID:%v LocalID:%v", vc, rID, lID)
- } else {
+ 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)
}
result <- HandshakeResult{ln, nil}
}()
@@ -671,7 +681,10 @@
vc.mu.Lock()
defer vc.mu.Unlock()
vc.waitForHandshakeLocked()
- return anonymousIfNilPublicID(vc.localID)
+ if vc.useOldSecurityModel() {
+ return anonymousIfNilPublicID(vc.localID)
+ }
+ return nil
}
// RemoteID returns the identity of the remote end of the VC.
@@ -679,7 +692,10 @@
vc.mu.Lock()
defer vc.mu.Unlock()
vc.waitForHandshakeLocked()
- return anonymousIfNilPublicID(vc.remoteID)
+ if vc.useOldSecurityModel() {
+ return anonymousIfNilPublicID(vc.remoteID)
+ }
+ return nil
}
// waitForHandshakeLocked blocks until an in-progress handshake (encryption
@@ -714,7 +730,9 @@
l = append(l, "Handshake not completed yet")
} else {
l = append(l, "Encryption: "+vc.crypter.String())
- l = append(l, fmt.Sprintf("LocalPrincipal:%v LocalBlessings:%v RemoteBlessings:%v", vc.localPrincipal.PublicKey(), vc.localBlessings, vc.remoteBlessings))
+ 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 {
@@ -725,6 +743,9 @@
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 {
diff --git a/runtimes/google/ipc/stream/vc/vc_test.go b/runtimes/google/ipc/stream/vc/vc_test.go
index e380374..086cc23 100644
--- a/runtimes/google/ipc/stream/vc/vc_test.go
+++ b/runtimes/google/ipc/stream/vc/vc_test.go
@@ -35,7 +35,7 @@
SecurityNone = veyron2.VCSecurityNone
SecurityTLS = veyron2.VCSecurityConfidential
- LatestVersion = version.IPCVersion3
+ LatestVersion = version.IPCVersion4
)
// testFlowEcho writes a random string of 'size' bytes on the flow and then
@@ -100,8 +100,6 @@
if err != nil {
t.Fatal(err)
}
- // TODO(ashankar): This should not be nil, but rather a dummy object (whose public
- // key does not match that of the principal)
if flow.RemoteBlessings() != nil {
t.Errorf("Server sent blessing %v over insecure transport", flow.RemoteBlessings())
}
@@ -183,8 +181,8 @@
func TestConnect(t *testing.T) { testConnect(t, SecurityNone) }
func TestConnectTLS(t *testing.T) { testConnect(t, SecurityTLS) }
-func testConnect_Version2(t *testing.T, security veyron2.VCSecurityLevel) {
- h, vc := New(security, version.IPCVersion2, sectest.NewPrincipal("client"), sectest.NewPrincipal("server"))
+func testConnect_Version3(t *testing.T, security veyron2.VCSecurityLevel) {
+ h, vc := New(security, version.IPCVersion3, sectest.NewPrincipal("client"), sectest.NewPrincipal("server"))
defer h.Close()
flow, err := vc.Connect()
if err != nil {
@@ -192,8 +190,8 @@
}
testFlowEcho(t, flow, 10)
}
-func TestConnect_Version2(t *testing.T) { testConnect_Version2(t, SecurityNone) }
-func TestConnect_Version2TLS(t *testing.T) { testConnect_Version2(t, SecurityTLS) }
+func TestConnect_Version3(t *testing.T) { testConnect_Version3(t, SecurityNone) }
+func TestConnect_Version3TLS(t *testing.T) { testConnect_Version3(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/stream/vif/vif.go b/runtimes/google/ipc/stream/vif/vif.go
index 06d27bd..c30a543 100644
--- a/runtimes/google/ipc/stream/vif/vif.go
+++ b/runtimes/google/ipc/stream/vif/vif.go
@@ -177,10 +177,22 @@
return vif, nil
}
+func adjustIPCVersionForOldSecurityModel(in naming.Endpoint, opts []stream.VCOpt) naming.Endpoint {
+ out := in
+ for _, o := range opts {
+ if r, ok := o.(*version.Range); ok {
+ out = r.Endpoint(out.Addr().Network(), out.Addr().String(), out.RoutingID())
+ vlog.Infof("Adjusted Dialer endpoint from %v to %v for OpenVC message because the old security model is being used", in, out)
+ }
+ }
+ return out
+}
+
// Dial creates a new VC to the provided remote identity, authenticating the VC
// with the provided local identity.
func (vif *VIF) Dial(remoteEP naming.Endpoint, opts ...stream.VCOpt) (stream.VC, error) {
- vc, err := vif.newVC(vif.allocVCI(), vif.localEP, remoteEP, true)
+ localEP := adjustIPCVersionForOldSecurityModel(vif.localEP, opts)
+ vc, err := vif.newVC(vif.allocVCI(), localEP, remoteEP, true)
if err != nil {
return nil, err
}
@@ -189,7 +201,7 @@
err = vif.sendOnExpressQ(&message.OpenVC{
VCI: vc.VCI(),
DstEndpoint: remoteEP,
- SrcEndpoint: vif.localEP,
+ SrcEndpoint: localEP,
Counters: counters})
if err != nil {
err = fmt.Errorf("vif.sendOnExpressQ(OpenVC) failed: %v", err)
@@ -667,11 +679,10 @@
// ShutdownVCs closes all VCs established to the provided remote endpoint.
// Returns the number of VCs that were closed.
func (vif *VIF) ShutdownVCs(remote naming.Endpoint) int {
- remoteStr := remote.String()
vcs := vif.vcMap.List()
n := 0
for _, vc := range vcs {
- if vc.RemoteAddr().String() == remoteStr {
+ if naming.Compare(vc.RemoteAddr().RoutingID(), remote.RoutingID()) {
vlog.VI(1).Infof("VCI %d on VIF %s being closed because of ShutdownVCs call", vc.VCI(), vif)
vif.closeVCAndSendMsg(vc, "")
n++
diff --git a/runtimes/google/ipc/stream/vif/vif_test.go b/runtimes/google/ipc/stream/vif/vif_test.go
index afddf53..aec55c7 100644
--- a/runtimes/google/ipc/stream/vif/vif_test.go
+++ b/runtimes/google/ipc/stream/vif/vif_test.go
@@ -325,7 +325,7 @@
ep := tc.ep.Endpoint("test", "addr", naming.FixedRoutingID(0x5))
clientVC, _, err := createVC(client, server, ep)
if (err != nil) != tc.expectError {
- t.Errorf("Error mismatch. Wanted error: %v, got %v", tc.expectError, err)
+ t.Errorf("Error mismatch. Wanted error: %v, got %v (client:%v, server:%v ep:%v)", tc.expectError, err, tc.client, tc.server, tc.ep)
}
if err != nil {
diff --git a/runtimes/google/ipc/version/version.go b/runtimes/google/ipc/version/version.go
index ca86911..33d251f 100644
--- a/runtimes/google/ipc/version/version.go
+++ b/runtimes/google/ipc/version/version.go
@@ -14,6 +14,10 @@
Min, Max version.IPCVersion
}
+// TODO(ashankar): Remove when the transition to the new security API is complete.
+func (*Range) IPCClientOpt() {}
+func (*Range) IPCStreamVCOpt() {}
+
var (
// supportedRange represents the range of protocol verions supported by this
// implementation.
@@ -21,7 +25,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.IPCVersion3}
+ supportedRange = &Range{Min: version.IPCVersion2, Max: version.IPCVersion4}
// Export the methods on supportedRange.
Endpoint = supportedRange.Endpoint
diff --git a/runtimes/google/naming/endpoint.go b/runtimes/google/naming/endpoint.go
index a69ffbe..48979b5 100644
--- a/runtimes/google/naming/endpoint.go
+++ b/runtimes/google/naming/endpoint.go
@@ -32,7 +32,7 @@
}
// NewEndpoint creates a new endpoint from a string as per naming.NewEndpoint
-func NewEndpoint(input string) (naming.Endpoint, error) {
+func NewEndpoint(input string) (*Endpoint, error) {
var ep Endpoint
// The prefix and suffix are optional.
diff --git a/runtimes/google/rt/ipc.go b/runtimes/google/rt/ipc.go
index 093ab53..c4cf92f 100644
--- a/runtimes/google/rt/ipc.go
+++ b/runtimes/google/rt/ipc.go
@@ -7,12 +7,14 @@
iipc "veyron.io/veyron/veyron/runtimes/google/ipc"
imanager "veyron.io/veyron/veyron/runtimes/google/ipc/stream/manager"
"veyron.io/veyron/veyron/runtimes/google/ipc/stream/vc"
+ iversion "veyron.io/veyron/veyron/runtimes/google/ipc/version"
ivtrace "veyron.io/veyron/veyron/runtimes/google/vtrace"
"veyron.io/veyron/veyron2"
"veyron.io/veyron/veyron2/context"
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/ipc/stream"
+ "veyron.io/veyron/veyron2/ipc/version"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/vtrace"
@@ -100,8 +102,10 @@
}
}
// Add the option that provides the local identity to the client.
- otherOpts = append(otherOpts, rt.newLocalID(id))
-
+ otherOpts = append(otherOpts, rt.newLocalID(id), vc.LocalPrincipal{rt.principal})
+ if !rt.useNewSecurityModelInIPCClients {
+ otherOpts = append(otherOpts, &iversion.Range{Min: version.IPCVersion2, Max: version.IPCVersion3})
+ }
return iipc.InternalNewClient(sm, ns, otherOpts...)
}
@@ -160,7 +164,7 @@
}
}
// Add the option that provides the local identity to the server.
- otherOpts = append(otherOpts, rt.newLocalID(id))
+ otherOpts = append(otherOpts, rt.newLocalID(id), vc.LocalPrincipal{rt.principal})
ctx := rt.NewContext()
return iipc.InternalNewServer(ctx, sm, ns, otherOpts...)
diff --git a/runtimes/google/rt/ipc_test.go b/runtimes/google/rt/ipc_test.go
index 3f97b45..91492a5 100644
--- a/runtimes/google/rt/ipc_test.go
+++ b/runtimes/google/rt/ipc_test.go
@@ -1,11 +1,8 @@
package rt_test
import (
- "fmt"
"reflect"
- "sort"
"testing"
- "time"
"veyron.io/veyron/veyron2"
"veyron.io/veyron/veyron2/ipc"
@@ -15,182 +12,149 @@
_ "veyron.io/veyron/veyron/lib/testutil"
"veyron.io/veyron/veyron/profiles"
- isecurity "veyron.io/veyron/veyron/runtimes/google/security"
vsecurity "veyron.io/veyron/veyron/security"
)
type testService struct{}
-func (*testService) EchoIDs(call ipc.ServerCall) (server, client []string) {
- return call.LocalID().Names(), call.RemoteID().Names()
+func (testService) EchoBlessings(call ipc.ServerCall) []string {
+ return call.RemoteBlessings().ForContext(call)
}
-type S []string
-
-func newID(name string) security.PrivateID {
- id, err := isecurity.NewPrivateID(name, nil)
+func newRT() veyron2.Runtime {
+ r, err := rt.New(veyron2.ForceNewSecurityModel{})
if err != nil {
panic(err)
}
- return id
+ return r
}
-func bless(blessor security.PrivateID, blessee security.PublicID, name string) security.PublicID {
- blessedID, err := blessor.Bless(blessee, name, 5*time.Minute, nil)
+type rootPrincipal struct {
+ p security.Principal
+ b security.Blessings
+}
+
+func newRootPrincipal(name string) *rootPrincipal {
+ p, err := vsecurity.NewPrincipal()
if err != nil {
panic(err)
}
- return blessedID
-}
-
-func add(store security.PublicIDStore, id security.PublicID, pattern security.BlessingPattern) {
- if err := store.Add(id, pattern); err != nil {
+ b, err := p.BlessSelf(name)
+ if err != nil {
panic(err)
}
+ return &rootPrincipal{p, b}
}
-func call(r veyron2.Runtime, client ipc.Client, name string) (clientNames, serverNames []string, err error) {
- c, err := client.StartCall(r.NewContext(), name, "EchoIDs", nil)
+func (r *rootPrincipal) Bless(p security.Principal, extension string) security.Blessings {
+ b, err := r.p.Bless(p.PublicKey(), r.b, extension, security.UnconstrainedUse())
if err != nil {
- return nil, nil, err
+ panic(err)
}
- if err := c.Finish(&serverNames, &clientNames); err != nil {
- return nil, nil, err
- }
- sort.Strings(clientNames)
- sort.Strings(serverNames)
- return
+ return b
}
-func TestClientServerIDs(t *testing.T) {
- stopServer := func(server ipc.Server) {
- if err := server.Stop(); err != nil {
- t.Fatalf("server.Stop failed: %s", err)
+func union(blessings ...security.Blessings) security.Blessings {
+ var ret security.Blessings
+ var err error
+ for _, b := range blessings {
+ if ret, err = security.UnionOfBlessings(ret, b); err != nil {
+ panic(err)
}
}
+ return ret
+}
+
+func TestClientServerBlessings(t *testing.T) {
var (
- self = newID("self")
- google = newID("google")
- veyron = newID("veyron")
+ rootAlpha, rootBeta, rootUnrecognized = newRootPrincipal("alpha"), newRootPrincipal("beta"), newRootPrincipal("unrecognized")
+ clientRT, serverRT = newRT(), newRT()
+ pclient, pserver = clientRT.Principal(), serverRT.Principal()
- googleGmailService = bless(google, self.PublicID(), "gmail")
- googleYoutubeService = bless(google, self.PublicID(), "youtube")
- veyronService = bless(veyron, self.PublicID(), "service")
- googleGmailClient = bless(google, self.PublicID(), "gmailClient")
- googleYoutubeClient = bless(google, self.PublicID(), "youtubeClient")
- veyronClient = bless(veyron, self.PublicID(), "client")
+ // A bunch of blessings
+ alphaClient = rootAlpha.Bless(pclient, "client")
+ betaClient = rootBeta.Bless(pclient, "client")
+ unrecognizedClient = rootUnrecognized.Bless(pclient, "client")
+
+ alphaServer = rootAlpha.Bless(pserver, "server")
+ betaServer = rootBeta.Bless(pserver, "server")
+ unrecognizedServer = rootUnrecognized.Bless(pserver, "server")
)
- isecurity.TrustIdentityProviders(google)
- isecurity.TrustIdentityProviders(veyron)
+ // Setup the client's blessing store
+ pclient.BlessingStore().Set(alphaClient, "alpha/server")
+ pclient.BlessingStore().Set(betaClient, "beta/...")
+ pclient.BlessingStore().Set(unrecognizedClient, security.AllPrincipals)
- serverR, err := rt.New(veyron2.RuntimeID(self))
+ tests := []struct {
+ server security.Blessings // Blessings presented by the server.
+
+ // Expected output
+ wantServer []string // Client's view of the server's blessings
+ wantClient []string // Server's view fo the client's blessings
+ }{
+ {
+ server: unrecognizedServer,
+ wantServer: nil,
+ wantClient: nil,
+ },
+ {
+ server: alphaServer,
+ wantServer: []string{"alpha/server"},
+ wantClient: []string{"alpha/client"},
+ },
+ {
+ server: union(alphaServer, betaServer),
+ wantServer: []string{"alpha/server", "beta/server"},
+ wantClient: []string{"alpha/client", "beta/client"},
+ },
+ }
+
+ // Have the client and server both trust both the root principals.
+ for _, rt := range []veyron2.Runtime{clientRT, serverRT} {
+ for _, root := range []*rootPrincipal{rootAlpha, rootBeta} {
+ if err := rt.Principal().AddToRoots(root.b); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+ // Start the server process.
+ server, err := serverRT.NewServer()
if err != nil {
- t.Fatalf("rt.New() failed: %s", err)
+ t.Fatal(err)
}
- clientR, err := rt.New(veyron2.RuntimeID(self))
- if err != nil {
- t.Fatalf("rt.New() failed: %s", err)
+ defer server.Stop()
+ var serverObjectName string
+ if endpoint, err := server.ListenX(profiles.LocalListenSpec); err != nil {
+ t.Fatal(err)
+ } else {
+ serverObjectName = naming.JoinAddressName(endpoint.String(), "")
}
-
- // Add PublicIDs for running "google/gmail" and "google/youtube" services to
- // serverR's PublicIDStore. Since these PublicIDs are meant to be by
- // servers only they are tagged with "".
- add(serverR.PublicIDStore(), googleGmailService, "")
- add(serverR.PublicIDStore(), googleYoutubeService, "")
- // Add PublicIDs for communicating the "google/gmail" and "google/youtube" services
- // to the clientR's PublicIDStore.
- add(clientR.PublicIDStore(), googleGmailClient, "google/...")
- add(clientR.PublicIDStore(), googleYoutubeClient, "google/youtube")
-
- type testcase struct {
- server, client security.PublicID
- defaultPattern security.BlessingPattern
- wantServerNames, wantClientNames []string
+ if err := server.Serve("", ipc.LeafDispatcher(testService{}, vsecurity.NewACLAuthorizer(vsecurity.OpenACL()))); err != nil {
+ t.Fatal(err)
}
- tests := []testcase{
- {
- defaultPattern: security.AllPrincipals,
- wantServerNames: S{"self", "google/gmail", "google/youtube"},
- wantClientNames: S{"self", "google/gmailClient", "google/youtubeClient"},
- },
- {
- defaultPattern: "google/gmail",
- wantServerNames: S{"google/gmail"},
- wantClientNames: S{"self", "google/gmailClient"},
- },
- {
- defaultPattern: "google/youtube",
- wantServerNames: S{"google/youtube"},
- wantClientNames: S{"self", "google/gmailClient", "google/youtubeClient"},
- },
- {
- server: veyronService,
- defaultPattern: security.AllPrincipals,
- wantServerNames: S{"veyron/service"},
- wantClientNames: S{"self"},
- },
- {
- client: veyronClient,
- defaultPattern: security.AllPrincipals,
- wantServerNames: S{"self", "google/gmail", "google/youtube"},
- wantClientNames: S{"veyron/client"},
- },
- {
- server: veyronService,
- client: veyronClient,
- defaultPattern: security.AllPrincipals,
- wantServerNames: S{"veyron/service"},
- wantClientNames: S{"veyron/client"},
- },
- }
- name := func(t testcase) string {
- return fmt.Sprintf("TestCase{clientPublicIDStore: %v, serverPublicIDStore: %v, client option: %v, server option: %v}", clientR.PublicIDStore(), serverR.PublicIDStore(), t.client, t.server)
- }
+ // Let it rip!
for _, test := range tests {
- if err := serverR.PublicIDStore().SetDefaultBlessingPattern(test.defaultPattern); err != nil {
- t.Errorf("serverR.PublicIDStore.SetDefaultBlessingPattern failed: %s", err)
- continue
- }
- server, err := serverR.NewServer(veyron2.LocalID(test.server))
+ // Create a new client per test so as to not re-use established authenticated VCs.
+ // TODO(ashankar,suharshs): Once blessings are exchanged "per-RPC", one client for all cases will suffice.
+ client, err := clientRT.NewClient()
if err != nil {
- t.Errorf("serverR.NewServer(...) failed: %s", err)
+ t.Errorf("clientRT.NewClient failed: %v", err)
continue
}
- endpoint, err := server.ListenX(profiles.LocalListenSpec)
- if err != nil {
- t.Errorf("error listening to service: ", err)
+ if err := pserver.BlessingStore().SetDefault(test.server); err != nil {
+ t.Errorf("pserver.SetDefault(%v) failed: %v", test.server, err)
continue
}
- defer stopServer(server)
- if err := server.Serve("", ipc.LeafDispatcher(&testService{},
- vsecurity.NewACLAuthorizer(security.ACL{In: map[security.BlessingPattern]security.LabelSet{
- security.AllPrincipals: security.AllLabels,
- }}))); err != nil {
- t.Errorf("error serving service: ", err)
- continue
+ var gotClient []string
+ if call, err := client.StartCall(clientRT.NewContext(), serverObjectName, "EchoBlessings", nil); err != nil {
+ t.Errorf("client.StartCall failed: %v", err)
+ } else if err = call.Finish(&gotClient); err != nil {
+ t.Errorf("call.Finish failed: %v", err)
+ } else if !reflect.DeepEqual(gotClient, test.wantClient) {
+ t.Errorf("%v: Got %v, want %v for client blessings", test.server, gotClient, test.wantServer)
+ } else if gotServer, _ := call.RemoteBlessings(); !reflect.DeepEqual(gotServer, test.wantServer) {
+ t.Errorf("%v: Got %v, want %v for server blessings", test.server, gotServer, test.wantClient)
}
-
- client, err := clientR.NewClient(veyron2.LocalID(test.client))
- if err != nil {
- t.Errorf("clientR.NewClient(...) failed: %s", err)
- continue
- }
- defer client.Close()
-
- clientNames, serverNames, err := call(clientR, client, naming.JoinAddressName(fmt.Sprintf("%v", endpoint), ""))
- if err != nil {
- t.Errorf("IPC failed: %s", err)
- continue
- }
- sort.Strings(test.wantClientNames)
- sort.Strings(test.wantServerNames)
- if !reflect.DeepEqual(clientNames, test.wantClientNames) {
- t.Errorf("TestCase: %s, Got clientNames: %v, want: %v", name(test), clientNames, test.wantClientNames)
- continue
- }
- if !reflect.DeepEqual(serverNames, test.wantServerNames) {
- t.Errorf("TestCase: %s, Got serverNames: %v, want: %v", name(test), serverNames, test.wantServerNames)
- continue
- }
+ client.Close()
}
}
diff --git a/runtimes/google/rt/rt.go b/runtimes/google/rt/rt.go
index fa8ab10..4cd8779 100644
--- a/runtimes/google/rt/rt.go
+++ b/runtimes/google/rt/rt.go
@@ -39,6 +39,10 @@
debug debugServer
nServers int // GUARDED_BY(mu)
cleaningUp bool // GUARDED_BY(mu)
+
+ // TODO(ashankar,ataly): Variables to help with the transition between the
+ // old and new security model. Will be removed once the transition is complete.
+ useNewSecurityModelInIPCClients bool
}
var _ veyron2.Runtime = (*vrt)(nil)
@@ -65,6 +69,8 @@
if v.Name != "google" && v.Name != "" {
return nil, fmt.Errorf("%q is the wrong name for this runtime", v.Name)
}
+ case veyron2.ForceNewSecurityModel:
+ rt.useNewSecurityModelInIPCClients = true
default:
return nil, fmt.Errorf("option has wrong type %T", o)
}
diff --git a/runtimes/google/rt/sectransition/sectransition.go b/runtimes/google/rt/sectransition/sectransition.go
new file mode 100644
index 0000000..1ac2734
--- /dev/null
+++ b/runtimes/google/rt/sectransition/sectransition.go
@@ -0,0 +1,72 @@
+// This package provides a shell test during the security model transition.
+package main
+
+import (
+ "flag"
+ "fmt"
+ "time"
+
+ "veyron.io/veyron/veyron/lib/signals"
+
+ "veyron.io/veyron/veyron2/ipc"
+ "veyron.io/veyron/veyron2/naming"
+ "veyron.io/veyron/veyron2/rt"
+ "veyron.io/veyron/veyron2/security"
+ "veyron.io/veyron/veyron2/vlog"
+)
+
+var runServer = flag.Bool("server", false, "If true, start a server. If false, start a client")
+
+type service struct{}
+
+func (service) Ping(call ipc.ServerCall) (string, error) {
+ return fmt.Sprintf("ClientBlessings: %v\nClientPublicID: %v", call.RemoteBlessings(), call.RemoteID()), nil
+}
+
+type authorizer struct{}
+
+func (authorizer) Authorize(security.Context) error { return nil }
+
+func main() {
+ r := rt.Init()
+ defer r.Cleanup()
+
+ if *runServer {
+ startServer(r.NewServer())
+ } else if len(flag.Args()) != 1 {
+ vlog.Fatalf("Expected exactly 1 argument, got %d (%v)", len(flag.Args()), flag.Args())
+ } else {
+ ctx, _ := r.NewContext().WithDeadline(time.Now().Add(10 * time.Second))
+ startClient(r.Client().StartCall(ctx, flag.Arg(0), "Ping", nil))
+ }
+}
+
+func startServer(server ipc.Server, err error) {
+ if err != nil {
+ vlog.Fatal(err)
+ }
+ defer server.Stop()
+
+ ep, err := server.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ vlog.Fatal(err)
+ }
+ fmt.Println("SERVER:", naming.JoinAddressName(ep.String(), ""))
+ server.Serve("", ipc.LeafDispatcher(service{}, authorizer{}))
+ <-signals.ShutdownOnSignals()
+}
+
+func startClient(call ipc.Call, err error) {
+ if err != nil {
+ vlog.Fatal(err)
+ }
+ var result string
+ var apperr error
+ if err = call.Finish(&result, &apperr); err != nil {
+ vlog.Fatalf("ipc.Call.Finish error: %v", err)
+ }
+ if apperr != nil {
+ vlog.Fatalf("Application error: %v", apperr)
+ }
+ fmt.Println(result)
+}
diff --git a/runtimes/google/rt/sectransition/test.sh b/runtimes/google/rt/sectransition/test.sh
new file mode 100755
index 0000000..d142e93
--- /dev/null
+++ b/runtimes/google/rt/sectransition/test.sh
@@ -0,0 +1,103 @@
+#!/bin/bash
+
+# Test compatibility of clients and servers using a combination of the old
+# and new security models (triggered by environment variables).
+
+. "${VEYRON_ROOT}/scripts/lib/shell_test.sh"
+
+readonly WORKDIR=$(shell::tmp_dir)
+set +e
+
+build() {
+ veyron go build veyron.io/veyron/veyron/runtimes/google/rt/sectransition || shell_test::fail "line ${LINENO}: failed to build sectransition binary"
+ veyron go build veyron.io/veyron/veyron/tools/identity || shell_test::fail "line ${LINENO}: failed to build identity"
+}
+
+
+startserver() {
+ # The server has access to both the old and new security model.
+ export VEYRON_IDENTITY="${WORKDIR}/old"
+ export VEYRON_CREDENTIALS="${WORKDIR}/new"
+ ./sectransition --server --logtostderr >"${SERVERLOG}" 2>&1 &
+ shell::wait_for "${SERVERLOG}" "SERVER"
+ local EP=$(grep "SERVER: " "${SERVERLOG}" | sed -e 's/SERVER: //')
+ echo "${EP}"
+}
+
+runclient() {
+ ./sectransition "${EP}" >"${CLIENTLOG}" 2>&1
+}
+
+oldmodel() {
+ awk '/ClientPublicID:/ {print $2}' "${CLIENTLOG}"
+}
+
+newmodel() {
+ awk '/ClientBlessings:/ {print $2}' "${CLIENTLOG}"
+}
+
+main() {
+ cd "${WORKDIR}"
+ build
+
+ # Generate an identity (old security model) that may be used by the client.
+ local -r OLD="${WORKDIR}/old"
+ ./identity generate "old" > "${OLD}"
+
+ local -r SERVERLOG="${WORKDIR}/server.log"
+ local -r CLIENTLOG="${WORKDIR}/client.log"
+ local -r EP=$(startserver)
+
+ # No environment variables set: PublicIDs from the old model should be exchanged.
+ unset VEYRON_IDENTITY
+ unset VEYRON_CREDENTIALS
+ runclient
+ echo " No environment variables: PublicID:$(oldmodel), Blessings:$(newmodel)"
+ if [[ $(oldmodel) == "<nil>" ]]; then
+ shell_test::fail "line ${LINENO}: PublicID not set when neither environment variable is set"
+ fi
+ if [[ $(newmodel) != "<nil>" ]]; then
+ shell_test::fail "line ${LINENO}: Blessings should not be set when neither environment variable is set (was $(newmodel))"
+ fi
+
+
+ # Old model envvar is set: not the new one: PublicIDs from the old model should be exchanged.
+ export VEYRON_IDENTITY="${WORKDIR}/old"
+ unset VEYRON_CREDENTIALS
+ runclient
+ echo " VEYRON_IDENTITY: PublicID:$(oldmodel), Blessings:$(newmodel)"
+ if [[ $(oldmodel) == "<nil>" ]]; then
+ shell_test::fail "line ${LINENO}: PublicID not set when only VEYRON_IDENTITY is set"
+ fi
+ if [[ $(newmodel) != "<nil>" ]]; then
+ shell_test::fail "line ${LINENO}: Blessings should not be set when only VEYRON_IDENTITY is set (was $(newmodel))"
+ fi
+
+ # New model envvar is set: Blessings should be exchanged.
+ unset VEYRON_IDENTITY
+ export VEYRON_CREDENTIALS="${WORKDIR}/new"
+ runclient
+ echo " VEYRON_CREDENTIALS: PublicID:$(oldmodel), Blessings:$(newmodel)"
+ if [[ $(oldmodel) != "<nil>" ]]; then
+ shell_test::fail "line ${LINENO}: PublicID should not be exchanged when VEYRON_CREDENTIALS is set (was $(oldmodel))"
+ fi
+ if [[ $(newmodel) == "<nil>" ]]; then
+ shell_test::fail "line ${LINENO}: Blessings should be exchanged when VEYRON_CREDENTIALS is set (was $(newmodel))"
+ fi
+
+ # Both environment variables are set: Blessings should be exchanged.
+ export VEYRON_IDENTITY="${WORKDIR}/old"
+ export VEYRON_CREDENTIALS="${WORKDIR}/new"
+ runclient
+ echo "VEYRON_IDENTITY & VEYRON_CREDENTIALS: PublicID:$(oldmodel), Blessings:$(newmodel)"
+ if [[ $(oldmodel) != "<nil>" ]]; then
+ shell_test::fail "line ${LINENO}: PublicID should not be exchanged when VEYRON_CREDENTIALS is set (was $(oldmodel))"
+ fi
+ if [[ $(newmodel) == "<nil>" ]]; then
+ shell_test::fail "line ${LINENO}: Blessings should be exchanged when VEYRON_CREDENTIALS is set (was $(newmodel))"
+ fi
+
+ shell_test::pass
+}
+
+main "$@"
diff --git a/runtimes/google/rt/security.go b/runtimes/google/rt/security.go
index 0370941..f034ce7 100644
--- a/runtimes/google/rt/security.go
+++ b/runtimes/google/rt/security.go
@@ -36,6 +36,9 @@
}
func (rt *vrt) initSecurity() error {
+ // Use the new security model in ipc.Client only if it was expicitly specified.
+ // At a later date, we will switch to using the new model always.
+ rt.useNewSecurityModelInIPCClients = rt.useNewSecurityModelInIPCClients || len(os.Getenv(VeyronCredentialsEnvVar)) > 0
if err := rt.initOldSecurity(); err != nil {
return err
}
diff --git a/security/acl_authorizer.go b/security/acl_authorizer.go
index 7a305ab..4ab195c 100644
--- a/security/acl_authorizer.go
+++ b/security/acl_authorizer.go
@@ -29,10 +29,8 @@
if ctx.LocalBlessings() != nil && ctx.RemoteBlessings() != nil && reflect.DeepEqual(ctx.LocalBlessings().PublicKey(), ctx.RemoteBlessings().PublicKey()) {
return nil
}
- if newAPI := (ctx.LocalBlessings() != nil && ctx.RemoteBlessings() != nil); !newAPI {
- if ctx.LocalID() != nil && ctx.RemoteID() != nil && reflect.DeepEqual(ctx.LocalID(), ctx.RemoteID()) {
- return nil
- }
+ if ctx.LocalID() != nil && ctx.RemoteID() != nil && reflect.DeepEqual(ctx.LocalID(), ctx.RemoteID()) {
+ return nil
}
var blessings []string
if ctx.RemoteBlessings() != nil {