Merge "veyron/security/audit: Implementation of an "auditing" Principal that logs all private key operations."
diff --git a/security/audit/id.go b/security/audit/id.go
index 0c0cdc4..b251ecc 100644
--- a/security/audit/id.go
+++ b/security/audit/id.go
@@ -12,8 +12,6 @@
 	auditor Auditor
 }
 
-type args []interface{}
-
 // NewPrivateID returns a security.PrivateID implementation that wraps over 'wrapped' but
 // logs all operations that use the private key of wrapped to the auditor.
 func NewPrivateID(wrapped security.PrivateID, auditor Auditor) security.PrivateID {
diff --git a/security/audit/id_test.go b/security/audit/id_test.go
index 8d01746..e655b01 100644
--- a/security/audit/id_test.go
+++ b/security/audit/id_test.go
@@ -99,7 +99,7 @@
 		if want := (audit.Entry{
 			Method:    test.Method,
 			Arguments: []interface{}(test.Args),
-			Results:   sliceOrNil(test.AuditedResult),
+			Results:   sliceOrNil(true, test.AuditedResult),
 			Timestamp: audited.Timestamp, // Hard to come up with the expected timestamp, relying on sanity check above.
 		}); !reflect.DeepEqual(audited, want) {
 			t.Errorf("id.%v(%#v) resulted in [%#v] being audited, wanted [%#v]", test.Method, test.Args, audited, want)
@@ -107,14 +107,7 @@
 	}
 }
 
