From 9443fdbf7ac1c55d44730e42f6805df2060ffd63 Mon Sep 17 00:00:00 2001 From: J Delaney Date: Fri, 9 Oct 2015 13:00:08 -0700 Subject: [PATCH 1/4] Add dedicated API for creating users --- client/client.go | 15 ++++++++++++++ core/core.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ redoctober.go | 23 +++++++++++----------- 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/client/client.go b/client/client.go index ad19101..abb18f3 100644 --- a/client/client.go +++ b/client/client.go @@ -149,6 +149,21 @@ func (c *RemoteServer) Delegate(req core.DelegateRequest) (*core.ResponseData, e return unmarshalResponseData(respBytes) } +// CreateUser issues a create-user request to the remote server +func (c *RemoteServer) CreateUser(req core.CreateUserRequest) (*core.ResponseData, error) { + reqBytes, err := json.Marshal(req) + if err != nil { + return nil, err + } + + respBytes, err := c.doAction("create-user", reqBytes) + if err != nil { + return nil, err + } + + 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) diff --git a/core/core.go b/core/core.go index a645c22..dabf3f4 100644 --- a/core/core.go +++ b/core/core.go @@ -51,6 +51,12 @@ type DelegateRequest struct { Labels []string } +type CreateUserRequest struct { + Name string + Password string + UserType string +} + type PasswordRequest struct { Name string Password string @@ -338,6 +344,51 @@ func Delegate(jsonIn []byte) ([]byte, error) { return jsonStatusOk() } +// Create User processes a create-user request. +func CreateUser(jsonIn []byte) ([]byte, error) { + var s CreateUserRequest + var err error + + defer func() { + if err != nil { + log.Printf("core.create-user failed: user=%s %v", s.Name, err) + } else { + log.Printf("core.create-user success: user=%s", s.Name) + } + }() + + if err = json.Unmarshal(jsonIn, &s); err != nil { + return jsonStatusError(err) + } + + // If no UserType if provided use the default one + if s.UserType == "" { + s.UserType = passvault.DefaultRecordType + } + + if records.NumRecords() == 0 { + err = errors.New("Vault is not created yet") + return jsonStatusError(err) + } + + // Validate the Name and Password as valid + if err = validateName(s.Name, s.Password); err != nil { + return jsonStatusError(err) + } + + _, found := records.GetRecord(s.Name) + if found { + err = errors.New("User with that name already exists") + return jsonStatusError(err) + } + + if _, err = records.AddNewRecord(s.Name, s.Password, false, s.UserType); err != nil { + return jsonStatusError(err) + } + + return jsonStatusOk() +} + // Password processes a password change request. func Password(jsonIn []byte) ([]byte, error) { var err error diff --git a/redoctober.go b/redoctober.go index e70eb5b..f0877d0 100644 --- a/redoctober.go +++ b/redoctober.go @@ -27,17 +27,18 @@ import ( // List of URLs to register and their related functions 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, - "/re-encrypt": core.ReEncrypt, - "/decrypt": core.Decrypt, - "/owners": core.Owners, - "/modify": core.Modify, - "/export": core.Export, + "/create": core.Create, + "/summary": core.Summary, + "/purge": core.Purge, + "/delegate": core.Delegate, + "/create-user": core.CreateUser, + "/password": core.Password, + "/encrypt": core.Encrypt, + "/re-encrypt": core.ReEncrypt, + "/decrypt": core.Decrypt, + "/owners": core.Owners, + "/modify": core.Modify, + "/export": core.Export, } type userRequest struct { From 2cb02e33bc2ce6e3653a7d6c23fa665530db1577 Mon Sep 17 00:00:00 2001 From: J Delaney Date: Fri, 9 Oct 2015 13:00:33 -0700 Subject: [PATCH 2/4] Update web interface to use dedicated user creation API --- redoctober.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/redoctober.go b/redoctober.go index f0877d0..b11b3c2 100644 --- a/redoctober.go +++ b/redoctober.go @@ -382,7 +382,7 @@ var indexHtml = []byte(`

Create User

-
+
@@ -396,11 +396,12 @@ var indexHtml = []byte(`
-
- -
-
- +
+ +
From f3c8ec98e67989e28c70116721aba19c90749839 Mon Sep 17 00:00:00 2001 From: J Delaney Date: Fri, 9 Oct 2015 13:00:45 -0700 Subject: [PATCH 3/4] Add tests for dedicated user creation API --- core/core_test.go | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/core/core_test.go b/core/core_test.go index 42e0cf9..145c60f 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -215,6 +215,76 @@ func TestSummary(t *testing.T) { } } +func TestCreateUser(t *testing.T) { + createUserJson := []byte("{\"Name\":\"Bill\",\"Password\":\"Lizard\"}") + createUserECCJson := []byte("{\"Name\":\"Cat\",\"Password\":\"Cheshire\",\"UserType\":\"ECC\"}") + createVaultJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\"}") + + Init("memory") + + // Check that users cannot be created before a vault is + respJson, err := CreateUser(createUserJson) + if err != nil { + t.Fatalf("Error in creating user before vault is created, %v", err) + } + + var s ResponseData + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in creating user before vault is created, %v", err) + } + if s.Status == "ok" { + t.Fatalf("Error in creating user before vault is created, %v", s.Status) + } + + // Check that a user can be created after a vault has been created + respJson, err = Create(createVaultJson) + if err != nil { + t.Fatalf("Error in creating account, %v", err) + } + + respJson, err = CreateUser(createUserJson) + if err != nil { + t.Fatalf("Error in creating user, %v", err) + } + + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in creating user, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in creating user, %v", s.Status) + } + + // Check that user creation can't happen twice with the same name + respJson, err = CreateUser(createUserJson) + if err != nil { + t.Fatalf("Error in creating user when one exists, %v", err) + } + + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in creating user when one exists, %v", err) + } + if s.Status == "ok" { + t.Fatalf("Error in creating user when one exists, %v", s.Status) + } + + // Check that a UserType can be specified for a user + respJson, err = CreateUser(createUserECCJson) + if err != nil { + t.Fatalf("Error in creating user with ECC UserType, %v", err) + } + + err = json.Unmarshal(respJson, &s) + if err != nil { + t.Fatalf("Error in creating user with ECC UserType, %v", err) + } + if s.Status != "ok" { + t.Fatalf("Error in creating user with ECC UserType, %v", s.Status) + } +} + func TestPassword(t *testing.T) { createJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\"}") delegateJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\",\"Time\":\"2h\",\"Uses\":1}") From 51f74f29e2c18833f43c8a6f6ae9879a0c8b43eb Mon Sep 17 00:00:00 2001 From: J Delaney Date: Fri, 9 Oct 2015 13:06:32 -0700 Subject: [PATCH 4/4] Update README to include documentation on create user API --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 4a39f0d..75b413f 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ format is POSTed and JSON is returned. - `/create`: Create the first admin account. - `/delegate`: Delegate a password to Red October + - `/create-user`: Create a user - `/modify`: Modify permissions - `/encrypt`: Encrypt - `/decrypt`: Decrypt @@ -109,6 +110,16 @@ Example query: $ curl --cacert cert/server.crt https://localhost:8080/delegate \ -d '{"Name":"Dodo","Password":"Dodgson","Time":"2h34m","Uses":3}' {"Status":"ok"} + +### Create User + +Create Users creates a new user account. + +Example query: + + $ curl --cacert cert/server.crt https://localhost:8080/create-user \ + -d '{"Name":"Bill","Password":"Lizard"}' + {"Status":"ok"} ### Summary