Asim Shankar | 6c247c4 | 2014-09-29 17:51:53 -0700 | [diff] [blame] | 1 | package audit |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "time" |
| 6 | |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 7 | "v.io/core/veyron2/security" |
Asim Shankar | 6c247c4 | 2014-09-29 17:51:53 -0700 | [diff] [blame] | 8 | ) |
| 9 | |
| 10 | // NewPrincipal returns a security.Principal implementation that logs |
| 11 | // all private key operations of 'wrapped' to 'auditor' (i.e., all calls to |
| 12 | // BlessSelf, Bless, MintDischarge and Sign). |
| 13 | func NewPrincipal(wrapped security.Principal, auditor Auditor) security.Principal { |
| 14 | return &auditingPrincipal{wrapped, auditor} |
| 15 | } |
| 16 | |
| 17 | type auditingPrincipal struct { |
| 18 | principal security.Principal |
| 19 | auditor Auditor |
| 20 | } |
| 21 | |
| 22 | type args []interface{} |
| 23 | |
| 24 | func (p *auditingPrincipal) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) { |
| 25 | blessings, err := p.principal.Bless(key, with, extension, caveat, additionalCaveats...) |
| 26 | if err = p.audit(err, "Bless", addCaveats(args{key, with, extension, caveat}, additionalCaveats...), blessings); err != nil { |
| 27 | return nil, err |
| 28 | } |
| 29 | return blessings, nil |
| 30 | } |
| 31 | |
| 32 | func (p *auditingPrincipal) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) { |
| 33 | blessings, err := p.principal.BlessSelf(name, caveats...) |
| 34 | if err = p.audit(err, "BlessSelf", addCaveats(args{name}, caveats...), blessings); err != nil { |
| 35 | return nil, err |
| 36 | } |
| 37 | return blessings, nil |
| 38 | } |
| 39 | |
| 40 | func (p *auditingPrincipal) Sign(message []byte) (security.Signature, error) { |
| 41 | // Do not save the signature itself. |
| 42 | sig, err := p.principal.Sign(message) |
| 43 | if err = p.audit(err, "Sign", args{message}, nil); err != nil { |
| 44 | return security.Signature{}, err |
| 45 | } |
| 46 | return sig, nil |
| 47 | } |
| 48 | |
| 49 | func (p *auditingPrincipal) MintDischarge(tp security.ThirdPartyCaveat, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Discharge, error) { |
| 50 | d, err := p.principal.MintDischarge(tp, caveat, additionalCaveats...) |
| 51 | // No need to log the discharge |
| 52 | if err = p.audit(err, "MintDischarge", addCaveats(args{tp, caveat}, additionalCaveats...), nil); err != nil { |
| 53 | return nil, err |
| 54 | } |
| 55 | return d, nil |
| 56 | } |
| 57 | |
gauthamt | f826393 | 2014-12-16 10:59:09 -0800 | [diff] [blame] | 58 | func (p *auditingPrincipal) BlessingsByName(name security.BlessingPattern) []security.Blessings { |
| 59 | return p.principal.BlessingsByName(name) |
| 60 | } |
| 61 | |
gauthamt | 8dc9a18 | 2015-01-08 18:03:18 -0800 | [diff] [blame] | 62 | func (p *auditingPrincipal) BlessingsInfo(b security.Blessings) map[string][]security.Caveat { |
gauthamt | f826393 | 2014-12-16 10:59:09 -0800 | [diff] [blame] | 63 | return p.principal.BlessingsInfo(b) |
| 64 | } |
| 65 | |
Asim Shankar | 6c247c4 | 2014-09-29 17:51:53 -0700 | [diff] [blame] | 66 | func (p *auditingPrincipal) PublicKey() security.PublicKey { return p.principal.PublicKey() } |
| 67 | func (p *auditingPrincipal) Roots() security.BlessingRoots { return p.principal.Roots() } |
| 68 | func (p *auditingPrincipal) BlessingStore() security.BlessingStore { return p.principal.BlessingStore() } |
| 69 | func (p *auditingPrincipal) AddToRoots(b security.Blessings) error { return p.principal.AddToRoots(b) } |
| 70 | |
| 71 | func (p *auditingPrincipal) audit(err error, method string, args args, result interface{}) error { |
| 72 | if err != nil { |
| 73 | return err |
| 74 | } |
| 75 | entry := Entry{Method: method, Timestamp: time.Now()} |
| 76 | if len(args) > 0 { |
| 77 | entry.Arguments = []interface{}(args) |
| 78 | } |
| 79 | if result != nil { |
| 80 | entry.Results = []interface{}{result} |
| 81 | } |
| 82 | if err := p.auditor.Audit(entry); err != nil { |
| 83 | return fmt.Errorf("failed to audit call to %q: %v", method, err) |
| 84 | } |
| 85 | return nil |
| 86 | } |
| 87 | |
| 88 | func addCaveats(args args, caveats ...security.Caveat) args { |
| 89 | for _, c := range caveats { |
Suharsh Sivakumar | 305626a | 2014-11-10 09:50:24 -0800 | [diff] [blame] | 90 | // TODO(ashankar,suharshs): Should isUnconstrainedCaveat in veyron2/security be exported and used here? |
| 91 | if len(c.ValidatorVOM) > 0 { |
| 92 | args = append(args, c) |
| 93 | } |
Asim Shankar | 6c247c4 | 2014-09-29 17:51:53 -0700 | [diff] [blame] | 94 | } |
| 95 | return args |
| 96 | } |