ref: Change the API of validators to accept *context.T
instead of security.Call.
Also we remove the Context() accessor from the security.Call and
add it back to rpc.ServerCall. This is in preparation to split
the ServerCall and security.Call interfaces.
MultiPart: 2/3
Change-Id: Ia41e4a60a3b995ddf349db39fc154cf25d5241bc
diff --git a/profiles/internal/rpc/client.go b/profiles/internal/rpc/client.go
index 61eaaab..3c070cd 100644
--- a/profiles/internal/rpc/client.go
+++ b/profiles/internal/rpc/client.go
@@ -349,9 +349,6 @@
return
}
- // TODO(ataly, bprosnitx, ashankar): Add 'ctx' to the security.Call created below
- // otherwise any custom caveat validators (defined in ctx) cannot be used while validating
- // caveats in this context. Also see: https://github.com/veyron/release-issues/issues/1230
seccall := security.NewCall(&security.CallParams{
LocalPrincipal: status.flow.LocalPrincipal(),
LocalBlessings: status.flow.LocalBlessings(),
diff --git a/profiles/internal/rpc/full_test.go b/profiles/internal/rpc/full_test.go
index 4a86966..8bf421c 100644
--- a/profiles/internal/rpc/full_test.go
+++ b/profiles/internal/rpc/full_test.go
@@ -206,7 +206,7 @@
if tp == nil {
return security.Discharge{}, fmt.Errorf("discharger: %v does not represent a third-party caveat", cav)
}
- if err := tp.Dischargeable(call); err != nil {
+ if err := tp.Dischargeable(call.Context()); err != nil {
return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", cav, err)
}
// Add a fakeTimeCaveat to be able to control discharge expiration via 'clock'.
@@ -1966,7 +1966,7 @@
if tp == nil {
return security.Discharge{}, fmt.Errorf("discharger: %v does not represent a third-party caveat", cav)
}
- if err := tp.Dischargeable(call); err != nil {
+ if err := tp.Dischargeable(call.Context()); err != nil {
return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", cav, err)
}
expDur := 10 * time.Millisecond
@@ -2050,7 +2050,7 @@
func init() {
rpc.RegisterUnknownProtocol("wsh", websocket.HybridDial, websocket.HybridListener)
- security.RegisterCaveatValidator(fakeTimeCaveat, func(_ security.Call, t int64) error {
+ security.RegisterCaveatValidator(fakeTimeCaveat, func(_ *context.T, t int64) error {
if now := clock.Now(); now > t {
return fmt.Errorf("fakeTimeCaveat expired: now=%d > then=%d", now, t)
}
diff --git a/profiles/internal/rt/ipc_test.go b/profiles/internal/rt/ipc_test.go
index e836c55..1ad062d 100644
--- a/profiles/internal/rt/ipc_test.go
+++ b/profiles/internal/rt/ipc_test.go
@@ -252,7 +252,7 @@
if tp == nil {
return security.Discharge{}, fmt.Errorf("discharger: not a third party caveat (%v)", cav)
}
- if err := tp.Dischargeable(call); err != nil {
+ if err := tp.Dischargeable(call.Context()); err != nil {
return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", tp, err)
}
// If its the first time being called, add an expiry caveat and a MethodCaveat for "EchoBlessings".
diff --git a/services/identity/internal/revocation/revocation_manager.go b/services/identity/internal/revocation/revocation_manager.go
index 9cd28e1..de4ab73 100644
--- a/services/identity/internal/revocation/revocation_manager.go
+++ b/services/identity/internal/revocation/revocation_manager.go
@@ -8,6 +8,7 @@
"sync"
"time"
+ "v.io/v23/context"
"v.io/v23/security"
)
@@ -78,7 +79,7 @@
return timestamp
}
-func isRevoked(_ security.Call, key []byte) error {
+func isRevoked(_ *context.T, key []byte) error {
revocationLock.RLock()
if revocationDB == nil {
revocationLock.RUnlock()
diff --git a/services/security/discharger/discharger.go b/services/security/discharger/discharger.go
index 9738c23..3d42000 100644
--- a/services/security/discharger/discharger.go
+++ b/services/security/discharger/discharger.go
@@ -18,7 +18,7 @@
if tp == nil {
return security.Discharge{}, fmt.Errorf("Caveat %v does not represent a third party caveat", caveat)
}
- if err := tp.Dischargeable(call); err != nil {
+ if err := tp.Dischargeable(call.Context()); err != nil {
return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", tp, err)
}
expiry, err := security.ExpiryCaveat(time.Now().Add(15 * time.Minute))
diff --git a/services/wsprd/rpc/server/authorizer.go b/services/wsprd/rpc/server/authorizer.go
index 2646f87..495b2cf 100644
--- a/services/wsprd/rpc/server/authorizer.go
+++ b/services/wsprd/rpc/server/authorizer.go
@@ -2,7 +2,6 @@
import (
"v.io/v23/context"
- "v.io/v23/security"
)
type authorizer struct {
@@ -10,5 +9,5 @@
}
func (a *authorizer) Authorize(ctx *context.T) error {
- return a.authFunc(security.GetCall(ctx))
+ return a.authFunc(ctx)
}
diff --git a/services/wsprd/rpc/server/server.go b/services/wsprd/rpc/server/server.go
index 01f7df4..6f90383 100644
--- a/services/wsprd/rpc/server/server.go
+++ b/services/wsprd/rpc/server/server.go
@@ -132,7 +132,7 @@
func (s *Server) createRemoteInvokerFunc(handle int32) remoteInvokeFunc {
return func(methodName string, args []interface{}, call rpc.StreamServerCall) <-chan *lib.ServerRpcReply {
- securityCall := s.convertSecurityCall(call, true)
+ securityCall := s.convertSecurityCall(call.Context(), true)
flow := s.helper.CreateNewFlow(s, call)
replyChan := make(chan *lib.ServerRpcReply, 1)
@@ -231,7 +231,7 @@
// Until the tests get fixed, we need to create a security context before creating the flow
// because creating the security context creates a flow and flow ids will be off.
// See https://github.com/veyron/release-issues/issues/1181
- securityCall := s.convertSecurityCall(call, true)
+ securityCall := s.convertSecurityCall(call.Context(), true)
globChan := make(chan naming.GlobReply, 1)
flow := s.helper.CreateNewFlow(s, &globStream{
@@ -331,10 +331,10 @@
// wsprCaveatValidator validates caveats in javascript.
// It resolves each []security.Caveat in cavs to an error (or nil) and collects them in a slice.
-func (s *Server) validateCavsInJavascript(call security.Call, cavs [][]security.Caveat) []error {
+func (s *Server) validateCavsInJavascript(ctx *context.T, cavs [][]security.Caveat) []error {
flow := s.helper.CreateNewFlow(s, nil)
req := CaveatValidationRequest{
- Call: s.convertSecurityCall(call, false),
+ Call: s.convertSecurityCall(ctx, false),
Cavs: cavs,
}
@@ -357,17 +357,17 @@
// TODO(bprosnitz) Consider using a different timeout than the standard rpc timeout.
var timeoutChan <-chan time.Time
- if deadline, ok := call.Context().Deadline(); ok {
+ if deadline, ok := ctx.Deadline(); ok {
timeoutChan = time.After(deadline.Sub(time.Now()))
}
select {
case <-timeoutChan:
- return makeListOfErrors(len(cavs), NewErrCaveatValidationTimeout(call.Context()))
+ return makeListOfErrors(len(cavs), NewErrCaveatValidationTimeout(ctx))
case reply := <-replyChan:
if len(reply) != len(cavs) {
vlog.VI(2).Infof("Wspr caveat validator received %d results from javascript but expected %d", len(reply), len(cavs))
- return makeListOfErrors(len(cavs), NewErrInvalidValidationResponseFromJavascript(call.Context()))
+ return makeListOfErrors(len(cavs), NewErrInvalidValidationResponseFromJavascript(ctx))
}
return reply
@@ -377,7 +377,7 @@
// wsprCaveatValidator validates caveats for javascript.
// Certain caveats (PublicKeyThirdPartyCaveatX) are intercepted and handled in go.
// This call validateCavsInJavascript to process the remaining caveats in javascript.
-func (s *Server) wsprCaveatValidator(call security.Call, cavs [][]security.Caveat) []error {
+func (s *Server) wsprCaveatValidator(ctx *context.T, cavs [][]security.Caveat) []error {
type validationStatus struct {
err error
isSet bool
@@ -391,7 +391,7 @@
for _, cav := range chainCavs {
switch cav.Id {
case security.PublicKeyThirdPartyCaveatX.Id:
- res := cav.Validate(call)
+ res := cav.Validate(ctx)
if res != nil {
valStatus[i] = validationStatus{
err: res,
@@ -413,7 +413,7 @@
}
}
- jsRes := s.validateCavsInJavascript(call, caveatChainsToValidate)
+ jsRes := s.validateCavsInJavascript(ctx, caveatChainsToValidate)
outResults := make([]error, len(cavs))
jsIndex := 0
@@ -429,7 +429,8 @@
return outResults
}
-func (s *Server) convertSecurityCall(call security.Call, includeBlessingStrings bool) SecurityCall {
+func (s *Server) convertSecurityCall(ctx *context.T, includeBlessingStrings bool) SecurityCall {
+ call := security.GetCall(ctx)
// TODO(bprosnitz) Local/Remote Endpoint should always be non-nil, but isn't
// due to a TODO in vc/auth.go
var localEndpoint string
@@ -457,7 +458,6 @@
LocalBlessings: localBlessings,
RemoteBlessings: s.convertBlessingsToHandle(call.RemoteBlessings()),
}
- ctx := call.Context()
if includeBlessingStrings {
secCall.LocalBlessingStrings = security.LocalBlessingNames(ctx)
secCall.RemoteBlessingStrings, _ = security.RemoteBlessingNames(ctx)
@@ -465,13 +465,13 @@
return secCall
}
-type remoteAuthFunc func(call security.Call) error
+type remoteAuthFunc func(ctx *context.T) error
func (s *Server) createRemoteAuthFunc(handle int32) remoteAuthFunc {
- return func(call security.Call) error {
+ return func(ctx *context.T) error {
// Until the tests get fixed, we need to create a security context before creating the flow
// because creating the security context creates a flow and flow ids will be off.
- securityCall := s.convertSecurityCall(call, true)
+ securityCall := s.convertSecurityCall(ctx, true)
flow := s.helper.CreateNewFlow(s, nil)
replyChan := make(chan error, 1)
@@ -658,10 +658,19 @@
s.outstandingRequestLock.Lock()
s.outstandingAuthRequests = make(map[int32]chan error)
s.outstandingServerRequests = make(map[int32]chan *lib.ServerRpcReply)
- s.outstandingValidationRequests = make(map[int32]chan []error)
s.outstandingRequestLock.Unlock()
s.serverStateLock.Unlock()
s.server.Stop()
+
+ // Only clear the validation requests map after stopping. clearing
+ // it can cause the publisher to get stuck waiting for a caveat validtion
+ // that will never be answered, which in turn causes it to not be
+ // able to stop which prevents the server from stopping.
+ s.serverStateLock.Lock()
+ s.outstandingRequestLock.Lock()
+ s.outstandingValidationRequests = make(map[int32]chan []error)
+ s.outstandingRequestLock.Unlock()
+ s.serverStateLock.Unlock()
}
func (s *Server) AddName(name string) error {