ref: BlessingsForPeer -> PeerAuthorizer.
Client now authorizes server during conn establishment.
MultiPart: 2/2
Change-Id: Ie80b83b36e7ec467c46d8b5414ec089abe0622c7
diff --git a/runtime/internal/flow/conn/auth.go b/runtime/internal/flow/conn/auth.go
index 40337ec..c057c2a 100644
--- a/runtime/internal/flow/conn/auth.go
+++ b/runtime/internal/flow/conn/auth.go
@@ -14,6 +14,7 @@
"golang.org/x/crypto/nacl/box"
"v.io/v23"
"v.io/v23/context"
+ "v.io/v23/flow"
"v.io/v23/flow/message"
"v.io/v23/rpc/version"
"v.io/v23/security"
@@ -27,7 +28,7 @@
authAcceptorTag = []byte("AuthAcpt\x00")
)
-func (c *Conn) dialHandshake(ctx *context.T, versions version.RPCVersionRange) error {
+func (c *Conn) dialHandshake(ctx *context.T, versions version.RPCVersionRange, auth flow.PeerAuthorizer) error {
binding, err := c.setup(ctx, versions)
if err != nil {
return err
@@ -37,12 +38,16 @@
bflow.worker.Release(ctx, DefaultBytesBufferedPerFlow)
c.blessingsFlow = newBlessingsFlow(ctx, &c.loopWG, bflow, true)
- if err = c.readRemoteAuth(ctx, authAcceptorTag, binding); err != nil {
+ rDischarges, err := c.readRemoteAuth(ctx, authAcceptorTag, binding)
+ if err != nil {
return err
}
if c.rBlessings.IsZero() {
return NewErrAcceptorBlessingsMissing(ctx)
}
+ if _, _, err := auth.AuthorizePeer(ctx, c.local, c.remote, c.rBlessings, rDischarges); err != nil {
+ return err
+ }
signedBinding, err := v23.GetPrincipal(ctx).Sign(append(authDialerTag, binding...))
if err != nil {
return err
@@ -82,7 +87,8 @@
if err = c.mp.writeMsg(ctx, lAuth); err != nil {
return err
}
- return c.readRemoteAuth(ctx, authDialerTag, binding)
+ _, err = c.readRemoteAuth(ctx, authDialerTag, binding)
+ return err
}
func (c *Conn) setup(ctx *context.T, versions version.RPCVersionRange) ([]byte, error) {
@@ -141,38 +147,39 @@
return binding, nil
}
-func (c *Conn) readRemoteAuth(ctx *context.T, tag []byte, binding []byte) error {
+func (c *Conn) readRemoteAuth(ctx *context.T, tag, binding []byte) (map[string]security.Discharge, error) {
var rauth *message.Auth
for {
msg, err := c.mp.readMsg(ctx)
if err != nil {
- return NewErrRecv(ctx, c.remote.String(), err)
+ return nil, NewErrRecv(ctx, c.remote.String(), err)
}
if rauth, _ = msg.(*message.Auth); rauth != nil {
break
}
if err = c.handleMessage(ctx, msg); err != nil {
- return err
+ return nil, err
}
}
+ var rDischarges map[string]security.Discharge
if rauth.BlessingsKey != 0 {
var err error
// TODO(mattr): Make sure we cancel out of this at some point.
- c.rBlessings, _, err = c.blessingsFlow.get(ctx, rauth.BlessingsKey, rauth.DischargeKey)
+ c.rBlessings, rDischarges, err = c.blessingsFlow.get(ctx, rauth.BlessingsKey, rauth.DischargeKey)
if err != nil {
- return err
+ return nil, err
}
c.rPublicKey = c.rBlessings.PublicKey()
} else {
c.rPublicKey = rauth.PublicKey
}
if c.rPublicKey == nil {
- return NewErrNoPublicKey(ctx)
+ return nil, NewErrNoPublicKey(ctx)
}
if !rauth.ChannelBinding.Verify(c.rPublicKey, append(tag, binding...)) {
- return NewErrInvalidChannelBinding(ctx)
+ return nil, NewErrInvalidChannelBinding(ctx)
}
- return nil
+ return rDischarges, nil
}
func (c *Conn) refreshDischarges(ctx *context.T) (bkey, dkey uint64, err error) {
diff --git a/runtime/internal/flow/conn/auth_test.go b/runtime/internal/flow/conn/auth_test.go
index c64bc5b..62eb294 100644
--- a/runtime/internal/flow/conn/auth_test.go
+++ b/runtime/internal/flow/conn/auth_test.go
@@ -16,6 +16,7 @@
"v.io/v23/verror"
vsecurity "v.io/x/ref/lib/security"
"v.io/x/ref/runtime/factories/fake"
+ "v.io/x/ref/runtime/internal/flow/flowtest"
"v.io/x/ref/test/goroutines"
"v.io/x/ref/test/testutil"
)
@@ -41,7 +42,7 @@
}
func dialFlow(t *testing.T, ctx *context.T, dc *Conn, b security.Blessings) flow.Flow {
- df, err := dc.Dial(ctx, makeBFP(b))
+ df, err := dc.Dial(ctx, peerAuthorizer{b})
if err != nil {
t.Fatal(err)
}
@@ -129,7 +130,7 @@
// We should not be able to dial in the other direction, because that flow
// manager is not willing to accept flows.
- _, err := ac.Dial(actx, testBFP)
+ _, err := ac.Dial(actx, flowtest.AllowAllPeersAuthorizer{})
if verror.ErrorID(err) != ErrDialingNonServer.ID {
t.Errorf("got %v, wanted ErrDialingNonServer", err)
}
diff --git a/runtime/internal/flow/conn/close_test.go b/runtime/internal/flow/conn/close_test.go
index 7ba0062..74a6c49 100644
--- a/runtime/internal/flow/conn/close_test.go
+++ b/runtime/internal/flow/conn/close_test.go
@@ -12,6 +12,7 @@
"v.io/v23"
"v.io/v23/context"
_ "v.io/x/ref/runtime/factories/fake"
+ "v.io/x/ref/runtime/internal/flow/flowtest"
"v.io/x/ref/test/goroutines"
)
@@ -64,10 +65,10 @@
d.Close(ctx, fmt.Errorf("Closing randomly."))
<-d.Closed()
<-a.Closed()
- if _, err := d.Dial(ctx, testBFP); err == nil {
+ if _, err := d.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err == nil {
t.Errorf("Nil error dialing on dialer")
}
- if _, err := a.Dial(ctx, testBFP); err == nil {
+ if _, err := a.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err == nil {
t.Errorf("Nil error dialing on acceptor")
}
}
diff --git a/runtime/internal/flow/conn/conn.go b/runtime/internal/flow/conn/conn.go
index 846fce3..8baf303 100644
--- a/runtime/internal/flow/conn/conn.go
+++ b/runtime/internal/flow/conn/conn.go
@@ -95,6 +95,7 @@
conn flow.MsgReadWriteCloser,
local, remote naming.Endpoint,
versions version.RPCVersionRange,
+ auth flow.PeerAuthorizer,
handshakeTimeout time.Duration,
handler FlowHandler,
events chan<- StatusUpdate) (*Conn, error) {
@@ -116,7 +117,7 @@
// TODO(mattr): This scheme for deadlines is nice, but it doesn't
// provide for cancellation when ctx is canceled.
t := time.AfterFunc(handshakeTimeout, func() { conn.Close() })
- err := c.dialHandshake(ctx, versions)
+ err := c.dialHandshake(ctx, versions, auth)
if stopped := t.Stop(); !stopped {
err = verror.NewErrTimeout(ctx)
}
@@ -179,7 +180,7 @@
}
// Dial dials a new flow on the Conn.
-func (c *Conn) Dial(ctx *context.T, fn flow.BlessingsForPeer) (flow.Flow, error) {
+func (c *Conn) Dial(ctx *context.T, auth flow.PeerAuthorizer) (flow.Flow, error) {
if c.rBlessings.IsZero() {
return nil, NewErrDialingNonServer(ctx)
}
@@ -187,10 +188,15 @@
if err != nil {
return nil, err
}
- blessings, discharges, err := fn(ctx, c.local, c.remote, c.rBlessings, rDischarges)
+ // TODO(suharshs): On the first flow dial, find a way to not call this twice.
+ rbnames, rejected, err := auth.AuthorizePeer(ctx, c.local, c.remote, c.rBlessings, rDischarges)
if err != nil {
return nil, err
}
+ blessings, discharges, err := auth.BlessingsForPeer(ctx, rbnames)
+ if err != nil {
+ return nil, NewErrNoBlessingsForPeer(ctx, rbnames, rejected, err)
+ }
bkey, dkey, err := c.blessingsFlow.put(ctx, blessings, discharges)
if err != nil {
return nil, err
diff --git a/runtime/internal/flow/conn/conn_test.go b/runtime/internal/flow/conn/conn_test.go
index ce1961b..cc18f1c 100644
--- a/runtime/internal/flow/conn/conn_test.go
+++ b/runtime/internal/flow/conn/conn_test.go
@@ -100,7 +100,7 @@
q1, q2 := make(chan flow.Flow, 1), make(chan flow.Flow, 1)
fh1, fh2 := fh(q1), fh(q2)
go func() {
- d, err := NewDialed(ctx, dmrw, ep, ep, versions, time.Minute, nil, nil)
+ d, err := NewDialed(ctx, dmrw, ep, ep, versions, flowtest.AllowAllPeersAuthorizer{}, time.Minute, nil, nil)
if err != nil {
panic(err)
}
@@ -115,7 +115,7 @@
}()
d, a := <-dch, <-ach
var f flow.Flow
- if f, err = d.Dial(ctx, flowtest.BlessingsForPeer); err != nil {
+ if f, err = d.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err != nil {
t.Fatal(err)
}
// Write a byte to send the openFlow message.
@@ -126,7 +126,7 @@
<-q1
// After updating to fh2 the flow should be accepted in fh2.
a.UpdateFlowHandler(ctx, fh2)
- if f, err = d.Dial(ctx, flowtest.BlessingsForPeer); err != nil {
+ if f, err = d.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err != nil {
t.Fatal(err)
}
// Write a byte to send the openFlow message.
diff --git a/runtime/internal/flow/conn/errors.vdl b/runtime/internal/flow/conn/errors.vdl
index 42b56bf..dcd8c02 100644
--- a/runtime/internal/flow/conn/errors.vdl
+++ b/runtime/internal/flow/conn/errors.vdl
@@ -4,6 +4,8 @@
package conn
+import "v.io/v23/security"
+
// These messages are constructed so as to avoid embedding a component/method name
// and are thus more suitable for inclusion in other verrors.
// This practice of omitting {1}{2} should be used throughout the flow implementations
@@ -26,4 +28,5 @@
AcceptorBlessingsMissing() {"en": "The acceptor did not send blessings."}
UpdatingNilFlowHandler() {"en": "nil flowHandler cannot be updated to non-nil value."}
BlessingsNotBound() {"en": "blessings not bound to connection remote public key"}
+ NoBlessingsForPeer(peerNames []string, rejected []security.RejectedBlessing, err error) {"en": "no blessings tagged for peer {peerNames}, rejected:{rejected}{:err}"}
)
diff --git a/runtime/internal/flow/conn/errors.vdl.go b/runtime/internal/flow/conn/errors.vdl.go
index 506f283..f4d3110 100644
--- a/runtime/internal/flow/conn/errors.vdl.go
+++ b/runtime/internal/flow/conn/errors.vdl.go
@@ -12,6 +12,9 @@
"v.io/v23/context"
"v.io/v23/i18n"
"v.io/v23/verror"
+
+ // VDL user imports
+ "v.io/v23/security"
)
var (
@@ -30,6 +33,7 @@
ErrAcceptorBlessingsMissing = verror.Register("v.io/x/ref/runtime/internal/flow/conn.AcceptorBlessingsMissing", verror.NoRetry, "{1:}{2:} The acceptor did not send blessings.")
ErrUpdatingNilFlowHandler = verror.Register("v.io/x/ref/runtime/internal/flow/conn.UpdatingNilFlowHandler", verror.NoRetry, "{1:}{2:} nil flowHandler cannot be updated to non-nil value.")
ErrBlessingsNotBound = verror.Register("v.io/x/ref/runtime/internal/flow/conn.BlessingsNotBound", verror.NoRetry, "{1:}{2:} blessings not bound to connection remote public key")
+ ErrNoBlessingsForPeer = verror.Register("v.io/x/ref/runtime/internal/flow/conn.NoBlessingsForPeer", verror.NoRetry, "{1:}{2:} no blessings tagged for peer {3}, rejected:{4}{:5}")
)
func init() {
@@ -48,6 +52,7 @@
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrAcceptorBlessingsMissing.ID), "{1:}{2:} The acceptor did not send blessings.")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrUpdatingNilFlowHandler.ID), "{1:}{2:} nil flowHandler cannot be updated to non-nil value.")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrBlessingsNotBound.ID), "{1:}{2:} blessings not bound to connection remote public key")
+ i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrNoBlessingsForPeer.ID), "{1:}{2:} no blessings tagged for peer {3}, rejected:{4}{:5}")
}
// NewErrMissingSetupOption returns an error with the ErrMissingSetupOption ID.
@@ -124,3 +129,8 @@
func NewErrBlessingsNotBound(ctx *context.T) error {
return verror.New(ErrBlessingsNotBound, ctx)
}
+
+// NewErrNoBlessingsForPeer returns an error with the ErrNoBlessingsForPeer ID.
+func NewErrNoBlessingsForPeer(ctx *context.T, peerNames []string, rejected []security.RejectedBlessing, err error) error {
+ return verror.New(ErrNoBlessingsForPeer, ctx, peerNames, rejected, err)
+}
diff --git a/runtime/internal/flow/conn/lameduck_test.go b/runtime/internal/flow/conn/lameduck_test.go
index b2f1def..67f0be8 100644
--- a/runtime/internal/flow/conn/lameduck_test.go
+++ b/runtime/internal/flow/conn/lameduck_test.go
@@ -12,6 +12,7 @@
"v.io/v23"
"v.io/v23/flow"
+ "v.io/x/ref/runtime/internal/flow/flowtest"
"v.io/x/ref/test/goroutines"
)
@@ -41,7 +42,7 @@
}()
// Dial a flow and write it (which causes it to open).
- f1, err := dc.Dial(ctx, testBFP)
+ f1, err := dc.Dial(ctx, flowtest.AllowAllPeersAuthorizer{})
if err != nil {
t.Fatal(err)
}
@@ -49,11 +50,11 @@
t.Fatal(err)
}
// Dial more flows, but don't write to them yet.
- f2, err := dc.Dial(ctx, testBFP)
+ f2, err := dc.Dial(ctx, flowtest.AllowAllPeersAuthorizer{})
if err != nil {
t.Fatal(err)
}
- f3, err := dc.Dial(ctx, testBFP)
+ f3, err := dc.Dial(ctx, flowtest.AllowAllPeersAuthorizer{})
if err != nil {
t.Fatal(err)
}
@@ -65,7 +66,7 @@
}
// Now we shouldn't be able to dial from dc because it's in lame duck mode.
- if _, err := dc.Dial(ctx, testBFP); err == nil {
+ if _, err := dc.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err == nil {
t.Fatalf("expected an error, got nil")
}
diff --git a/runtime/internal/flow/conn/util_test.go b/runtime/internal/flow/conn/util_test.go
index eeb7207..1454c60 100644
--- a/runtime/internal/flow/conn/util_test.go
+++ b/runtime/internal/flow/conn/util_test.go
@@ -51,7 +51,7 @@
if dflows != nil {
handler = fh(dflows)
}
- d, err := NewDialed(dctx, dmrw, ep, ep, versions, time.Minute, handler, events)
+ d, err := NewDialed(dctx, dmrw, ep, ep, versions, flowtest.AllowAllPeersAuthorizer{}, time.Minute, handler, events)
if err != nil {
panic(err)
}
@@ -79,31 +79,28 @@
dctx, actx = actx, dctx
aflows, dflows = dflows, aflows
}
- df, err := d.Dial(dctx, testBFP)
+ df, err := d.Dial(dctx, flowtest.AllowAllPeersAuthorizer{})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
return df, aflows, func() { d.Close(dctx, nil); a.Close(actx, nil) }
}
-func testBFP(
+type peerAuthorizer struct {
+ blessings security.Blessings
+}
+
+func (peerAuthorizer) AuthorizePeer(
ctx *context.T,
localEndpoint, remoteEndpoint naming.Endpoint,
remoteBlessings security.Blessings,
remoteDischarges map[string]security.Discharge,
-) (security.Blessings, map[string]security.Discharge, error) {
- return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
+) ([]string, []security.RejectedBlessing, error) {
+ return nil, nil, nil
}
-func makeBFP(in security.Blessings) flow.BlessingsForPeer {
- return func(
- ctx *context.T,
- localEndpoint, remoteEndpoint naming.Endpoint,
- remoteBlessings security.Blessings,
- remoteDischarges map[string]security.Discharge,
- ) (security.Blessings, map[string]security.Discharge, error) {
- dis := securitylib.PrepareDischarges(
- ctx, in, security.DischargeImpetus{}, time.Minute)
- return in, dis, nil
- }
+func (a peerAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+ security.Blessings, map[string]security.Discharge, error) {
+ dis := securitylib.PrepareDischarges(ctx, a.blessings, security.DischargeImpetus{}, time.Minute)
+ return a.blessings, dis, nil
}
diff --git a/runtime/internal/flow/flowtest/flowtest.go b/runtime/internal/flow/flowtest/flowtest.go
index b9a9907..d330015 100644
--- a/runtime/internal/flow/flowtest/flowtest.go
+++ b/runtime/internal/flow/flowtest/flowtest.go
@@ -98,11 +98,18 @@
return nil
}
-func BlessingsForPeer(
+type AllowAllPeersAuthorizer struct{}
+
+func (AllowAllPeersAuthorizer) AuthorizePeer(
ctx *context.T,
localEndpoint, remoteEndpoint naming.Endpoint,
remoteBlessings security.Blessings,
remoteDischarges map[string]security.Discharge,
-) (security.Blessings, map[string]security.Discharge, error) {
+) ([]string, []security.RejectedBlessing, error) {
+ return nil, nil, nil
+}
+
+func (AllowAllPeersAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+ security.Blessings, map[string]security.Discharge, error) {
return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
}
diff --git a/runtime/internal/flow/manager/conncache_test.go b/runtime/internal/flow/manager/conncache_test.go
index 4dcc990..f277b84 100644
--- a/runtime/internal/flow/manager/conncache_test.go
+++ b/runtime/internal/flow/manager/conncache_test.go
@@ -296,7 +296,7 @@
ach := make(chan *connpackage.Conn)
go func() {
d, err := connpackage.NewDialed(ctx, dmrw, ep, ep,
- version.RPCVersionRange{Min: 1, Max: 5}, time.Minute, nil, nil)
+ version.RPCVersionRange{Min: 1, Max: 5}, flowtest.AllowAllPeersAuthorizer{}, time.Minute, nil, nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
@@ -313,7 +313,7 @@
}()
conn := <-dch
<-ach
- f, err := conn.Dial(ctx, flowtest.BlessingsForPeer)
+ f, err := conn.Dial(ctx, flowtest.AllowAllPeersAuthorizer{})
if err != nil {
t.Fatal(err)
}
diff --git a/runtime/internal/flow/manager/manager.go b/runtime/internal/flow/manager/manager.go
index 044ae8a..185ff12 100644
--- a/runtime/internal/flow/manager/manager.go
+++ b/runtime/internal/flow/manager/manager.go
@@ -190,7 +190,7 @@
return
default:
}
- f, c, err := m.internalDial(ctx, ep, proxyBlessingsForPeer{}.run)
+ f, c, err := m.internalDial(ctx, ep, proxyAuthorizer{})
if err != nil {
ctx.Error(err)
continue
@@ -239,11 +239,20 @@
return res.Endpoints, nil
}
-type proxyBlessingsForPeer struct{}
-
// TODO(suharshs): Figure out what blessings to present here. And present discharges.
-func (proxyBlessingsForPeer) run(ctx *context.T, lep, rep naming.Endpoint, rb security.Blessings,
- rd map[string]security.Discharge) (security.Blessings, map[string]security.Discharge, error) {
+type proxyAuthorizer struct{}
+
+func (proxyAuthorizer) AuthorizePeer(
+ ctx *context.T,
+ localEndpoint, remoteEndpoint naming.Endpoint,
+ remoteBlessings security.Blessings,
+ remoteDischarges map[string]security.Discharge,
+) ([]string, []security.RejectedBlessing, error) {
+ return nil, nil, nil
+}
+
+func (a proxyAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+ security.Blessings, map[string]security.Discharge, error) {
return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
}
@@ -379,17 +388,17 @@
}
}
-// Dial creates a Flow to the provided remote endpoint, using 'fn' to
+// Dial creates a Flow to the provided remote endpoint, using 'auth' to
// determine the blessings that will be sent to the remote end.
//
// To maximize re-use of connections, the Manager will also Listen on Dialed
// connections for the lifetime of the connection.
-func (m *manager) Dial(ctx *context.T, remote naming.Endpoint, fn flow.BlessingsForPeer) (flow.Flow, error) {
- f, _, err := m.internalDial(ctx, remote, fn)
+func (m *manager) Dial(ctx *context.T, remote naming.Endpoint, auth flow.PeerAuthorizer) (flow.Flow, error) {
+ f, _, err := m.internalDial(ctx, remote, auth)
return f, err
}
-func (m *manager) internalDial(ctx *context.T, remote naming.Endpoint, fn flow.BlessingsForPeer) (flow.Flow, *conn.Conn, error) {
+func (m *manager) internalDial(ctx *context.T, remote naming.Endpoint, auth flow.PeerAuthorizer) (flow.Flow, *conn.Conn, error) {
// Disallow making connections to ourselves.
// TODO(suharshs): Figure out the right thing to do here. We could create a "localflow"
// that bypasses auth and is added to the accept queue immediately.
@@ -445,6 +454,7 @@
localEndpoint(flowConn, m.rid),
remote,
version.Supported,
+ auth,
handshakeTimeout,
fh,
events,
@@ -460,7 +470,7 @@
return nil, nil, flow.NewErrBadState(ctx, err)
}
}
- f, err := c.Dial(ctx, fn)
+ f, err := c.Dial(ctx, auth)
if err != nil {
return nil, nil, flow.NewErrDialFailed(ctx, err)
}
@@ -477,6 +487,7 @@
proxyConn.LocalEndpoint(),
remote,
version.Supported,
+ auth,
handshakeTimeout,
fh,
events)
@@ -490,7 +501,7 @@
if err := m.cache.InsertWithRoutingID(c); err != nil {
return nil, nil, flow.NewErrBadState(ctx, err)
}
- f, err = c.Dial(ctx, fn)
+ f, err = c.Dial(ctx, auth)
if err != nil {
proxyConn.Close(ctx, err)
return nil, nil, flow.NewErrDialFailed(ctx, err)
diff --git a/runtime/internal/flow/manager/manager_test.go b/runtime/internal/flow/manager/manager_test.go
index c151586..7efc876 100644
--- a/runtime/internal/flow/manager/manager_test.go
+++ b/runtime/internal/flow/manager/manager_test.go
@@ -37,7 +37,7 @@
}
dm := New(ctx, naming.FixedRoutingID(0x1111))
- testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+ testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
shutdown()
<-am.Closed()
@@ -59,14 +59,14 @@
t.Fatalf("got cache size %v, want %v", got, want)
}
// After dialing a connection the cache should hold one connection.
- testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+ testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
if got, want := len(dm.(*manager).cache.addrCache), 1; got != want {
t.Fatalf("got cache size %v, want %v", got, want)
}
old := dm.(*manager).cache.ridCache[am.RoutingID()]
// After dialing another connection the cache should still hold one connection
// because the connections should be reused.
- testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+ testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
if got, want := len(dm.(*manager).cache.addrCache), 1; got != want {
t.Errorf("got cache size %v, want %v", got, want)
}
@@ -89,9 +89,9 @@
}
dm := New(ctx, naming.FixedRoutingID(0x1111))
- testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+ testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
// Now am should be able to make a flow to dm even though dm is not listening.
- testFlows(t, ctx, am, dm, flowtest.BlessingsForPeer)
+ testFlows(t, ctx, am, dm, flowtest.AllowAllPeersAuthorizer{})
shutdown()
<-am.Closed()
@@ -107,13 +107,13 @@
t.Fatal(err)
}
nulldm := New(ctx, naming.NullRoutingID)
- _, af := testFlows(t, ctx, nulldm, am, flowtest.BlessingsForPeer)
+ _, af := testFlows(t, ctx, nulldm, am, flowtest.AllowAllPeersAuthorizer{})
// Ensure that the remote blessings of the underlying conn of the accepted flow are zero.
if rBlessings := af.Conn().(*conn.Conn).RemoteBlessings(); !rBlessings.IsZero() {
t.Errorf("got %v, want zero-value blessings", rBlessings)
}
dm := New(ctx, naming.FixedRoutingID(0x1111))
- _, af = testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+ _, af = testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
// Ensure that the remote blessings of the underlying conn of the accepted flow are
// non-zero if we did specify a RoutingID.
if rBlessings := af.Conn().(*conn.Conn).RemoteBlessings(); rBlessings.IsZero() {
@@ -135,11 +135,11 @@
t.Fatal(err)
}
dm := New(ctx, naming.FixedRoutingID(0x1111))
- testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+ testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
am.StopListening(ctx)
- if f, err := dm.Dial(ctx, am.ListeningEndpoints()[0], flowtest.BlessingsForPeer); err == nil {
+ if f, err := dm.Dial(ctx, am.ListeningEndpoints()[0], flowtest.AllowAllPeersAuthorizer{}); err == nil {
t.Errorf("dialing a lame duck should fail, but didn't %#v.", f)
}
@@ -148,10 +148,10 @@
<-dm.Closed()
}
-func testFlows(t *testing.T, ctx *context.T, dm, am flow.Manager, bFn flow.BlessingsForPeer) (df, af flow.Flow) {
+func testFlows(t *testing.T, ctx *context.T, dm, am flow.Manager, auth flow.PeerAuthorizer) (df, af flow.Flow) {
ep := am.ListeningEndpoints()[0]
var err error
- df, err = dm.Dial(ctx, ep, bFn)
+ df, err = dm.Dial(ctx, ep, auth)
if err != nil {
t.Fatal(err)
}
diff --git a/runtime/internal/rpc/benchmark/simple/main.go b/runtime/internal/rpc/benchmark/simple/main.go
index fb1d52c..fb30f0a 100644
--- a/runtime/internal/rpc/benchmark/simple/main.go
+++ b/runtime/internal/rpc/benchmark/simple/main.go
@@ -58,7 +58,7 @@
if ref.RPCTransitionState() >= ref.XServers {
m := fmanager.New(nctx, naming.FixedRoutingID(0xc))
b.StartTimer()
- _, err := m.Dial(nctx, serverEP, flowtest.BlessingsForPeer)
+ _, err := m.Dial(nctx, serverEP, flowtest.AllowAllPeersAuthorizer{})
if err != nil {
ctx.Fatalf("Dial failed: %v", err)
}
diff --git a/runtime/internal/rpc/client.go b/runtime/internal/rpc/client.go
index 33db6e7..1d62312 100644
--- a/runtime/internal/rpc/client.go
+++ b/runtime/internal/rpc/client.go
@@ -62,7 +62,7 @@
errNoBlessingsForPeer = reg(".errNoBlessingsForPeer", "no blessings tagged for peer {3}{:4}")
errBlessingGrant = reg(".errBlessingGrant", "failed to grant blessing to server with blessings{:3}")
errBlessingAdd = reg(".errBlessingAdd", "failed to add blessing granted to server{:3}")
- errServerAuthorizeFailed = reg(".errServerAuthorizedFailed", "failed to authorize flow with remote blessings{:3} {:4}")
+ errPeerAuthorizeFailed = reg(".errPeerAuthorizedFailed", "failed to authorize flow with remote blessings{:3} {:4}")
errPrepareBlessingsAndDischarges = reg(".prepareBlessingsAndDischarges", "failed to prepare blessings and discharges: remote blessings{:3} {:4}")
@@ -390,9 +390,9 @@
Suffix: status.suffix,
})
if err := auth.Authorize(ctx, seccall); err != nil {
- // We will test for errServerAuthorizeFailed in failedTryCall and report
+ // We will test for errPeerAuthorizeFailed in failedTryCall and report
// verror.ErrNotTrusted
- status.serverErr = suberr(verror.New(errServerAuthorizeFailed, ctx, status.flow.RemoteBlessings(), err))
+ status.serverErr = suberr(verror.New(errPeerAuthorizeFailed, ctx, status.flow.RemoteBlessings(), err))
ctx.VI(2).Infof("rpc: Failed to authorize Flow created with server %v: %s", server, status.serverErr.Err)
status.flow.Close()
status.flow = nil
@@ -630,7 +630,7 @@
for _, r := range responses {
if r != nil && r.serverErr != nil && r.serverErr.Err != nil {
switch verror.ErrorID(r.serverErr.Err) {
- case stream.ErrNotTrusted.ID, verror.ErrNotTrusted.ID, errServerAuthorizeFailed.ID:
+ case stream.ErrNotTrusted.ID, verror.ErrNotTrusted.ID, errPeerAuthorizeFailed.ID:
topLevelError = verror.ErrNotTrusted
topLevelAction = verror.NoRetry
onlyErrNetwork = false
diff --git a/runtime/internal/rpc/xclient.go b/runtime/internal/rpc/xclient.go
index c96d14a..04cc52d 100644
--- a/runtime/internal/rpc/xclient.go
+++ b/runtime/internal/rpc/xclient.go
@@ -186,8 +186,8 @@
status.serverErr = suberr(verror.New(errInvalidEndpoint, ctx))
return
}
- bfp := blessingsForPeer{auth, method, suffix, args}.run
- flow, err := c.flowMgr.Dial(ctx, ep, bfp)
+ peerAuth := peerAuthorizer{auth, method, suffix, args}
+ flow, err := c.flowMgr.Dial(ctx, ep, peerAuth)
if err != nil {
ctx.VI(2).Infof("rpc: failed to create Flow with %v: %v", server, err)
status.serverErr = suberr(err)
@@ -197,7 +197,7 @@
// Create a type flow, note that we use c.ctx instead of ctx.
// This is because type flows have a longer lifetime than the
// main flow being constructed.
- tflow, err := c.flowMgr.Dial(c.ctx, ep, bfp)
+ tflow, err := c.flowMgr.Dial(c.ctx, ep, peerAuth)
if err != nil {
status.serverErr = suberr(newErrTypeFlowFailure(ctx, err))
flow.Close()
@@ -226,18 +226,18 @@
status.flow = flow
}
-type blessingsForPeer struct {
+type peerAuthorizer struct {
auth security.Authorizer
method string
suffix string
args []interface{}
}
-func (x blessingsForPeer) run(
+func (x peerAuthorizer) AuthorizePeer(
ctx *context.T,
localEP, remoteEP naming.Endpoint,
remoteBlessings security.Blessings,
- remoteDischarges map[string]security.Discharge) (security.Blessings, map[string]security.Discharge, error) {
+ remoteDischarges map[string]security.Discharge) ([]string, []security.RejectedBlessing, error) {
localPrincipal := v23.GetPrincipal(ctx)
call := security.NewCall(&security.CallParams{
Timestamp: time.Now(),
@@ -250,16 +250,24 @@
RemoteEndpoint: remoteEP,
})
if err := x.auth.Authorize(ctx, call); err != nil {
- return security.Blessings{}, nil, verror.New(errServerAuthorizeFailed, ctx, call.RemoteBlessings(), err)
+ return nil, nil, verror.New(errPeerAuthorizeFailed, ctx, call.RemoteBlessings(), err)
}
- serverB, serverBRejected := security.RemoteBlessingNames(ctx, call)
- clientB := localPrincipal.BlessingStore().ForPeer(serverB...)
+ peerNames, rejectedPeerNames := security.RemoteBlessingNames(ctx, call)
+ return peerNames, rejectedPeerNames, nil
+}
+
+func (x peerAuthorizer) BlessingsForPeer(ctx *context.T, peerNames []string) (
+ security.Blessings, map[string]security.Discharge, error) {
+ localPrincipal := v23.GetPrincipal(ctx)
+ clientB := localPrincipal.BlessingStore().ForPeer(peerNames...)
if clientB.IsZero() {
// TODO(ataly, ashankar): We need not error out here and instead can just
// send the <nil> blessings to the server.
- return security.Blessings{}, nil, verror.New(errNoBlessingsForPeer, ctx, serverB, serverBRejected)
+ // TODO(suharshs): Make this a different error when we are making all the vdl errors
+ // in a errors.vdl file.
+ return security.Blessings{}, nil, verror.New(errNoBlessingsForPeer, ctx, nil, nil)
}
- impetus, err := mkDischargeImpetus(serverB, x.method, x.args)
+ impetus, err := mkDischargeImpetus(peerNames, x.method, x.args)
if err != nil {
return security.Blessings{}, nil, err
}
@@ -446,7 +454,7 @@
for _, r := range responses {
if r != nil && r.serverErr != nil && r.serverErr.Err != nil {
switch verror.ErrorID(r.serverErr.Err) {
- case /*stream.ErrNotTrusted.ID,*/ verror.ErrNotTrusted.ID, errServerAuthorizeFailed.ID:
+ case /*stream.ErrNotTrusted.ID,*/ verror.ErrNotTrusted.ID, errPeerAuthorizeFailed.ID:
topLevelError = verror.ErrNotTrusted
topLevelAction = verror.NoRetry
onlyErrNetwork = false
@@ -601,7 +609,7 @@
Suffix: suffix,
})
// TODO(suharshs): Its unfortunate that we compute these here and also in the
- // blessingsForPeer.run function. Find a way to only do this once.
+ // peerAuthorizer struct. Find a way to only do this once.
fc.remoteBNames, _ = security.RemoteBlessingNames(ctx, call)
var grantedB security.Blessings
for _, o := range opts {
diff --git a/services/xproxyd/proxy_test.go b/services/xproxyd/proxy_test.go
index 5343d26..58bd616 100644
--- a/services/xproxyd/proxy_test.go
+++ b/services/xproxyd/proxy_test.go
@@ -184,7 +184,7 @@
func testEndToEndConnection(t *testing.T, ctx *context.T, dm, am flow.Manager, aep naming.Endpoint) error {
// The dialing flow.Manager dials a flow to the accepting flow.Manager.
want := "Do you read me?"
- df, err := dm.Dial(ctx, aep, bfp)
+ df, err := dm.Dial(ctx, aep, allowAllPeersAuthorizer{})
if err != nil {
return err
}
@@ -232,12 +232,19 @@
return err
}
-func bfp(
+type allowAllPeersAuthorizer struct{}
+
+func (allowAllPeersAuthorizer) AuthorizePeer(
ctx *context.T,
localEndpoint, remoteEndpoint naming.Endpoint,
remoteBlessings security.Blessings,
remoteDischarges map[string]security.Discharge,
-) (security.Blessings, map[string]security.Discharge, error) {
+) ([]string, []security.RejectedBlessing, error) {
+ return nil, nil, nil
+}
+
+func (allowAllPeersAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+ security.Blessings, map[string]security.Discharge, error) {
return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
}
diff --git a/services/xproxyd/proxyd.go b/services/xproxyd/proxyd.go
index 1ead875..b0c1941 100644
--- a/services/xproxyd/proxyd.go
+++ b/services/xproxyd/proxyd.go
@@ -137,7 +137,7 @@
return nil, err
}
}
- fout, err := p.m.Dial(ctx, ep, proxyBlessingsForPeer{}.run)
+ fout, err := p.m.Dial(ctx, ep, proxyAuthorizer{})
if err != nil {
return nil, err
}
@@ -207,7 +207,7 @@
return
default:
}
- f, err := p.m.Dial(ctx, ep, proxyBlessingsForPeer{}.run)
+ f, err := p.m.Dial(ctx, ep, proxyAuthorizer{})
if err != nil {
ctx.Error(err)
continue
diff --git a/services/xproxyd/util.go b/services/xproxyd/util.go
index e14e23e..a42779d 100644
--- a/services/xproxyd/util.go
+++ b/services/xproxyd/util.go
@@ -75,11 +75,20 @@
return blessingOpts
}
-type proxyBlessingsForPeer struct{}
-
// TODO(suharshs): Figure out what blessings to present here. And present discharges.
-func (proxyBlessingsForPeer) run(ctx *context.T, lep, rep naming.Endpoint, rb security.Blessings,
- rd map[string]security.Discharge) (security.Blessings, map[string]security.Discharge, error) {
+type proxyAuthorizer struct{}
+
+func (proxyAuthorizer) AuthorizePeer(
+ ctx *context.T,
+ localEndpoint, remoteEndpoint naming.Endpoint,
+ remoteBlessings security.Blessings,
+ remoteDischarges map[string]security.Discharge,
+) ([]string, []security.RejectedBlessing, error) {
+ return nil, nil, nil
+}
+
+func (a proxyAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+ security.Blessings, map[string]security.Discharge, error) {
return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
}