You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							338 lines
						
					
					
						
							8.7 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							338 lines
						
					
					
						
							8.7 KiB
						
					
					
				
								package dash
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"context"
							 | 
						|
									"crypto/rand"
							 | 
						|
									"encoding/base64"
							 | 
						|
									"fmt"
							 | 
						|
									"time"
							 | 
						|
								
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/credential"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								// CreateObjectStoreUser creates a new user using the credential manager
							 | 
						|
								func (s *AdminServer) CreateObjectStoreUser(req CreateUserRequest) (*ObjectStoreUser, error) {
							 | 
						|
									if s.credentialManager == nil {
							 | 
						|
										return nil, fmt.Errorf("credential manager not available")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									ctx := context.Background()
							 | 
						|
								
							 | 
						|
									// Create new identity
							 | 
						|
									newIdentity := &iam_pb.Identity{
							 | 
						|
										Name:    req.Username,
							 | 
						|
										Actions: req.Actions,
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Add account if email is provided
							 | 
						|
									if req.Email != "" {
							 | 
						|
										newIdentity.Account = &iam_pb.Account{
							 | 
						|
											Id:           generateAccountId(),
							 | 
						|
											DisplayName:  req.Username,
							 | 
						|
											EmailAddress: req.Email,
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Generate access key if requested
							 | 
						|
									var accessKey, secretKey string
							 | 
						|
									if req.GenerateKey {
							 | 
						|
										accessKey = generateAccessKey()
							 | 
						|
										secretKey = generateSecretKey()
							 | 
						|
										newIdentity.Credentials = []*iam_pb.Credential{
							 | 
						|
											{
							 | 
						|
												AccessKey: accessKey,
							 | 
						|
												SecretKey: secretKey,
							 | 
						|
											},
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Create user using credential manager
							 | 
						|
									err := s.credentialManager.CreateUser(ctx, newIdentity)
							 | 
						|
									if err != nil {
							 | 
						|
										if err == credential.ErrUserAlreadyExists {
							 | 
						|
											return nil, fmt.Errorf("user %s already exists", req.Username)
							 | 
						|
										}
							 | 
						|
										return nil, fmt.Errorf("failed to create user: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Return created user
							 | 
						|
									user := &ObjectStoreUser{
							 | 
						|
										Username:    req.Username,
							 | 
						|
										Email:       req.Email,
							 | 
						|
										AccessKey:   accessKey,
							 | 
						|
										SecretKey:   secretKey,
							 | 
						|
										Permissions: req.Actions,
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return user, nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// UpdateObjectStoreUser updates an existing user
							 | 
						|
								func (s *AdminServer) UpdateObjectStoreUser(username string, req UpdateUserRequest) (*ObjectStoreUser, error) {
							 | 
						|
									if s.credentialManager == nil {
							 | 
						|
										return nil, fmt.Errorf("credential manager not available")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									ctx := context.Background()
							 | 
						|
								
							 | 
						|
									// Get existing user
							 | 
						|
									identity, err := s.credentialManager.GetUser(ctx, username)
							 | 
						|
									if err != nil {
							 | 
						|
										if err == credential.ErrUserNotFound {
							 | 
						|
											return nil, fmt.Errorf("user %s not found", username)
							 | 
						|
										}
							 | 
						|
										return nil, fmt.Errorf("failed to get user: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Create updated identity
							 | 
						|
									updatedIdentity := &iam_pb.Identity{
							 | 
						|
										Name:        identity.Name,
							 | 
						|
										Account:     identity.Account,
							 | 
						|
										Credentials: identity.Credentials,
							 | 
						|
										Actions:     identity.Actions,
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Update actions if provided
							 | 
						|
									if len(req.Actions) > 0 {
							 | 
						|
										updatedIdentity.Actions = req.Actions
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Update email if provided
							 | 
						|
									if req.Email != "" {
							 | 
						|
										if updatedIdentity.Account == nil {
							 | 
						|
											updatedIdentity.Account = &iam_pb.Account{
							 | 
						|
												Id:          generateAccountId(),
							 | 
						|
												DisplayName: username,
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
										updatedIdentity.Account.EmailAddress = req.Email
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Update user using credential manager
							 | 
						|
									err = s.credentialManager.UpdateUser(ctx, username, updatedIdentity)
							 | 
						|
									if err != nil {
							 | 
						|
										return nil, fmt.Errorf("failed to update user: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Return updated user
							 | 
						|
									user := &ObjectStoreUser{
							 | 
						|
										Username:    username,
							 | 
						|
										Email:       req.Email,
							 | 
						|
										Permissions: updatedIdentity.Actions,
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Get first access key for display
							 | 
						|
									if len(updatedIdentity.Credentials) > 0 {
							 | 
						|
										user.AccessKey = updatedIdentity.Credentials[0].AccessKey
							 | 
						|
										user.SecretKey = updatedIdentity.Credentials[0].SecretKey
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return user, nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// DeleteObjectStoreUser deletes a user using the credential manager
							 | 
						|
								func (s *AdminServer) DeleteObjectStoreUser(username string) error {
							 | 
						|
									if s.credentialManager == nil {
							 | 
						|
										return fmt.Errorf("credential manager not available")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									ctx := context.Background()
							 | 
						|
								
							 | 
						|
									// Delete user using credential manager
							 | 
						|
									err := s.credentialManager.DeleteUser(ctx, username)
							 | 
						|
									if err != nil {
							 | 
						|
										if err == credential.ErrUserNotFound {
							 | 
						|
											return fmt.Errorf("user %s not found", username)
							 | 
						|
										}
							 | 
						|
										return fmt.Errorf("failed to delete user: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// GetObjectStoreUserDetails returns detailed information about a user
							 | 
						|
								func (s *AdminServer) GetObjectStoreUserDetails(username string) (*UserDetails, error) {
							 | 
						|
									if s.credentialManager == nil {
							 | 
						|
										return nil, fmt.Errorf("credential manager not available")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									ctx := context.Background()
							 | 
						|
								
							 | 
						|
									// Get user using credential manager
							 | 
						|
									identity, err := s.credentialManager.GetUser(ctx, username)
							 | 
						|
									if err != nil {
							 | 
						|
										if err == credential.ErrUserNotFound {
							 | 
						|
											return nil, fmt.Errorf("user %s not found", username)
							 | 
						|
										}
							 | 
						|
										return nil, fmt.Errorf("failed to get user: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									details := &UserDetails{
							 | 
						|
										Username: username,
							 | 
						|
										Actions:  identity.Actions,
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Set email from account if available
							 | 
						|
									if identity.Account != nil {
							 | 
						|
										details.Email = identity.Account.EmailAddress
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Convert credentials to access key info
							 | 
						|
									for _, cred := range identity.Credentials {
							 | 
						|
										details.AccessKeys = append(details.AccessKeys, AccessKeyInfo{
							 | 
						|
											AccessKey: cred.AccessKey,
							 | 
						|
											SecretKey: cred.SecretKey,
							 | 
						|
											CreatedAt: time.Now().AddDate(0, -1, 0), // Mock creation date
							 | 
						|
										})
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return details, nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// CreateAccessKey creates a new access key for a user
							 | 
						|
								func (s *AdminServer) CreateAccessKey(username string) (*AccessKeyInfo, error) {
							 | 
						|
									if s.credentialManager == nil {
							 | 
						|
										return nil, fmt.Errorf("credential manager not available")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									ctx := context.Background()
							 | 
						|
								
							 | 
						|
									// Check if user exists
							 | 
						|
									_, err := s.credentialManager.GetUser(ctx, username)
							 | 
						|
									if err != nil {
							 | 
						|
										if err == credential.ErrUserNotFound {
							 | 
						|
											return nil, fmt.Errorf("user %s not found", username)
							 | 
						|
										}
							 | 
						|
										return nil, fmt.Errorf("failed to get user: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Generate new access key
							 | 
						|
									accessKey := generateAccessKey()
							 | 
						|
									secretKey := generateSecretKey()
							 | 
						|
								
							 | 
						|
									credential := &iam_pb.Credential{
							 | 
						|
										AccessKey: accessKey,
							 | 
						|
										SecretKey: secretKey,
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Create access key using credential manager
							 | 
						|
									err = s.credentialManager.CreateAccessKey(ctx, username, credential)
							 | 
						|
									if err != nil {
							 | 
						|
										return nil, fmt.Errorf("failed to create access key: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return &AccessKeyInfo{
							 | 
						|
										AccessKey: accessKey,
							 | 
						|
										SecretKey: secretKey,
							 | 
						|
										CreatedAt: time.Now(),
							 | 
						|
									}, nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// DeleteAccessKey deletes an access key for a user
							 | 
						|
								func (s *AdminServer) DeleteAccessKey(username, accessKeyId string) error {
							 | 
						|
									if s.credentialManager == nil {
							 | 
						|
										return fmt.Errorf("credential manager not available")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									ctx := context.Background()
							 | 
						|
								
							 | 
						|
									// Delete access key using credential manager
							 | 
						|
									err := s.credentialManager.DeleteAccessKey(ctx, username, accessKeyId)
							 | 
						|
									if err != nil {
							 | 
						|
										if err == credential.ErrUserNotFound {
							 | 
						|
											return fmt.Errorf("user %s not found", username)
							 | 
						|
										}
							 | 
						|
										if err == credential.ErrAccessKeyNotFound {
							 | 
						|
											return fmt.Errorf("access key %s not found for user %s", accessKeyId, username)
							 | 
						|
										}
							 | 
						|
										return fmt.Errorf("failed to delete access key: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// GetUserPolicies returns the policies for a user (actions)
							 | 
						|
								func (s *AdminServer) GetUserPolicies(username string) ([]string, error) {
							 | 
						|
									if s.credentialManager == nil {
							 | 
						|
										return nil, fmt.Errorf("credential manager not available")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									ctx := context.Background()
							 | 
						|
								
							 | 
						|
									// Get user using credential manager
							 | 
						|
									identity, err := s.credentialManager.GetUser(ctx, username)
							 | 
						|
									if err != nil {
							 | 
						|
										if err == credential.ErrUserNotFound {
							 | 
						|
											return nil, fmt.Errorf("user %s not found", username)
							 | 
						|
										}
							 | 
						|
										return nil, fmt.Errorf("failed to get user: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return identity.Actions, nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// UpdateUserPolicies updates the policies (actions) for a user
							 | 
						|
								func (s *AdminServer) UpdateUserPolicies(username string, actions []string) error {
							 | 
						|
									if s.credentialManager == nil {
							 | 
						|
										return fmt.Errorf("credential manager not available")
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									ctx := context.Background()
							 | 
						|
								
							 | 
						|
									// Get existing user
							 | 
						|
									identity, err := s.credentialManager.GetUser(ctx, username)
							 | 
						|
									if err != nil {
							 | 
						|
										if err == credential.ErrUserNotFound {
							 | 
						|
											return fmt.Errorf("user %s not found", username)
							 | 
						|
										}
							 | 
						|
										return fmt.Errorf("failed to get user: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Create updated identity with new actions
							 | 
						|
									updatedIdentity := &iam_pb.Identity{
							 | 
						|
										Name:        identity.Name,
							 | 
						|
										Account:     identity.Account,
							 | 
						|
										Credentials: identity.Credentials,
							 | 
						|
										Actions:     actions,
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Update user using credential manager
							 | 
						|
									err = s.credentialManager.UpdateUser(ctx, username, updatedIdentity)
							 | 
						|
									if err != nil {
							 | 
						|
										return fmt.Errorf("failed to update user policies: %w", err)
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Helper functions for generating keys and IDs
							 | 
						|
								func generateAccessKey() string {
							 | 
						|
									// Generate 20-character access key (AWS standard)
							 | 
						|
									const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
							 | 
						|
									b := make([]byte, 20)
							 | 
						|
									for i := range b {
							 | 
						|
										b[i] = charset[randomInt(len(charset))]
							 | 
						|
									}
							 | 
						|
									return string(b)
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func generateSecretKey() string {
							 | 
						|
									// Generate 40-character secret key (AWS standard)
							 | 
						|
									b := make([]byte, 30) // 30 bytes = 40 characters in base64
							 | 
						|
									rand.Read(b)
							 | 
						|
									return base64.StdEncoding.EncodeToString(b)
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func generateAccountId() string {
							 | 
						|
									// Generate 12-digit account ID
							 | 
						|
									b := make([]byte, 8)
							 | 
						|
									rand.Read(b)
							 | 
						|
									return fmt.Sprintf("%012d", b[0]<<24|b[1]<<16|b[2]<<8|b[3])
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func randomInt(max int) int {
							 | 
						|
									b := make([]byte, 1)
							 | 
						|
									rand.Read(b)
							 | 
						|
									return int(b[0]) % max
							 | 
						|
								}
							 |