aboutsummaryrefslogtreecommitdiff
path: root/weed/credential/memory/memory_store.go
diff options
context:
space:
mode:
authorChris Lu <chrislusf@users.noreply.github.com>2025-07-12 01:13:11 -0700
committerGitHub <noreply@github.com>2025-07-12 01:13:11 -0700
commit687a6a6c1de0fb67b51ec9bfd1781a6c255ff695 (patch)
tree3ee2890c890e67a170cec2692425528aa9cd795f /weed/credential/memory/memory_store.go
parent49d43003e1f5063c57cd1b122469c0cb68d0cd79 (diff)
downloadseaweedfs-687a6a6c1de0fb67b51ec9bfd1781a6c255ff695.tar.xz
seaweedfs-687a6a6c1de0fb67b51ec9bfd1781a6c255ff695.zip
Admin UI: Add policies (#6968)
* add policies to UI, accessing filer directly * view, edit policies * add back buttons for "users" page * remove unused * fix ui dark mode when modal is closed * bucket view details button * fix browser buttons * filer action button works * clean up masters page * fix volume servers action buttons * fix collections page action button * fix properties page * more obvious * fix directory creation file mode * Update file_browser_handlers.go * directory permission
Diffstat (limited to 'weed/credential/memory/memory_store.go')
-rw-r--r--weed/credential/memory/memory_store.go303
1 files changed, 5 insertions, 298 deletions
diff --git a/weed/credential/memory/memory_store.go b/weed/credential/memory/memory_store.go
index e6117bf48..f0f383c04 100644
--- a/weed/credential/memory/memory_store.go
+++ b/weed/credential/memory/memory_store.go
@@ -1,9 +1,6 @@
package memory
import (
- "context"
- "encoding/json"
- "fmt"
"sync"
"github.com/seaweedfs/seaweedfs/weed/credential"
@@ -19,8 +16,9 @@ func init() {
// This is primarily intended for testing purposes
type MemoryStore struct {
mu sync.RWMutex
- users map[string]*iam_pb.Identity // username -> identity
- accessKeys map[string]string // access_key -> username
+ users map[string]*iam_pb.Identity // username -> identity
+ accessKeys map[string]string // access_key -> username
+ policies map[string]credential.PolicyDocument // policy_name -> policy_document
initialized bool
}
@@ -38,313 +36,22 @@ func (store *MemoryStore) Initialize(configuration util.Configuration, prefix st
store.users = make(map[string]*iam_pb.Identity)
store.accessKeys = make(map[string]string)
+ store.policies = make(map[string]credential.PolicyDocument)
store.initialized = true
return nil
}
-func (store *MemoryStore) LoadConfiguration(ctx context.Context) (*iam_pb.S3ApiConfiguration, error) {
- store.mu.RLock()
- defer store.mu.RUnlock()
-
- if !store.initialized {
- return nil, fmt.Errorf("store not initialized")
- }
-
- config := &iam_pb.S3ApiConfiguration{}
-
- // Convert all users to identities
- for _, user := range store.users {
- // Deep copy the identity to avoid mutation issues
- identityCopy := store.deepCopyIdentity(user)
- config.Identities = append(config.Identities, identityCopy)
- }
-
- return config, nil
-}
-
-func (store *MemoryStore) SaveConfiguration(ctx context.Context, config *iam_pb.S3ApiConfiguration) error {
- store.mu.Lock()
- defer store.mu.Unlock()
-
- if !store.initialized {
- return fmt.Errorf("store not initialized")
- }
-
- // Clear existing data
- store.users = make(map[string]*iam_pb.Identity)
- store.accessKeys = make(map[string]string)
-
- // Add all identities
- for _, identity := range config.Identities {
- // Deep copy to avoid mutation issues
- identityCopy := store.deepCopyIdentity(identity)
- store.users[identity.Name] = identityCopy
-
- // Index access keys
- for _, credential := range identity.Credentials {
- store.accessKeys[credential.AccessKey] = identity.Name
- }
- }
-
- return nil
-}
-
-func (store *MemoryStore) CreateUser(ctx context.Context, identity *iam_pb.Identity) error {
- store.mu.Lock()
- defer store.mu.Unlock()
-
- if !store.initialized {
- return fmt.Errorf("store not initialized")
- }
-
- if _, exists := store.users[identity.Name]; exists {
- return credential.ErrUserAlreadyExists
- }
-
- // Check for duplicate access keys
- for _, cred := range identity.Credentials {
- if _, exists := store.accessKeys[cred.AccessKey]; exists {
- return fmt.Errorf("access key %s already exists", cred.AccessKey)
- }
- }
-
- // Deep copy to avoid mutation issues
- identityCopy := store.deepCopyIdentity(identity)
- store.users[identity.Name] = identityCopy
-
- // Index access keys
- for _, cred := range identity.Credentials {
- store.accessKeys[cred.AccessKey] = identity.Name
- }
-
- return nil
-}
-
-func (store *MemoryStore) GetUser(ctx context.Context, username string) (*iam_pb.Identity, error) {
- store.mu.RLock()
- defer store.mu.RUnlock()
-
- if !store.initialized {
- return nil, fmt.Errorf("store not initialized")
- }
-
- user, exists := store.users[username]
- if !exists {
- return nil, credential.ErrUserNotFound
- }
-
- // Return a deep copy to avoid mutation issues
- return store.deepCopyIdentity(user), nil
-}
-
-func (store *MemoryStore) UpdateUser(ctx context.Context, username string, identity *iam_pb.Identity) error {
- store.mu.Lock()
- defer store.mu.Unlock()
-
- if !store.initialized {
- return fmt.Errorf("store not initialized")
- }
-
- existingUser, exists := store.users[username]
- if !exists {
- return credential.ErrUserNotFound
- }
-
- // Remove old access keys from index
- for _, cred := range existingUser.Credentials {
- delete(store.accessKeys, cred.AccessKey)
- }
-
- // Check for duplicate access keys (excluding current user)
- for _, cred := range identity.Credentials {
- if existingUsername, exists := store.accessKeys[cred.AccessKey]; exists && existingUsername != username {
- return fmt.Errorf("access key %s already exists", cred.AccessKey)
- }
- }
-
- // Deep copy to avoid mutation issues
- identityCopy := store.deepCopyIdentity(identity)
- store.users[username] = identityCopy
-
- // Re-index access keys
- for _, cred := range identity.Credentials {
- store.accessKeys[cred.AccessKey] = username
- }
-
- return nil
-}
-
-func (store *MemoryStore) DeleteUser(ctx context.Context, username string) error {
- store.mu.Lock()
- defer store.mu.Unlock()
-
- if !store.initialized {
- return fmt.Errorf("store not initialized")
- }
-
- user, exists := store.users[username]
- if !exists {
- return credential.ErrUserNotFound
- }
-
- // Remove access keys from index
- for _, cred := range user.Credentials {
- delete(store.accessKeys, cred.AccessKey)
- }
-
- // Remove user
- delete(store.users, username)
-
- return nil
-}
-
-func (store *MemoryStore) ListUsers(ctx context.Context) ([]string, error) {
- store.mu.RLock()
- defer store.mu.RUnlock()
-
- if !store.initialized {
- return nil, fmt.Errorf("store not initialized")
- }
-
- var usernames []string
- for username := range store.users {
- usernames = append(usernames, username)
- }
-
- return usernames, nil
-}
-
-func (store *MemoryStore) GetUserByAccessKey(ctx context.Context, accessKey string) (*iam_pb.Identity, error) {
- store.mu.RLock()
- defer store.mu.RUnlock()
-
- if !store.initialized {
- return nil, fmt.Errorf("store not initialized")
- }
-
- username, exists := store.accessKeys[accessKey]
- if !exists {
- return nil, credential.ErrAccessKeyNotFound
- }
-
- user, exists := store.users[username]
- if !exists {
- // This should not happen, but handle it gracefully
- return nil, credential.ErrUserNotFound
- }
-
- // Return a deep copy to avoid mutation issues
- return store.deepCopyIdentity(user), nil
-}
-
-func (store *MemoryStore) CreateAccessKey(ctx context.Context, username string, cred *iam_pb.Credential) error {
- store.mu.Lock()
- defer store.mu.Unlock()
-
- if !store.initialized {
- return fmt.Errorf("store not initialized")
- }
-
- user, exists := store.users[username]
- if !exists {
- return credential.ErrUserNotFound
- }
-
- // Check if access key already exists
- if _, exists := store.accessKeys[cred.AccessKey]; exists {
- return fmt.Errorf("access key %s already exists", cred.AccessKey)
- }
-
- // Add credential to user
- user.Credentials = append(user.Credentials, &iam_pb.Credential{
- AccessKey: cred.AccessKey,
- SecretKey: cred.SecretKey,
- })
-
- // Index the access key
- store.accessKeys[cred.AccessKey] = username
-
- return nil
-}
-
-func (store *MemoryStore) DeleteAccessKey(ctx context.Context, username string, accessKey string) error {
- store.mu.Lock()
- defer store.mu.Unlock()
-
- if !store.initialized {
- return fmt.Errorf("store not initialized")
- }
-
- user, exists := store.users[username]
- if !exists {
- return credential.ErrUserNotFound
- }
-
- // Find and remove the credential
- var newCredentials []*iam_pb.Credential
- found := false
- for _, cred := range user.Credentials {
- if cred.AccessKey == accessKey {
- found = true
- // Remove from access key index
- delete(store.accessKeys, accessKey)
- } else {
- newCredentials = append(newCredentials, cred)
- }
- }
-
- if !found {
- return credential.ErrAccessKeyNotFound
- }
-
- user.Credentials = newCredentials
- return nil
-}
-
func (store *MemoryStore) Shutdown() {
store.mu.Lock()
defer store.mu.Unlock()
- // Clear all data
store.users = nil
store.accessKeys = nil
+ store.policies = nil
store.initialized = false
}
-// deepCopyIdentity creates a deep copy of an identity to avoid mutation issues
-func (store *MemoryStore) deepCopyIdentity(identity *iam_pb.Identity) *iam_pb.Identity {
- if identity == nil {
- return nil
- }
-
- // Use JSON marshaling/unmarshaling for deep copy
- // This is simple and safe for protobuf messages
- data, err := json.Marshal(identity)
- if err != nil {
- // Fallback to shallow copy if JSON fails
- return &iam_pb.Identity{
- Name: identity.Name,
- Account: identity.Account,
- Credentials: identity.Credentials,
- Actions: identity.Actions,
- }
- }
-
- var copy iam_pb.Identity
- if err := json.Unmarshal(data, &copy); err != nil {
- // Fallback to shallow copy if JSON fails
- return &iam_pb.Identity{
- Name: identity.Name,
- Account: identity.Account,
- Credentials: identity.Credentials,
- Actions: identity.Actions,
- }
- }
-
- return &copy
-}
-
// Reset clears all data in the store (useful for testing)
func (store *MemoryStore) Reset() {
store.mu.Lock()