Skip to content

Commit 07cc80a

Browse files
committed
feat: implement compliance orchestrator backend client and evaluation logic
1 parent 2c44b06 commit 07cc80a

4 files changed

Lines changed: 16 additions & 23 deletions

File tree

plugins/compliance-orchestrator/client/opensearch.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ func (b *BackendClient) ExecuteSQLQuery(ctx context.Context, sql string) (SQLRes
6666
return SQLResult{}, fmt.Errorf("failed to decode SQL response: %w", err)
6767
}
6868

69-
// Convertir a tu tipo interno
7069
return SQLResult{
7170
Rows: result.DataRows,
7271
Count: result.Total,

plugins/compliance-orchestrator/evaluator/evaluator.go

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,20 @@ func NewEvaluator(backend *client.BackendClient) *Evaluator {
1818
}
1919

2020
func (e *Evaluator) Evaluate(ctx context.Context, cfg models.ControlConfig) (models.ControlEvaluation, error) {
21-
// 1. Obtener index patterns activos
21+
2222
patterns, err := e.backend.GetActiveIndexPatterns(ctx)
2323
if err != nil {
2424
return models.ControlEvaluation{}, fmt.Errorf("failed to get index patterns: %w", err)
2525
}
2626

2727
results := make([]models.QueryEvaluation, 0)
28-
applicable := make([]models.QueryEvaluation, 0) // solo queries con indexPattern activo
28+
applicable := make([]models.QueryEvaluation, 0)
2929

30-
// 2. Evaluar cada QueryConfig
3130
for _, q := range cfg.QueriesConfigs {
3231
catcher.Info("Evaluating query", map[string]any{
3332
"query_id": q.ID,
3433
})
3534

36-
// 2.1 Si el index pattern NO está activo → NOT_APPLICABLE
3735
if !patternExists(int(q.IndexPatternID), patterns) {
3836
reason := "Index pattern not active"
3937
qr := models.QueryEvaluation{
@@ -47,20 +45,16 @@ func (e *Evaluator) Evaluate(ctx context.Context, cfg models.ControlConfig) (mod
4745
continue
4846
}
4947

50-
// 2.2 Evaluar query normalmente
5148
qr := e.evaluateQuery(ctx, q)
5249
results = append(results, qr)
5350

54-
// 2.3 Solo las queries aplicables participan en la estrategia ALL/ANY
5551
if qr.Status != models.QueryStatusNotApplicable {
5652
applicable = append(applicable, qr)
5753
}
5854
}
5955

60-
// 3. Combinar resultados según la estrategia del control
6156
finalStatus := computeControlStatus(cfg.ControlStrategy, applicable)
6257

63-
// 4. Construir evaluación final
6458
return models.ControlEvaluation{
6559
ControlConfigID: cfg.ID,
6660
ControlName: cfg.ControlName,
@@ -70,7 +64,6 @@ func (e *Evaluator) Evaluate(ctx context.Context, cfg models.ControlConfig) (mod
7064
}
7165

7266
func (e *Evaluator) evaluateQuery(ctx context.Context, q models.QueryConfig) models.QueryEvaluation {
73-
// Ejecutar la query SQL real contra OpenSearch
7467
res, err := e.backend.ExecuteSQLQuery(ctx, q.SQLQuery)
7568
if err != nil {
7669
msg := fmt.Sprintf("query execution failed: %v", err)
@@ -84,14 +77,12 @@ func (e *Evaluator) evaluateQuery(ctx context.Context, q models.QueryConfig) mod
8477
}
8578
}
8679

87-
// Limitar evidencia (por ejemplo, a 50 filas)
8880
const evidenceLimit = 50
8981
rawRows := res.Rows
9082
if len(rawRows) > evidenceLimit {
9183
rawRows = rawRows[:evidenceLimit]
9284
}
9385

94-
// Convertir [][]any → []map[string]any para OpenSearch
9586
evidence := make([]map[string]any, 0, len(rawRows))
9687
for _, row := range rawRows {
9788
rowMap := map[string]any{}
@@ -101,7 +92,6 @@ func (e *Evaluator) evaluateQuery(ctx context.Context, q models.QueryConfig) mod
10192
evidence = append(evidence, rowMap)
10293
}
10394

104-
// Evaluar la regla con los hits obtenidos
10595
status, errMsg := evaluateQueryRule(q, res.Count)
10696

10797
return models.QueryEvaluation{
@@ -116,7 +106,6 @@ func (e *Evaluator) evaluateQuery(ctx context.Context, q models.QueryConfig) mod
116106

117107
func evaluateQueryRule(q models.QueryConfig, hits int) (models.QueryEvaluationStatus, *string) {
118108
switch q.EvaluationRule {
119-
120109
case models.NoHitsAllowed:
121110
if hits == 0 {
122111
return models.QueryStatusCompliant, nil
@@ -152,9 +141,7 @@ func evaluateQueryRule(q models.QueryConfig, hits int) (models.QueryEvaluationSt
152141
func computeControlStatus(strategy models.ComplianceStrategy, results []models.QueryEvaluation) models.ControlEvaluationStatus {
153142

154143
switch strategy {
155-
156144
case models.StrategyAll:
157-
// ALL → todas deben ser COMPLIANT
158145
for _, r := range results {
159146
if r.Status != models.QueryStatusCompliant {
160147
return models.ControlStatusNonCompliant
@@ -163,7 +150,6 @@ func computeControlStatus(strategy models.ComplianceStrategy, results []models.Q
163150
return models.ControlStatusCompliant
164151

165152
case models.StrategyAny:
166-
// ANY → basta con que una sea COMPLIANT
167153
for _, r := range results {
168154
if r.Status == models.QueryStatusCompliant {
169155
return models.ControlStatusCompliant
@@ -172,7 +158,6 @@ func computeControlStatus(strategy models.ComplianceStrategy, results []models.Q
172158
return models.ControlStatusNonCompliant
173159

174160
default:
175-
// fallback seguro
176161
return models.ControlStatusNonCompliant
177162
}
178163
}

plugins/compliance-orchestrator/scheduler/scheduler.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,24 @@ var Jobs chan models.ControlConfig
1414
func StartScheduler(ctx context.Context, backend *client.BackendClient) {
1515
Jobs = make(chan models.ControlConfig, 1000)
1616

17-
ticker := time.NewTicker(30 * time.Second)
17+
ticker := time.NewTicker(24 * time.Hour)
18+
19+
// TODO: ELENA QUITAR - Ejecutar inmediatamente
20+
configs, err := backend.GetControlConfigs(ctx)
21+
if err == nil {
22+
catcher.Info("Scheduler: sending configs", map[string]any{
23+
"cantidad": len(configs),
24+
"timestamp": time.Now().String(),
25+
})
26+
27+
for _, cfg := range configs {
28+
Jobs <- cfg
29+
}
30+
} // HASTA AQUI
1831

1932
for {
2033
select {
2134
case <-ctx.Done():
22-
// Shutdown limpio
2335
return
2436

2537
case <-ticker.C:

plugins/compliance-orchestrator/workers/worker.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ func StartWorkers(ctx context.Context, backend *client.BackendClient) {
2828
"control": cfg.ID,
2929
})
3030

31-
// Ejecutar evaluación del control (incluye todas las queries)
3231
result, err := eval.Evaluate(ctx, cfg)
3332
if err != nil {
3433
catcher.Error("evaluation failed", err, map[string]any{
@@ -38,7 +37,6 @@ func StartWorkers(ctx context.Context, backend *client.BackendClient) {
3837
continue
3938
}
4039

41-
// Construir documento para guardar en OpenSearch
4240
doc := models.EvaluationDocument{
4341
ControlID: cfg.ID,
4442
ControlName: cfg.ControlName,
@@ -47,7 +45,6 @@ func StartWorkers(ctx context.Context, backend *client.BackendClient) {
4745
QueryEvaluations: result.QueryEvaluations,
4846
}
4947

50-
// Guardar en OpenSearch
5148
fmt.Println("Evaluation Document:", doc)
5249
err = backend.IndexEvaluationResult(ctx, "v11-log-compliance-evaluation", doc)
5350
if err != nil {

0 commit comments

Comments
 (0)