Skip to main content
Glama
Keeper-Security

Keeper Secrets Manager - MCP

capture_test.go8.52 kB
package integration import ( "encoding/base64" "flag" "fmt" "os" "path/filepath" "testing" "github.com/keeper-security/ksm-mcp/internal/testing/capture" ksm "github.com/keeper-security/secrets-manager-go/core" ) var ( captureData = flag.Bool("capture", false, "Capture real KSM data for fixtures") oneTimeToken = flag.String("token", "", "One-time token for KSM") configFile = flag.String("config", "", "Base64 config file path") outputDir = flag.String("output", "fixtures", "Output directory for captured data") ) func TestCaptureRealData(t *testing.T) { if !*captureData { t.Skip("Skipping data capture test. Use -capture flag to enable") } // Use provided values or defaults for testing token := *oneTimeToken if token == "" { token = os.Getenv("KSM_ONE_TIME_TOKEN") if token == "" { token = "US:3J8QgphqMQjeEr_BHvELdfvbRwPNbqr9FgzSo6SqGaU" // Your provided token } } configPath := *configFile if configPath == "" { configPath = os.Getenv("KSM_CONFIG_FILE") if configPath == "" { configPath = "/Users/mustinov/Downloads/config.base64" // Your provided path } } // Read config file configData, err := os.ReadFile(configPath) if err != nil { t.Fatalf("Failed to read config file: %v", err) } // Initialize KSM client options := &ksm.ClientOptions{ Token: token, Config: ksm.NewMemoryKeyValueStorage(string(configData)), } client := ksm.NewSecretsManager(options) // Create data capture captureDir := filepath.Join(*outputDir, "ksm-capture") dc := capture.NewDataCapture(captureDir) // Capture vault data if err := dc.CaptureVault(client); err != nil { t.Fatalf("Failed to capture vault data: %v", err) } // Verify captured data fixtureFile := filepath.Join(captureDir, "vault_fixtures.json") if _, err := os.Stat(fixtureFile); os.IsNotExist(err) { t.Fatalf("Fixture file was not created") } // Load and verify fixtures captured, err := capture.LoadFixtures(fixtureFile) if err != nil { t.Fatalf("Failed to load fixtures: %v", err) } t.Logf("Successfully captured %d records", len(captured.Records)) t.Logf("Folders: %d", len(captured.Folders)) t.Logf("Files: %d", len(captured.Files)) t.Logf("API calls: %d", len(captured.Calls)) } // TestGenerateMockData generates mock data without real KSM connection func TestGenerateMockData(t *testing.T) { // This test always runs and generates mock data outputDir := filepath.Join("fixtures", "mock-data") if err := os.MkdirAll(outputDir, 0755); err != nil { t.Fatalf("Failed to create output directory: %v", err) } // Generate large test files (couple of megs as requested) largeConfigData := generateLargeConfigFile(2 * 1024 * 1024) // 2MB largeConfigPath := filepath.Join(outputDir, "large_config.json") if err := os.WriteFile(largeConfigPath, largeConfigData, 0644); err != nil { t.Fatalf("Failed to write large config file: %v", err) } largeSQLDump := generateSQLDump(3 * 1024 * 1024) // 3MB sqlDumpPath := filepath.Join(outputDir, "database_dump.sql") if err := os.WriteFile(sqlDumpPath, largeSQLDump, 0644); err != nil { t.Fatalf("Failed to write SQL dump file: %v", err) } // Generate binary test file binaryData := generateBinaryFile(1 * 1024 * 1024) // 1MB binaryPath := filepath.Join(outputDir, "test_binary.dat") if err := os.WriteFile(binaryPath, binaryData, 0644); err != nil { t.Fatalf("Failed to write binary file: %v", err) } t.Logf("Generated mock test files:") t.Logf("- Large config: %s (%.2f MB)", largeConfigPath, float64(len(largeConfigData))/1024/1024) t.Logf("- SQL dump: %s (%.2f MB)", sqlDumpPath, float64(len(largeSQLDump))/1024/1024) t.Logf("- Binary file: %s (%.2f MB)", binaryPath, float64(len(binaryData))/1024/1024) } func generateLargeConfigFile(size int) []byte { config := `{ "application": { "name": "TestApplication", "version": "1.0.0", "environment": "production", "debug": false, "features": {` // Add many feature flags for i := 0; i < 1000; i++ { if i > 0 { config += "," } config += fmt.Sprintf(` "feature_%d": { "enabled": %v, "description": "Test feature number %d for testing large configuration files", "metadata": { "created": "2024-01-01T00:00:00Z", "author": "test_user_%d", "tags": ["test", "feature", "config"] } }`, i, i%2 == 0, i, i%10) } config += ` }, "servers": [` // Add server configurations for i := 0; i < 50; i++ { if i > 0 { config += "," } config += fmt.Sprintf(` { "id": "server_%d", "host": "server%d.example.com", "port": %d, "protocol": "https", "region": "us-east-%d", "capacity": %d, "metrics": { "cpu_usage": %.2f, "memory_usage": %.2f, "disk_usage": %.2f, "network_in": %d, "network_out": %d } }`, i, i, 8000+i, (i%4)+1, (i+1)*100, float64(i%100)/100, float64((i+20)%100)/100, float64((i+40)%100)/100, i*1024*1024, i*512*1024) } config += ` ] } }` // Pad to reach target size result := []byte(config) for len(result) < size { result = append(result, []byte("\n// Padding to reach target file size\n")...) result = append(result, []byte(fmt.Sprintf("// Line %d: Lorem ipsum dolor sit amet, consectetur adipiscing elit...\n", len(result)))...) } return result[:size] } func generateSQLDump(size int) []byte { dump := `-- Test Database Dump -- Generated for KSM MCP Testing -- Version: 1.0.0 -- Date: 2024-01-23 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; START TRANSACTION; SET time_zone = "+00:00"; CREATE DATABASE IF NOT EXISTS test_database; USE test_database; -- Table structure for users CREATE TABLE IF NOT EXISTS users ( id INT(11) NOT NULL AUTO_INCREMENT, username VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, password_hash VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY username (username), UNIQUE KEY email (email) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- Dumping data for table users INSERT INTO users (username, email, password_hash) VALUES ` // Generate user records for i := 0; i < 10000; i++ { if i > 0 { dump += ",\n" } hashBytes := []byte(fmt.Sprintf("hash_%d_padding_to_make_it_longer_for_base64_encoding", i)) encodedHash := base64.StdEncoding.EncodeToString(hashBytes) if len(encodedHash) > 60 { encodedHash = encodedHash[:60] } dump += fmt.Sprintf("('user_%d', 'user%d@example.com', '$2y$10$%s')", i, i, encodedHash) } dump += ";\n\n" // Add more tables dump += ` -- Table structure for logs CREATE TABLE IF NOT EXISTS application_logs ( id BIGINT NOT NULL AUTO_INCREMENT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, level VARCHAR(10) NOT NULL, message TEXT, metadata JSON, PRIMARY KEY (id), KEY idx_timestamp (timestamp), KEY idx_level (level) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- Dumping data for table application_logs INSERT INTO application_logs (level, message, metadata) VALUES ` // Generate log records for i := 0; i < 5000; i++ { if i > 0 { dump += ",\n" } level := []string{"DEBUG", "INFO", "WARN", "ERROR"}[i%4] dump += fmt.Sprintf("('%s', 'Log message %d: %s', '{\"request_id\": \"%d\", \"user_id\": %d}')", level, i, generateRandomMessage(i), i*1000, i%1000) } dump += ";\n\nCOMMIT;\n" // Pad to reach target size result := []byte(dump) for len(result) < size { result = append(result, []byte("\n-- Additional padding data\n")...) result = append(result, []byte(fmt.Sprintf("-- Padding line %d\n", len(result)))...) } return result[:size] } func generateBinaryFile(size int) []byte { // Generate pseudo-random binary data data := make([]byte, size) // Add some structure to make it interesting // File header copy(data[0:8], []byte("TESTBIN\x00")) // Version data[8] = 1 data[9] = 0 data[10] = 0 data[11] = 0 // Fill with pattern for i := 12; i < size; i++ { data[i] = byte((i * 7) % 256) } return data } func generateRandomMessage(seed int) string { messages := []string{ "Processing request", "Database query executed", "Cache miss for key", "User authenticated successfully", "File uploaded", "Background job completed", "API rate limit checked", "Session validated", "Configuration reloaded", "Health check passed", } return messages[seed%len(messages)] }

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