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.
		
		
		
		
		
			
		
			
				
					
					
						
							221 lines
						
					
					
						
							6.3 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							221 lines
						
					
					
						
							6.3 KiB
						
					
					
				| package credential | |
| 
 | |
| import ( | |
| 	"context" | |
| 	"fmt" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/glog" | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb" | |
| 	"github.com/seaweedfs/seaweedfs/weed/util" | |
| ) | |
| 
 | |
| // MigrateCredentials migrates credentials from one store to another | |
| func MigrateCredentials(fromStoreName, toStoreName CredentialStoreTypeName, configuration util.Configuration, fromPrefix, toPrefix string) error { | |
| 	ctx := context.Background() | |
| 
 | |
| 	// Create source credential manager | |
| 	fromCM, err := NewCredentialManager(fromStoreName, configuration, fromPrefix) | |
| 	if err != nil { | |
| 		return fmt.Errorf("failed to create source credential manager (%s): %v", fromStoreName, err) | |
| 	} | |
| 	defer fromCM.Shutdown() | |
| 
 | |
| 	// Create destination credential manager | |
| 	toCM, err := NewCredentialManager(toStoreName, configuration, toPrefix) | |
| 	if err != nil { | |
| 		return fmt.Errorf("failed to create destination credential manager (%s): %v", toStoreName, err) | |
| 	} | |
| 	defer toCM.Shutdown() | |
| 
 | |
| 	// Load configuration from source | |
| 	glog.Infof("Loading configuration from %s store...", fromStoreName) | |
| 	config, err := fromCM.LoadConfiguration(ctx) | |
| 	if err != nil { | |
| 		return fmt.Errorf("failed to load configuration from source store: %w", err) | |
| 	} | |
| 
 | |
| 	if config == nil || len(config.Identities) == 0 { | |
| 		glog.Info("No identities found in source store") | |
| 		return nil | |
| 	} | |
| 
 | |
| 	glog.Infof("Found %d identities in source store", len(config.Identities)) | |
| 
 | |
| 	// Migrate each identity | |
| 	var migrated, failed int | |
| 	for _, identity := range config.Identities { | |
| 		glog.V(1).Infof("Migrating user: %s", identity.Name) | |
| 
 | |
| 		// Check if user already exists in destination | |
| 		existingUser, err := toCM.GetUser(ctx, identity.Name) | |
| 		if err != nil && err != ErrUserNotFound { | |
| 			glog.Errorf("Failed to check if user %s exists in destination: %v", identity.Name, err) | |
| 			failed++ | |
| 			continue | |
| 		} | |
| 
 | |
| 		if existingUser != nil { | |
| 			glog.Warningf("User %s already exists in destination store, skipping", identity.Name) | |
| 			continue | |
| 		} | |
| 
 | |
| 		// Create user in destination | |
| 		err = toCM.CreateUser(ctx, identity) | |
| 		if err != nil { | |
| 			glog.Errorf("Failed to create user %s in destination store: %v", identity.Name, err) | |
| 			failed++ | |
| 			continue | |
| 		} | |
| 
 | |
| 		migrated++ | |
| 		glog.V(1).Infof("Successfully migrated user: %s", identity.Name) | |
| 	} | |
| 
 | |
| 	glog.Infof("Migration completed: %d migrated, %d failed", migrated, failed) | |
| 
 | |
| 	if failed > 0 { | |
| 		return fmt.Errorf("migration completed with %d failures", failed) | |
| 	} | |
| 
 | |
| 	return nil | |
| } | |
| 
 | |
| // ExportCredentials exports credentials from a store to a configuration | |
| func ExportCredentials(storeName CredentialStoreTypeName, configuration util.Configuration, prefix string) (*iam_pb.S3ApiConfiguration, error) { | |
| 	ctx := context.Background() | |
| 
 | |
| 	// Create credential manager | |
| 	cm, err := NewCredentialManager(storeName, configuration, prefix) | |
| 	if err != nil { | |
| 		return nil, fmt.Errorf("failed to create credential manager (%s): %v", storeName, err) | |
| 	} | |
| 	defer cm.Shutdown() | |
| 
 | |
| 	// Load configuration | |
| 	config, err := cm.LoadConfiguration(ctx) | |
| 	if err != nil { | |
| 		return nil, fmt.Errorf("failed to load configuration: %w", err) | |
| 	} | |
| 
 | |
| 	return config, nil | |
| } | |
| 
 | |
