11 KiB
11 KiB
WSS (WebSocket Secure) Implementation Plan
Overview
This document outlines the complete implementation plan for adding WSS support to both the server and client_ws components, with optional configuration and comprehensive examples.
Current State Analysis
Server (src/server)
- ✅ Basic TLS infrastructure with
rustls
andrustls-pemfile
- ✅ Certificate loading functionality (
load_rustls_config
) - ✅ Optional TLS configuration in
ServerConfig
- ✅ Existing cert.pem and key.pem files for testing
- ⚠️ TLS configuration could be enhanced with better error handling
- ⚠️ Missing WSS-specific examples and tests
Client (src/client_ws)
- ✅ Basic TLS support with
native-tls
andtokio-native-tls
- ✅ Cross-platform WebSocket support (native + WASM)
- ⚠️ TLS connector accepts invalid certificates (development mode)
- ⚠️ No automatic WSS URL detection
- ⚠️ Missing WSS-specific configuration options
Implementation Phases
Phase 1: Server WSS Enhancement ✅ READY TO IMPLEMENT
1.1 Enhanced ServerConfig
#[derive(Clone)]
pub struct ServerConfig {
pub circle_name: String,
pub circle_public_key: String,
pub host: String,
pub port: u16,
pub redis_url: String,
pub enable_auth: bool,
// Enhanced TLS Configuration
pub enable_tls: bool, // Explicit TLS enable flag
pub cert_path: Option<String>, // Path to certificate file
pub key_path: Option<String>, // Path to private key file
pub tls_port: Option<u16>, // Optional separate TLS port
pub tls_accept_invalid_certs: bool, // For development
}
1.2 Improved TLS Loading
- Better error messages for certificate loading failures
- Validation of certificate and key file existence
- Support for different certificate formats
- Logging of TLS configuration status
1.3 Enhanced spawn_circle_server
- Clear logging of HTTP vs HTTPS mode
- Better error handling for TLS configuration
- Support for running both HTTP and HTTPS simultaneously (if needed)
Phase 2: Client WSS Enhancement
2.1 WSS URL Detection
impl CircleWsClient {
fn is_wss_url(&self) -> bool {
self.ws_url.starts_with("wss://")
}
fn requires_tls(&self) -> bool {
self.is_wss_url()
}
}
2.2 Enhanced TLS Configuration
pub struct TlsConfig {
pub accept_invalid_certs: bool,
pub accept_invalid_hostnames: bool,
pub ca_cert_path: Option<String>,
pub client_cert_path: Option<String>,
pub client_key_path: Option<String>,
}
impl CircleWsClientBuilder {
pub fn with_tls_config(mut self, tls_config: TlsConfig) -> Self {
self.tls_config = Some(tls_config);
self
}
}
2.3 Cross-Platform WSS Support
- Native: Enhanced
tokio-tungstenite
withrustls
support - WASM: Ensure
gloo-net
handles WSS URLs correctly - Consistent error handling across platforms
Phase 3: Examples and Testing
3.1 Basic WSS Example
// examples/wss_basic_example.rs
// Demonstrates basic WSS connection without authentication
3.2 WSS + Authentication Example
// examples/wss_auth_example.rs
// Demonstrates WSS connection with secp256k1 authentication
3.3 End-to-End Secure Example
// examples/wss_end_to_end_example.rs
// Complete server + client WSS with authentication
3.4 Certificate Generation Helper
// examples/wss_cert_generation.rs
// Helper to generate self-signed certificates for development
Phase 4: Documentation and Integration
4.1 Update README files
- Server WSS configuration guide
- Client WSS usage examples
- Certificate management instructions
4.2 Integration Tests
- WSS connection establishment
- WSS + authentication flow
- Certificate validation scenarios
Technical Implementation Details
Server Enhancements
Enhanced Certificate Loading
fn load_rustls_config(
cert_path: &str,
key_path: &str,
) -> Result<RustlsServerConfig, TlsConfigError> {
// Validate file existence
if !std::path::Path::new(cert_path).exists() {
return Err(TlsConfigError::CertificateNotFound(cert_path.to_string()));
}
if !std::path::Path::new(key_path).exists() {
return Err(TlsConfigError::PrivateKeyNotFound(key_path.to_string()));
}
// Enhanced error handling for certificate loading
// Support for different key formats (PKCS8, RSA, etc.)
// Validation of certificate chain
}
TLS Error Types
#[derive(Error, Debug)]
pub enum TlsConfigError {
#[error("Certificate file not found: {0}")]
CertificateNotFound(String),
#[error("Private key file not found: {0}")]
PrivateKeyNotFound(String),
#[error("Invalid certificate format: {0}")]
InvalidCertificate(String),
#[error("Invalid private key format: {0}")]
InvalidPrivateKey(String),
#[error("TLS configuration error: {0}")]
ConfigurationError(String),
}
Client Enhancements
WSS Connection Logic
impl CircleWsClient {
async fn create_tls_connector(&self) -> Result<TlsConnector, CircleWsClientError> {
let mut builder = TlsConnector::builder();
if let Some(tls_config) = &self.tls_config {
builder.danger_accept_invalid_certs(tls_config.accept_invalid_certs);
builder.danger_accept_invalid_hostnames(tls_config.accept_invalid_hostnames);
// Load custom CA certificates if provided
if let Some(ca_cert_path) = &tls_config.ca_cert_path {
// Load and add CA certificate
}
}
builder.build().map_err(|e| {
CircleWsClientError::ConnectionError(format!("TLS configuration failed: {}", e))
})
}
}
Example Structure
Basic WSS Example
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Start WSS server
let config = ServerConfig {
enable_tls: true,
cert_path: Some("cert.pem".to_string()),
key_path: Some("key.pem".to_string()),
port: 8443,
// ... other config
};
let (server_task, _handle) = spawn_circle_server(config)?;
// Connect WSS client
let mut client = CircleWsClientBuilder::new("wss://localhost:8443/ws".to_string())
.with_tls_config(TlsConfig {
accept_invalid_certs: true, // For development
..Default::default()
})
.build();
client.connect().await?;
// Test basic functionality
let result = client.play("print('Hello WSS!')".to_string()).await?;
println!("Result: {}", result.output);
client.disconnect().await;
Ok(())
}
WSS + Authentication Example
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Start authenticated WSS server
let config = ServerConfig {
enable_tls: true,
enable_auth: true,
cert_path: Some("cert.pem".to_string()),
key_path: Some("key.pem".to_string()),
port: 8443,
// ... other config
};
// Connect authenticated WSS client
let private_key = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
let mut client = CircleWsClientBuilder::new("wss://localhost:8443/ws".to_string())
.with_keypair(private_key.to_string())
.with_tls_config(TlsConfig {
accept_invalid_certs: true,
..Default::default()
})
.build();
client.connect().await?;
// Authenticate over secure connection
match client.authenticate().await? {
true => println!("Authenticated successfully over WSS"),
false => println!("Authentication failed"),
}
// Test authenticated request over secure connection
let result = client.play("print('Authenticated WSS request!')".to_string()).await?;
println!("Secure result: {}", result.output);
client.disconnect().await;
Ok(())
}
Testing Strategy
Unit Tests
- TLS configuration validation
- Certificate loading error handling
- WSS URL detection
- TLS connector creation
Integration Tests
- WSS server startup with valid certificates
- WSS client connection establishment
- WSS + authentication flow
- Error scenarios (invalid certificates, connection failures)
End-to-End Tests
- Complete WSS server + client communication
- Authentication over WSS
- Multiple concurrent WSS connections
- Certificate validation scenarios
Security Considerations
Development vs Production
- Development: Accept self-signed certificates, invalid hostnames
- Production: Strict certificate validation, proper CA chains
Certificate Management
- Clear documentation for certificate generation
- Support for Let's Encrypt certificates
- Certificate rotation considerations
TLS Configuration
- Modern TLS versions (1.2+)
- Secure cipher suites
- HSTS headers for web clients
File Changes Required
New Files
examples/wss_basic_example.rs
examples/wss_auth_example.rs
examples/wss_end_to_end_example.rs
examples/wss_cert_generation.rs
src/server/src/tls_config.rs
(optional)src/client_ws/src/tls_config.rs
(optional)
Modified Files
src/server/src/lib.rs
- Enhanced TLS supportsrc/server/cmd/main.rs
- TLS CLI optionssrc/client_ws/src/lib.rs
- WSS supportsrc/client_ws/Cargo.toml
- Additional TLS dependenciessrc/server/Cargo.toml
- Enhanced TLS dependenciessrc/server/README.md
- WSS documentationsrc/client_ws/README.md
- WSS usage guide
Dependencies
Server Additional Dependencies
# Enhanced TLS support
rustls-webpki = "0.103"
rustls-native-certs = "0.7"
Client Additional Dependencies
# Enhanced TLS support for native
rustls = { version = "0.23", optional = true }
tokio-rustls = { version = "0.26", optional = true }
rustls-native-certs = { version = "0.7", optional = true }
[features]
default = ["crypto"]
crypto = ["secp256k1", "sha3"]
rustls-tls = ["rustls", "tokio-rustls", "rustls-native-certs"]
Implementation Order
- Phase 1a: Enhance server TLS configuration and error handling
- Phase 1b: Create basic WSS server example and test
- Phase 1c: Validate server WSS functionality with manual testing
- Phase 2a: Enhance client WSS support
- Phase 2b: Create client WSS examples
- Phase 2c: Test client WSS connectivity
- Phase 3: Create end-to-end WSS examples
- Phase 4: Integration tests and documentation
Success Criteria
- ✅ Server can start with WSS enabled using existing certificates
- ✅ Client can connect to WSS server with proper TLS validation
- ✅ Authentication works over WSS connections
- ✅ Examples demonstrate all WSS functionality
- ✅ Tests validate WSS behavior
- ✅ Documentation explains WSS configuration
- ✅ Cross-platform compatibility (native + WASM)
Next Steps
- Switch to Code mode for implementation
- Start with Phase 1a: Server TLS enhancements
- Create and test basic WSS server example
- Validate functionality before proceeding to client