Skip to content

refact: pkg/database decisions extract, rename #3635

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/database/alertfilter.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ func alertPredicatesFromFilter(filter map[string][]string) ([]predicate.Alert, e
return predicates, nil
}

func BuildAlertRequestFromFilter(alerts *ent.AlertQuery, filter map[string][]string) (*ent.AlertQuery, error) {
func applyAlertFilter(alerts *ent.AlertQuery, filter map[string][]string) (*ent.AlertQuery, error) {
preds, err := alertPredicatesFromFilter(filter)
if err != nil {
return nil, err
Expand Down
6 changes: 3 additions & 3 deletions pkg/database/alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -750,15 +750,15 @@ func (c *Client) CreateAlert(ctx context.Context, machineID string, alertList []
return alertIDs, nil
}

func (c *Client) AlertsCountPerScenario(ctx context.Context, filters map[string][]string) (map[string]int, error) {
func (c *Client) AlertsCountPerScenario(ctx context.Context, filter map[string][]string) (map[string]int, error) {
var res []struct {
Scenario string
Count int
}

query := c.Ent.Alert.Query()

query, err := BuildAlertRequestFromFilter(query, filters)
query, err := applyAlertFilter(query, filter)
if err != nil {
return nil, fmt.Errorf("failed to build alert request: %w", err)
}
Expand Down Expand Up @@ -809,7 +809,7 @@ func (c *Client) QueryAlertWithFilter(ctx context.Context, filter map[string][]s
for {
alerts := c.Ent.Alert.Query()

alerts, err := BuildAlertRequestFromFilter(alerts, filter)
alerts, err := applyAlertFilter(alerts, filter)
if err != nil {
return nil, err
}
Expand Down
208 changes: 208 additions & 0 deletions pkg/database/decisionfilter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
package database

import (
"fmt"
"strconv"
"strings"

"github.com/pkg/errors"

"github.com/crowdsecurity/crowdsec/pkg/database/ent"
"github.com/crowdsecurity/crowdsec/pkg/database/ent/decision"
"github.com/crowdsecurity/crowdsec/pkg/database/ent/predicate"
"github.com/crowdsecurity/crowdsec/pkg/types"
)

func applyDecisionFilter(query *ent.DecisionQuery, filter map[string][]string) (*ent.DecisionQuery, error) {
var (
err error
start_ip, start_sfx, end_ip, end_sfx int64
ip_sz int
)

contains := true
/*if contains is true, return bans that *contains* the given value (value is the inner)
else, return bans that are *contained* by the given value (value is the outer)*/

/*the simulated filter is a bit different : if it's not present *or* set to false, specifically exclude records with simulated to true */
if v, ok := filter["simulated"]; ok {
if v[0] == "false" {
query = query.Where(decision.SimulatedEQ(false))
}

Check warning on line 31 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L29-L31

Added lines #L29 - L31 were not covered by tests

delete(filter, "simulated")

Check warning on line 33 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L33

Added line #L33 was not covered by tests
} else {
query = query.Where(decision.SimulatedEQ(false))
}

for param, value := range filter {
switch param {
case "contains":
contains, err = strconv.ParseBool(value[0])
if err != nil {
return nil, errors.Wrapf(InvalidFilter, "invalid contains value : %s", err)
}

Check warning on line 44 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L43-L44

Added lines #L43 - L44 were not covered by tests
case "scopes", "scope": // Swagger mentions both of them, let's just support both to make sure we don't break anything
scopes := strings.Split(value[0], ",")
for i, scope := range scopes {
switch strings.ToLower(scope) {
case "ip":
scopes[i] = types.Ip
case "range":
scopes[i] = types.Range
case "country":
scopes[i] = types.Country
case "as":
scopes[i] = types.AS

Check warning on line 56 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L53-L56

Added lines #L53 - L56 were not covered by tests
}
}

query = query.Where(decision.ScopeIn(scopes...))
case "value":
query = query.Where(decision.ValueEQ(value[0]))
case "type":
query = query.Where(decision.TypeEQ(value[0]))
case "origins":
query = query.Where(
decision.OriginIn(strings.Split(value[0], ",")...),
)
case "scenarios_containing":
predicates := decisionPredicatesFromStr(value[0], decision.ScenarioContainsFold)
query = query.Where(decision.Or(predicates...))
case "scenarios_not_containing":
predicates := decisionPredicatesFromStr(value[0], decision.ScenarioContainsFold)
query = query.Where(decision.Not(
decision.Or(
predicates...,
),
))

Check warning on line 78 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L65-L78

Added lines #L65 - L78 were not covered by tests
case "ip", "range":
ip_sz, start_ip, start_sfx, end_ip, end_sfx, err = types.Addr2Ints(value[0])
if err != nil {
return nil, errors.Wrapf(InvalidIPOrRange, "unable to convert '%s' to int: %s", value[0], err)
}
case "limit":
limit, err := strconv.Atoi(value[0])
if err != nil {
return nil, errors.Wrapf(InvalidFilter, "invalid limit value : %s", err)
}

Check warning on line 88 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L82-L88

Added lines #L82 - L88 were not covered by tests

query = query.Limit(limit)
case "offset":
offset, err := strconv.Atoi(value[0])
if err != nil {
return nil, errors.Wrapf(InvalidFilter, "invalid offset value : %s", err)
}

Check warning on line 95 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L90-L95

Added lines #L90 - L95 were not covered by tests

query = query.Offset(offset)
case "id_gt":
id, err := strconv.Atoi(value[0])
if err != nil {
return nil, errors.Wrapf(InvalidFilter, "invalid id_gt value : %s", err)
}

Check warning on line 102 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L97-L102

Added lines #L97 - L102 were not covered by tests

query = query.Where(decision.IDGT(id))

Check warning on line 104 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L104

Added line #L104 was not covered by tests
}
}

query, err = decisionIPFilter(query, contains, ip_sz, start_ip, start_sfx, end_ip, end_sfx)
if err != nil {
return nil, fmt.Errorf("fail to apply StartIpEndIpFilter: %w", err)
}

Check warning on line 111 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L110-L111

Added lines #L110 - L111 were not covered by tests

return query, nil
}

func decisionIPv4Filter(decisions *ent.DecisionQuery, contains bool, ip_sz int, start_ip int64, start_sfx int64, end_ip int64, end_sfx int64) (*ent.DecisionQuery, error) {
if contains {
/*Decision contains {start_ip,end_ip}*/
return decisions.Where(decision.And(
decision.StartIPLTE(start_ip),
decision.EndIPGTE(end_ip),
decision.IPSizeEQ(int64(ip_sz)))), nil
}

/*Decision is contained within {start_ip,end_ip}*/
return decisions.Where(decision.And(
decision.StartIPGTE(start_ip),
decision.EndIPLTE(end_ip),
decision.IPSizeEQ(int64(ip_sz)))), nil
}

func decisionIPv6Filter(decisions *ent.DecisionQuery, contains bool, ip_sz int, start_ip int64, start_sfx int64, end_ip int64, end_sfx int64) (*ent.DecisionQuery, error) {
/*decision contains {start_ip,end_ip}*/
if contains {
return decisions.Where(decision.And(
// matching addr size
decision.IPSizeEQ(int64(ip_sz)),
decision.Or(
// decision.start_ip < query.start_ip
decision.StartIPLT(start_ip),
decision.And(
// decision.start_ip == query.start_ip
decision.StartIPEQ(start_ip),
// decision.start_suffix <= query.start_suffix
decision.StartSuffixLTE(start_sfx),
)),
decision.Or(
// decision.end_ip > query.end_ip
decision.EndIPGT(end_ip),
decision.And(
// decision.end_ip == query.end_ip
decision.EndIPEQ(end_ip),
// decision.end_suffix >= query.end_suffix
decision.EndSuffixGTE(end_sfx),
),
),
)), nil
}

/*decision is contained within {start_ip,end_ip}*/
return decisions.Where(decision.And(
// matching addr size
decision.IPSizeEQ(int64(ip_sz)),
decision.Or(
// decision.start_ip > query.start_ip
decision.StartIPGT(start_ip),
decision.And(
// decision.start_ip == query.start_ip
decision.StartIPEQ(start_ip),
// decision.start_suffix >= query.start_suffix
decision.StartSuffixGTE(start_sfx),
)),
decision.Or(
// decision.end_ip < query.end_ip
decision.EndIPLT(end_ip),
decision.And(
// decision.end_ip == query.end_ip
decision.EndIPEQ(end_ip),
// decision.end_suffix <= query.end_suffix
decision.EndSuffixLTE(end_sfx),
),
),
)), nil
}

func decisionIPFilter(decisions *ent.DecisionQuery, contains bool, ip_sz int, start_ip int64, start_sfx int64, end_ip int64, end_sfx int64) (*ent.DecisionQuery, error) {
switch ip_sz {
case 4:
return decisionIPv4Filter(decisions, contains, ip_sz, start_ip, start_sfx, end_ip, end_sfx)
case 16:
return decisionIPv6Filter(decisions, contains, ip_sz, start_ip, start_sfx, end_ip, end_sfx)
case 0:
return decisions, nil
default:
return nil, errors.Wrapf(InvalidFilter, "unknown ip size %d", ip_sz)

Check warning on line 195 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L194-L195

Added lines #L194 - L195 were not covered by tests
}
}

func decisionPredicatesFromStr(s string, predicateFunc func(string) predicate.Decision) []predicate.Decision {
words := strings.Split(s, ",")
predicates := make([]predicate.Decision, len(words))

for i, word := range words {
predicates[i] = predicateFunc(word)
}

Check warning on line 205 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L199-L205

Added lines #L199 - L205 were not covered by tests

return predicates

Check warning on line 207 in pkg/database/decisionfilter.go

View check run for this annotation

Codecov / codecov/patch

pkg/database/decisionfilter.go#L207

Added line #L207 was not covered by tests
}
Loading