blob: b7f9347c2f07e715562279bbdefac76fe2524ecc [file] [log] [blame]
Asim Shankar6c247c42014-09-29 17:51:53 -07001package audit
2
3import (
4 "fmt"
5 "time"
6
Jiri Simsa764efb72014-12-25 20:57:03 -08007 "v.io/core/veyron2/security"
Asim Shankar6c247c42014-09-29 17:51:53 -07008)
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).
13func NewPrincipal(wrapped security.Principal, auditor Auditor) security.Principal {
14 return &auditingPrincipal{wrapped, auditor}
15}
16
17type auditingPrincipal struct {
18 principal security.Principal
19 auditor Auditor
20}
21
22type args []interface{}
23
24func (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
32func (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
40func (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
49func (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
gauthamtf8263932014-12-16 10:59:09 -080058func (p *auditingPrincipal) BlessingsByName(name security.BlessingPattern) []security.Blessings {
59 return p.principal.BlessingsByName(name)
60}
61
gauthamt8dc9a182015-01-08 18:03:18 -080062func (p *auditingPrincipal) BlessingsInfo(b security.Blessings) map[string][]security.Caveat {
gauthamtf8263932014-12-16 10:59:09 -080063 return p.principal.BlessingsInfo(b)
64}
65
Asim Shankar6c247c42014-09-29 17:51:53 -070066func (p *auditingPrincipal) PublicKey() security.PublicKey { return p.principal.PublicKey() }
67func (p *auditingPrincipal) Roots() security.BlessingRoots { return p.principal.Roots() }
68func (p *auditingPrincipal) BlessingStore() security.BlessingStore { return p.principal.BlessingStore() }
69func (p *auditingPrincipal) AddToRoots(b security.Blessings) error { return p.principal.AddToRoots(b) }
70
71func (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
88func addCaveats(args args, caveats ...security.Caveat) args {
89 for _, c := range caveats {
Suharsh Sivakumar305626a2014-11-10 09:50:24 -080090 // 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 Shankar6c247c42014-09-29 17:51:53 -070094 }
95 return args
96}