Compare commits
2 Commits
7c16b2bf4d
...
9af59158b2
| Author | SHA1 | Date | |
|---|---|---|---|
| 9af59158b2 | |||
| e118fe6698 |
109
REQUIREMENTS.md
109
REQUIREMENTS.md
@@ -690,3 +690,112 @@ When a machine is selected, show comprehensive info in side panel:
|
|||||||
- Single binary server (Docker or native)
|
- Single binary server (Docker or native)
|
||||||
- Single binary agent (MSI installer + standalone EXE)
|
- Single binary agent (MSI installer + standalone EXE)
|
||||||
- Cloud-hostable or on-premises
|
- Cloud-hostable or on-premises
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Team Feedback (2025-12-28)
|
||||||
|
|
||||||
|
### Howard's Requirements
|
||||||
|
|
||||||
|
#### Core Remote Support & Access Capabilities
|
||||||
|
|
||||||
|
1. **Screen Sharing & Remote Control**
|
||||||
|
- View and interact with the end-user's desktop in real time
|
||||||
|
- Technicians can control mouse and keyboard, just like sitting at the remote machine
|
||||||
|
|
||||||
|
2. **Attended & Unattended Access**
|
||||||
|
- Attended support: on-demand support sessions where the user connects via a session code or link
|
||||||
|
- Unattended access: persistent remote connections that allow access anytime without user presence
|
||||||
|
|
||||||
|
3. **Session Management**
|
||||||
|
- Initiate, pause, transfer, and end remote sessions
|
||||||
|
- Session transfer: pass control of a session to another technician
|
||||||
|
- Session pause and idle timeout controls
|
||||||
|
|
||||||
|
4. **File & Clipboard Sharing**
|
||||||
|
- Drag-and-drop file transfer between local and remote systems
|
||||||
|
- Clipboard sharing for copy/paste between devices
|
||||||
|
|
||||||
|
5. **Multi-Session Handling**
|
||||||
|
- Technicians can manage multiple concurrent remote sessions
|
||||||
|
|
||||||
|
6. **Multi-Monitor Support**
|
||||||
|
- Seamlessly switch between multiple monitors on the remote system
|
||||||
|
|
||||||
|
#### Advanced Support & Administrative Functions
|
||||||
|
|
||||||
|
7. **Backstage / Silent Support Mode**
|
||||||
|
- Execute tasks, run scripts, and troubleshoot without disrupting the user's screen (background session)
|
||||||
|
|
||||||
|
8. **Shared & Personal Toolboxes**
|
||||||
|
- Save commonly used tools, scripts, or executables
|
||||||
|
- Share them with team members for reuse in sessions
|
||||||
|
|
||||||
|
9. **Custom Scripts & Automation**
|
||||||
|
- Automate repetitive tasks during remote sessions
|
||||||
|
|
||||||
|
10. **Diagnostic & Command Tools**
|
||||||
|
- Run PowerShell, Command Prompt, view system event logs, uninstall apps, start/stop services, kill processes, etc.
|
||||||
|
- Better PowerShell/CMD running abilities with configurable timeouts (checkboxes/text boxes instead of typing every time)
|
||||||
|
|
||||||
|
#### Security & Access Control Features
|
||||||
|
|
||||||
|
11. **Encryption**
|
||||||
|
- All traffic is secured with AES-256 encryption
|
||||||
|
|
||||||
|
12. **Role-Based Permissions**
|
||||||
|
- Create granular technician roles and permissions to control who can do what
|
||||||
|
|
||||||
|
13. **Two-Factor & Login Security**
|
||||||
|
- Support for multi-factor authentication (MFA) and other secure login methodologies
|
||||||
|
|
||||||
|
14. **Session Consent & Alerts**
|
||||||
|
- Require end-user consent before connecting (configurable)
|
||||||
|
- Alerts notify users of maintenance or work in progress
|
||||||
|
|
||||||
|
15. **Audit Logs & Session Recording**
|
||||||
|
- Automatically record sessions
|
||||||
|
- Maintain detailed logs of connections and actions for compliance
|
||||||
|
|
||||||
|
#### Communication & Collaboration Tools
|
||||||
|
|
||||||
|
16. **Real-Time Chat**
|
||||||
|
- Text chat between technician and end user during sessions
|
||||||
|
|
||||||
|
17. **Screen Annotations**
|
||||||
|
- Draw and highlight areas on the user's screen for clearer instructions
|
||||||
|
|
||||||
|
#### Cross-Platform & Mobile Support
|
||||||
|
|
||||||
|
18. **Cross-Platform Support**
|
||||||
|
- Remote control across Windows, macOS, Linux, iOS, and Android
|
||||||
|
|
||||||
|
19. **Mobile Technician Support**
|
||||||
|
- Technicians can support clients from mobile devices (view screens, send Ctrl-Alt-Delete, reboot)
|
||||||
|
|
||||||
|
20. **Guest Mobile Support**
|
||||||
|
- Remote assistance for user Android and iOS devices
|
||||||
|
|
||||||
|
#### Integration & Customization
|
||||||
|
|
||||||
|
21. **PSA & Ticketing Integrations**
|
||||||
|
- Launch support sessions from RMM/PSA and other ticketing systems
|
||||||
|
|
||||||
|
22. **Custom Branding & Interface**
|
||||||
|
- White-labeling, logos, colors, and custom client titles
|
||||||
|
|
||||||
|
23. **Machine Organization & Search**
|
||||||
|
- Dynamic grouping of devices and custom property filtering to locate machines quickly
|
||||||
|
|
||||||
|
#### Reporting & Monitoring
|
||||||
|
|
||||||
|
24. **Session & System Reports**
|
||||||
|
- Audit logs, session histories, technician performance data, etc.
|
||||||
|
|
||||||
|
25. **Diagnostic Reporting**
|
||||||
|
- Collect performance and diagnostic information during or after sessions
|
||||||
|
|
||||||
|
### Additional Notes from Howard
|
||||||
|
|
||||||
|
- **64-bit client requirement** - ScreenConnect doesn't have a 64-bit client, which limits deployment options
|
||||||
|
- **PowerShell timeout controls** - Should have UI controls (checkboxes/text boxes) for timeouts rather than typing commands every time
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
/// Agent configuration
|
/// Agent configuration
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@@ -13,6 +14,10 @@ pub struct Config {
|
|||||||
/// Agent API key for authentication
|
/// Agent API key for authentication
|
||||||
pub api_key: String,
|
pub api_key: String,
|
||||||
|
|
||||||
|
/// Unique agent identifier (generated on first run)
|
||||||
|
#[serde(default = "generate_agent_id")]
|
||||||
|
pub agent_id: String,
|
||||||
|
|
||||||
/// Optional hostname override
|
/// Optional hostname override
|
||||||
pub hostname_override: Option<String>,
|
pub hostname_override: Option<String>,
|
||||||
|
|
||||||
@@ -25,6 +30,10 @@ pub struct Config {
|
|||||||
pub encoding: EncodingConfig,
|
pub encoding: EncodingConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_agent_id() -> String {
|
||||||
|
Uuid::new_v4().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct CaptureConfig {
|
pub struct CaptureConfig {
|
||||||
/// Target frames per second (1-60)
|
/// Target frames per second (1-60)
|
||||||
@@ -101,9 +110,15 @@ impl Config {
|
|||||||
let contents = std::fs::read_to_string(&config_path)
|
let contents = std::fs::read_to_string(&config_path)
|
||||||
.with_context(|| format!("Failed to read config from {:?}", config_path))?;
|
.with_context(|| format!("Failed to read config from {:?}", config_path))?;
|
||||||
|
|
||||||
let config: Config = toml::from_str(&contents)
|
let mut config: Config = toml::from_str(&contents)
|
||||||
.with_context(|| "Failed to parse config file")?;
|
.with_context(|| "Failed to parse config file")?;
|
||||||
|
|
||||||
|
// Ensure agent_id is set and saved
|
||||||
|
if config.agent_id.is_empty() {
|
||||||
|
config.agent_id = generate_agent_id();
|
||||||
|
let _ = config.save();
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(config);
|
return Ok(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,13 +129,22 @@ impl Config {
|
|||||||
let api_key = std::env::var("GURUCONNECT_API_KEY")
|
let api_key = std::env::var("GURUCONNECT_API_KEY")
|
||||||
.unwrap_or_else(|_| "dev-key".to_string());
|
.unwrap_or_else(|_| "dev-key".to_string());
|
||||||
|
|
||||||
Ok(Config {
|
let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
|
||||||
|
.unwrap_or_else(|_| generate_agent_id());
|
||||||
|
|
||||||
|
let config = Config {
|
||||||
server_url,
|
server_url,
|
||||||
api_key,
|
api_key,
|
||||||
|
agent_id,
|
||||||
hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
|
hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
|
||||||
capture: CaptureConfig::default(),
|
capture: CaptureConfig::default(),
|
||||||
encoding: EncodingConfig::default(),
|
encoding: EncodingConfig::default(),
|
||||||
})
|
};
|
||||||
|
|
||||||
|
// Save config with generated agent_id for persistence
|
||||||
|
let _ = config.save();
|
||||||
|
|
||||||
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the configuration file path
|
/// Get the configuration file path
|
||||||
@@ -182,6 +206,7 @@ pub fn example_config() -> &'static str {
|
|||||||
# Server connection
|
# Server connection
|
||||||
server_url = "wss://connect.example.com/ws"
|
server_url = "wss://connect.example.com/ws"
|
||||||
api_key = "your-agent-api-key"
|
api_key = "your-agent-api-key"
|
||||||
|
agent_id = "auto-generated-uuid"
|
||||||
|
|
||||||
# Optional: override hostname
|
# Optional: override hostname
|
||||||
# hostname_override = "custom-hostname"
|
# hostname_override = "custom-hostname"
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ impl SessionManager {
|
|||||||
|
|
||||||
let transport = WebSocketTransport::connect(
|
let transport = WebSocketTransport::connect(
|
||||||
&self.config.server_url,
|
&self.config.server_url,
|
||||||
|
&self.config.agent_id,
|
||||||
&self.config.api_key,
|
&self.config.api_key,
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
|
|||||||
@@ -29,17 +29,17 @@ pub struct WebSocketTransport {
|
|||||||
|
|
||||||
impl WebSocketTransport {
|
impl WebSocketTransport {
|
||||||
/// Connect to the server
|
/// Connect to the server
|
||||||
pub async fn connect(url: &str, api_key: &str) -> Result<Self> {
|
pub async fn connect(url: &str, agent_id: &str, api_key: &str) -> Result<Self> {
|
||||||
// Append API key as query parameter
|
// Append agent_id and API key as query parameters
|
||||||
let url_with_auth = if url.contains('?') {
|
let url_with_params = if url.contains('?') {
|
||||||
format!("{}&api_key={}", url, api_key)
|
format!("{}&agent_id={}&api_key={}", url, agent_id, api_key)
|
||||||
} else {
|
} else {
|
||||||
format!("{}?api_key={}", url, api_key)
|
format!("{}?agent_id={}&api_key={}", url, agent_id, api_key)
|
||||||
};
|
};
|
||||||
|
|
||||||
tracing::info!("Connecting to {}", url);
|
tracing::info!("Connecting to {} as agent {}", url, agent_id);
|
||||||
|
|
||||||
let (ws_stream, response) = connect_async(&url_with_auth)
|
let (ws_stream, response) = connect_async(&url_with_params)
|
||||||
.await
|
.await
|
||||||
.context("Failed to connect to WebSocket server")?;
|
.context("Failed to connect to WebSocket server")?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user