Files
ophion/internal/ai/insights.go
bigtux 547619a1a7 feat: Add JWT authentication and API key security
- Add users table for dashboard authentication (email, password_hash, role)
- Add api_keys table for agent authentication (key_hash, prefix, name)
- Implement JWT auth with 24h expiration
- Implement API key auth with SHA256 hashing
- Add auth endpoints: POST /api/v1/auth/login, POST /api/v1/auth/register
- Add API key endpoints: GET/POST/DELETE /api/v1/api-keys
- Protect all /api/v1/* routes (except /health and /auth/*)
- Create default admin user (admin@ophion.local)
- First registered user automatically becomes admin
- Use bcrypt for password hashing (cost 12)
- Use SHA256 for API key hashing
- Add security headers middleware
2026-02-06 14:37:04 -03:00

397 lines
10 KiB
Go

package ai
import (
"context"
"encoding/json"
"fmt"
)
// InsightsEngine motor de geração de insights
type InsightsEngine struct {
engine *AIEngine
}
// DailyInsights insights diários gerados pela IA
type DailyInsights struct {
Date string `json:"date"`
Summary string `json:"summary"`
Highlights []Highlight `json:"highlights"`
Concerns []Concern `json:"concerns"`
Improvements []Improvement `json:"improvements"`
CostAnalysis CostAnalysis `json:"cost_analysis"`
SecurityInsights []SecurityInsight `json:"security_insights"`
Predictions []Prediction `json:"predictions"`
Score HealthScore `json:"health_score"`
}
// Highlight destaque positivo
type Highlight struct {
Title string `json:"title"`
Description string `json:"description"`
Metric string `json:"metric"`
Value string `json:"value"`
}
// Concern preocupação identificada
type Concern struct {
Title string `json:"title"`
Description string `json:"description"`
Severity string `json:"severity"`
Affected []string `json:"affected"`
Suggestion string `json:"suggestion"`
}
// Improvement sugestão de melhoria
type Improvement struct {
Title string `json:"title"`
Description string `json:"description"`
ExpectedImpact string `json:"expected_impact"`
Effort string `json:"effort"` // low, medium, high
Priority int `json:"priority"`
}
// CostAnalysis análise de custos
type CostAnalysis struct {
TotalEstimated float64 `json:"total_estimated"`
ByResource map[string]float64 `json:"by_resource"`
WastedResources []WastedResource `json:"wasted_resources"`
SavingOpportunities []SavingOpportunity `json:"saving_opportunities"`
TrendVsLastMonth float64 `json:"trend_vs_last_month"`
}
// WastedResource recurso subutilizado
type WastedResource struct {
Resource string `json:"resource"`
Host string `json:"host"`
Usage float64 `json:"usage_percent"`
Suggestion string `json:"suggestion"`
PotentialSaving float64 `json:"potential_saving"`
}
// SavingOpportunity oportunidade de economia
type SavingOpportunity struct {
Description string `json:"description"`
Action string `json:"action"`
MonthlySaving float64 `json:"monthly_saving"`
Risk string `json:"risk"`
}
// SecurityInsight insight de segurança
type SecurityInsight struct {
Type string `json:"type"` // anomaly, vulnerability, compliance
Severity string `json:"severity"`
Title string `json:"title"`
Description string `json:"description"`
AffectedHosts []string `json:"affected_hosts"`
Recommendation string `json:"recommendation"`
References []string `json:"references"`
}
// Prediction previsão
type Prediction struct {
Metric string `json:"metric"`
Host string `json:"host"`
Current float64 `json:"current"`
Predicted float64 `json:"predicted"`
TimeFrame string `json:"time_frame"`
Confidence float64 `json:"confidence"`
Warning string `json:"warning"`
}
// HealthScore pontuação de saúde
type HealthScore struct {
Overall int `json:"overall"` // 0-100
Availability int `json:"availability"`
Performance int `json:"performance"`
Security int `json:"security"`
Trend string `json:"trend"` // improving, stable, declining
Explanation string `json:"explanation"`
}
// NewInsightsEngine cria novo engine de insights
func NewInsightsEngine(engine *AIEngine) *InsightsEngine {
return &InsightsEngine{engine: engine}
}
// GenerateDailyInsights gera insights diários
func (i *InsightsEngine) GenerateDailyInsights(ctx context.Context, data DailyData) (*DailyInsights, error) {
prompt := fmt.Sprintf(`Analise os dados das últimas 24 horas e gere insights acionáveis:
RESUMO DO DIA:
- Período: %s
- Total de hosts: %d
- Alertas disparados: %d
- Incidentes: %d
- Uptime médio: %.2f%%
MÉTRICAS AGREGADAS:
%s
TOP 5 HOSTS COM MAIS ALERTAS:
%s
DEPLOYS REALIZADOS:
%s
ERROS MAIS FREQUENTES NOS LOGS:
%s
CUSTOS ESTIMADOS:
- Compute: R$ %.2f
- Storage: R$ %.2f
- Network: R$ %.2f
Gere um relatório completo em JSON:
{
"date": "YYYY-MM-DD",
"summary": "resumo executivo do dia (2-3 frases)",
"highlights": [
{"title": "...", "description": "...", "metric": "...", "value": "..."}
],
"concerns": [
{"title": "...", "description": "...", "severity": "low|medium|high", "affected": ["host1"], "suggestion": "..."}
],
"improvements": [
{"title": "...", "description": "...", "expected_impact": "...", "effort": "low|medium|high", "priority": 1}
],
"cost_analysis": {
"total_estimated": 1234.56,
"wasted_resources": [
{"resource": "CPU", "host": "...", "usage_percent": 5.0, "suggestion": "...", "potential_saving": 100.0}
],
"saving_opportunities": [
{"description": "...", "action": "...", "monthly_saving": 200.0, "risk": "low"}
],
"trend_vs_last_month": 5.5
},
"security_insights": [
{"type": "anomaly|vulnerability|compliance", "severity": "...", "title": "...", "description": "...", "affected_hosts": [], "recommendation": "..."}
],
"predictions": [
{"metric": "disk.usage", "host": "...", "current": 70.0, "predicted": 95.0, "time_frame": "7 dias", "confidence": 0.85, "warning": "..."}
],
"health_score": {
"overall": 85,
"availability": 99,
"performance": 78,
"security": 82,
"trend": "improving|stable|declining",
"explanation": "..."
}
}`,
data.Period,
data.TotalHosts,
data.AlertsCount,
data.IncidentsCount,
data.AvgUptime,
data.MetricsSummary,
data.TopAlertHosts,
data.Deploys,
data.TopErrors,
data.CostCompute,
data.CostStorage,
data.CostNetwork,
)
response, err := i.engine.chat(ctx, prompt)
if err != nil {
return nil, err
}
var insights DailyInsights
if err := json.Unmarshal([]byte(response), &insights); err != nil {
return nil, fmt.Errorf("failed to parse insights: %w", err)
}
return &insights, nil
}
// DetectSecurityAnomalies detecta anomalias de segurança
func (i *InsightsEngine) DetectSecurityAnomalies(ctx context.Context, data SecurityData) ([]SecurityInsight, error) {
prompt := fmt.Sprintf(`Analise os dados de segurança e identifique anomalias ou ameaças:
LOGINS NAS ÚLTIMAS 24H:
%s
CONEXÕES DE REDE SUSPEITAS:
%s
MUDANÇAS DE CONFIGURAÇÃO:
%s
PROCESSOS INCOMUNS:
%s
FALHAS DE AUTENTICAÇÃO:
%s
Identifique:
1. Comportamentos anômalos
2. Possíveis tentativas de ataque
3. Violações de compliance
4. Configurações inseguras
Responda em JSON:
{
"insights": [
{
"type": "anomaly|vulnerability|compliance|intrusion_attempt",
"severity": "low|medium|high|critical",
"title": "título descritivo",
"description": "descrição detalhada",
"affected_hosts": ["host1"],
"evidence": "evidência encontrada",
"recommendation": "ação recomendada",
"references": ["CVE-xxx", "link"]
}
],
"risk_level": "low|medium|high|critical",
"requires_immediate_action": boolean
}`,
data.Logins,
data.SuspiciousConnections,
data.ConfigChanges,
data.UnusualProcesses,
data.AuthFailures,
)
response, err := i.engine.chat(ctx, prompt)
if err != nil {
return nil, err
}
var result struct {
Insights []SecurityInsight `json:"insights"`
}
if err := json.Unmarshal([]byte(response), &result); err != nil {
return nil, err
}
return result.Insights, nil
}
// DailyData dados para análise diária
type DailyData struct {
Period string
TotalHosts int
AlertsCount int
IncidentsCount int
AvgUptime float64
MetricsSummary string
TopAlertHosts string
Deploys string
TopErrors string
CostCompute float64
CostStorage float64
CostNetwork float64
}
// SecurityData dados para análise de segurança
type SecurityData struct {
Logins string
SuspiciousConnections string
ConfigChanges string
UnusualProcesses string
AuthFailures string
}
// GenerateExecutiveReport gera relatório executivo semanal/mensal
func (i *InsightsEngine) GenerateExecutiveReport(ctx context.Context, period string, data ReportData) (*ExecutiveReport, error) {
prompt := fmt.Sprintf(`Gere um relatório executivo de %s para liderança técnica:
PERÍODO: %s
KPIs:
- Uptime: %.2f%%
- MTTR: %s
- Incidentes: %d (vs período anterior: %+d)
- Alertas: %d
- Deploys: %d
PRINCIPAIS INCIDENTES:
%s
MELHORIAS IMPLEMENTADAS:
%s
CUSTOS:
%s
SEGURANÇA:
%s
Gere relatório executivo em JSON:
{
"period": "...",
"executive_summary": "resumo de 3-4 frases para C-level",
"key_metrics": {...},
"achievements": ["conquista 1", "conquista 2"],
"challenges": ["desafio 1", "desafio 2"],
"action_items": [
{"item": "...", "owner": "...", "due_date": "...", "priority": "high|medium|low"}
],
"next_period_focus": ["foco 1", "foco 2"],
"budget_status": {"current": 1000, "projected": 1200, "variance": "..."},
"risk_summary": "resumo de riscos"
}`,
period,
data.Period,
data.Uptime,
data.MTTR,
data.Incidents,
data.IncidentsDelta,
data.Alerts,
data.Deploys,
data.MainIncidents,
data.Improvements,
data.CostsSummary,
data.SecuritySummary,
)
response, err := i.engine.chat(ctx, prompt)
if err != nil {
return nil, err
}
var report ExecutiveReport
if err := json.Unmarshal([]byte(response), &report); err != nil {
return nil, err
}
return &report, nil
}
// ReportData dados para relatório executivo
type ReportData struct {
Period string
Uptime float64
MTTR string
Incidents int
IncidentsDelta int
Alerts int
Deploys int
MainIncidents string
Improvements string
CostsSummary string
SecuritySummary string
}
// ExecutiveReport relatório executivo
type ExecutiveReport struct {
Period string `json:"period"`
ExecutiveSummary string `json:"executive_summary"`
Achievements []string `json:"achievements"`
Challenges []string `json:"challenges"`
ActionItems []ActionItem `json:"action_items"`
NextPeriodFocus []string `json:"next_period_focus"`
RiskSummary string `json:"risk_summary"`
}
// ActionItem item de ação
type ActionItem struct {
Item string `json:"item"`
Owner string `json:"owner"`
DueDate string `json:"due_date"`
Priority string `json:"priority"`
}