blob: d11382eca60bd3de9c30989f98d14ffbfb8b9e87 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package caveats
import (
"fmt"
"time"
"v.io/x/ref/services/identity/internal/revocation"
"v.io/v23/security"
)
type CaveatFactory interface {
New(caveatInfo CaveatInfo) (security.Caveat, error)
}
type CaveatInfo struct {
Type string
Args []interface{}
}
type caveatFactory map[string]func(args ...interface{}) (security.Caveat, error)
func NewCaveatFactory() CaveatFactory {
return caveatFactory{
"Expiry": expiryCaveat,
"Method": methodCaveat,
"PeerBlessings": peerBlessingsCaveat,
"Revocation": revocationCaveat,
}
}
func (c caveatFactory) New(caveatInfo CaveatInfo) (security.Caveat, error) {
fact, exists := c[caveatInfo.Type]
if !exists {
return security.Caveat{}, fmt.Errorf("caveat %s does not exist in CaveatFactory", caveatInfo.Type)
}
return fact(caveatInfo.Args...)
}
func expiryCaveat(args ...interface{}) (security.Caveat, error) {
var empty security.Caveat
if len(args) != 1 {
return empty, fmt.Errorf("expiry caveat: must input exactly one time argument")
}
t, ok := args[0].(time.Time)
if !ok {
return empty, fmt.Errorf("expiry caveat: received arg of type %T, expected time.Time", args[0])
}
return security.NewExpiryCaveat(t)
}
func methodCaveat(args ...interface{}) (security.Caveat, error) {
if len(args) < 1 {
return security.Caveat{}, fmt.Errorf("method caveat requires at least one argument")
}
methods, err := interfacesToStrings(args)
if err != nil {
return security.Caveat{}, fmt.Errorf("method caveat: %v", err)
}
return security.NewMethodCaveat(methods[0], methods[1:]...)
}
func peerBlessingsCaveat(args ...interface{}) (security.Caveat, error) {
if len(args) < 1 {
return security.Caveat{}, fmt.Errorf("peer-blessings caveat requires at least one argument")
}
patterns, err := interfacesToBlessingPatterns(args)
if err != nil {
return security.Caveat{}, fmt.Errorf("peer-blessings caveat: %v", err)
}
return security.NewCaveat(security.PeerBlessingsCaveat, patterns)
}
func interfacesToStrings(args []interface{}) ([]string, error) {
var s []string
for _, arg := range args {
a, ok := arg.(string)
if !ok {
return nil, fmt.Errorf("received arg of type %T, expected string", arg)
}
s = append(s, a)
}
return s, nil
}
func interfacesToBlessingPatterns(args []interface{}) ([]security.BlessingPattern, error) {
var bps []security.BlessingPattern
for _, arg := range args {
a, ok := arg.(security.BlessingPattern)
if !ok {
return nil, fmt.Errorf("received arg of type %T, expected security.BlessingPattern", arg)
}
bps = append(bps, a)
}
return bps, nil
}
func revocationCaveat(args ...interface{}) (security.Caveat, error) {
var empty security.Caveat
if len(args) != 3 {
return empty, fmt.Errorf("revocation caveat: must input a revocation manager, publickey, and discharge location")
}
revocationManager, ok := args[0].(revocation.RevocationManager)
if !ok {
return empty, fmt.Errorf("revocation caveat: received args of type %T, expected revocation.RevocationManager", args[0])
}
publicKey, ok := args[1].(security.PublicKey)
if !ok {
return empty, fmt.Errorf("revocation caveat: received args of type %T, expected security.PublicKey", args[1])
}
dischargerLocation, ok := args[2].(string)
if !ok {
return empty, fmt.Errorf("revocation caveat: received args of type %T, expected string", args[2])
}
return revocationManager.NewCaveat(publicKey, dischargerLocation)
}