From 6756ce5426a892546d3252e9896422eb4d2117ec Mon Sep 17 00:00:00 2001 From: Jonas Plum Date: Sat, 22 Oct 2022 15:12:37 +0200 Subject: [PATCH] Remove user passwords (#539) * Remove user passwords Co-authored-by: Jonas Plum --- auth.go | 9 ++++---- cmd/catalyst-dev/main.go | 6 ++--- database/migrations/migrations.go | 2 -- database/user.go | 33 +++++----------------------- definition/users.yaml | 3 --- generated/catalyst.json | 9 -------- generated/catalyst.yml | 6 ----- generated/community.json | 9 -------- generated/community.yml | 6 ----- generated/model/model.go | 15 +++++-------- ui/src/client/api.ts | 18 --------------- ui/src/components/UserDataEditor.vue | 5 +++++ ui/src/views/User.vue | 7 +++--- 13 files changed, 27 insertions(+), 101 deletions(-) diff --git a/auth.go b/auth.go index 344bccb..05400e7 100644 --- a/auth.go +++ b/auth.go @@ -33,11 +33,10 @@ func (c *catalystResolver) UserCreateIfNotExists(ctx context.Context, user *maut _, err = c.database.UserCreateSetupAPIKey(ctx, password) } else { _, err = c.database.UserCreate(ctx, &model.UserForm{ - Apikey: user.APIKey, - Blocked: user.Blocked, - ID: user.ID, - Password: &password, - Roles: user.Roles, + Apikey: user.APIKey, + Blocked: user.Blocked, + ID: user.ID, + Roles: user.Roles, }) if err != nil { return err diff --git a/cmd/catalyst-dev/main.go b/cmd/catalyst-dev/main.go index 1912e37..f63ff0e 100644 --- a/cmd/catalyst-dev/main.go +++ b/cmd/catalyst-dev/main.go @@ -41,20 +41,20 @@ func main() { log.Fatal(err) } - _, _ = theCatalyst.DB.UserCreate(context.Background(), &model.UserForm{ID: "eve", Roles: []string{"admin"}, Password: pointer.String("eve")}) + _, _ = theCatalyst.DB.UserCreate(context.Background(), &model.UserForm{ID: "eve", Roles: []string{"admin"}}) _ = theCatalyst.DB.UserDataCreate(context.Background(), "eve", &model.UserData{ Name: pointer.String("Eve"), Email: pointer.String("eve@example.com"), Image: &avatarEve, }) - _, _ = theCatalyst.DB.UserCreate(context.Background(), &model.UserForm{ID: "kevin", Roles: []string{"admin"}, Password: pointer.String("kevin")}) + _, _ = theCatalyst.DB.UserCreate(context.Background(), &model.UserForm{ID: "kevin", Roles: []string{"admin"}}) _ = theCatalyst.DB.UserDataCreate(context.Background(), "kevin", &model.UserData{ Name: pointer.String("Kevin"), Email: pointer.String("kevin@example.com"), Image: &avatarKevin, }) - _, _ = theCatalyst.DB.UserCreate(context.Background(), &model.UserForm{ID: "tom", Roles: []string{"admin"}, Password: pointer.String("tom")}) + _, _ = theCatalyst.DB.UserCreate(context.Background(), &model.UserForm{ID: "tom", Roles: []string{"admin"}}) _ = theCatalyst.DB.UserDataCreate(context.Background(), "tom", &model.UserData{ Name: pointer.String("tom"), Email: pointer.String("tom@example.com"), diff --git a/database/migrations/migrations.go b/database/migrations/migrations.go index fb7ce95..fcd422e 100644 --- a/database/migrations/migrations.go +++ b/database/migrations/migrations.go @@ -61,8 +61,6 @@ func generateMigrations() ([]Migration, error) { &updateDocument[model.Settings]{ID: "update-settings-global-1", Collection: "settings", Key: "global", Document: &model.Settings{ArtifactStates: []*model.Type{{Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(model.TypeColorInfo)}, {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(model.TypeColorError)}, {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(model.TypeColorSuccess)}}, ArtifactKinds: []*model.Type{{Icon: "mdi-server", ID: "asset", Name: "Asset"}, {Icon: "mdi-bullseye", ID: "ioc", Name: "IOC"}}, Timeformat: "yyyy-MM-dd hh:mm:ss"}}, - &updateSchema{ID: "update-user-simple-login", Name: "users", DataType: "user", Schema: `{"type":"object","properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"roles":{"items":{"type":"string"},"type":"array"},"salt":{"type":"string"},"sha256":{"type":"string"},"sha512":{"type":"string"}},"required":["blocked","apikey","roles"],"$id":"#/definitions/User"}`}, - &mapRoles{ID: "simplify-roles"}, }, nil } diff --git a/database/user.go b/database/user.go index 5b7f9a7..ca83f2e 100644 --- a/database/user.go +++ b/database/user.go @@ -3,7 +3,6 @@ package database import ( "context" "crypto/sha256" - "crypto/sha512" "errors" "fmt" "log" @@ -34,13 +33,11 @@ func generateKey() string { return string(b) } -func toUser(user *model.UserForm, salt, sha256, sha512 *string) *model.User { +func toUser(user *model.UserForm, sha256 *string) *model.User { u := &model.User{ Blocked: user.Blocked, Roles: user.Roles, - Salt: salt, Sha256: sha256, - Sha512: sha512, Apikey: user.Apikey, } @@ -89,16 +86,14 @@ func (db *Database) UserGetOrCreate(ctx context.Context, newUser *model.UserForm } func (db *Database) UserCreate(ctx context.Context, newUser *model.UserForm) (*model.NewUserResponse, error) { - var key, salt, sha256Hash, sha512Hash *string + var key, sha256Hash *string if newUser.Apikey { key, sha256Hash = generateAPIKey() - } else if newUser.Password != nil { - salt, sha512Hash = hashUserPassword(newUser) } var doc model.User newctx := driver.WithReturnNew(ctx, &doc) - meta, err := db.userCollection.CreateDocument(ctx, newctx, strcase.ToKebab(newUser.ID), toUser(newUser, salt, sha256Hash, sha512Hash)) + meta, err := db.userCollection.CreateDocument(ctx, newctx, strcase.ToKebab(newUser.ID), toUser(newUser, sha256Hash)) if err != nil { return nil, err } @@ -117,7 +112,7 @@ func (db *Database) UserCreateSetupAPIKey(ctx context.Context, key string) (*mod var doc model.User newctx := driver.WithReturnNew(ctx, &doc) - meta, err := db.userCollection.CreateDocument(ctx, newctx, strcase.ToKebab(newUser.ID), toUser(newUser, nil, sha256Hash, nil)) + meta, err := db.userCollection.CreateDocument(ctx, newctx, strcase.ToKebab(newUser.ID), toUser(newUser, sha256Hash)) if err != nil { return nil, err } @@ -136,19 +131,11 @@ func (db *Database) UserUpdate(ctx context.Context, id string, user *model.UserF return nil, errors.New("cannot update an API key") } - var salt, sha512Hash *string - if user.Password != nil { - salt, sha512Hash = hashUserPassword(user) - } else { - salt = doc.Salt - sha512Hash = doc.Sha512 - } - ctx = driver.WithReturnNew(ctx, &doc) user.ID = id - meta, err := db.userCollection.ReplaceDocument(ctx, id, toUser(user, salt, nil, sha512Hash)) + meta, err := db.userCollection.ReplaceDocument(ctx, id, toUser(user, nil)) if err != nil { return nil, err } @@ -244,13 +231,3 @@ func generateAPIKey() (key, sha256Hash *string) { return &newKey, sha256Hash } - -func hashUserPassword(newUser *model.UserForm) (salt, sha512Hash *string) { - if newUser.Password != nil { - saltKey := generateKey() - salt = &saltKey - sha512Hash = pointer.String(fmt.Sprintf("%x", sha512.Sum512([]byte(saltKey+*newUser.Password)))) - } - - return salt, sha512Hash -} diff --git a/definition/users.yaml b/definition/users.yaml index 5f05d60..1f6482c 100644 --- a/definition/users.yaml +++ b/definition/users.yaml @@ -90,7 +90,6 @@ definitions: required: [ id, blocked, roles, apikey ] properties: id: { type: string } - password: { type: string } blocked: { type: boolean } apikey: { type: boolean } roles: { type: array, items: { type: string } } @@ -102,9 +101,7 @@ definitions: blocked: { type: boolean } apikey: { type: boolean } roles: { type: array, items: { type: string } } - salt: { type: string } sha256: { type: string } # for api keys - sha512: { type: string } # for users UserResponse: type: object diff --git a/generated/catalyst.json b/generated/catalyst.json index c02657d..8a58489 100644 --- a/generated/catalyst.json +++ b/generated/catalyst.json @@ -7102,14 +7102,8 @@ }, "type" : "array" }, - "salt" : { - "type" : "string" - }, "sha256" : { "type" : "string" - }, - "sha512" : { - "type" : "string" } }, "required" : [ "apikey", "blocked", "roles" ], @@ -7168,9 +7162,6 @@ "id" : { "type" : "string" }, - "password" : { - "type" : "string" - }, "roles" : { "items" : { "type" : "string" diff --git a/generated/catalyst.yml b/generated/catalyst.yml index 02ed724..df8e599 100644 --- a/generated/catalyst.yml +++ b/generated/catalyst.yml @@ -1285,12 +1285,8 @@ definitions: items: type: string type: array - salt: - type: string sha256: type: string - sha512: - type: string required: - blocked - apikey @@ -1338,8 +1334,6 @@ definitions: type: boolean id: type: string - password: - type: string roles: items: type: string diff --git a/generated/community.json b/generated/community.json index 711d88a..bef3830 100644 --- a/generated/community.json +++ b/generated/community.json @@ -6523,14 +6523,8 @@ }, "type" : "array" }, - "salt" : { - "type" : "string" - }, "sha256" : { "type" : "string" - }, - "sha512" : { - "type" : "string" } }, "required" : [ "apikey", "blocked", "roles" ], @@ -6589,9 +6583,6 @@ "id" : { "type" : "string" }, - "password" : { - "type" : "string" - }, "roles" : { "items" : { "type" : "string" diff --git a/generated/community.yml b/generated/community.yml index 1a0b321..d5ad8b5 100644 --- a/generated/community.yml +++ b/generated/community.yml @@ -1166,12 +1166,8 @@ definitions: items: type: string type: array - salt: - type: string sha256: type: string - sha512: - type: string required: - blocked - apikey @@ -1219,8 +1215,6 @@ definitions: type: boolean id: type: string - password: - type: string roles: items: type: string diff --git a/generated/model/model.go b/generated/model/model.go index 461d027..ac2643e 100755 --- a/generated/model/model.go +++ b/generated/model/model.go @@ -116,10 +116,10 @@ func init() { gojsonschema.NewStringLoader(`{"type":"object","properties":{"default_groups":{"items":{"type":"string"},"type":"array"},"default_playbooks":{"items":{"type":"string"},"type":"array"},"default_template":{"type":"string"},"icon":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name","icon","default_template","default_playbooks"],"$id":"#/definitions/TicketTypeResponse"}`), gojsonschema.NewStringLoader(`{"type":"object","properties":{"artifacts":{"items":{"$ref":"#/definitions/Artifact"},"type":"array"},"comments":{"items":{"$ref":"#/definitions/Comment"},"type":"array"},"created":{"format":"date-time","type":"string"},"details":{"type":"object"},"files":{"items":{"$ref":"#/definitions/File"},"type":"array"},"id":{"format":"int64","type":"integer"},"logs":{"items":{"$ref":"#/definitions/LogEntry"},"type":"array"},"modified":{"format":"date-time","type":"string"},"name":{"type":"string"},"owner":{"type":"string"},"playbooks":{"type":"object","additionalProperties":{"$ref":"#/definitions/PlaybookResponse"}},"read":{"items":{"type":"string"},"type":"array"},"references":{"items":{"$ref":"#/definitions/Reference"},"type":"array"},"schema":{"type":"string"},"status":{"type":"string"},"tickets":{"items":{"$ref":"#/definitions/TicketSimpleResponse"},"type":"array"},"type":{"type":"string"},"write":{"items":{"type":"string"},"type":"array"}},"required":["id","name","type","status","created","modified","schema"],"$id":"#/definitions/TicketWithTickets"}`), gojsonschema.NewStringLoader(`{"type":"object","properties":{"color":{"title":"Color","type":"string","enum":["error","info","success","warning"]},"icon":{"title":"Icon (https://materialdesignicons.com)","type":"string"},"id":{"title":"ID","type":"string"},"name":{"title":"Name","type":"string"}},"required":["id","name","icon"],"$id":"#/definitions/Type"}`), - gojsonschema.NewStringLoader(`{"type":"object","properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"roles":{"items":{"type":"string"},"type":"array"},"salt":{"type":"string"},"sha256":{"type":"string"},"sha512":{"type":"string"}},"required":["blocked","apikey","roles"],"$id":"#/definitions/User"}`), + gojsonschema.NewStringLoader(`{"type":"object","properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"roles":{"items":{"type":"string"},"type":"array"},"sha256":{"type":"string"}},"required":["blocked","apikey","roles"],"$id":"#/definitions/User"}`), gojsonschema.NewStringLoader(`{"type":"object","properties":{"email":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"timeformat":{"title":"Time Format (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)","type":"string"}},"$id":"#/definitions/UserData"}`), gojsonschema.NewStringLoader(`{"type":"object","properties":{"email":{"type":"string"},"id":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"timeformat":{"title":"Time Format (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)","type":"string"}},"required":["id"],"$id":"#/definitions/UserDataResponse"}`), - gojsonschema.NewStringLoader(`{"type":"object","properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"id":{"type":"string"},"password":{"type":"string"},"roles":{"items":{"type":"string"},"type":"array"}},"required":["id","blocked","roles","apikey"],"$id":"#/definitions/UserForm"}`), + gojsonschema.NewStringLoader(`{"type":"object","properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"id":{"type":"string"},"roles":{"items":{"type":"string"},"type":"array"}},"required":["id","blocked","roles","apikey"],"$id":"#/definitions/UserForm"}`), gojsonschema.NewStringLoader(`{"type":"object","properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"id":{"type":"string"},"roles":{"items":{"type":"string"},"type":"array"}},"required":["id","blocked","roles","apikey"],"$id":"#/definitions/UserResponse"}`), gojsonschema.NewStringLoader(`{"type":"object","properties":{"aggregation":{"type":"string"},"filter":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["bar","line","pie"]},"width":{"maximum":12,"type":"integer"}},"required":["name","type","aggregation","width"],"$id":"#/definitions/Widget"}`), ) @@ -588,9 +588,7 @@ type User struct { Apikey bool `json:"apikey"` Blocked bool `json:"blocked"` Roles []string `json:"roles"` - Salt *string `json:"salt,omitempty"` Sha256 *string `json:"sha256,omitempty"` - Sha512 *string `json:"sha512,omitempty"` } type UserData struct { @@ -609,11 +607,10 @@ type UserDataResponse struct { } type UserForm struct { - Apikey bool `json:"apikey"` - Blocked bool `json:"blocked"` - ID string `json:"id"` - Password *string `json:"password,omitempty"` - Roles []string `json:"roles"` + Apikey bool `json:"apikey"` + Blocked bool `json:"blocked"` + ID string `json:"id"` + Roles []string `json:"roles"` } type UserResponse struct { diff --git a/ui/src/client/api.ts b/ui/src/client/api.ts index 5e1b8b0..4cb23e1 100644 --- a/ui/src/client/api.ts +++ b/ui/src/client/api.ts @@ -2186,24 +2186,12 @@ export interface User { * @memberof User */ 'roles': Array; - /** - * - * @type {string} - * @memberof User - */ - 'salt'?: string; /** * * @type {string} * @memberof User */ 'sha256'?: string; - /** - * - * @type {string} - * @memberof User - */ - 'sha512'?: string; } /** * @@ -2297,12 +2285,6 @@ export interface UserForm { * @memberof UserForm */ 'id': string; - /** - * - * @type {string} - * @memberof UserForm - */ - 'password'?: string; /** * * @type {Array} diff --git a/ui/src/components/UserDataEditor.vue b/ui/src/components/UserDataEditor.vue index f37e0ca..383efbc 100644 --- a/ui/src/components/UserDataEditor.vue +++ b/ui/src/components/UserDataEditor.vue @@ -130,6 +130,11 @@ export default Vue.extend({ components: { VueCropper }, + watch: { + "userdata": function () { + this.editoruserdata = this.userdata; + }, + }, methods: { saveUserData: function() { this.$emit("save", this.editoruserdata); diff --git a/ui/src/views/User.vue b/ui/src/views/User.vue index 3296011..36a47e4 100644 --- a/ui/src/views/User.vue +++ b/ui/src/views/User.vue @@ -17,11 +17,12 @@ API Key User + Users can only be created via OIDC. - + (API Key) - +