-func sliceOrNil(item interface{}) []interface{} {
-	if item == nil {
-		return nil
-	}
-	return []interface{}{item}
-}
-
-func TestUnauditedMethods(t *testing.T) {
+func TestUnauditedMethodsOnPrivateID(t *testing.T) {
 	var (
 		mockID      = new(mockID)
 		mockAuditor = new(mockAuditor)
@@ -213,29 +206,6 @@
 
 func (id *mockID) PublicKey() security.PublicKey { return id.NextResult.(security.PublicKey) }
 
-type mockAuditor struct {
-	LastEntry audit.Entry
-	NextError error
-}
-
-func (a *mockAuditor) Audit(entry audit.Entry) error {
-	if a.NextError != nil {
-		err := a.NextError
-		a.NextError = nil
-		return err
-	}
-	a.LastEntry = entry
-	return nil
-}
-
-func (a *mockAuditor) Release() audit.Entry {
-	entry := a.LastEntry
-	a.LastEntry = audit.Entry{}
-	return entry
-}
-
-type V []interface{}
-
 // thirdPartyCaveat implements security.ThirdPartyCaveat
 type thirdPartyCaveat struct{}
 
@@ -247,6 +217,12 @@
 }
 func (thirdPartyCaveat) Dischargeable(security.Context) error { return nil }
 
+// discharge implements the security.Discharge interface
+type discharge struct{}
+
+func (*discharge) ID() string                                     { return "thirdPartyCaveatID" }
+func (*discharge) ThirdPartyCaveats() []security.ThirdPartyCaveat { return nil }
+
 // context implements security.Context
 type context struct{}
 
@@ -255,32 +231,10 @@
 func (context) Suffix() string                            { return "suffix" }
 func (context) Label() security.Label                     { return security.ReadLabel }
 func (context) Discharges() map[string]security.Discharge { return nil }
-func (context) LocalID() security.PublicID                { return nil }
-func (context) RemoteID() security.PublicID               { return nil }
 func (context) LocalPrincipal() security.Principal        { return nil }
 func (context) LocalBlessings() security.Blessings        { return nil }
 func (context) RemoteBlessings() security.Blessings       { return nil }
+func (context) LocalID() security.PublicID                { return nil }
+func (context) RemoteID() security.PublicID               { return nil }
 func (context) LocalEndpoint() naming.Endpoint            { return nil }
 func (context) RemoteEndpoint() naming.Endpoint           { return nil }
-
-// discharge implements the security.Discharge interface
-type discharge struct{}
-
-func (*discharge) ID() string                                     { return "thirdPartyCaveatID" }
-func (*discharge) ThirdPartyCaveats() []security.ThirdPartyCaveat { return nil }
-
-func call(receiver interface{}, method string, args V) (results []interface{}, err interface{}) {
-	defer func() {
-		err = recover()
-	}()
-	callargs := make([]reflect.Value, len(args))
-	for idx, arg := range args {
-		callargs[idx] = reflect.ValueOf(arg)
-	}
-	callresults := reflect.ValueOf(receiver).MethodByName(method).Call(callargs)
-	results = make([]interface{}, len(callresults))
-	for idx, res := range callresults {
-		results[idx] = res.Interface()
-	}
-	return
-}
diff --git a/security/audit/principal.go b/security/audit/principal.go
new file mode 100644
index 0000000..c7c2e50
--- /dev/null
+++ b/security/audit/principal.go
@@ -0,0 +1,85 @@
+package audit
+
+import (
+	"fmt"
+	"time"
+
+	"veyron.io/veyron/veyron2/security"
+)
+
+// NewPrincipal returns a security.Principal implementation that logs
+// all private key operations of 'wrapped' to 'auditor' (i.e., all calls to
+// BlessSelf, Bless, MintDischarge and Sign).
+func NewPrincipal(wrapped security.Principal, auditor Auditor) security.Principal {
+	return &auditingPrincipal{wrapped, auditor}
+}
+
+type auditingPrincipal struct {
+	principal security.Principal
+	auditor   Auditor
+}
+
+type args []interface{}
+
+func (p *auditingPrincipal) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) {
+	blessings, err := p.principal.Bless(key, with, extension, caveat, additionalCaveats...)
+	if err = p.audit(err, "Bless", addCaveats(args{key, with, extension, caveat}, additionalCaveats...), blessings); err != nil {
+		return nil, err
+	}
+	return blessings, nil
+}
+
+func (p *auditingPrincipal) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) {
+	blessings, err := p.principal.BlessSelf(name, caveats...)
+	if err = p.audit(err, "BlessSelf", addCaveats(args{name}, caveats...), blessings); err != nil {
+		return nil, err
+	}
+	return blessings, nil
+}
+
+func (p *auditingPrincipal) Sign(message []byte) (security.Signature, error) {
+	// Do not save the signature itself.
+	sig, err := p.principal.Sign(message)
+	if err = p.audit(err, "Sign", args{message}, nil); err != nil {
+		return security.Signature{}, err
+	}
+	return sig, nil
+}
+
+func (p *auditingPrincipal) MintDischarge(tp security.ThirdPartyCaveat, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Discharge, error) {
+	d, err := p.principal.MintDischarge(tp, caveat, additionalCaveats...)
+	// No need to log the discharge
+	if err = p.audit(err, "MintDischarge", addCaveats(args{tp, caveat}, additionalCaveats...), nil); err != nil {
+		return nil, err
+	}
+	return d, nil
+}
+
+func (p *auditingPrincipal) PublicKey() security.PublicKey         { return p.principal.PublicKey() }
+func (p *auditingPrincipal) Roots() security.BlessingRoots         { return p.principal.Roots() }
+func (p *auditingPrincipal) BlessingStore() security.BlessingStore { return p.principal.BlessingStore() }
+func (p *auditingPrincipal) AddToRoots(b security.Blessings) error { return p.principal.AddToRoots(b) }
+
+func (p *auditingPrincipal) audit(err error, method string, args args, result interface{}) error {
+	if err != nil {
+		return err
+	}
+	entry := Entry{Method: method, Timestamp: time.Now()}
+	if len(args) > 0 {
+		entry.Arguments = []interface{}(args)
+	}
+	if result != nil {
+		entry.Results = []interface{}{result}
+	}
+	if err := p.auditor.Audit(entry); err != nil {
+		return fmt.Errorf("failed to audit call to %q: %v", method, err)
+	}
+	return nil
+}
+
+func addCaveats(args args, caveats ...security.Caveat) args {
+	for _, c := range caveats {
+		args = append(args, c)
+	}
+	return args
+}
diff --git a/security/audit/principal_test.go b/security/audit/principal_test.go
new file mode 100644
index 0000000..ba3d356
--- /dev/null
+++ b/security/audit/principal_test.go
@@ -0,0 +1,272 @@
+package audit_test
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"errors"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+
+	"veyron.io/veyron/veyron/security/audit"
+	"veyron.io/veyron/veyron2/security"
+)
+
+func TestAuditingPrincipal(t *testing.T) {
+	var (
+		thirdPartyCaveat, discharge = newThirdPartyCaveatAndDischarge(t)
+		wantErr                     = errors.New("call failed") // The error returned by call calls to mockID operations
+
+		mockP   = new(mockPrincipal)
+		auditor = new(mockAuditor)
+		p       = audit.NewPrincipal(mockP, auditor)
+	)
+	tests := []struct {
+		Method      string
+		Args        V
+		Result      interface{} // Result returned by the Method call.
+		AuditResult bool        // If true, Result should appear in the audit log. If false, it should not.
+	}{
+		{"BlessSelf", V{"self"}, newBlessing(t, "blessing"), true},
+		{"Bless", V{newPrincipal(t).PublicKey(), newBlessing(t, "root"), "extension", security.UnconstrainedUse()}, newBlessing(t, "root/extension"), true},
+		{"MintDischarge", V{thirdPartyCaveat, security.UnconstrainedUse()}, discharge, false},
+		{"Sign", V{make([]byte, 10)}, security.Signature{R: []byte{1}, S: []byte{1}}, false},
+	}
+	for _, test := range tests {
+		// Test1: If the underlying operation fails, the error should be returned and nothing should be audited.
+		mockP.NextError = wantErr
+		results, err := call(p, test.Method, test.Args)
+		if err != nil {
+			t.Errorf("failed to invoke p.%v(%#v): %v", test.Method, test.Args, err)
+			continue
+		}
+		if got, ok := results[len(results)-1].(error); !ok || got != wantErr {
+			t.Errorf("p.%v(%#v) returned (..., %v), want (..., %v)", test.Method, test.Args, got, wantErr)
+		}
+		if audited := auditor.Release(); !reflect.DeepEqual(audited, audit.Entry{}) {
+			t.Errorf("p.%v(%#v) resulted in [%+v] being written to the audit log, nothing should have been", test.Method, test.Args, audited)
+		}
+
+		// Test2: If the auditor fails, then the operation should fail too.
+		auditor.NextError = errors.New("auditor failed")
+		results, err = call(p, test.Method, test.Args)
+		if err != nil {
+			t.Errorf("failed to invoke p.%v(%#v): %v", test.Method, test.Args, err)
+			continue
+		}
+		if got, ok := results[len(results)-1].(error); !ok || !strings.HasSuffix(got.Error(), "auditor failed") {
+			t.Errorf("p.%v(%#v) returned %v when auditor failed, wanted (..., %v)", test.Method, test.Args, results, "... auditor failed")
+		}
+
+		// Test3: If the underlying operation succeeds, should return the same value and write to the audit log.
+		now := time.Now()
+		mockP.NextResult = test.Result
+		results, err = call(p, test.Method, test.Args)
+		audited := auditor.Release()
+		if err != nil {
+			t.Errorf("failed to invoke p.%v(%#v): %v", test.Method, test.Args, err)
+			continue
+		}
+		if got := results[len(results)-1]; got != nil {
+			t.Errorf("p.%v(%#v) returned an error: %v", test.Method, test.Args, got)
+		}
+		if got := results[0]; !reflect.DeepEqual(got, test.Result) {
+			t.Errorf("p.%v(%#v) returned %v(%T) want %v(%T)", test.Method, test.Args, got, got, test.Result, test.Result)
+		}
+		if audited.Timestamp.Before(now) || audited.Timestamp.IsZero() {
+			t.Errorf("p.%v(%#v) audited the time as %v, should have been a time after %v", test.Method, test.Args, audited.Timestamp, now)
+		}
+		if want := (audit.Entry{
+			Method:    test.Method,
+			Arguments: []interface{}(test.Args),
+			Results:   sliceOrNil(test.AuditResult, test.Result),
+			Timestamp: audited.Timestamp, // Hard to come up with the expected timestamp, relying on sanity check above.
+		}); !reflect.DeepEqual(audited, want) {
+			t.Errorf("p.%v(%#v) resulted in [%#v] being audited, wanted [%#v]", test.Method, test.Args, audited, want)
+		}
+	}
+}
+
+func TestUnauditedMethodsOnPrincipal(t *testing.T) {
+	var (
+		auditor  = new(mockAuditor)
+		p        = newPrincipal(t)
+		auditedP = audit.NewPrincipal(p, auditor)
+	)
+	blessing, err := p.BlessSelf("self")
+	if err != nil {
+		t.Fatal(err)
+	}
+	tests := []struct {
+		Method string
+		Args   V
+	}{
+		{"PublicKey", V{}},
+		{"Roots", V{}},
+		{"AddToRoots", V{blessing}},
+		{"BlessingStore", V{}},
+	}
+
+	for _, test := range tests {
+		want, err := call(p, test.Method, test.Args)
+		if err != nil {
+			t.Fatalf("%v: %v", test.Method, err)
+		}
+		got, err := call(auditedP, test.Method, test.Args)
+		if err != nil {
+			t.Fatalf("%v: %v", test.Method, err)
+		}
+		if !reflect.DeepEqual(got, want) {
+			t.Errorf("Got %v, want %v", got, want)
+		}
+		if gotEntry := auditor.Release(); !reflect.DeepEqual(gotEntry, audit.Entry{}) {
+			t.Errorf("Unexpected entry in audit log: %v", gotEntry)
+		}
+	}
+}
+
+type mockPrincipal struct {
+	NextResult interface{}
+	NextError  error
+}
+
+func (p *mockPrincipal) reset() {
+	p.NextError = nil
+	p.NextResult = nil
+}
+
+func (p *mockPrincipal) Bless(security.PublicKey, security.Blessings, string, security.Caveat, ...security.Caveat) (security.Blessings, error) {
+	defer p.reset()
+	b, _ := p.NextResult.(security.Blessings)
+	return b, p.NextError
+}
+
+func (p *mockPrincipal) BlessSelf(string, ...security.Caveat) (security.Blessings, error) {
+	defer p.reset()
+	b, _ := p.NextResult.(security.Blessings)
+	return b, p.NextError
+}
+
+func (p *mockPrincipal) Sign([]byte) (sig security.Signature, err error) {
+	defer p.reset()
+	sig, _ = p.NextResult.(security.Signature)
+	err = p.NextError
+	return
+}
+
+func (p *mockPrincipal) MintDischarge(security.ThirdPartyCaveat, security.Caveat, ...security.Caveat) (security.Discharge, error) {
+	defer p.reset()
+	d, _ := p.NextResult.(security.Discharge)
+	return d, p.NextError
+}
+
+func (p *mockPrincipal) PublicKey() security.PublicKey         { return p.NextResult.(security.PublicKey) }
+func (p *mockPrincipal) Roots() security.BlessingRoots         { return nil }
+func (p *mockPrincipal) BlessingStore() security.BlessingStore { return nil }
+func (p *mockPrincipal) AddToRoots(b security.Blessings) error { return nil }
+
+type mockAuditor struct {
+	LastEntry audit.Entry
+	NextError error
+}
+
+func (a *mockAuditor) Audit(entry audit.Entry) error {
+	if a.NextError != nil {
+		err := a.NextError
+		a.NextError = nil
+		return err
+	}
+	a.LastEntry = entry
+	return nil
+}
+
+func (a *mockAuditor) Release() audit.Entry {
+	entry := a.LastEntry
+	a.LastEntry = audit.Entry{}
+	return entry
+}
+
+type V []interface{}
+
+func call(receiver interface{}, method string, args V) (results []interface{}, err interface{}) {
+	defer func() {
+		err = recover()
+	}()
+	callargs := make([]reflect.Value, len(args))
+	for idx, arg := range args {
+		callargs[idx] = reflect.ValueOf(arg)
+	}
+	callresults := reflect.ValueOf(receiver).MethodByName(method).Call(callargs)
+	results = make([]interface{}, len(callresults))
+	for idx, res := range callresults {
+		results[idx] = res.Interface()
+	}
+	return
+}
+
+func sliceOrNil(include bool, item interface{}) []interface{} {
+	if item != nil && include {
+		return []interface{}{item}
+	}
+	return nil
+}
+
+func newPrincipal(t *testing.T) security.Principal {
+	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		t.Fatal(err)
+	}
+	signer := security.NewInMemoryECDSASigner(key)
+	p, err := security.CreatePrincipal(signer, &store{signer.PublicKey()}, &roots{})
+	if err != nil {
+		t.Fatal(err)
+	}
+	return p
+}
+
+func newCaveat(c security.Caveat, err error) security.Caveat {
+	if err != nil {
+		panic(err)
+	}
+	return c
+}
+
+func newBlessing(t *testing.T, name string) security.Blessings {
+	b, err := newPrincipal(t).BlessSelf(name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return b
+}
+
+func newThirdPartyCaveatAndDischarge(t *testing.T) (security.ThirdPartyCaveat, security.Discharge) {
+	p := newPrincipal(t)
+	c, err := security.NewPublicKeyCaveat(p.PublicKey(), "location", security.ThirdPartyRequirements{}, newCaveat(security.MethodCaveat("method")))
+	if err != nil {
+		t.Fatal(err)
+	}
+	d, err := p.MintDischarge(c, security.UnconstrainedUse())
+	if err != nil {
+		t.Fatal(err)
+	}
+	return c, d
+}
+
+// TODO(ashankar,ataly): Consider moving these implementations to veyron2/security/test so that various
+// test libraries do not need to implement this.
+type store struct {
+	key security.PublicKey
+}
+
+func (*store) Add(blessings security.Blessings, forPeers security.BlessingPattern) error { return nil }
+func (*store) ForPeer(peerBlesssings ...string) security.Blessings                       { return nil }
+func (*store) SetDefault(blessings security.Blessings) error                             { return nil }
+func (*store) Default() security.Blessings                                               { return nil }
+func (s *store) PublicKey() security.PublicKey                                           { return s.key }
+
+type roots struct{}
+
+func (*roots) Add(security.PublicKey, security.BlessingPattern) error { return nil }
+func (*roots) Recognized(security.PublicKey, string) error            { return nil }