blob: 3cee53a1eecf6e7e78b51989e1def0386f9ca8f9 [file] [log] [blame]
package blesser
import (
"bytes"
"fmt"
"time"
"veyron.io/veyron/veyron/services/identity"
"veyron.io/veyron/veyron/services/identity/util"
"veyron.io/veyron/veyron2"
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/vdl/vdlutil"
"veyron.io/veyron/veyron2/vom"
)
type macaroonBlesser struct {
rt veyron2.Runtime
key []byte
}
// BlessingMacaroon contains the data that is encoded into the macaroon for creating blessings.
type BlessingMacaroon struct {
Creation time.Time
Caveats []security.Caveat
Name string
}
// NewMacaroonBlesserServer provides an identity.MacaroonBlesser Service that uses an
// bless macaroon.
//
// Blessings generated by this server expire after duration. If domain is non-empty, then blessings
// are generated only for email addresses from that domain.
func NewMacaroonBlesserServer(r veyron2.Runtime, key []byte) interface{} {
return identity.NewServerMacaroonBlesser(&macaroonBlesser{
rt: r,
key: key,
})
}
func (b *macaroonBlesser) Bless(ctx ipc.ServerContext, macaroon string) (vdlutil.Any, error) {
inputs, err := util.Macaroon(macaroon).Decode(b.key)
if err != nil {
return nil, err
}
m := BlessingMacaroon{}
if err := vom.NewDecoder(bytes.NewBuffer(inputs)).Decode(&m); err != nil {
return nil, err
}
if time.Now().After(m.Creation.Add(time.Minute * 5)) {
return nil, fmt.Errorf("bless failed: macaroon has expired")
}
return b.bless(ctx, m.Name, m.Caveats)
}
func (b *macaroonBlesser) bless(ctx ipc.ServerContext, name string, caveats []security.Caveat) (vdlutil.Any, error) {
self := b.rt.Identity()
var err error
// Use the blessing that was used to authenticate with the client to bless it.
if self, err = self.Derive(ctx.LocalID()); err != nil {
return nil, err
}
return self.Bless(ctx.RemoteID(), name, time.Hour*24*365, caveats)
}