Skip to main content
Glama

Keeper Secrets Manager - MCP

profiles.go9.37 kB
package commands import ( "fmt" "os" "path/filepath" "strings" "text/tabwriter" "time" "github.com/keeper-security/ksm-mcp/internal/config" "github.com/keeper-security/ksm-mcp/internal/storage" "github.com/spf13/cobra" ) // profilesCmd represents the profiles command var profilesCmd = &cobra.Command{ Use: "profiles", Short: "Manage KSM profiles", Long: `List, delete, and manage Keeper Secrets Manager profiles. Profiles store encrypted KSM configurations that can be used to connect to different Keeper accounts or vaults.`, } // profilesListCmd represents the profiles list command var profilesListCmd = &cobra.Command{ Use: "list", Short: "List all profiles", Long: `List all configured KSM profiles with their metadata.`, RunE: runProfilesList, } // profilesDeleteCmd represents the profiles delete command var profilesDeleteCmd = &cobra.Command{ Use: "delete [profile]", Short: "Delete a profile", Long: `Delete a KSM profile. This action cannot be undone.`, Args: cobra.ExactArgs(1), RunE: runProfilesDelete, } // profilesSetDefaultCmd represents the profiles set-default command var profilesSetDefaultCmd = &cobra.Command{ Use: "set-default [profile]", Short: "Set default profile", Long: `Set the default profile to use when no --profile flag is specified.`, Args: cobra.ExactArgs(1), RunE: runProfilesSetDefault, } // profilesShowCmd represents the profiles show command var profilesShowCmd = &cobra.Command{ Use: "show [profile]", Short: "Show profile details", Long: `Show detailed information about a specific profile.`, Args: cobra.ExactArgs(1), RunE: runProfilesShow, } func init() { rootCmd.AddCommand(profilesCmd) profilesCmd.AddCommand(profilesListCmd) profilesCmd.AddCommand(profilesDeleteCmd) profilesCmd.AddCommand(profilesSetDefaultCmd) profilesCmd.AddCommand(profilesShowCmd) } func runProfilesList(cmd *cobra.Command, args []string) error { // Get config directory configDir := os.Getenv("KSM_MCP_CONFIG_DIR") if configDir == "" { home, err := os.UserHomeDir() if err != nil { return fmt.Errorf("failed to get home directory: %w", err) } configDir = filepath.Join(home, ".keeper", "ksm-mcp") } // Load config to get default profile cfg, err := config.Load(filepath.Join(configDir, "config.yaml")) if err != nil { return fmt.Errorf("failed to load config: %w", err) } // Create storage var store *storage.ProfileStore if cfg.Security.ProtectionPasswordHash != "" { fmt.Fprint(os.Stderr, "Enter protection password: ") password, readErr := readPassword() if readErr != nil { return fmt.Errorf("failed to read password: %w", readErr) } store, err = storage.NewProfileStoreWithPassword(configDir, password) if err != nil { return fmt.Errorf("failed to unlock profile store: %w", err) } } else { store = storage.NewProfileStore(configDir) } // List profiles profileNames := store.ListProfiles() if len(profileNames) == 0 { fmt.Println("No profiles configured.") fmt.Println("\nTo create a profile, run:") fmt.Println(" ksm-mcp init --profile <name> --token <token>") return nil } // Display profiles in a table w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintln(w, "PROFILE\tDEFAULT") fmt.Fprintln(w, "-------\t-------") for _, name := range profileNames { isDefault := "" if name == cfg.Profiles.Default { isDefault = "✓" } fmt.Fprintf(w, "%s\t%s\n", name, isDefault) } _ = w.Flush() return nil } func runProfilesDelete(cmd *cobra.Command, args []string) error { profileName := args[0] // Get config directory configDir := os.Getenv("KSM_MCP_CONFIG_DIR") if configDir == "" { home, err := os.UserHomeDir() if err != nil { return fmt.Errorf("failed to get home directory: %w", err) } configDir = filepath.Join(home, ".keeper", "ksm-mcp") } // Load config cfg, err := config.Load(filepath.Join(configDir, "config.yaml")) if err != nil { return fmt.Errorf("failed to load config: %w", err) } // Create storage var store *storage.ProfileStore if cfg.Security.ProtectionPasswordHash != "" { fmt.Fprint(os.Stderr, "Enter protection password: ") password, readErr := readPassword() if readErr != nil { return fmt.Errorf("failed to read password: %w", readErr) } store, err = storage.NewProfileStoreWithPassword(configDir, password) if err != nil { return fmt.Errorf("failed to unlock profile store: %w", err) } } else { store = storage.NewProfileStore(configDir) } // Confirm deletion fmt.Printf("Are you sure you want to delete profile '%s'? This action cannot be undone.\n", profileName) fmt.Print("Type 'yes' to confirm: ") var confirm string _, _ = fmt.Scanln(&confirm) if strings.ToLower(strings.TrimSpace(confirm)) != "yes" { fmt.Println("Deletion cancelled.") return nil } // Delete profile if err := store.DeleteProfile(profileName); err != nil { return fmt.Errorf("failed to delete profile: %w", err) } // If this was the default profile, clear it if cfg.Profiles.Default == profileName { cfg.Profiles.Default = "" if err := cfg.SaveDefault(); err != nil { return fmt.Errorf("failed to update config: %w", err) } fmt.Println("⚠️ Default profile cleared") } fmt.Printf("✓ Profile '%s' deleted successfully\n", profileName) return nil } func runProfilesSetDefault(cmd *cobra.Command, args []string) error { profileName := args[0] // Get config directory configDir := os.Getenv("KSM_MCP_CONFIG_DIR") if configDir == "" { home, err := os.UserHomeDir() if err != nil { return fmt.Errorf("failed to get home directory: %w", err) } configDir = filepath.Join(home, ".keeper", "ksm-mcp") } // Load config cfg, err := config.Load(filepath.Join(configDir, "config.yaml")) if err != nil { return fmt.Errorf("failed to load config: %w", err) } // Create storage to verify profile exists var store *storage.ProfileStore if cfg.Security.ProtectionPasswordHash != "" { fmt.Fprint(os.Stderr, "Enter protection password: ") password, readErr := readPassword() if readErr != nil { return fmt.Errorf("failed to read password: %w", readErr) } store, err = storage.NewProfileStoreWithPassword(configDir, password) if err != nil { return fmt.Errorf("failed to unlock profile store: %w", err) } } else { store = storage.NewProfileStore(configDir) } // Check if profile exists if _, err := store.GetProfile(profileName); err != nil { return fmt.Errorf("profile '%s' does not exist", profileName) } // Update default profile cfg.Profiles.Default = profileName if err := cfg.SaveDefault(); err != nil { return fmt.Errorf("failed to save config: %w", err) } fmt.Printf("✓ Default profile set to '%s'\n", profileName) return nil } func runProfilesShow(cmd *cobra.Command, args []string) error { profileName := args[0] // Get config directory configDir := os.Getenv("KSM_MCP_CONFIG_DIR") if configDir == "" { home, err := os.UserHomeDir() if err != nil { return fmt.Errorf("failed to get home directory: %w", err) } configDir = filepath.Join(home, ".keeper", "ksm-mcp") } // Load config cfg, err := config.Load(filepath.Join(configDir, "config.yaml")) if err != nil { return fmt.Errorf("failed to load config: %w", err) } // Create storage var store *storage.ProfileStore if cfg.Security.ProtectionPasswordHash != "" { fmt.Fprint(os.Stderr, "Enter protection password: ") password, readErr := readPassword() if readErr != nil { return fmt.Errorf("failed to read password: %w", readErr) } store, err = storage.NewProfileStoreWithPassword(configDir, password) if err != nil { return fmt.Errorf("failed to unlock profile store: %w", err) } } else { store = storage.NewProfileStore(configDir) } // Get profile profile, err := store.GetProfile(profileName) if err != nil { return fmt.Errorf("profile '%s' not found", profileName) } // Display profile information fmt.Printf("Profile: %s\n", profile.Name) fmt.Printf("Default: %v\n", profile.Name == cfg.Profiles.Default) if !profile.CreatedAt.IsZero() { fmt.Printf("Created: %s\n", profile.CreatedAt.Format(time.RFC3339)) } if !profile.UpdatedAt.IsZero() { fmt.Printf("Updated: %s\n", profile.UpdatedAt.Format(time.RFC3339)) } // Show KSM config details (without sensitive data) if len(profile.Config) > 0 { fmt.Println("\nKSM Configuration:") if clientId, ok := profile.Config["clientId"]; ok { fmt.Printf(" Client ID: %s\n", clientId) } if hostname, ok := profile.Config["hostname"]; ok && hostname != "" { fmt.Printf(" Hostname: %s\n", hostname) } if privateKey, ok := profile.Config["privateKey"]; ok { fmt.Printf(" Private Key: %s\n", maskSensitive(privateKey)) } if appKey, ok := profile.Config["appKey"]; ok { fmt.Printf(" App Key: %s\n", maskSensitive(appKey)) } } // Get metadata about secrets access allMetadata := store.GetProfileMetadata() if metadata, ok := allMetadata[profileName]; ok { fmt.Println("\nMetadata:") fmt.Printf(" Created: %s\n", metadata.CreatedAt.Format(time.RFC3339)) if !metadata.UpdatedAt.IsZero() { fmt.Printf(" Updated: %s\n", metadata.UpdatedAt.Format(time.RFC3339)) } } return nil } func maskSensitive(value string) string { if len(value) <= 8 { return "********" } return value[:4] + "..." + value[len(value)-4:] }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Keeper-Security/keeper-mcp-golang-docker'

If you have feedback or need assistance with the MCP directory API, please join our Discord server