| // ImportCredentials imports credentials from a configuration to a store | |
| func ImportCredentials(storeName CredentialStoreTypeName, configuration util.Configuration, prefix string, config *iam_pb.S3ApiConfiguration) error { | |
| 	ctx := context.Background() | |
| 
 | |
| 	// Create credential manager | |
| 	cm, err := NewCredentialManager(storeName, configuration, prefix) | |
| 	if err != nil { | |
| 		return fmt.Errorf("failed to create credential manager (%s): %v", storeName, err) | |
| 	} | |
| 	defer cm.Shutdown() | |
| 
 | |
| 	// Import each identity | |
| 	var imported, failed int | |
| 	for _, identity := range config.Identities { | |
| 		glog.V(1).Infof("Importing user: %s", identity.Name) | |
| 
 | |
| 		// Check if user already exists | |
| 		existingUser, err := cm.GetUser(ctx, identity.Name) | |
| 		if err != nil && err != ErrUserNotFound { | |
| 			glog.Errorf("Failed to check if user %s exists: %v", identity.Name, err) | |
| 			failed++ | |
| 			continue | |
| 		} | |
| 
 | |
| 		if existingUser != nil { | |
| 			glog.Warningf("User %s already exists, skipping", identity.Name) | |
| 			continue | |
| 		} | |
| 
 | |
| 		// Create user | |
| 		err = cm.CreateUser(ctx, identity) | |
| 		if err != nil { | |
| 			glog.Errorf("Failed to create user %s: %v", identity.Name, err) | |
| 			failed++ | |
| 			continue | |
| 		} | |
| 
 | |
| 		imported++ | |
| 		glog.V(1).Infof("Successfully imported user: %s", identity.Name) | |
| 	} | |
| 
 | |
| 	glog.Infof("Import completed: %d imported, %d failed", imported, failed) | |
| 
 | |
| 	if failed > 0 { | |
| 		return fmt.Errorf("import completed with %d failures", failed) | |
| 	} | |
| 
 | |
| 	return nil | |
| } | |
| 
 | |
| // ValidateCredentials validates that all credentials in a store are accessible | |
| func ValidateCredentials(storeName CredentialStoreTypeName, configuration util.Configuration, prefix string) error { | |
| 	ctx := context.Background() | |
| 
 | |
| 	// Create credential manager | |
| 	cm, err := NewCredentialManager(storeName, configuration, prefix) | |
| 	if err != nil { | |
| 		return fmt.Errorf("failed to create credential manager (%s): %v", storeName, err) | |
| 	} | |
| 	defer cm.Shutdown() | |
| 
 | |
| 	// Load configuration | |
| 	config, err := cm.LoadConfiguration(ctx) | |
| 	if err != nil { | |
| 		return fmt.Errorf("failed to load configuration: %w", err) | |
| 	} | |
| 
 | |
| 	if config == nil || len(config.Identities) == 0 { | |
| 		glog.Info("No identities found in store") | |
| 		return nil | |
| 	} | |
| 
 | |
| 	glog.Infof("Validating %d identities...", len(config.Identities)) | |
| 
 | |
| 	// Validate each identity | |
| 	var validated, failed int | |
| 	for _, identity := range config.Identities { | |
| 		// Check if user can be retrieved | |
| 		user, err := cm.GetUser(ctx, identity.Name) | |
| 		if err != nil { | |
| 			glog.Errorf("Failed to retrieve user %s: %v", identity.Name, err) | |
| 			failed++ | |
| 			continue | |
| 		} | |
| 
 | |
| 		if user == nil { | |
| 			glog.Errorf("User %s not found", identity.Name) | |
| 			failed++ | |
| 			continue | |
| 		} | |
| 
 | |
| 		// Validate access keys | |
| 		for _, credential := range identity.Credentials { | |
| 			accessKeyUser, err := cm.GetUserByAccessKey(ctx, credential.AccessKey) | |
| 			if err != nil { | |
| 				glog.Errorf("Failed to retrieve user by access key %s: %v", credential.AccessKey, err) | |
| 				failed++ | |
| 				continue | |
| 			} | |
| 
 | |
| 			if accessKeyUser == nil || accessKeyUser.Name != identity.Name { | |
| 				glog.Errorf("Access key %s does not map to correct user %s", credential.AccessKey, identity.Name) | |
| 				failed++ | |
| 				continue | |
| 			} | |
| 		} | |
| 
 | |
| 		validated++ | |
| 		glog.V(1).Infof("Successfully validated user: %s", identity.Name) | |
| 	} | |
| 
 | |
| 	glog.Infof("Validation completed: %d validated, %d failed", validated, failed) | |
| 
 | |
| 	if failed > 0 { | |
| 		return fmt.Errorf("validation completed with %d failures", failed) | |
| 	} | |
| 
 | |
| 	return nil | |
| }
 |