Files
wehub-resource-sync 161ef94b4f
Check engine pin consistency / Dockerfile / CI pin consistency (push) Successful in 8s
Sirius CI/CD Pipeline / Detect Changes (push) Successful in 23s
Validate Docker Configuration / Validate Docker Compose Configuration (push) Successful in 47s
Sirius CI/CD Pipeline / Build API (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Build UI (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Engine Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Merge API Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Merge UI Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Build Engine (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Build Infra (${{ matrix.service }}, ${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-postgres) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-rabbitmq) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-valkey) (push) Has been cancelled
Sirius CI/CD Pipeline / Integration Test (push) Has been cancelled
Sirius CI/CD Pipeline / Public Stack Contract (push) Has been cancelled
Sirius CI/CD Pipeline / Dispatch Demo Deployment (sirius-demo branch) (push) Has been cancelled
Sirius CI/CD Pipeline / Dispatch Demo Canary (main branch) (push) Has been cancelled
Sirius CI/CD Pipeline / Guard Registry Namespace (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:25 +08:00

751 lines
19 KiB
Markdown

---
title: "Go API SDK Architecture"
description: "Comprehensive guide to the Sirius Go API SDK architecture, design patterns, and integration"
template: "TEMPLATE.documentation-standard"
llm_context: "high"
categories: ["architecture", "sdk", "backend"]
tags: ["go", "api", "sdk", "database", "orm", "gorm"]
related_docs:
- "README.architecture.md"
- "../operations/README.sdk-releases.md"
- "../../../minor-projects/go-api/README.md"
search_keywords: ["go-api", "sdk", "gorm", "database", "models", "postgres", "rabbitmq", "valkey"]
---
# Go API SDK Architecture
## Overview
The **Sirius Go API SDK** (`github.com/SiriusScan/go-api`) is a shared library that provides:
- **Core data models** (Host, Port, Vulnerability, Service)
- **Database operations** (PostgreSQL via GORM)
- **Message queue integration** (RabbitMQ)
- **Key-value store** (ValKey/Redis)
- **NVD API integration** (vulnerability data enrichment)
**Design Principles:**
- **Shared Types**: Single source of truth for data structures
- **Abstraction**: Database and queue operations hidden behind clean APIs
- **Source Attribution**: Track which tool found each piece of data
- **Flexibility**: Works across multiple projects (scanner, API server, agents)
## Package Structure
```
go-api/
├── sirius/ # Core functionality
│ ├── sirius.go # Core types (Host, Port, Vulnerability, Service)
│ ├── postgres/ # Database operations
│ │ ├── connection.go # DB initialization and connection management
│ │ ├── host_operations.go # Host CRUD operations
│ │ ├── vulnerability_operations.go
│ │ └── models/ # Database models (GORM)
│ │ ├── host.go # Host, Port, Service models
│ │ ├── vulnerability.go # Vulnerability, CVE models
│ │ └── scan_source.go # Source attribution models
│ ├── host/ # Host management SDK
│ │ ├── host.go # Basic host operations
│ │ └── source_aware.go # Source-attributed operations
│ ├── queue/ # RabbitMQ integration
│ │ └── queue.go # Publish/subscribe operations
│ ├── store/ # Key-value store (ValKey/Redis)
│ │ └── store.go # KV operations
│ └── logging/ # Logging infrastructure
│ ├── client.go # Logging client
│ └── api/ # Logging API server
├── nvd/ # NVD API integration
│ └── nvd.go # CVE data fetching
├── migrations/ # Database schema migrations
└── docs/ # SDK documentation
```
## Core Data Models
### Host Model
**File:** `sirius/sirius.go`
```go
type Host struct {
HID string // Host identifier
OS string // Operating system
OSVersion string // OS version
IP string // IP address
Hostname string // DNS hostname
Ports []Port // Open ports
Services []Service // Running services
Vulnerabilities []Vulnerability // Found vulnerabilities
CPE []string // Common Platform Enumeration
Agent *SiriusAgent // Optional agent info
}
```
### Port Model
**File:** `sirius/sirius.go` (Core), `sirius/postgres/models/host.go` (Database)
```go
// Core type (used by applications)
type Port struct {
Number int `json:"number"` // Port number (22, 80, 443, etc.)
Protocol string `json:"protocol"` // tcp, udp
State string `json:"state"` // open, closed, filtered
}
// Database model (used by GORM)
type Port struct {
gorm.Model // ID, CreatedAt, UpdatedAt, DeletedAt
Number int // Port number
Protocol string // Protocol
State string // State
Hosts []Host `gorm:"many2many:host_ports"`
HostPorts []HostPort `gorm:"foreignKey:PortID"`
}
```
**Key Design Decision:** Port numbers are stored in the `Number` field, NOT the auto-increment `ID` field. This allows the same port (e.g., port 22) to be associated with multiple hosts without conflicts.
### Vulnerability Model
**File:** `sirius/sirius.go` (Core), `sirius/postgres/models/vulnerability.go` (Database)
```go
// Core type
type Vulnerability struct {
VID string `json:"vid"` // CVE ID (CVE-2017-0144)
Title string `json:"title"` // Vulnerability title
Description string `json:"description"` // Description
RiskScore float64 `json:"risk_score"` // CVSS score (0-10)
}
// Database model
type Vulnerability struct {
gorm.Model
VID string `gorm:"column:v_id;uniqueIndex"` // Unique CVE ID
Description string
Title string
RiskScore float64
Hosts []Host `gorm:"many2many:host_vulnerabilities"`
HostVulnerabilities []HostVulnerability `gorm:"foreignKey:VulnerabilityID"`
}
```
## Source Attribution System
### Purpose
Track **which tool** found **which data** on **which host** at **what time**. This enables:
- **Audit trails**: Know where data came from
- **Tool comparison**: Compare effectiveness of different scanners
- **Historical tracking**: See when vulnerabilities first appeared
- **Confidence scoring**: Weight findings by source reliability
### Junction Tables with Source
**HostPort Junction Table:**
```go
type HostPort struct {
HostID uint `json:"host_id" gorm:"primaryKey"`
PortID uint `json:"port_id" gorm:"primaryKey"`
Source string `json:"source" gorm:"primaryKey"` // nmap, rustscan, naabu
SourceVersion string `json:"source_version"` // Tool version
FirstSeen time.Time `json:"first_seen"` // First detection
LastSeen time.Time `json:"last_seen"` // Last confirmation
Status string `json:"status" gorm:"default:active"` // active, resolved
Notes string `json:"notes,omitempty"` // Config details
}
```
**Primary Key:** `(host_id, port_id, source)` allows:
- Same port on same host tracked by multiple tools
- Comparison of results between tools
- Historical view of port states
**HostVulnerability Junction Table:**
Similar structure with additional fields:
- `Confidence` (0.0-1.0): How confident is this finding?
- `Port` (optional): Specific port where vulnerability found
- `ServiceInfo`: Service details
### Using Source Attribution
**Example: Add host with source:**
```go
import (
"github.com/SiriusScan/go-api/sirius"
"github.com/SiriusScan/go-api/sirius/host"
"github.com/SiriusScan/go-api/sirius/postgres/models"
)
// Create host data
hostData := sirius.Host{
IP: "192.168.1.100",
Ports: []sirius.Port{
{Number: 22, Protocol: "tcp", State: "open"},
{Number: 80, Protocol: "tcp", State: "open"},
},
}
// Create source metadata
source := models.ScanSource{
Name: "nmap",
Version: "7.94",
Config: "ports:1-1000;template:quick;timing:T4",
}
// Submit with source attribution
err := host.AddHostWithSource(hostData, source)
```
## Database Operations
### Connection Management
**File:** `sirius/postgres/connection.go`
```go
// Get database connection (singleton)
db := postgres.GetDB()
// Initialize schema
err := postgres.InitDB()
```
**Environment Variables:**
- `DATABASE_HOST` (default: `localhost`)
- `DATABASE_PORT` (default: `5432`)
- `DATABASE_USER` (default: `postgres`)
- `DATABASE_PASSWORD` (default: `postgres`)
- `DATABASE_NAME` (default: `sirius`)
### Host Operations
**Basic Operations (Legacy):**
```go
import "github.com/SiriusScan/go-api/sirius/host"
// Add or update host
err := host.AddHost(hostData)
// Get host by IP
hostData, err := host.GetHost("192.168.1.100")
// Get all hosts
hosts, err := host.GetAllHosts()
// Delete host
err := host.DeleteHost("192.168.1.100")
```
**Source-Aware Operations (Recommended):**
```go
// Add/update with source tracking
err := host.AddHostWithSource(hostData, source)
// Get host with all source attributions
hostWithSources, err := host.GetHostWithSources("192.168.1.100")
// Get vulnerability history by source
history, err := host.GetVulnerabilityHistory(hostID, vulnID)
// Get source coverage statistics
stats, err := host.GetSourceCoverageStats()
```
### Mapping Between Core and Database Types
**File:** `sirius/host/host.go`
```go
// Convert database model to core type
siriusHost := host.MapDBHostToSiriusHost(dbHost)
// Convert core type to database model
dbHost := host.MapSiriusHostToDBHost(siriusHost)
```
**Important:** These functions handle:
- Port.Number ↔ Port field mapping
- Relationship loading (ports, services, vulnerabilities)
- Type conversions
## Message Queue Integration
### RabbitMQ
**File:** `sirius/queue/queue.go`
```go
import "github.com/SiriusScan/go-api/sirius/queue"
// Publish message to queue
err := queue.Publish("scan", scanMessage)
// Listen for messages
queue.Listen("scan", func(msg string) {
// Process message
})
```
**Environment Variables:**
- `RABBITMQ_HOST` (default: `localhost`)
- `RABBITMQ_PORT` (default: `5672`)
- `RABBITMQ_USER` (default: `guest`)
- `RABBITMQ_PASSWORD` (default: `guest`)
**Common Queues:**
- `scan` - Scan requests
- `scanner_logs` - Scanner log events
- `agent_commands` - Agent commands
- `terminal` - Terminal commands
## Key-Value Store Integration
### ValKey/Redis
**File:** `sirius/store/store.go`
```go
import "github.com/SiriusScan/go-api/sirius/store"
// Set value
err := store.SetValue(ctx, "key", "value")
// Get value
result, err := store.GetValue(ctx, "key")
// Delete value
err := store.DeleteValue(ctx, "key")
// List keys
keys, err := store.ListKeys(ctx, "pattern:*")
```
**Environment Variables:**
- `VALKEY_HOST` (default: `localhost`)
- `VALKEY_PORT` (default: `6379`)
**Common Use Cases:**
- Real-time scan progress tracking
- Template storage (scan templates)
- Temporary data caching
## NVD Integration
### CVE Data Enrichment
**File:** `nvd/nvd.go`
```go
import "github.com/SiriusScan/go-api/nvd"
// Fetch CVE details from NVD
cveData, err := nvd.GetCVE("CVE-2017-0144")
// Access CVSS scores
score := cveData.Metrics.CvssMetricV31[0].CvssData.BaseScore
```
**Rate Limiting:** NVD API has rate limits. SDK respects these limits.
## Integration Patterns
### Pattern 1: Local Development with Replace Directive
**Use Case:** Developing changes to go-api and dependent project simultaneously
**go.mod:**
```go
module github.com/SiriusScan/app-scanner
replace github.com/SiriusScan/go-api => ../go-api // Local development
require (
github.com/SiriusScan/go-api v0.0.11 // Version for production
)
```
**Benefits:**
- Test SDK changes immediately
- No need to publish SDK for every test
- Easy debugging across projects
### Pattern 2: Production Use with Versioned Import
**Use Case:** Production deployments
**go.mod:**
```go
module github.com/SiriusScan/app-scanner
require (
github.com/SiriusScan/go-api v0.0.11 // Specific version
)
```
**Benefits:**
- Reproducible builds
- Version pinning
- Explicit dependency management
### Pattern 3: Container Development with Volume Mounts
**Use Case:** Docker-based development (sirius-engine, sirius-api)
**docker-compose.dev.yaml:**
```yaml
services:
sirius-engine:
volumes:
- ../minor-projects/go-api:/go-api:ro # Mount SDK source
- ../minor-projects/app-scanner:/app-scanner
```
**go.mod in container:**
```go
replace github.com/SiriusScan/go-api => /go-api
```
**Benefits:**
- Live code reload
- No rebuild for SDK changes
- Mirrors local development
## Version Management
### Semantic Versioning
**Format:** `v{MAJOR}.{MINOR}.{PATCH}`
**Rules:**
- **MAJOR** (0.x.x → 1.x.x): Breaking changes, incompatible API changes
- **MINOR** (x.0.x → x.1.x): New features, backward compatible
- **PATCH** (x.x.0 → x.x.1): Bug fixes, backward compatible
**Current:** v0.0.11 (pre-1.0, unstable API)
### Breaking Change Policy
**What Constitutes a Breaking Change:**
- ✅ Renaming exported fields (e.g., `Port.ID``Port.Number`)
- ✅ Changing function signatures
- ✅ Removing exported functions/types
- ✅ Changing database schema in non-backward-compatible way
- ❌ Adding new fields (backward compatible)
- ❌ Adding new functions (backward compatible)
- ❌ Internal implementation changes
**Communication:**
- Document in CHANGELOG.md with `BREAKING CHANGE:` prefix
- Include migration guide
- Increment version appropriately
- Notify dependent projects
### Compatibility Guarantees
**Before v1.0.0:**
- ⚠️ No API stability guaranteed
- Breaking changes may occur in patch releases
- Use exact version pinning in production
**After v1.0.0:**
- ✅ Semantic versioning strictly followed
- ✅ Breaking changes only in major versions
- ✅ Deprecation warnings before removal
## Development Workflow
### Making Changes to SDK
**1. Create feature branch:**
```bash
cd go-api
git checkout -b feature/my-change
```
**2. Make changes and test locally:**
```bash
# Edit files
go test ./...
go build ./...
```
**3. Test in dependent project:**
```bash
cd ../app-scanner
# Ensure replace directive points to ../go-api
go mod tidy
go build .
```
**4. Commit and push:**
```bash
cd ../go-api
git add .
git commit -m "feat: add new feature"
git push origin feature/my-change
```
**5. Create Pull Request**
**6. After merge to main:**
- CI/CD automatically creates new release
- Update dependent projects to new version
### Testing Changes
**Unit Tests:**
```bash
cd go-api
go test ./...
```
**Integration Tests:**
```bash
# Test with actual database
DATABASE_HOST=localhost go test ./sirius/postgres/...
# Test with actual RabbitMQ
RABBITMQ_HOST=localhost go test ./sirius/queue/...
```
**Manual Testing:**
```bash
# Use in dependent project with replace directive
cd app-scanner
go run main.go
```
### Contributing Guidelines
**Code Style:**
- Follow Go idioms and best practices
- Use `gofmt` for formatting
- Write meaningful commit messages (conventional commits)
- Add tests for new functionality
**Documentation:**
- Update CHANGELOG.md for user-facing changes
- Add godoc comments for exported types/functions
- Update SDK documentation for architectural changes
**Pull Requests:**
- Keep PRs focused and small
- Include test coverage
- Reference related issues
- Wait for CI/CD to pass
## Common Patterns & Best Practices
### Pattern: Bulk Operations
**Problem:** Need to process many hosts efficiently
**Solution:**
```go
// Use transactions for bulk operations
db := postgres.GetDB()
tx := db.Begin()
for _, hostData := range hosts {
dbHost := host.MapSiriusHostToDBHost(hostData)
if err := tx.Create(&dbHost).Error; err != nil {
tx.Rollback()
return err
}
}
tx.Commit()
```
### Pattern: Error Handling
**Problem:** Need consistent error handling
**Solution:**
```go
import "fmt"
// Wrap errors with context
if err != nil {
return fmt.Errorf("failed to add host %s: %w", ip, err)
}
// Check for specific errors
if errors.Is(err, gorm.ErrRecordNotFound) {
// Handle not found
}
```
### Pattern: Connection Pooling
**Problem:** Efficient database connections
**Solution:**
```go
// GetDB() returns singleton with connection pool
db := postgres.GetDB()
// Configure in connection.go:
sqlDB, _ := db.DB()
sqlDB.SetMaxOpenConns(25)
sqlDB.SetMaxIdleConns(5)
sqlDB.SetConnMaxLifetime(5 * time.Minute)
```
### Pattern: Graceful Shutdown
**Problem:** Clean up resources on exit
**Solution:**
```go
func main() {
// Initialize connections
db := postgres.GetDB()
// Handle shutdown
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c
// Cleanup
sqlDB, _ := db.DB()
sqlDB.Close()
}
```
## Troubleshooting
### Issue: "Module not found"
**Problem:**
```
go: github.com/SiriusScan/go-api@v0.0.11: invalid version: unknown revision v0.0.11
```
**Solutions:**
1. Check if version exists: `git ls-remote --tags https://github.com/SiriusScan/go-api`
2. Clear Go module cache: `go clean -modcache`
3. Use `replace` directive for local development
### Issue: "Undefined field after update"
**Problem:**
```
port.ID undefined (type sirius.Port has no field or method ID)
```
**Solution:**
- Check CHANGELOG.md for breaking changes
- Update code to use new field names (e.g., `port.Number`)
- Run `go mod tidy` after updating version
### Issue: Database connection fails
**Problem:**
```
failed to connect to database: connection refused
```
**Solution:**
1. Check environment variables are set correctly
2. Verify database is running: `docker ps | grep postgres`
3. Test connection: `psql -h localhost -U postgres -d sirius`
### Issue: "Duplicate key violation"
**Problem:**
```
ERROR: duplicate key value violates unique constraint "ports_pkey"
```
**Solution:**
- Ensure using SDK version ≥ v0.0.11 (fixes Port.ID conflict)
- Run migration 005_fix_critical_schema_issues
- Clear old data if necessary
## Migration Guides
### Migrating from v0.0.9/v0.0.10 to v0.0.11
**Breaking Changes:**
1. `Port.ID``Port.Number`
2. `CVEDataMeta.ID``CVEDataMeta.CVEIdentifier`
**Code Changes Required:**
**Before:**
```go
port := sirius.Port{
ID: 22,
Protocol: "tcp",
}
ports := make([]int, len(host.Ports))
for i, port := range host.Ports {
ports[i] = port.ID // ❌ No longer exists
}
```
**After:**
```go
port := sirius.Port{
Number: 22,
Protocol: "tcp",
}
ports := make([]int, len(host.Ports))
for i, port := range host.Ports {
ports[i] = port.Number // ✅ Correct
}
```
**Database Migration:**
```bash
# Run migration in container
docker exec sirius-engine bash -c "cd /tmp/migrations && go run 005_fix_critical_schema_issues/main.go"
```
**Verification:**
1. Update go.mod: `require github.com/SiriusScan/go-api v0.0.11`
2. Run: `go mod tidy`
3. Find all references: `grep -r "port\.ID" .`
4. Replace with `port.Number`
5. Test build: `go build ./...`
6. Run tests: `go test ./...`
## References
### Related Documentation
- [SDK Release Process](../operations/README.sdk-releases.md) - How to release new SDK versions
- [System Architecture](README.architecture.md) - Overall Sirius architecture
- [go-api README](../../../minor-projects/go-api/README.md) - SDK getting started guide
- [go-api CHANGELOG](../../../minor-projects/go-api/CHANGELOG.md) - Version history
### External Resources
- [GORM Documentation](https://gorm.io/docs/)
- [Go Module Reference](https://go.dev/ref/mod)
- [RabbitMQ Go Client](https://github.com/streadway/amqp)
- [ValKey Documentation](https://valkey.io/docs/)
---
**Last Updated:** 2025-10-26
**SDK Version:** v0.0.11
**Author:** Sirius Team