-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Certificate Bootstrap & Storage Management
Overview
Implement the certificate bootstrap process and local storage management system. This includes handling the initial manually-provisioned certificate, transitioning to API-managed certificates, and managing the file system operations for certificate storage with proper backup and retention policies.
Requirements
Storage Structure Implementation
Create and manage the following directory structure:
/etc/certs/
├── bootstrap/ # Bootstrap certificate (manually provisioned)
│ ├── cert.pem # Bootstrap certificate
│ ├── key.pem # Bootstrap private key
│ └── ca-chain.pem # CA certificate chain
├── current/
│ ├── cert.pem # Current API-managed certificate
│ ├── key.pem # Current private key
│ ├── ca-chain.pem # CA certificate chain
│ └── serial # Serial number for renewal tracking
├── backup/
│ ├── cert-20250901.pem # Backup certificates (by date)
│ ├── key-20250901.pem # Backup private keys
│ └── ca-chain-20250901.pem # Backup CA chains
├── pending/
│ ├── cert.pem # New certificate being validated
│ └── key.pem # New private key
└── logs/
└── rotation.log # Certificate rotation audit log
Module Structure
Implement the following modules:
internal/
├── bootstrap/
│ └── bootstrap.go # Bootstrap certificate handling
├── storage/
│ ├── filesystem.go # File system operations
│ └── permissions.go # Permission managementBootstrap Process
Implement bootstrap certificate handling in internal/bootstrap/bootstrap.go:
type BootstrapManager struct {
config *BootstrapConfig
storage *storage.Manager
logger *slog.Logger
}
type BootstrapStatus struct {
HasBootstrap bool
HasCurrent bool
BootstrapValid bool
CurrentValid bool
NeedsTransition bool
}
// Core functions to implement:
func (b *BootstrapManager) ValidateBootstrapCertificate() error
func (b *BootstrapManager) GetBootstrapStatus() (*BootstrapStatus, error)
func (b *BootstrapManager) IsBootstrapCertificate(cert *x509.Certificate) bool
func (b *BootstrapManager) ShouldTransitionFromBootstrap() bool
func (b *BootstrapManager) MarkTransitionComplete() errorBootstrap logic requirements:
- Validate bootstrap certificate exists and is valid
- Detect whether current certificate is bootstrap or API-managed
- Track transition state (never re-bootstrap once transitioned)
- Bootstrap certificates are identified by:
- Location in
/etc/certs/bootstrap/ - Lack of serial number file
- Not tracked by Certificate API
- Location in
Storage Manager
Implement storage operations in internal/storage/filesystem.go:
type StorageManager struct {
basePath string
permissions *PermissionConfig
logger *slog.Logger
mutex sync.RWMutex
}
type Certificate struct {
Certificate []byte
PrivateKey []byte
CAChain []byte
SerialNumber string
}
// Core functions to implement:
func (s *StorageManager) Initialize() error
func (s *StorageManager) ReadBootstrapCertificate() (*Certificate, error)
func (s *StorageManager) ReadCurrentCertificate() (*Certificate, error)
func (s *StorageManager) WritePendingCertificate(cert *Certificate) error
func (s *StorageManager) PromotePendingToCurrent() error
func (s *StorageManager) BackupCurrentCertificate() error
func (s *StorageManager) CleanupOldBackups(retentionCount int) error
func (s *StorageManager) GetCertificateExpiry(location string) (time.Time, error)Atomic Certificate Replacement
Implement atomic file operations to prevent partial updates:
func (s *StorageManager) PromotePendingToCurrent() error {
// 1. Validate pending certificate exists and is valid
// 2. Create backup of current certificate with timestamp
// 3. Prepare new certificate files in temporary location
// 4. Use atomic rename operations for each file
// 5. Update serial number file
// 6. Verify successful replacement
// 7. Clean up temporary files
}Requirements:
- Use
os.Rename()for atomic operations - Never leave system in inconsistent state
- Rollback on any failure during replacement
- Maintain audit log of all operations
Permission Management
Implement permission handling in internal/storage/permissions.go:
type PermissionManager struct {
certFileMode os.FileMode // 0644
keyFileMode os.FileMode // 0600
directoryMode os.FileMode // 0755
owner string // "root"
group string // "ssl-cert"
}
// Core functions to implement:
func (p *PermissionManager) SetFilePermissions(path string, isPrivateKey bool) error
func (p *PermissionManager) SetDirectoryPermissions(path string) error
func (p *PermissionManager) ValidatePermissions(path string) error
func (p *PermissionManager) SetOwnership(path string) errorBackup and Retention
Implement backup management:
type BackupManager struct {
storage *StorageManager
retentionCount int
backupPath string
}
func (b *BackupManager) CreateBackup(cert *Certificate) error {
// Generate timestamp-based filename
// Copy certificate, key, and CA chain to backup directory
// Maintain permissions on backup files
// Return error if backup fails
}
func (b *BackupManager) CleanupOldBackups() error {
// List all backup files
// Sort by timestamp
// Keep only the most recent N backups
// Securely delete old backups (overwrite before deletion)
}Certificate Validation
Implement certificate validation utilities:
func ValidateCertificate(certPEM []byte) error {
// Parse PEM-encoded certificate
// Verify certificate format
// Check expiry date
// Validate key usage extensions
// Return detailed error on validation failure
}
func ValidatePrivateKeyMatch(certPEM, keyPEM []byte) error {
// Verify private key matches certificate
// Check key strength (minimum RSA 2048 or ECDSA P-256)
// Return error if mismatch or weak key
}
func ValidateCAChain(chainPEM []byte) error {
// Parse CA chain
// Verify chain validity
// Check for expired certificates in chain
}Acceptance Criteria
-
Storage Initialization
- Creates all required directories with correct permissions
- Handles existing directory structures gracefully
- Validates bootstrap certificate if present
-
Bootstrap Handling
- Correctly identifies bootstrap vs API-managed certificates
- Tracks transition state persistently
- Never attempts to renew bootstrap certificate
- Successfully transitions from bootstrap to API-managed cert
-
File Operations
- All certificate replacements are atomic
- No partial updates possible
- Rollback on failure maintains previous state
- Proper file permissions set on all operations
-
Backup Management
- Creates timestamped backups before replacement
- Maintains configured number of backups
- Cleans up old backups automatically
- Preserves permissions on backup files
-
Certificate Validation
- Validates certificate format and expiry
- Verifies private key matches certificate
- Checks CA chain validity
- Provides detailed validation errors
Security Requirements
- Private keys must have 0600 permissions (readable only by owner)
- Certificate files must have 0644 permissions
- Secure deletion of old private keys (overwrite before removal)
- Audit log for all certificate operations
- No private keys in logs or error messages
Error Handling
- Detailed error messages for troubleshooting
- Distinguish between recoverable and fatal errors
- Log all operations with outcomes
- Preserve system state on errors
Testing Requirements
- Unit tests for all storage operations
- Test atomic replacement with simulated failures
- Test permission setting and validation
- Test backup creation and cleanup
- Test bootstrap detection and transition logic
- Integration tests with actual file system operations
- Test concurrent access scenarios (use mutex)
Dependencies
- Standard Go crypto/x509 package for certificate handling
- Standard os package for file operations
- No external dependencies required for this module