docs: Add comprehensive project documentation from claude-projects scan
Added: - PROJECTS_INDEX.md - Master catalog of 7 active projects - GURURMM_API_ACCESS.md - Complete API documentation and credentials - clients/dataforth/dos-test-machines/README.md - DOS update system docs - clients/grabb-durando/website-migration/README.md - Migration procedures - clients/internal-infrastructure/ix-server-issues-2026-01-13.md - Server issues - projects/msp-tools/guru-connect/README.md - Remote desktop architecture - projects/msp-tools/toolkit/README.md - MSP PowerShell tools - projects/internal/acg-website-2025/README.md - Website rebuild docs - test_gururmm_api.py - GuruRMM API testing script Modified: - credentials.md - Added GuruRMM database and API credentials - GuruRMM agent integration files (WebSocket transport) Total: 38,000+ words of comprehensive project documentation Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
625
projects/gururmm-agent/TESTING_AND_DEPLOYMENT.md
Normal file
625
projects/gururmm-agent/TESTING_AND_DEPLOYMENT.md
Normal file
@@ -0,0 +1,625 @@
|
||||
# GuruRMM Agent - Claude Integration Testing & Deployment Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This guide covers testing and deployment of the Claude Code integration for the GuruRMM agent running on AD2 (Windows Server 2022).
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### On Development Machine
|
||||
- Rust toolchain (1.70+)
|
||||
- cargo installed
|
||||
- Git for Windows (for testing)
|
||||
|
||||
### On AD2 Server
|
||||
- Claude Code CLI installed and in PATH
|
||||
- GuruRMM agent service installed
|
||||
- Access to C:\Shares\test\ directory
|
||||
- Administrator privileges for service restart
|
||||
|
||||
---
|
||||
|
||||
## Local Testing (Development Machine)
|
||||
|
||||
### Step 1: Build the Project
|
||||
|
||||
```bash
|
||||
cd agent
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
[OK] Compiling gururmm-agent v0.1.0
|
||||
[OK] Finished release [optimized] target(s) in X.XXs
|
||||
```
|
||||
|
||||
### Step 2: Run Unit Tests
|
||||
|
||||
```bash
|
||||
cargo test
|
||||
```
|
||||
|
||||
**Expected tests to pass:**
|
||||
- `test_sanitize_task_input_valid`
|
||||
- `test_sanitize_task_input_empty`
|
||||
- `test_sanitize_task_input_injection`
|
||||
- `test_sanitize_task_input_too_long`
|
||||
- `test_rate_limiter_allows_under_limit`
|
||||
|
||||
### Step 3: Run Clippy (Linter)
|
||||
|
||||
```bash
|
||||
cargo clippy -- -D warnings
|
||||
```
|
||||
|
||||
**Should show no warnings or errors**
|
||||
|
||||
### Step 4: Format Check
|
||||
|
||||
```bash
|
||||
cargo fmt -- --check
|
||||
```
|
||||
|
||||
**Should show no formatting issues**
|
||||
|
||||
---
|
||||
|
||||
## Integration Testing (On AD2 Server)
|
||||
|
||||
### Test 1: Simple Task Execution
|
||||
|
||||
**Test Command via GuruRMM API:**
|
||||
|
||||
```bash
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "List all PowerShell files in the current directory",
|
||||
"working_directory": "C:\\Shares\\test\\scripts"
|
||||
}'
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"status": "completed",
|
||||
"output": "Found 3 PowerShell files:\n1. sync-from-nas.ps1\n2. import.ps1\n3. test-connection.ps1",
|
||||
"error": null,
|
||||
"duration_seconds": 12,
|
||||
"files_analyzed": []
|
||||
}
|
||||
```
|
||||
|
||||
### Test 2: Task with Context Files
|
||||
|
||||
**Test Command:**
|
||||
|
||||
```bash
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "Analyze this log for errors in the last 24 hours",
|
||||
"working_directory": "C:\\Shares\\test\\scripts",
|
||||
"context_files": ["sync-from-nas.log"]
|
||||
}'
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"status": "completed",
|
||||
"output": "Analysis complete. Found 2 errors:\n1. [2026-01-21 14:32] Connection timeout to NAS\n2. [2026-01-21 18:15] File copy failed: insufficient space",
|
||||
"error": null,
|
||||
"duration_seconds": 18,
|
||||
"files_analyzed": ["C:\\Shares\\test\\scripts\\sync-from-nas.log"]
|
||||
}
|
||||
```
|
||||
|
||||
### Test 3: Invalid Working Directory (Security Test)
|
||||
|
||||
**Test Command:**
|
||||
|
||||
```bash
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "List files",
|
||||
"working_directory": "C:\\Windows\\System32"
|
||||
}'
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"error": "[ERROR] Working directory 'C:\\Windows\\System32' is outside allowed path 'C:\\Shares\\test'"
|
||||
}
|
||||
```
|
||||
|
||||
### Test 4: Command Injection Attempt (Security Test)
|
||||
|
||||
**Test Command:**
|
||||
|
||||
```bash
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "List files; Remove-Item C:\\important.txt"
|
||||
}'
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"error": "[ERROR] Task contains forbidden character ';' that could be used for command injection"
|
||||
}
|
||||
```
|
||||
|
||||
### Test 5: Timeout Handling
|
||||
|
||||
**Test Command:**
|
||||
|
||||
```bash
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "Analyze this extremely complex codebase with deep reasoning",
|
||||
"working_directory": "C:\\Shares\\test",
|
||||
"timeout": 10
|
||||
}'
|
||||
```
|
||||
|
||||
**Expected Response (if Claude takes >10 seconds):**
|
||||
```json
|
||||
{
|
||||
"status": "timeout",
|
||||
"output": null,
|
||||
"error": "[ERROR] Claude Code execution timed out after 10 seconds",
|
||||
"duration_seconds": 10,
|
||||
"files_analyzed": []
|
||||
}
|
||||
```
|
||||
|
||||
### Test 6: Rate Limiting
|
||||
|
||||
**Test Command (execute 11 times rapidly):**
|
||||
|
||||
```bash
|
||||
# Execute this command 11 times in quick succession
|
||||
for i in {1..11}; do
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "Echo test '$i'"
|
||||
}'
|
||||
done
|
||||
```
|
||||
|
||||
**Expected Behavior:**
|
||||
- First 10 requests: Execute successfully
|
||||
- 11th request: Returns rate limit error
|
||||
|
||||
**Expected Response (11th request):**
|
||||
```json
|
||||
{
|
||||
"error": "[ERROR] Rate limit exceeded: Maximum 10 tasks per hour"
|
||||
}
|
||||
```
|
||||
|
||||
### Test 7: Concurrent Execution Limit
|
||||
|
||||
**Test Command (execute 3 simultaneously with long-running tasks):**
|
||||
|
||||
```bash
|
||||
# Terminal 1
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "Complex analysis that takes 60 seconds",
|
||||
"timeout": 120
|
||||
}' &
|
||||
|
||||
# Terminal 2 (immediately after)
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "Another complex analysis",
|
||||
"timeout": 120
|
||||
}' &
|
||||
|
||||
# Terminal 3 (immediately after)
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "Third task should be rejected",
|
||||
"timeout": 120
|
||||
}'
|
||||
```
|
||||
|
||||
**Expected Behavior:**
|
||||
- First 2 requests: Execute concurrently
|
||||
- 3rd request: Returns concurrent limit error
|
||||
|
||||
**Expected Response (3rd request):**
|
||||
```json
|
||||
{
|
||||
"error": "[ERROR] Concurrent task limit exceeded: Maximum 2 tasks"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment Process
|
||||
|
||||
### Step 1: Build Release Binary
|
||||
|
||||
**On development machine or build server:**
|
||||
|
||||
```powershell
|
||||
cd agent
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
**Binary location:** `agent\target\release\gururmm-agent.exe`
|
||||
|
||||
### Step 2: Stop GuruRMM Agent Service on AD2
|
||||
|
||||
```powershell
|
||||
# Connect to AD2 via RDP or SSH
|
||||
# Open PowerShell as Administrator
|
||||
|
||||
Stop-Service -Name "gururmm-agent" -Force
|
||||
```
|
||||
|
||||
**Verify service stopped:**
|
||||
```powershell
|
||||
Get-Service -Name "gururmm-agent"
|
||||
# Should show Status: Stopped
|
||||
```
|
||||
|
||||
### Step 3: Backup Existing Agent Binary
|
||||
|
||||
```powershell
|
||||
$backupPath = "C:\Program Files\GuruRMM\backups\gururmm-agent-$(Get-Date -Format 'yyyy-MM-dd-HHmmss').exe"
|
||||
Copy-Item "C:\Program Files\GuruRMM\gururmm-agent.exe" -Destination $backupPath
|
||||
Write-Output "[OK] Backup created: $backupPath"
|
||||
```
|
||||
|
||||
### Step 4: Deploy New Binary
|
||||
|
||||
```powershell
|
||||
# Copy new binary from development machine to AD2
|
||||
# (Use RDP copy-paste, SCP, or network share)
|
||||
|
||||
Copy-Item "\\dev-machine\share\gururmm-agent.exe" -Destination "C:\Program Files\GuruRMM\gururmm-agent.exe" -Force
|
||||
Write-Output "[OK] New binary deployed"
|
||||
```
|
||||
|
||||
### Step 5: Verify Binary Integrity
|
||||
|
||||
```powershell
|
||||
# Check file size and modification date
|
||||
Get-Item "C:\Program Files\GuruRMM\gururmm-agent.exe" | Select-Object Name, Length, LastWriteTime
|
||||
```
|
||||
|
||||
### Step 6: Start GuruRMM Agent Service
|
||||
|
||||
```powershell
|
||||
Start-Service -Name "gururmm-agent"
|
||||
```
|
||||
|
||||
**Verify service started:**
|
||||
```powershell
|
||||
Get-Service -Name "gururmm-agent"
|
||||
# Should show Status: Running
|
||||
```
|
||||
|
||||
### Step 7: Check Service Logs
|
||||
|
||||
```powershell
|
||||
# View recent logs
|
||||
Get-Content "C:\Program Files\GuruRMM\logs\agent.log" -Tail 50
|
||||
```
|
||||
|
||||
**Look for:**
|
||||
```
|
||||
[OK] GuruRMM Agent started successfully
|
||||
[OK] WebSocket connection established to 172.16.3.30:3001
|
||||
[OK] Claude task executor initialized
|
||||
```
|
||||
|
||||
### Step 8: Run Smoke Test
|
||||
|
||||
```bash
|
||||
# From any machine with access to GuruRMM API
|
||||
curl -X POST "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command_type": "claude_task",
|
||||
"task": "Echo deployment verification test",
|
||||
"working_directory": "C:\\Shares\\test"
|
||||
}'
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"status": "completed",
|
||||
"output": "Deployment verification test complete",
|
||||
"error": null,
|
||||
"duration_seconds": 5,
|
||||
"files_analyzed": []
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rollback Process
|
||||
|
||||
If deployment fails or issues are detected:
|
||||
|
||||
### Step 1: Stop Service
|
||||
|
||||
```powershell
|
||||
Stop-Service -Name "gururmm-agent" -Force
|
||||
```
|
||||
|
||||
### Step 2: Restore Previous Binary
|
||||
|
||||
```powershell
|
||||
# Find latest backup
|
||||
$latestBackup = Get-ChildItem "C:\Program Files\GuruRMM\backups\" |
|
||||
Sort-Object LastWriteTime -Descending |
|
||||
Select-Object -First 1
|
||||
|
||||
Copy-Item $latestBackup.FullName -Destination "C:\Program Files\GuruRMM\gururmm-agent.exe" -Force
|
||||
Write-Output "[OK] Restored backup: $($latestBackup.Name)"
|
||||
```
|
||||
|
||||
### Step 3: Restart Service
|
||||
|
||||
```powershell
|
||||
Start-Service -Name "gururmm-agent"
|
||||
Get-Service -Name "gururmm-agent"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Service won't start after deployment
|
||||
|
||||
**Symptoms:**
|
||||
```
|
||||
Start-Service : Service 'gururmm-agent' failed to start
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
1. Check event logs: `Get-EventLog -LogName Application -Source "gururmm-agent" -Newest 10`
|
||||
2. Check agent logs: `Get-Content "C:\Program Files\GuruRMM\logs\agent.log" -Tail 100`
|
||||
3. Verify binary is correct architecture (x64)
|
||||
4. Check dependencies: `dumpbin /dependents gururmm-agent.exe`
|
||||
5. Rollback to previous version if needed
|
||||
|
||||
### Issue: Claude tasks fail with "command not found"
|
||||
|
||||
**Symptoms:**
|
||||
```json
|
||||
{
|
||||
"status": "failed",
|
||||
"error": "[ERROR] Failed to spawn Claude Code process: program not found"
|
||||
}
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
1. Verify Claude Code is installed: `claude --version`
|
||||
2. Check PATH environment variable: `$env:PATH`
|
||||
3. Add Claude to system PATH if missing
|
||||
4. Restart agent service after PATH changes
|
||||
|
||||
### Issue: Working directory validation fails
|
||||
|
||||
**Symptoms:**
|
||||
```json
|
||||
{
|
||||
"error": "[ERROR] Invalid working directory 'C:\\Shares\\test\\scripts': Access is denied"
|
||||
}
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
1. Verify directory exists: `Test-Path "C:\Shares\test\scripts"`
|
||||
2. Check permissions: `Get-Acl "C:\Shares\test\scripts"`
|
||||
3. Ensure agent service account has read access
|
||||
4. Create directory if missing: `New-Item -ItemType Directory -Path "C:\Shares\test\scripts"`
|
||||
|
||||
### Issue: Rate limiting not working correctly
|
||||
|
||||
**Symptoms:**
|
||||
- More than 10 tasks execute in one hour
|
||||
|
||||
**Solution:**
|
||||
1. Verify system time is correct: `Get-Date`
|
||||
2. Check agent logs for rate limiter initialization
|
||||
3. Restart agent service to reset rate limiter state
|
||||
|
||||
---
|
||||
|
||||
## Monitoring & Maintenance
|
||||
|
||||
### Log Rotation
|
||||
|
||||
Configure log rotation to prevent disk space issues:
|
||||
|
||||
```powershell
|
||||
# Add to scheduled task (daily)
|
||||
$logFile = "C:\Program Files\GuruRMM\logs\agent.log"
|
||||
if ((Get-Item $logFile).Length -gt 10MB) {
|
||||
Move-Item $logFile "$logFile.old" -Force
|
||||
Restart-Service -Name "gururmm-agent"
|
||||
}
|
||||
```
|
||||
|
||||
### Performance Monitoring
|
||||
|
||||
Monitor Claude task execution metrics:
|
||||
|
||||
```powershell
|
||||
# Query GuruRMM API for task statistics
|
||||
curl "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/stats"
|
||||
```
|
||||
|
||||
**Key metrics to watch:**
|
||||
- Average task duration
|
||||
- Success rate
|
||||
- Timeout rate
|
||||
- Rate limit hits
|
||||
- Concurrent task rejections
|
||||
|
||||
### Regular Testing
|
||||
|
||||
Schedule automated tests (weekly):
|
||||
|
||||
```powershell
|
||||
# test-claude-integration.ps1
|
||||
$testResult = Invoke-RestMethod -Uri "http://172.16.3.30:3001/api/agents/{AD2_AGENT_ID}/command" `
|
||||
-Method Post `
|
||||
-ContentType "application/json" `
|
||||
-Body '{
|
||||
"command_type": "claude_task",
|
||||
"task": "Weekly integration test",
|
||||
"working_directory": "C:\\Shares\\test"
|
||||
}'
|
||||
|
||||
if ($testResult.status -eq "completed") {
|
||||
Write-Output "[OK] Weekly Claude integration test passed"
|
||||
} else {
|
||||
Write-Output "[ERROR] Weekly Claude integration test failed"
|
||||
# Send alert email
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Working Directory Restriction
|
||||
|
||||
The agent restricts Claude tasks to `C:\Shares\test\` and subdirectories. This prevents:
|
||||
- Access to system files
|
||||
- Access to sensitive configuration
|
||||
- Lateral movement attacks
|
||||
|
||||
**To modify allowed paths:**
|
||||
1. Edit `agent/src/claude.rs`
|
||||
2. Change `DEFAULT_WORKING_DIR` constant
|
||||
3. Rebuild and redeploy
|
||||
|
||||
### Command Injection Prevention
|
||||
|
||||
The agent sanitizes task inputs by blocking:
|
||||
- Shell metacharacters: `& | ; $ ( ) < >`
|
||||
- Newlines and carriage returns
|
||||
- Backticks and command substitution
|
||||
|
||||
**These are blocked for security** - do not disable.
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
Prevents abuse:
|
||||
- Max 10 tasks per hour per agent
|
||||
- Max 2 concurrent tasks
|
||||
- Prevents resource exhaustion
|
||||
- Mitigates DoS attacks
|
||||
|
||||
**To adjust limits:**
|
||||
1. Edit `agent/src/claude.rs`
|
||||
2. Modify `MAX_TASKS_PER_WINDOW` and `MAX_CONCURRENT_TASKS`
|
||||
3. Rebuild and redeploy
|
||||
|
||||
---
|
||||
|
||||
## Support & Contact
|
||||
|
||||
**Project:** GuruRMM Agent Claude Integration
|
||||
**Version:** 1.0.0
|
||||
**Date:** 2026-01-21
|
||||
**Author:** Coding Agent (Claude Sonnet 4.5)
|
||||
|
||||
For issues or questions:
|
||||
1. Check agent logs: `C:\Program Files\GuruRMM\logs\agent.log`
|
||||
2. Check GuruRMM server logs: `http://172.16.3.30:3001/logs`
|
||||
3. Review this documentation
|
||||
4. Contact GuruRMM support team
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Example API Responses
|
||||
|
||||
### Successful Task Execution
|
||||
```json
|
||||
{
|
||||
"status": "completed",
|
||||
"output": "Task completed successfully. Found 3 files with errors.",
|
||||
"error": null,
|
||||
"duration_seconds": 24,
|
||||
"files_analyzed": ["C:\\Shares\\test\\scripts\\sync-from-nas.log"]
|
||||
}
|
||||
```
|
||||
|
||||
### Task Failure
|
||||
```json
|
||||
{
|
||||
"status": "failed",
|
||||
"output": "Partial output before failure...",
|
||||
"error": "[ERROR] Claude Code exited with code 1: File not found: config.json",
|
||||
"duration_seconds": 8,
|
||||
"files_analyzed": []
|
||||
}
|
||||
```
|
||||
|
||||
### Task Timeout
|
||||
```json
|
||||
{
|
||||
"status": "timeout",
|
||||
"output": null,
|
||||
"error": "[ERROR] Claude Code execution timed out after 300 seconds",
|
||||
"duration_seconds": 300,
|
||||
"files_analyzed": ["C:\\Shares\\test\\large-log.txt"]
|
||||
}
|
||||
```
|
||||
|
||||
### Rate Limit Error
|
||||
```json
|
||||
{
|
||||
"error": "[ERROR] Rate limit exceeded: Maximum 10 tasks per hour"
|
||||
}
|
||||
```
|
||||
|
||||
### Concurrent Limit Error
|
||||
```json
|
||||
{
|
||||
"error": "[ERROR] Concurrent task limit exceeded: Maximum 2 tasks"
|
||||
}
|
||||
```
|
||||
|
||||
### Security Violation Error
|
||||
```json
|
||||
{
|
||||
"error": "[ERROR] Working directory 'C:\\Windows' is outside allowed path 'C:\\Shares\\test'"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**End of Testing & Deployment Guide**
|
||||
Reference in New Issue
Block a user