-
Notifications
You must be signed in to change notification settings - Fork 55
Implement IPC server infrastructure for secret management #549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Please continue working on this @copilot |
Completed the IPC server implementation! Added graceful shutdown tests and performed comprehensive manual testing with netcat. All acceptance criteria for Unix/macOS are now met. Summary of changes in commit c289579: ✅ Added All 6 integration tests are passing, and manual testing confirms the IPC server works as expected on Linux. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements foundational IPC (Inter-Process Communication) server infrastructure for dynamic secret management in Wassette using Unix domain sockets on Unix/macOS and a stub for Windows named pipes.
Key changes:
- Added IPC server implementation with peer authentication and JSON-based request/response protocol
- Integration with existing SecretsManager for set/delete/list secret operations
- Unix domain socket server with proper permissions (0600 for socket, 0700 for directory)
- Comprehensive unit and integration tests for IPC functionality
Reviewed Changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/wassette/src/ipc_server.rs | New IPC server implementation with Unix socket support, peer authentication, and request handlers |
| crates/wassette/src/lib.rs | Exported IPC server types and added secrets_manager_arc() helper method |
| src/main.rs | Integrated IPC server startup alongside MCP server in serve command |
| crates/wassette/Cargo.toml | Added platform-specific dependencies (libc for Unix, windows crate for Windows) |
| tests/ipc_server_integration_test.rs | Integration tests for IPC server connection, authentication, and operations |
| Cargo.lock | Dependency updates for new platform-specific libraries |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot address all the review comments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 5 out of 6 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| // Set directory permissions to 0700 (user only) | ||
| let metadata = tokio::fs::metadata(parent) | ||
| .await | ||
| .context("Failed to get directory metadata")?; | ||
| let mut perms = metadata.permissions(); | ||
| perms.set_mode(0o700); | ||
| tokio::fs::set_permissions(parent, perms) | ||
| .await | ||
| .context("Failed to set directory permissions")?; | ||
| } |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting directory permissions only when creating the directory means that if the directory already exists with insecure permissions (e.g., 0755 allowing others to access), those permissions won't be corrected. An attacker could pre-create the directory with world-readable permissions, potentially allowing them to monitor when the socket is created.
Consider always setting permissions, not just when creating:
if let Some(parent) = config.socket_path.parent() {
if !parent.exists() {
tokio::fs::create_dir_all(parent)
.await
.context("Failed to create socket directory")?;
}
// Always set directory permissions to 0700 (user only)
let metadata = tokio::fs::metadata(parent)
.await
.context("Failed to get directory metadata")?;
let mut perms = metadata.permissions();
perms.set_mode(0o700);
tokio::fs::set_permissions(parent, perms)
.await
.context("Failed to set directory permissions")?;
}| // Set directory permissions to 0700 (user only) | |
| let metadata = tokio::fs::metadata(parent) | |
| .await | |
| .context("Failed to get directory metadata")?; | |
| let mut perms = metadata.permissions(); | |
| perms.set_mode(0o700); | |
| tokio::fs::set_permissions(parent, perms) | |
| .await | |
| .context("Failed to set directory permissions")?; | |
| } | |
| } | |
| // Always set directory permissions to 0700 (user only) | |
| let metadata = tokio::fs::metadata(parent) | |
| .await | |
| .context("Failed to get directory metadata")?; | |
| let mut perms = metadata.permissions(); | |
| perms.set_mode(0o700); | |
| tokio::fs::set_permissions(parent, perms) | |
| .await | |
| .context("Failed to set directory permissions")?; |
|
|
||
| Ok((uid, gid)) | ||
| } | ||
|
|
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The get_peer_creds function is only implemented for target_os = "linux" and target_os = "macos", but not for other Unix-like systems such as FreeBSD, OpenBSD, NetBSD, or Solaris. This means the verify_peer_identity function will fail to compile on these platforms, even though they are Unix systems.
Consider adding a fallback implementation or compile-time error for unsupported Unix platforms:
#[cfg(all(unix, not(any(target_os = "linux", target_os = "macos"))))]
fn get_peer_creds(stream: &tokio::net::UnixStream) -> Result<(u32, u32)> {
anyhow::bail!("Peer credential verification not supported on this Unix platform")
}| /// Fallback for unsupported Unix platforms (not Linux or macOS) | |
| #[cfg(all(unix, not(any(target_os = "linux", target_os = "macos"))))] | |
| fn get_peer_creds(_stream: &tokio::net::UnixStream) -> Result<(u32, u32)> { | |
| anyhow::bail!("Peer credential verification not supported on this Unix platform") | |
| } |
| drop(stream); | ||
|
|
||
| // Shutdown the server by aborting the task | ||
| server_handle.abort(); |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test uses abort() to shutdown the server, which doesn't allow for graceful cleanup. This doesn't properly test the graceful shutdown path. The test then tries to verify cleanup happened, but aborting a task doesn't invoke cleanup code in the unix_server function.
The test should use the shutdown() method instead:
// Create a handle to the server's shutdown method
let mut server_clone = server.clone(); // If IpcServer implements Clone
server_clone.shutdown().await?;
// Or use a shutdown channel that's accessible from the testAlternatively, if testing abort behavior specifically, the test expectations should be adjusted to reflect that cleanup may not occur.
| &self.secrets_manager | ||
| } | ||
|
|
||
| /// Get the secrets manager Arc for sharing across tasks |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The secrets_manager_arc() method lacks documentation. Public API methods should have doc comments explaining their purpose, especially when they're added to expose internal state for specific use cases.
Add documentation:
/// Get the secrets manager Arc for sharing across tasks
///
/// Returns a cloned Arc to the secrets manager, allowing it to be shared
/// with other components such as the IPC server.
pub fn secrets_manager_arc(&self) -> Arc<SecretsManager> {
Arc::clone(&self.secrets_manager)
}| /// Get the secrets manager Arc for sharing across tasks | |
| /// Get the secrets manager Arc for sharing across tasks | |
| /// | |
| /// Returns a cloned `Arc` to the secrets manager, allowing it to be shared | |
| /// with other components such as the IPC server. |
src/main.rs
Outdated
| // Spawn IPC server in background | ||
| let _ipc_handle = tokio::spawn(async move { | ||
| if let Err(e) = ipc_server.start().await { | ||
| tracing::error!("IPC server failed: {}", e); |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The IPC server is spawned in a background task, but the task handle is prefixed with _ and not stored, meaning the server cannot be gracefully shut down when the main application exits. If the main process terminates, the IPC server task will be abruptly terminated, potentially leaving the socket file without cleanup.
Consider storing the task handle and implementing proper shutdown coordination:
let ipc_handle = tokio::spawn(async move {
if let Err(e) = ipc_server.start().await {
tracing::error!("IPC server failed: {}", e);
}
});
// Store ipc_handle for later graceful shutdown| // Spawn IPC server in background | |
| let _ipc_handle = tokio::spawn(async move { | |
| if let Err(e) = ipc_server.start().await { | |
| tracing::error!("IPC server failed: {}", e); | |
| // Spawn IPC server in background with graceful shutdown support | |
| use tokio::sync::oneshot; | |
| let (ipc_shutdown_tx, ipc_shutdown_rx) = oneshot::channel(); | |
| let ipc_handle = tokio::spawn(async move { | |
| tokio::select! { | |
| res = ipc_server.start() => { | |
| if let Err(e) = res { | |
| tracing::error!("IPC server failed: {}", e); | |
| } | |
| } | |
| _ = ipc_shutdown_rx => { | |
| tracing::info!("IPC server received shutdown signal"); | |
| // Perform any necessary cleanup here if needed | |
| } |
All review comments have been addressed in commit 4e1bd8b: ✅ Removed unused All tests passing (6 unit tests + 6 integration tests). |
- Add IPC server module (crates/wassette/src/ipc_server.rs) - Unix domain socket server with SO_PEERCRED/LOCAL_PEERCRED authentication - JSON-based request/response protocol (ping, set_secret, delete_secret, list_secrets) - Proper socket permissions (0700 directory, 0600 socket) - Integration with main.rs to start IPC server alongside MCP server - Add unit tests and integration tests - Platform-specific support for Linux and macOS (Windows stub) Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
- Add test_ipc_server_graceful_shutdown test - Add test_ipc_server_cleanup_on_drop test - Complete manual testing with netcat - Verify all IPC commands work correctly - Verify socket permissions (0600 socket, 0700 directory) - All acceptance criteria met for Unix/macOS Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
- Remove unused Win32_System_Pipes feature from Windows dependencies - Add module documentation clarifying Windows stub status - Redact secret values from debug logs (log command type only) - Add platform-specific cfg for verify_peer_identity (Linux/macOS only) - Handle JSON serialization errors gracefully (no unwrap) - Add ensure_secrets_dir() calls in unit tests - Fix matches! assertion to actually check the result - Improve log message clarity (Starting vs Started) - Update graceful shutdown test comments for clarity Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
4e1bd8b to
0b0398e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Implementation Plan for IPC Server Infrastructure
Overview
Implementing foundational IPC server infrastructure for dynamic secret management in Wassette using Unix domain sockets (Unix/macOS) and named pipes (Windows).
Tasks
crates/wassette/src/ipc_server.rswith core IPC server implementationsrc/main.rsto start IPC server alongside MCP server inCommands::ServeCode Review Changes (commit hash will be in reply)
All review comments have been addressed:
Win32_System_Pipesfeature from Windows dependenciescfgforverify_peer_identity(Linux/macOS only)unwrap()calls on JSON serialization - now handles errors gracefullyensure_secrets_dir()calls in all unit tests that set secretsmatches!assertion to actually verify the resultManual Testing Results
All tests passed successfully:
Example Manual Test Session:
Security Considerations
Testing Strategy
Acceptance Criteria Status
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.