From 6e4957554cf7370f58a94a60cf83a624d4526deb Mon Sep 17 00:00:00 2001 From: Giulio Iotti Date: Wed, 15 Jul 2015 10:26:54 +0000 Subject: [PATCH 1/2] Implement purge action to remove all delegates, closes #48 --- README.md | 9 +++++++++ client/client.go | 15 ++++++++++++++ core/core.go | 31 +++++++++++++++++++++++++++++ core/core_test.go | 45 +++++++++++++++++++++++++++++++++++++++++- passvault/passvault.go | 10 ++++++++++ redoctober.go | 1 + 6 files changed, 110 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e38af1f..2fd7c51 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,15 @@ Example input JSON format: -d '{"Name":"Alice","Password":"Lewis","ToModify":"Bill","Command":"admin"}' {"Status":"ok"} +### Purge + +Purge deletes all delegates for an encryption key. + +Example input JSON format: + + $ curl --cacert cert/server.crt https://localhost:8080/purge \ + -d '{"Name":"Alice","Password":"Lewis"}' + {"Status":"ok"} ### Web interface diff --git a/client/client.go b/client/client.go index 22609ae..2b843bc 100644 --- a/client/client.go +++ b/client/client.go @@ -144,6 +144,21 @@ func (c *RemoteServer) Delegate(req core.DelegateRequest) (*core.ResponseData, e return unmarshalResponseData(respBytes) } +// Purge issues a purge request to the remote server +func (c *RemoteServer) Purge(req core.DelegateRequest) (*core.ResponseData, error) { + reqBytes, err := json.Marshal(req) + if err != nil { + return nil, err + } + + respBytes, err := c.doAction("purge", reqBytes) + if err != nil { + return nil, err + } + + return unmarshalResponseData(respBytes) +} + // Modify issues a modify request to the remote server func (c *RemoteServer) Modify(req core.ModifyRequest) (*core.ResponseData, error) { reqBytes, err := json.Marshal(req) diff --git a/core/core.go b/core/core.go index 4d91719..cac0634 100644 --- a/core/core.go +++ b/core/core.go @@ -36,6 +36,11 @@ type SummaryRequest struct { Password string } +type PurgeRequest struct { + Name string + Password string +} + type DelegateRequest struct { Name string Password string @@ -251,6 +256,32 @@ func Summary(jsonIn []byte) ([]byte, error) { return jsonSummary() } +// Purge processes a delegation purge request. +func Purge(jsonIn []byte) ([]byte, error) { + var s PurgeRequest + if err := json.Unmarshal(jsonIn, &s); err != nil { + return jsonStatusError(err) + } + + if records.NumRecords() == 0 { + return jsonStatusError(errors.New("Vault is not created yet")) + } + + // Validate the Name and Password as valid and admin + if err := validateUser(s.Name, s.Password, true); err != nil { + log.Printf("failed to validate %s as admin for purge request: %s", s.Name, err) + return jsonStatusError(err) + } + + if err := records.DeleteNonAdmin(); err != nil { + log.Printf("failed to purge non-admin delegates: %s", err) + return jsonStatusError(err) + } + + cache.FlushCache() + return jsonStatusOk() +} + // Delegate processes a delegation request. func Delegate(jsonIn []byte) ([]byte, error) { var s DelegateRequest diff --git a/core/core_test.go b/core/core_test.go index fb5f7ec..9522305 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -7,8 +7,8 @@ package core import ( "bytes" "encoding/json" - "reflect" "os" + "reflect" "sort" "testing" @@ -161,6 +161,49 @@ func TestSummary(t *testing.T) { if dataLive.Type != passvault.DefaultRecordType { t.Fatalf("Error in summary of account, record missing") } + + var s1 SummaryData + + // check for summary of initialized vault without non-admin members after purge + respJson, err = Purge(createJson) + if err != nil { + t.Fatalf("Error in purging, %v", err) + } + err = json.Unmarshal(respJson, &s1) + if err != nil { + t.Fatalf("Error in purging, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in purging, %v", s.Status) + } + + respJson, err = Summary(createJson) + if err != nil { + t.Fatalf("Error in summary of account with no vault, %v", err) + } + err = json.Unmarshal(respJson, &s1) + if err != nil { + t.Fatalf("Error in summary of account with no vault, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in summary of account with no vault, %v", s.Status) + } + + data, ok = s1.All["Alice"] + if !ok { + t.Fatalf("Error in summary of account, record missing") + } + if data.Admin != true { + t.Fatalf("Error in summary of account, record missing") + } + if data.Type != passvault.DefaultRecordType { + t.Fatalf("Error in summary of account, record missing") + } + + _, ok = s1.All["Bob"] + if ok { + t.Fatalf("Error in summary of account, record not purged") + } } func TestPassword(t *testing.T) { diff --git a/passvault/passvault.go b/passvault/passvault.go index 9990e9e..f71c545 100644 --- a/passvault/passvault.go +++ b/passvault/passvault.go @@ -434,6 +434,16 @@ func (records *Records) DeleteRecord(name string) error { return errors.New("Record missing") } +// DeleteNonAdmin removes all record without admin status. +func (records *Records) DeleteNonAdmin() error { + for name, pr := range records.Passwords { + if !pr.IsAdmin() { + delete(records.Passwords, name) + } + } + return records.WriteRecordsToDisk() +} + // RevokeRecord removes admin status from a record. func (records *Records) RevokeRecord(name string) error { if rec, ok := records.GetRecord(name); ok { diff --git a/redoctober.go b/redoctober.go index defb717..d2b9d3a 100644 --- a/redoctober.go +++ b/redoctober.go @@ -29,6 +29,7 @@ import ( var functions = map[string]func([]byte) ([]byte, error){ "/create": core.Create, "/summary": core.Summary, + "/purge": core.Purge, "/delegate": core.Delegate, "/password": core.Password, "/encrypt": core.Encrypt, From 209df8d9a66450b98c1808eb5ad5a2879b1ef27f Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Mon, 20 Jul 2015 23:47:47 -0700 Subject: [PATCH 2/2] Add purge command to clear delegations. Closes #48. --- core/core.go | 23 ++++++++++++++--------- core/core_test.go | 13 +++++++++++-- passvault/passvault.go | 10 ---------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/core/core.go b/core/core.go index cac0634..2a5ab3c 100644 --- a/core/core.go +++ b/core/core.go @@ -259,22 +259,27 @@ func Summary(jsonIn []byte) ([]byte, error) { // Purge processes a delegation purge request. func Purge(jsonIn []byte) ([]byte, error) { var s PurgeRequest - if err := json.Unmarshal(jsonIn, &s); err != nil { + var err error + + defer func() { + if err != nil { + log.Printf("core.purge failed: user=%s %v", s.Name, err) + } else { + log.Printf("core.purge success: user=%s", s.Name) + } + }() + + if err = json.Unmarshal(jsonIn, &s); err != nil { return jsonStatusError(err) } if records.NumRecords() == 0 { - return jsonStatusError(errors.New("Vault is not created yet")) - } - - // Validate the Name and Password as valid and admin - if err := validateUser(s.Name, s.Password, true); err != nil { - log.Printf("failed to validate %s as admin for purge request: %s", s.Name, err) + err = errors.New("vault has not been created") return jsonStatusError(err) } - if err := records.DeleteNonAdmin(); err != nil { - log.Printf("failed to purge non-admin delegates: %s", err) + // Validate the Name and Password as valid and admin + if err = validateUser(s.Name, s.Password, true); err != nil { return jsonStatusError(err) } diff --git a/core/core_test.go b/core/core_test.go index 9522305..e665d18 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -163,6 +163,10 @@ func TestSummary(t *testing.T) { } var s1 SummaryData + delegations := cache.GetSummary() + if len(delegations) == 0 { + t.Fatal("no delegations active") + } // check for summary of initialized vault without non-admin members after purge respJson, err = Purge(createJson) @@ -201,8 +205,13 @@ func TestSummary(t *testing.T) { } _, ok = s1.All["Bob"] - if ok { - t.Fatalf("Error in summary of account, record not purged") + if !ok { + t.Fatal("Bob was removed from the list of users") + } + + delegations = cache.GetSummary() + if len(delegations) != 0 { + t.Fatalf("purge failed to clear delegations (%d delegations remain)", len(delegations)) } } diff --git a/passvault/passvault.go b/passvault/passvault.go index f71c545..9990e9e 100644 --- a/passvault/passvault.go +++ b/passvault/passvault.go @@ -434,16 +434,6 @@ func (records *Records) DeleteRecord(name string) error { return errors.New("Record missing") } -// DeleteNonAdmin removes all record without admin status. -func (records *Records) DeleteNonAdmin() error { - for name, pr := range records.Passwords { - if !pr.IsAdmin() { - delete(records.Passwords, name) - } - } - return records.WriteRecordsToDisk() -} - // RevokeRecord removes admin status from a record. func (records *Records) RevokeRecord(name string) error { if rec, ok := records.GetRecord(name); ok {