Add docs and project files - force for Culurien
This commit is contained in:
199
docs/3_BACKLOG/P1-001_Agent-Install-ID-Parsing-Issue.md
Normal file
199
docs/3_BACKLOG/P1-001_Agent-Install-ID-Parsing-Issue.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# P1-001: Agent Install ID Parsing Issue
|
||||
|
||||
**Priority:** P1 (Major)
|
||||
**Source Reference:** From needsfixingbeforepush.md line 3
|
||||
**Date Identified:** 2025-11-12
|
||||
|
||||
## Problem Description
|
||||
|
||||
The `generateInstallScript` function in downloads.go is not properly extracting the `agent_id` query parameter, causing the install script to always generate new agent IDs instead of using existing registered agent IDs for upgrades.
|
||||
|
||||
## Current Behavior
|
||||
|
||||
Install script downloads always generate new UUIDs instead of preserving existing agent IDs:
|
||||
|
||||
```bash
|
||||
# BEFORE (broken)
|
||||
curl -sfL "http://localhost:8080/api/v1/install/linux?agent_id=6fdba4c92c4d4d33a4010e98db0df72d8bbe3d62c6b7e0a33cef3325e29bdd6d"
|
||||
# Result: AGENT_ID="cf865204-125a-491d-976f-5829b6c081e6" (NEW UUID generated)
|
||||
```
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
For upgrade scenarios, the install script should preserve the existing agent ID passed via query parameter:
|
||||
|
||||
```bash
|
||||
# AFTER (fixed)
|
||||
curl -sfL "http://localhost:8080/api/v1/install/linux?agent_id=6fdba4c92c4d4d33a4010e98db0df72d8bbe3d62c6b7e0a33cef3325e29bdd6d"
|
||||
# Result: AGENT_ID="6fdba4c92c4d4d33a4010e98db0df72d8bbe3d62c6b7e0a33cef3325e29bdd6d" (PASSED UUID)
|
||||
```
|
||||
|
||||
## Root Cause Analysis
|
||||
|
||||
The `generateInstallScript` function only looks at query parameters but doesn't properly validate/extract the UUID format from the `agent_id` parameter. The function likely ignores or fails to parse the existing agent ID, falling back to generating a new UUID each time.
|
||||
|
||||
## Proposed Solution
|
||||
|
||||
Implement proper agent ID parsing with security validation following this priority order:
|
||||
|
||||
1. **Header:** `X-Agent-ID` (most secure, not exposed in URLs/logs)
|
||||
2. **Path:** `/api/v1/install/:platform/:agent_id` (legacy support)
|
||||
3. **Query:** `?agent_id=uuid` (fallback for current usage)
|
||||
|
||||
All paths must:
|
||||
- Validate UUID format before using
|
||||
- Enforce rate limiting on agent ID reuse
|
||||
- Apply signature validation for security
|
||||
|
||||
## Implementation Details
|
||||
|
||||
```go
|
||||
// Example fix in downloads.go
|
||||
func generateInstallScript(c *gin.Context) (string, error) {
|
||||
var agentID string
|
||||
|
||||
// Priority 1: Check header (most secure)
|
||||
if agentID = c.GetHeader("X-Agent-ID"); agentID != "" {
|
||||
if isValidUUID(agentID) {
|
||||
// Use header agent ID
|
||||
}
|
||||
}
|
||||
|
||||
// Priority 2: Check path parameter
|
||||
if agentID == "" {
|
||||
if agentID = c.Param("agent_id"); agentID != "" {
|
||||
if isValidUUID(agentID) {
|
||||
// Use path agent ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Priority 3: Check query parameter (current broken behavior)
|
||||
if agentID == "" {
|
||||
if agentID = c.Query("agent_id"); agentID != "" {
|
||||
if isValidUUID(agentID) {
|
||||
// Use query agent ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Generate new UUID if no valid agent ID provided
|
||||
if agentID == "" {
|
||||
agentID = generateNewUUID()
|
||||
}
|
||||
|
||||
// Generate install script with the determined agent ID
|
||||
return generateScriptTemplate(agentID), nil
|
||||
}
|
||||
```
|
||||
|
||||
## Definition of Done
|
||||
|
||||
- [ ] Install script preserves existing agent ID when provided via query parameter
|
||||
- [ ] Agent ID format validation (UUID v4) prevents malformed IDs
|
||||
- [ ] New UUID generated only when no valid agent ID is provided
|
||||
- [ ] Security validation prevents agent ID spoofing
|
||||
- [ ] Rate limiting prevents abuse of agent ID reuse
|
||||
- [ ] Backward compatibility maintained for existing install methods
|
||||
|
||||
## Test Plan
|
||||
|
||||
1. **Query Parameter Test:**
|
||||
```bash
|
||||
# Test with valid UUID in query parameter
|
||||
TEST_UUID="6fdba4c92c4d4d33a4010e98db0df72d8bbe3d62c6b7e0a33cef3325e29bdd6d"
|
||||
|
||||
curl -sfL "http://localhost:8080/api/v1/install/linux?agent_id=$TEST_UUID" | grep "AGENT_ID="
|
||||
|
||||
# Expected: AGENT_ID="$TEST_UUID" (same UUID)
|
||||
# Not: AGENT_ID="<new-generated-uuid>"
|
||||
```
|
||||
|
||||
2. **Invalid UUID Test:**
|
||||
```bash
|
||||
# Test with malformed UUID
|
||||
curl -sfL "http://localhost:8080/api/v1/install/linux?agent_id=invalid-uuid" | grep "AGENT_ID="
|
||||
|
||||
# Expected: AGENT_ID="<new-generated-uuid>" (rejects invalid, generates new)
|
||||
```
|
||||
|
||||
3. **Empty Parameter Test:**
|
||||
```bash
|
||||
# Test with empty agent_id parameter
|
||||
curl -sfL "http://localhost:8080/api/v1/install/linux?agent_id=" | grep "AGENT_ID="
|
||||
|
||||
# Expected: AGENT_ID="<new-generated-uuid>" (empty treated as not provided)
|
||||
```
|
||||
|
||||
4. **No Parameter Test:**
|
||||
```bash
|
||||
# Test without agent_id parameter (current behavior)
|
||||
curl -sfL "http://localhost:8080/api/v1/install/linux" | grep "AGENT_ID="
|
||||
|
||||
# Expected: AGENT_ID="<new-generated-uuid>" (maintain backward compatibility)
|
||||
```
|
||||
|
||||
5. **Security Validation Test:**
|
||||
```bash
|
||||
# Test with UUID validation edge cases
|
||||
curl -sfL "http://localhost:8080/api/v1/install/linux?agent_id=00000000-0000-0000-0000-000000000000" | grep "AGENT_ID="
|
||||
|
||||
# Should handle edge cases appropriately
|
||||
```
|
||||
|
||||
## Files to Modify
|
||||
|
||||
- `aggregator-server/internal/api/handlers/downloads.go` (main fix location)
|
||||
- Add UUID validation utility functions
|
||||
- Potentially update rate limiting logic for agent ID reuse
|
||||
- Add tests for install script generation
|
||||
|
||||
## Impact
|
||||
|
||||
- **Agent Upgrades:** Prevents agent identity loss during upgrades/reinstallation
|
||||
- **Agent Management:** Maintains consistent agent identity across system lifecycle
|
||||
- **Audit Trail:** Preserves agent history and command continuity
|
||||
- **User Experience:** Allows seamless agent reinstallation without re-registration
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Agent ID Spoofing:** Must validate that agent ID belongs to legitimate agent
|
||||
- **Rate Limiting:** Prevent abuse of agent ID reuse for malicious purposes
|
||||
- **Signature Validation:** Ensure agent ID requests are authenticated
|
||||
- **Audit Logging:** Log agent ID reuse attempts for security monitoring
|
||||
|
||||
## Upgrade Scenario Use Case
|
||||
|
||||
```bash
|
||||
# Agent needs upgrade/reinstallation on same machine
|
||||
# Admin provides existing agent ID to preserve history
|
||||
EXISTING_AGENT_ID="6fdba4c92c4d4d33a4010e98db0df72d8bbe3d62c6b7e0a33cef3325e29bdd6d"
|
||||
|
||||
# Install script preserves agent identity
|
||||
curl -sfL "http://redflag-server:8080/api/v1/install/linux?agent_id=$EXISTING_AGENT_ID" | sudo bash
|
||||
|
||||
# Result: Agent reinstalls with same ID, preserving:
|
||||
# - Command history
|
||||
# - Configuration settings
|
||||
# - Agent registration record
|
||||
# - Audit trail continuity
|
||||
```
|
||||
|
||||
## Verification Commands
|
||||
|
||||
After fix implementation:
|
||||
|
||||
```bash
|
||||
# Verify query parameter preservation
|
||||
UUID="6fdba4c92c4d4d33a4010e98db0df72d8bbe3d62c6b7e0a33cef3325e29bdd6d"
|
||||
SCRIPT=$(curl -sfL "http://localhost:8080/api/v1/install/linux?agent_id=$UUID")
|
||||
echo "$SCRIPT" | grep "AGENT_ID="
|
||||
|
||||
# Should output: AGENT_ID="6fdba4c92c4d4d33a4010e98db0df72d8bbe3d62c6b7e0a33cef3325e29bdd6d"
|
||||
|
||||
# Test invalid UUID rejection
|
||||
INVALID_SCRIPT=$(curl -sfL "http://localhost:8080/api/v1/install/linux?agent_id=invalid")
|
||||
echo "$INVALID_SCRIPT" | grep "AGENT_ID="
|
||||
|
||||
# Should output different UUID (generated new)
|
||||
```
|
||||
Reference in New Issue
Block a user