feat: Implement storage provider management functionality

- Added new routes and handlers for managing storage providers, including creation, editing, and deletion.
- Introduced a new StorageProvider form component for user input.
- Enhanced the database schema to support storage provider references in transfer configurations.
- Implemented encryption for sensitive fields in storage provider data.
- Added tests for storage provider API endpoints and integration with the database.
- Updated frontend components to support storage provider selection and testing.
This commit is contained in:
StarFleetCPTN
2025-04-16 17:18:53 -07:00
parent 88d0ac815a
commit 31871bd16e
59 changed files with 15842 additions and 594 deletions
+189
View File
@@ -0,0 +1,189 @@
# Encryption Security Framework
The Encryption Security Framework provides a comprehensive solution for secure credential handling, encryption/decryption operations, audit logging, monitoring, and key rotation in the GoMFT application.
## Features
- **Security Auditing**: Detailed logging of encryption and decryption operations
- **Security Monitoring**: Real-time monitoring and alerting for security events
- **Key Rotation**: Safe rotation of encryption keys across database models
- **Performance Benchmarking**: Measure encryption performance impact
- **Security Testing**: Comprehensive testing for encryption implementation
- **Secure Log Handling**: Ensures no sensitive data is exposed in logs
## Architecture
The framework follows a modular design with clear separation of concerns:
```
┌─────────────────────────────────────────────────────────┐
│ Security Framework │
├─────────────┬─────────────┬────────────┬───────────────┤
│ Encryption │ Security │ Security │ Key Rotation │
│ Service │ Auditor │ Monitor │ Utility │
└─────────────┴─────────────┴────────────┴───────────────┘
```
### Core Components
1. **SecurityFramework**: The main facade that ties all components together
2. **SecurityAuditor**: Logs encryption-related events with proper sanitization
3. **SecurityMonitor**: Provides monitoring, alerting, and reporting capabilities
4. **RotationUtility**: Manages the process of rotating encryption keys
5. **SecurityTestingFramework**: Tests and benchmarks encryption implementation
## Usage
### Basic Setup
```go
import (
"github.com/starfleetcptn/gomft/internal/encryption"
"github.com/starfleetcptn/gomft/internal/encryptionsecurity"
)
// Create dependencies (implement the FrameworkDependencies interface)
deps := YourDependencyProvider()
// Create encryption service
encryptionService, _ := encryption.NewEncryptionService(keyManager)
// Create security framework
securityFramework, _ := encryptionsecurity.NewSecurityFramework(
db,
encryptionService,
encryptionsecurity.DefaultSecurityFrameworkOptions(),
deps,
)
```
### Encrypt/Decrypt with Auditing
```go
// Encrypt with auditing
encryptedData, err := securityFramework.EncryptWithAudit(
data,
"password",
"StorageProvider",
userID,
)
// Decrypt with auditing
decryptedData, err := securityFramework.DecryptWithAudit(
encryptedData,
"password",
"StorageProvider",
userID,
)
```
### Key Rotation
```go
// Setup old and new encryption services
oldService, _ := encryption.NewEncryptionService(oldKeyManager)
newService, _ := encryption.NewEncryptionService(newKeyManager)
// Models to rotate keys for
models := []interface{}{&StorageProvider{}, &OtherModel{}}
// Execute key rotation
stats, err := securityFramework.RotateEncryptionKeys(
context.Background(),
oldService,
newService,
models,
adminUserID,
)
```
### Performance Benchmarking
```go
// Benchmark encryption performance (e.g., with 1KB data for 10 seconds)
metrics, _ := securityFramework.BenchmarkEncryptionPerformance(
1024,
10 * time.Second,
)
fmt.Printf("Operations per second: %.2f\n", metrics.OperationsPerSecond)
fmt.Printf("Average latency: %v\n", metrics.AverageLatency)
```
### Security Reports
```go
// Generate a security report for the last 24 hours
startTime := time.Now().Add(-24 * time.Hour)
endTime := time.Now()
reportFile, _ := os.Create("security_report.json")
defer reportFile.Close()
securityFramework.GenerateSecurityReport(startTime, endTime, reportFile)
```
## Implementation Details
### Dependency Injection
The framework uses dependency injection to avoid hard dependencies and facilitate testing:
```go
type FrameworkDependencies struct {
CreateAuditor func(logPath string, enableDetailed bool) (SecurityAuditor, error)
CreateMonitor func(auditor SecurityAuditor) SecurityMonitor
CreateAlertHandler func(logPath string) (AlertHandler, error)
CreateTestingFramework func(auditor SecurityAuditor, monitor SecurityMonitor) SecurityTestingFramework
CreateDummyService func() (*encryption.EncryptionService, error)
CreateRotationUtility func(db *gorm.DB, oldService, newService *encryption.EncryptionService,
auditor SecurityAuditor, monitor SecurityMonitor,
options RotationOptions) (RotationUtility, error)
}
```
### Key Rotation Process
1. **Preparation**: Analyze database models to identify encrypted fields
2. **Batch Processing**: Process records in manageable batches
3. **Decryption/Re-encryption**: Decrypt with old key, re-encrypt with new key
4. **Validation**: Verify data integrity after rotation
5. **Monitoring**: Log all activities and create detailed reports
### Security Best Practices
- **Zero Trust Principle**: Never assume data is safe, always validate
- **Defense in Depth**: Multiple layers of security
- **Least Privilege**: Components only have access to what they need
- **Secure Defaults**: Sensible default settings for security
- **Comprehensive Logging**: All security events are logged
- **Monitored Access**: All access to sensitive data is monitored
- **Fail Securely**: On failures, the system defaults to secure state
## Secure Logging
Special attention is paid to ensure sensitive data is never exposed in logs:
- All error messages are sanitized to remove potential sensitive information
- Key material is never logged in any form
- Timestamps and operation metadata are logged without actual data content
- Access to sensitive data is logged without revealing the actual data
## Performance Considerations
- **Batch Processing**: Key rotation is performed in configurable batches
- **Resource Control**: Memory and CPU usage are optimized for encryption operations
- **Timeouts**: All operations have configurable timeouts
- **Benchmarking**: Performance metrics help identify bottlenecks
## Future Enhancements
- **Distributed Coordination**: Support for coordinated key rotation in distributed systems
- **Real-time Metrics**: Integration with metrics collection systems
- **Anomaly Detection**: Machine learning based detection of unusual encryption patterns
- **Compliance Reporting**: Pre-configured reports for common compliance frameworks
## Additional Resources
- [Encryption Package Documentation](../encryption/README.md)
- [Key Rotation Documentation](../encryption/keyrotation/README.md)
- [Database Integration](../../database/encryption_middleware.md)
@@ -0,0 +1,426 @@
// Package encryptionsecurity provides a security framework for encryption operations.
package encryptionsecurity
import (
"context"
"fmt"
"io"
"os"
"time"
"github.com/starfleetcptn/gomft/internal/encryption"
"github.com/starfleetcptn/gomft/internal/encryption/keyrotation"
"gorm.io/gorm"
)
// SecurityAuditor defines the interface for the security auditing component
type SecurityAuditor interface {
LogEncryptionEvent(operation string, fieldType, modelType string, success bool, err error, keyVersion string, userID uint, duration time.Duration)
LogDecryptionEvent(operation string, fieldType, modelType string, success bool, err error, keyVersion string, userID uint, duration time.Duration)
LogKeyRotationEvent(oldVersion, newVersion string, success bool, err error, userID uint)
LogKeyRotationEventWithDescription(oldVersion, newVersion string, success bool, description string, userID uint)
SetDetailedMode(detailed bool)
Close() error
}
// SecurityMonitor defines the interface for the security monitoring component
type SecurityMonitor interface {
SetAlertHandler(handler AlertHandler)
SetAlertThreshold(eventType string, threshold int)
AttachToAuditor() func(interface{})
GenerateReport(startTime, endTime time.Time, writer io.Writer) error
}
// AlertHandler defines the interface for handling security alerts
type AlertHandler interface {
HandleAlert(interface{})
}
// RotationOptions contains configuration for the key rotation process
type RotationOptions struct {
BatchSize int
Parallelism int
DryRun bool
Timeout time.Duration
}
// RotationUtility defines the interface for the key rotation component
type RotationUtility interface {
RotateKeysForModels(ctx context.Context, models []interface{}) (*keyrotation.RotationStats, error)
}
// SecurityTestingFramework defines the interface for the security testing component
type SecurityTestingFramework interface {
SetOutputDirectory(dir string)
SetTestingLevel(level int)
RunAllTests(encryptionService *encryption.EncryptionService) ([]*TestResult, error)
BenchmarkEncryptionPerformance(service *encryption.EncryptionService, dataSize int, duration time.Duration) (*PerformanceMetrics, error)
}
// TestResult represents the outcome of a security test
type TestResult struct {
Name string `json:"name"`
Success bool `json:"success"`
ElapsedTime time.Duration `json:"elapsed_time"`
Error string `json:"error,omitempty"`
Details string `json:"details,omitempty"`
}
// PerformanceMetrics contains performance data for encryption operations
type PerformanceMetrics struct {
OperationsPerSecond float64 `json:"operations_per_second"`
AverageLatency time.Duration `json:"average_latency"`
P95Latency time.Duration `json:"p95_latency"`
P99Latency time.Duration `json:"p99_latency"`
MemoryUsageMB float64 `json:"memory_usage_mb"`
CPUUsagePercent float64 `json:"cpu_usage_percent"`
}
// SecurityFramework provides a unified interface to the security audit, monitoring,
// key rotation, and testing capabilities.
type SecurityFramework struct {
encryptionService *encryption.EncryptionService
auditor SecurityAuditor
monitor SecurityMonitor
rotationUtil RotationUtility
testingFramework SecurityTestingFramework
db *gorm.DB
}
// SecurityFrameworkOptions configures the security framework
type SecurityFrameworkOptions struct {
EnableDetailedAuditing bool
AuditLogPath string
AlertLogPath string
EnableMonitoring bool
RotationBatchSize int
RotationParallelism int
EnableTestingFramework bool
TestOutputDirectory string
TestingLevel int // Using int instead of audit.TestingLevel
}
// DefaultSecurityFrameworkOptions returns sensible defaults
func DefaultSecurityFrameworkOptions() *SecurityFrameworkOptions {
return &SecurityFrameworkOptions{
EnableDetailedAuditing: true,
AuditLogPath: "logs/encryption_audit.log",
AlertLogPath: "logs/encryption_alerts.log",
EnableMonitoring: true,
RotationBatchSize: 100,
RotationParallelism: 2,
EnableTestingFramework: true,
TestOutputDirectory: "test_results",
TestingLevel: 0, // BasicTesting
}
}
// FrameworkDependencies defines the functions needed to create the components of the security framework
type FrameworkDependencies struct {
CreateAuditor func(logPath string, enableDetailed bool) (SecurityAuditor, error)
CreateMonitor func(auditor SecurityAuditor) SecurityMonitor
CreateAlertHandler func(logPath string) (AlertHandler, error)
CreateTestingFramework func(auditor SecurityAuditor, monitor SecurityMonitor) SecurityTestingFramework
CreateDummyService func() (*encryption.EncryptionService, error)
CreateRotationUtility func(db *gorm.DB, oldService, newService *encryption.EncryptionService, auditor SecurityAuditor, monitor SecurityMonitor, options RotationOptions) (RotationUtility, error)
}
// NewSecurityFramework creates a new SecurityFramework
func NewSecurityFramework(
db *gorm.DB,
encryptionService *encryption.EncryptionService,
options *SecurityFrameworkOptions,
deps FrameworkDependencies,
) (*SecurityFramework, error) {
if encryptionService == nil {
return nil, fmt.Errorf("encryption service is required")
}
// Use default options if none provided
if options == nil {
options = DefaultSecurityFrameworkOptions()
}
// Create the auditor
var auditor SecurityAuditor
var err error
if options.AuditLogPath != "" {
// Create directories if they don't exist
dir := getDirectoryPath(options.AuditLogPath)
if err := os.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("failed to create audit log directory: %w", err)
}
}
auditor, err = deps.CreateAuditor(options.AuditLogPath, options.EnableDetailedAuditing)
if err != nil {
return nil, fmt.Errorf("failed to create auditor: %w", err)
}
// Create the monitor
monitor := deps.CreateMonitor(auditor)
// Configure alert handler if path is specified
if options.AlertLogPath != "" {
dir := getDirectoryPath(options.AlertLogPath)
if err := os.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("failed to create alert log directory: %w", err)
}
alertHandler, err := deps.CreateAlertHandler(options.AlertLogPath)
if err != nil {
return nil, fmt.Errorf("failed to create alert handler: %w", err)
}
monitor.SetAlertHandler(alertHandler)
}
// Set up alert thresholds
monitor.SetAlertThreshold("decryption_failure", 5)
monitor.SetAlertThreshold("encryption_failure", 5)
monitor.SetAlertThreshold("key_rotation", 1)
// Wire up monitor to auditor
// This would be implemented by the consumer
_ = monitor.AttachToAuditor()
// Create testing framework
testingFramework := deps.CreateTestingFramework(auditor, monitor)
if options.EnableTestingFramework {
// Configure testing framework
if options.TestOutputDirectory != "" {
testingFramework.SetOutputDirectory(options.TestOutputDirectory)
}
testingFramework.SetTestingLevel(options.TestingLevel)
}
// Set up rotation utility if database is provided
var rotationUtil RotationUtility
if db != nil {
// For rotation, we'll need a dummy service for testing initially
// This will be replaced with actual services during rotation
dummyService, err := deps.CreateDummyService()
if err != nil {
return nil, fmt.Errorf("failed to create dummy encryption service: %w", err)
}
// Create rotation options
rotationOptions := RotationOptions{
BatchSize: options.RotationBatchSize,
Parallelism: options.RotationParallelism,
DryRun: false,
Timeout: 24 * time.Hour,
}
// Create rotation utility
rotationUtil, err = deps.CreateRotationUtility(
db,
dummyService,
dummyService,
auditor,
monitor,
rotationOptions,
)
if err != nil {
return nil, fmt.Errorf("failed to create rotation utility: %w", err)
}
}
return &SecurityFramework{
encryptionService: encryptionService,
auditor: auditor,
monitor: monitor,
rotationUtil: rotationUtil,
testingFramework: testingFramework,
db: db,
}, nil
}
// EncryptWithAudit encrypts data with auditing
func (sf *SecurityFramework) EncryptWithAudit(
data []byte,
fieldType string,
modelType string,
userID uint,
) ([]byte, error) {
startTime := time.Now()
encrypted, err := sf.encryptionService.Encrypt(data)
duration := time.Since(startTime)
// Use a placeholder for key version if not available in EncryptionService
keyVersion := "current"
sf.auditor.LogEncryptionEvent(
"Encrypt",
fieldType,
modelType,
err == nil,
err,
keyVersion,
userID,
duration,
)
return encrypted, err
}
// DecryptWithAudit decrypts data with auditing
func (sf *SecurityFramework) DecryptWithAudit(
encryptedData []byte,
fieldType string,
modelType string,
userID uint,
) ([]byte, error) {
startTime := time.Now()
decrypted, err := sf.encryptionService.Decrypt(encryptedData)
duration := time.Since(startTime)
// Use a placeholder for key version if not available in EncryptionService
keyVersion := "current"
sf.auditor.LogDecryptionEvent(
"Decrypt",
fieldType,
modelType,
err == nil,
err,
keyVersion,
userID,
duration,
)
return decrypted, err
}
// EncryptStringWithAudit encrypts a string with auditing
func (sf *SecurityFramework) EncryptStringWithAudit(
data string,
fieldType string,
modelType string,
userID uint,
) (string, error) {
startTime := time.Now()
encrypted, err := sf.encryptionService.EncryptString(data)
duration := time.Since(startTime)
// Use a placeholder for key version if not available in EncryptionService
keyVersion := "current"
sf.auditor.LogEncryptionEvent(
"EncryptString",
fieldType,
modelType,
err == nil,
err,
keyVersion,
userID,
duration,
)
return encrypted, err
}
// DecryptStringWithAudit decrypts a string with auditing
func (sf *SecurityFramework) DecryptStringWithAudit(
encryptedData string,
fieldType string,
modelType string,
userID uint,
) (string, error) {
startTime := time.Now()
decrypted, err := sf.encryptionService.DecryptString(encryptedData)
duration := time.Since(startTime)
// Use a placeholder for key version if not available in EncryptionService
keyVersion := "current"
sf.auditor.LogDecryptionEvent(
"DecryptString",
fieldType,
modelType,
err == nil,
err,
keyVersion,
userID,
duration,
)
return decrypted, err
}
// RotateEncryptionKeys rotates encryption keys for models with encrypted fields
func (sf *SecurityFramework) RotateEncryptionKeys(
ctx context.Context,
oldService, newService *encryption.EncryptionService,
models []interface{},
userID uint,
) (*keyrotation.RotationStats, error) {
if sf.rotationUtil == nil || sf.db == nil {
return nil, fmt.Errorf("database and rotation utility are required for key rotation")
}
// Check services
if oldService == nil || newService == nil {
return nil, fmt.Errorf("both old and new encryption services are required")
}
// Log key rotation start
oldVersion := "previous"
newVersion := "current"
sf.auditor.LogKeyRotationEvent(oldVersion, newVersion, true, nil, userID)
// Perform key rotation
stats, err := sf.rotationUtil.RotateKeysForModels(ctx, models)
// Log key rotation completion
sf.auditor.LogKeyRotationEventWithDescription(
oldVersion,
newVersion,
err == nil,
fmt.Sprintf("Key rotation completed: processed %d records, failed %d",
stats.ProcessedRecords, stats.FailedRecords),
userID,
)
return stats, err
}
// RunSecurityTests runs encryption security tests
func (sf *SecurityFramework) RunSecurityTests() ([]*TestResult, error) {
return sf.testingFramework.RunAllTests(sf.encryptionService)
}
// BenchmarkEncryptionPerformance measures encryption performance
func (sf *SecurityFramework) BenchmarkEncryptionPerformance(
dataSize int,
duration time.Duration,
) (*PerformanceMetrics, error) {
return sf.testingFramework.BenchmarkEncryptionPerformance(
sf.encryptionService,
dataSize,
duration,
)
}
// GenerateSecurityReport generates a security report
func (sf *SecurityFramework) GenerateSecurityReport(
startTime, endTime time.Time,
writer io.Writer,
) error {
return sf.monitor.GenerateReport(startTime, endTime, writer)
}
// Close properly closes any resources
func (sf *SecurityFramework) Close() error {
if sf.auditor != nil {
return sf.auditor.Close()
}
return nil
}
// getDirectoryPath extracts the directory path from a file path
func getDirectoryPath(filePath string) string {
for i := len(filePath) - 1; i >= 0; i-- {
if filePath[i] == '/' || filePath[i] == '\\' {
return filePath[:i]
}
}
return ""
}