security: Define a VDL type for discharges (Part 2/2)
More details in:
commit 4617b0475f31283d1ffde494f99e36f67cb2c1c5
= https://vanadium-review.googlesource.com/#/c/3601/
= https://github.com/veyron/release-issues/issues/634
With this commit, the security infrastructure should no longer decode
into the "vdl.Any" type, i.e., it always decodes into concrete types and
thus should be immune to renamings/reorganization of packages.
Change-Id: Ibf1be9537c855e040e2df45f99ede4ec2be6c43e
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index e330ff7..7945478 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -764,14 +764,9 @@
fc.blessings = fc.flow.LocalPrincipal().BlessingStore().ForPeer(fc.server...)
blessingsRequest = clientEncodeBlessings(fc.flow.VCDataCache(), fc.blessings)
}
- // TODO(ashankar):DISCHARGEVDL: This should become:
- // discharges := make([]security.WireDischarge, len(fc.discharges))
- // for i, d := range fc.discharges {
- // discharges[i] = security.MarshalDischarge(d)
- // }
- anyDischarges := make([]vdl.AnyRep, len(fc.discharges))
+ discharges := make([]security.WireDischarge, len(fc.discharges))
for i, d := range fc.discharges {
- anyDischarges[i] = d
+ discharges[i] = security.MarshalDischarge(d)
}
req := ipc.Request{
Suffix: suffix,
@@ -780,7 +775,7 @@
Timeout: int64(timeout),
GrantedBlessings: security.MarshalBlessings(blessings),
Blessings: blessingsRequest,
- Discharges: anyDischarges,
+ Discharges: discharges,
TraceRequest: ivtrace.Request(fc.ctx),
}
if err := fc.enc.Encode(req); err != nil {
diff --git a/runtimes/google/ipc/discharges.go b/runtimes/google/ipc/discharges.go
index 2c196cc..5bf42f7 100644
--- a/runtimes/google/ipc/discharges.go
+++ b/runtimes/google/ipc/discharges.go
@@ -113,28 +113,15 @@
vlog.VI(3).Infof("Discharge fetch for %v failed: %v", tp, err)
return
}
- // TODO(ashankar):DISCHARGEVDL:This should become:
- // var wire security.WireDischarge
- var dAny vdl.AnyRep
- if ierr := call.Finish(&dAny, &err); ierr != nil || err != nil {
+ var wire security.WireDischarge
+ if ierr := call.Finish(&wire, &err); ierr != nil || err != nil {
vlog.VI(3).Infof("Discharge fetch for %v failed: (%v, %v)", cav, err, ierr)
return
}
- var d security.Discharge
- switch v := dAny.(type) {
- case security.WireDischarge:
- if d, err = security.NewDischarge(v); err != nil {
- vlog.Errorf("fetchDischarges: server at %s sent an invalid discharge: %v", tp.Location(), err)
- } else {
- vlog.VI(3).Infof("Fetched discharge for %v: %v", tp, d)
- }
- case security.Discharge:
- d = v
- vlog.VI(3).Infof("Fetched discharge for %v: %v", tp, d)
- default:
- vlog.Errorf("fetchDischarges: server at %s sent an unexpected %T", tp.Location(), dAny)
+ d, err := security.NewDischarge(wire)
+ if err != nil {
+ vlog.Errorf("fetchDischarges: server at %s sent a malformed discharge: %v", tp.Location(), err)
}
-
discharges <- fetched{i, d}
}(i, ctx, caveats[i])
}
diff --git a/runtimes/google/ipc/errors.vdl b/runtimes/google/ipc/errors.vdl
index 8f36256..8a1118c 100644
--- a/runtimes/google/ipc/errors.vdl
+++ b/runtimes/google/ipc/errors.vdl
@@ -26,12 +26,6 @@
badDischarge(index uint64, err error) {
"en": "failed to decode discharge #{index}: {err}",
}
- badDischargeType(index uint64, t typeobject) {
- "en": "discharge #{index} type {t} isn't registered",
- }
- badDischargeImpl(index uint64, t string) {
- "en": "discharge #{index} type {t} doesn't implement security.Discharge",
- }
badAuth(suffix, method string, err error) {
"en": "not authorized to call {suffix}.{method}: {err}",
}
diff --git a/runtimes/google/ipc/errors.vdl.go b/runtimes/google/ipc/errors.vdl.go
index cc9a829..820833a 100644
--- a/runtimes/google/ipc/errors.vdl.go
+++ b/runtimes/google/ipc/errors.vdl.go
@@ -7,7 +7,6 @@
// VDL system imports
"v.io/core/veyron2/context"
"v.io/core/veyron2/i18n"
- "v.io/core/veyron2/vdl"
"v.io/core/veyron2/verror"
// VDL user imports
@@ -23,8 +22,6 @@
errBadBlessings = verror.Register("v.io/core/veyron/runtimes/google/ipc.badBlessings", verror.NoRetry, "{1:}{2:} failed to decode blessings: {3}")
errBadBlessingsCache = verror.Register("v.io/core/veyron/runtimes/google/ipc.badBlessingsCache", verror.NoRetry, "{1:}{2:} failed to find blessings in cache: {3}")
errBadDischarge = verror.Register("v.io/core/veyron/runtimes/google/ipc.badDischarge", verror.NoRetry, "{1:}{2:} failed to decode discharge #{3}: {4}")
- errBadDischargeType = verror.Register("v.io/core/veyron/runtimes/google/ipc.badDischargeType", verror.NoRetry, "{1:}{2:} discharge #{3} type {4} isn't registered")
- errBadDischargeImpl = verror.Register("v.io/core/veyron/runtimes/google/ipc.badDischargeImpl", verror.NoRetry, "{1:}{2:} discharge #{3} type {4} doesn't implement security.Discharge")
errBadAuth = verror.Register("v.io/core/veyron/runtimes/google/ipc.badAuth", verror.NoRetry, "{1:}{2:} not authorized to call {3}.{4}: {5}")
)
@@ -36,8 +33,6 @@
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadBlessings.ID), "{1:}{2:} failed to decode blessings: {3}")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadBlessingsCache.ID), "{1:}{2:} failed to find blessings in cache: {3}")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadDischarge.ID), "{1:}{2:} failed to decode discharge #{3}: {4}")
- i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadDischargeType.ID), "{1:}{2:} discharge #{3} type {4} isn't registered")
- i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadDischargeImpl.ID), "{1:}{2:} discharge #{3} type {4} doesn't implement security.Discharge")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadAuth.ID), "{1:}{2:} not authorized to call {3}.{4}: {5}")
}
@@ -76,16 +71,6 @@
return verror.New(errBadDischarge, ctx, index, err)
}
-// newErrBadDischargeType returns an error with the errBadDischargeType ID.
-func newErrBadDischargeType(ctx *context.T, index uint64, t *vdl.Type) error {
- return verror.New(errBadDischargeType, ctx, index, t)
-}
-
-// newErrBadDischargeImpl returns an error with the errBadDischargeImpl ID.
-func newErrBadDischargeImpl(ctx *context.T, index uint64, t string) error {
- return verror.New(errBadDischargeImpl, ctx, index, t)
-}
-
// newErrBadAuth returns an error with the errBadAuth ID.
func newErrBadAuth(ctx *context.T, suffix string, method string, err error) error {
return verror.New(errBadAuth, ctx, suffix, method, err)
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 185b13c..f64dea2 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -185,7 +185,7 @@
type dischargeServer struct{}
-func (*dischargeServer) Discharge(ctx ipc.ServerCall, cav security.Caveat, _ security.DischargeImpetus) (vdl.AnyRep, error) {
+func (*dischargeServer) Discharge(ctx ipc.ServerCall, cav security.Caveat, _ security.DischargeImpetus) (security.WireDischarge, error) {
tp := cav.ThirdPartyDetails()
if tp == nil {
return nil, fmt.Errorf("discharger: %v does not represent a third-party caveat", cav)
@@ -198,7 +198,11 @@
if err != nil {
return nil, fmt.Errorf("failed to create an expiration on the discharge: %v", err)
}
- return ctx.LocalPrincipal().MintDischarge(cav, expiry)
+ d, err := ctx.LocalPrincipal().MintDischarge(cav, expiry)
+ if err != nil {
+ return nil, err
+ }
+ return security.MarshalDischarge(d), nil
}
func startServer(t *testing.T, principal security.Principal, sm stream.Manager, ns naming.Namespace, name string, disp ipc.Dispatcher, opts ...ipc.ServerOpt) (naming.Endpoint, ipc.Server) {
@@ -758,7 +762,7 @@
traceid []uniqueid.Id
}
-func (s *dischargeTestServer) Discharge(ctx ipc.ServerContext, cav vdl.AnyRep, impetus security.DischargeImpetus) (vdl.AnyRep, error) {
+func (s *dischargeTestServer) Discharge(ctx ipc.ServerContext, cav security.Caveat, impetus security.DischargeImpetus) (security.WireDischarge, error) {
s.impetus = append(s.impetus, impetus)
s.traceid = append(s.traceid, vtrace.GetSpan(ctx.Context()).Trace())
return nil, fmt.Errorf("discharges not issued")
@@ -1471,11 +1475,15 @@
called bool
}
-func (m *mockDischarger) Discharge(ctx ipc.ServerContext, caveat security.Caveat, _ security.DischargeImpetus) (vdl.AnyRep, error) {
+func (m *mockDischarger) Discharge(ctx ipc.ServerContext, caveat security.Caveat, _ security.DischargeImpetus) (security.WireDischarge, error) {
m.mu.Lock()
m.called = true
m.mu.Unlock()
- return ctx.LocalPrincipal().MintDischarge(caveat, security.UnconstrainedUse())
+ d, err := ctx.LocalPrincipal().MintDischarge(caveat, security.UnconstrainedUse())
+ if err != nil {
+ return nil, err
+ }
+ return security.MarshalDischarge(d), nil
}
func TestNoDischargesOpt(t *testing.T) {
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index 7030d7c..3665d59 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -18,7 +18,6 @@
"v.io/core/veyron2/options"
"v.io/core/veyron2/security"
"v.io/core/veyron2/services/security/access"
- "v.io/core/veyron2/vdl"
"v.io/core/veyron2/verror"
"v.io/core/veyron2/vlog"
"v.io/core/veyron2/vom"
@@ -1175,24 +1174,11 @@
}
for i, d := range req.Discharges {
- if w, ok := d.(security.WireDischarge); ok {
- dis, err := security.NewDischarge(w)
- if err != nil {
- return verror.New(verror.BadProtocol, fs.T, newErrBadDischarge(fs.T, uint64(i), err))
- }
- fs.discharges[dis.ID()] = dis
- continue
+ dis, err := security.NewDischarge(d)
+ if err != nil {
+ return verror.New(verror.BadProtocol, fs.T, newErrBadDischarge(fs.T, uint64(i), err))
}
- // TODO(ashankar):DISCHARGEVDL: The rest of this block (inside
- // the for loop) should go away.
- if dis, ok := d.(security.Discharge); ok {
- fs.discharges[dis.ID()] = dis
- continue
- }
- if v, ok := d.(*vdl.Value); ok {
- return verror.New(verror.BadProtocol, fs.T, newErrBadDischargeType(fs.T, uint64(i), v.Type()))
- }
- return verror.New(verror.BadProtocol, fs.T, newErrBadDischargeImpl(fs.T, uint64(i), fmt.Sprintf("%T", d)))
+ fs.discharges[dis.ID()] = dis
}
return nil
}
diff --git a/runtimes/google/rt/ipc_test.go b/runtimes/google/rt/ipc_test.go
index df5e560..488b4e8 100644
--- a/runtimes/google/rt/ipc_test.go
+++ b/runtimes/google/rt/ipc_test.go
@@ -15,7 +15,6 @@
"v.io/core/veyron/lib/testutil"
tsecurity "v.io/core/veyron/lib/testutil/security"
_ "v.io/core/veyron/profiles"
- "v.io/core/veyron2/vdl"
"v.io/core/veyron2/verror"
)
@@ -30,7 +29,7 @@
type dischargeService struct{}
-func (dischargeService) Discharge(ctx ipc.ServerCall, cav security.Caveat, _ security.DischargeImpetus) (vdl.AnyRep, error) {
+func (dischargeService) Discharge(ctx ipc.ServerCall, cav security.Caveat, _ security.DischargeImpetus) (security.WireDischarge, error) {
tp := cav.ThirdPartyDetails()
if tp == nil {
return nil, fmt.Errorf("discharger: not a third party caveat (%v)", cav)
@@ -38,7 +37,11 @@
if err := tp.Dischargeable(ctx); err != nil {
return nil, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", tp, err)
}
- return ctx.LocalPrincipal().MintDischarge(cav, security.UnconstrainedUse())
+ d, err := ctx.LocalPrincipal().MintDischarge(cav, security.UnconstrainedUse())
+ if err != nil {
+ return nil, err
+ }
+ return security.MarshalDischarge(d), nil
}
func newCtx(rootCtx *context.T) *context.T {
diff --git a/services/security/discharger.vdl b/services/security/discharger.vdl
index f6df28a..0cfdd88 100644
--- a/services/security/discharger.vdl
+++ b/services/security/discharger.vdl
@@ -7,7 +7,5 @@
// Discharge is called by a principal that holds a blessing with a third
// party caveat and seeks to get a discharge that proves the fulfillment of
// this caveat.
- //
- // TODO(ashankar):DISCHARGEVDL: The return type should become security.WireDischarge
- Discharge(Caveat security.Caveat, Impetus security.DischargeImpetus) (Discharge any | error)
+ Discharge(Caveat security.Caveat, Impetus security.DischargeImpetus) (Discharge security.WireDischarge | error)
}
diff --git a/services/security/discharger.vdl.go b/services/security/discharger.vdl.go
index 3e3c9f0..041d339 100644
--- a/services/security/discharger.vdl.go
+++ b/services/security/discharger.vdl.go
@@ -8,7 +8,6 @@
"v.io/core/veyron2"
"v.io/core/veyron2/context"
"v.io/core/veyron2/ipc"
- "v.io/core/veyron2/vdl"
// VDL user imports
"v.io/core/veyron2/security"
@@ -22,9 +21,7 @@
// Discharge is called by a principal that holds a blessing with a third
// party caveat and seeks to get a discharge that proves the fulfillment of
// this caveat.
- //
- // TODO(ashankar):DISCHARGEVDL: The return type should become security.WireDischarge
- Discharge(ctx *context.T, Caveat security.Caveat, Impetus security.DischargeImpetus, opts ...ipc.CallOpt) (Discharge vdl.AnyRep, err error)
+ Discharge(ctx *context.T, Caveat security.Caveat, Impetus security.DischargeImpetus, opts ...ipc.CallOpt) (Discharge security.WireDischarge, err error)
}
// DischargerClientStub adds universal methods to DischargerClientMethods.
@@ -56,7 +53,7 @@
return veyron2.GetClient(ctx)
}
-func (c implDischargerClientStub) Discharge(ctx *context.T, i0 security.Caveat, i1 security.DischargeImpetus, opts ...ipc.CallOpt) (o0 vdl.AnyRep, err error) {
+func (c implDischargerClientStub) Discharge(ctx *context.T, i0 security.Caveat, i1 security.DischargeImpetus, opts ...ipc.CallOpt) (o0 security.WireDischarge, err error) {
var call ipc.Call
if call, err = c.c(ctx).StartCall(ctx, c.name, "Discharge", []interface{}{i0, i1}, opts...); err != nil {
return
@@ -75,9 +72,7 @@
// Discharge is called by a principal that holds a blessing with a third
// party caveat and seeks to get a discharge that proves the fulfillment of
// this caveat.
- //
- // TODO(ashankar):DISCHARGEVDL: The return type should become security.WireDischarge
- Discharge(ctx ipc.ServerContext, Caveat security.Caveat, Impetus security.DischargeImpetus) (Discharge vdl.AnyRep, err error)
+ Discharge(ctx ipc.ServerContext, Caveat security.Caveat, Impetus security.DischargeImpetus) (Discharge security.WireDischarge, err error)
}
// DischargerServerStubMethods is the server interface containing
@@ -115,7 +110,7 @@
gs *ipc.GlobState
}
-func (s implDischargerServerStub) Discharge(ctx ipc.ServerContext, i0 security.Caveat, i1 security.DischargeImpetus) (vdl.AnyRep, error) {
+func (s implDischargerServerStub) Discharge(ctx ipc.ServerContext, i0 security.Caveat, i1 security.DischargeImpetus) (security.WireDischarge, error) {
return s.impl.Discharge(ctx, i0, i1)
}
@@ -138,13 +133,13 @@
Methods: []ipc.MethodDesc{
{
Name: "Discharge",
- Doc: "// Discharge is called by a principal that holds a blessing with a third\n// party caveat and seeks to get a discharge that proves the fulfillment of\n// this caveat.\n//\n// TODO(ashankar):DISCHARGEVDL: The return type should become security.WireDischarge",
+ Doc: "// Discharge is called by a principal that holds a blessing with a third\n// party caveat and seeks to get a discharge that proves the fulfillment of\n// this caveat.",
InArgs: []ipc.ArgDesc{
{"Caveat", ``}, // security.Caveat
{"Impetus", ``}, // security.DischargeImpetus
},
OutArgs: []ipc.ArgDesc{
- {"Discharge", ``}, // vdl.AnyRep
+ {"Discharge", ``}, // security.WireDischarge
{"err", ``}, // error
},
},
diff --git a/services/security/discharger/discharger.go b/services/security/discharger/discharger.go
index a61aea1..5f4b436 100644
--- a/services/security/discharger/discharger.go
+++ b/services/security/discharger/discharger.go
@@ -7,14 +7,13 @@
services "v.io/core/veyron/services/security"
"v.io/core/veyron2/ipc"
"v.io/core/veyron2/security"
- "v.io/core/veyron2/vdl"
)
// dischargerd issues discharges for all caveats present in the current
// namespace with no additional caveats iff the caveat is valid.
type dischargerd struct{}
-func (dischargerd) Discharge(ctx ipc.ServerContext, caveat security.Caveat, _ security.DischargeImpetus) (vdl.AnyRep, error) {
+func (dischargerd) Discharge(ctx ipc.ServerContext, caveat security.Caveat, _ security.DischargeImpetus) (security.WireDischarge, error) {
tp := caveat.ThirdPartyDetails()
if tp == nil {
return nil, fmt.Errorf("Caveat %v does not represent a third party caveat", caveat)
@@ -26,7 +25,11 @@
if err != nil {
return nil, fmt.Errorf("unable to create expiration caveat on the discharge: %v", err)
}
- return ctx.LocalPrincipal().MintDischarge(caveat, expiry)
+ d, err := ctx.LocalPrincipal().MintDischarge(caveat, expiry)
+ if err != nil {
+ return nil, err
+ }
+ return security.MarshalDischarge(d), nil
}
// NewDischarger returns a discharger service implementation that grants