veyron/security/audit: Implementation of an "auditing" Principal that
logs all private key operations.

This is part of the new security model, where Principal replaces
the old PrivateID. Ultimately, auditingID will go away and
only this auditingPrincipal will be left behind (in use by
the identity HTTP server and "agent" process implementations).

Change-Id: I75e638e859d03feb3a1f4d6e2478e60b9b7d462c
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 }