From fbd0326e2e73b165e22f62451399dd370fe471c4 Mon Sep 17 00:00:00 2001 From: Lukasz Janyst Date: Fri, 13 May 2022 11:52:23 +0200 Subject: [PATCH] users: Implement the key slot management API Issue #13 --- pkg/users/credentials/store.go | 99 +++++++++++++++++++++++++++++++--- pkg/users/types.go | 3 ++ pkg/users/user.go | 21 ++++++++ 3 files changed, 116 insertions(+), 7 deletions(-) diff --git a/pkg/users/credentials/store.go b/pkg/users/credentials/store.go index 62c9af0..0f5e2e8 100644 --- a/pkg/users/credentials/store.go +++ b/pkg/users/credentials/store.go @@ -18,6 +18,7 @@ package credentials import ( + "encoding/base64" "encoding/json" "errors" "os" @@ -28,13 +29,14 @@ import ( ) var ( - ErrNotFound = errors.New("Credentials not found") - ErrLocked = errors.New("Credentials are locked") - ErrDecryptionFailed = errors.New("Decryption of credentials failed") - ErrEncryptionFailed = errors.New("Encryption of credentials failed") - ErrUnauthorized = errors.New("Bridge credentials checking failed") - ErrAlreadyExists = errors.New("Credential already exists") - log = logrus.WithField("pkg", "credentials") + ErrNotFound = errors.New("Credentials not found") + ErrLocked = errors.New("Credentials are locked") + ErrDecryptionFailed = errors.New("Decryption of credentials failed") + ErrEncryptionFailed = errors.New("Encryption of credentials failed") + ErrUnauthorized = errors.New("Bridge credentials checking failed") + ErrAlreadyExists = errors.New("Credential already exists") + ErrCantRemoveMainSlot = errors.New("Cannot remove the main key slot") + log = logrus.WithField("pkg", "credentials") ) // Store is an encrypted credentials store. @@ -162,6 +164,89 @@ func (s *Store) UpdateToken(userID, uid, ref string) (*Credentials, error) { return credentials, s.saveCredentials() } +func (s *Store) ListKeySlots(userID string) ([]string, error) { + s.lock.Lock() + defer s.lock.Unlock() + + credentials, ok := s.creds[userID] + if !ok { + return nil, ErrNotFound + } + + slots := []string{} + for k := range credentials.SealedKeys { + if k != "main" { + slots = append(slots, k) + } + } + + sort.Strings(slots) + slots = append([]string{"main"}, slots...) + + return slots, nil +} + +func (s *Store) RemoveKeySlot(userID, slot string) error { + s.lock.Lock() + defer s.lock.Unlock() + + credentials, ok := s.creds[userID] + if !ok { + return ErrNotFound + } + + if slot == "main" { + return ErrCantRemoveMainSlot + } + + key, ok := credentials.SealedKeys[slot] + if !ok { + return ErrNotFound + } + + delete(credentials.SealedKeys, slot) + + if err := s.saveCredentials(); err != nil { + credentials.SealedKeys[slot] = key + return err + } + + return nil +} + +func (s *Store) AddKeySlot(userID, slot, mainKey string) (string, error) { + s.lock.Lock() + defer s.lock.Unlock() + + credentials, ok := s.creds[userID] + if !ok { + return "", ErrNotFound + } + + _, ok = credentials.SealedKeys[slot] + if ok { + return "", ErrAlreadyExists + } + + err := credentials.Unlock("main", mainKey) + if err != nil { + return "", err + } + + var key [32]byte + copy(key[:], GenerateKey(32)) + if err := credentials.SealKey(slot, key); err != nil { + return "", err + } + + if err := s.saveCredentials(); err != nil { + delete(credentials.SealedKeys, slot) + return "", err + } + + return base64.StdEncoding.EncodeToString(key[:]), nil +} + func (s *Store) Logout(userID string) (*Credentials, error) { s.lock.Lock() defer s.lock.Unlock() diff --git a/pkg/users/types.go b/pkg/users/types.go index 4812536..bf4d687 100644 --- a/pkg/users/types.go +++ b/pkg/users/types.go @@ -29,6 +29,9 @@ type CredentialsStorer interface { UpdateEmails(userID string, emails []string) (*credentials.Credentials, error) UpdatePassword(userID string, password []byte) (*credentials.Credentials, error) UpdateToken(userID, uid, ref string) (*credentials.Credentials, error) + ListKeySlots(userID string) ([]string, error) + RemoveKeySlot(userID, slot string) error + AddKeySlot(userID, slot, mainKey string) (string, error) Logout(userID string) (*credentials.Credentials, error) Delete(userID string) error } diff --git a/pkg/users/user.go b/pkg/users/user.go index 86863f9..e82b139 100644 --- a/pkg/users/user.go +++ b/pkg/users/user.go @@ -491,6 +491,27 @@ func (u *User) logout() error { return nil } +func (u *User) ListKeySlots() ([]string, error) { + u.lock.RLock() + defer u.lock.RUnlock() + + return u.credStorer.ListKeySlots(u.userID) +} + +func (u *User) RemoveKeySlot(slot string) error { + u.lock.Lock() + defer u.lock.Unlock() + + return u.credStorer.RemoveKeySlot(u.userID, slot) +} + +func (u *User) AddKeySlot(slot, mainKey string) (string, error) { + u.lock.Lock() + defer u.lock.Unlock() + + return u.credStorer.AddKeySlot(u.userID, slot, mainKey) +} + func (u *User) closeEventLoopAndCacher() { if u.store == nil { return