diff --git a/go.mod b/go.mod index 6b7a378b4..33f303557 100644 --- a/go.mod +++ b/go.mod @@ -173,6 +173,7 @@ require ( github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect github.com/ugorji/go/codec v1.2.6 // indirect + github.com/umahmood/haversine v0.0.0-20151105152445-808ab04add26 // indirect github.com/vjeantet/grok v1.0.1 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect diff --git a/go.sum b/go.sum index 7d759b35d..3a6b327de 100644 --- a/go.sum +++ b/go.sum @@ -921,6 +921,8 @@ github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= +github.com/umahmood/haversine v0.0.0-20151105152445-808ab04add26 h1:UFHFmFfixpmfRBcxuu+LA9l8MdURWVdVNUHxO5n1d2w= +github.com/umahmood/haversine v0.0.0-20151105152445-808ab04add26/go.mod h1:IGhd0qMDsUa9acVjsbsT7bu3ktadtGOHI79+idTew/M= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vjeantet/grok v1.0.1 h1:2rhIR7J4gThTgcZ1m2JY4TrJZNgjn985U28kT2wQrJ4= github.com/vjeantet/grok v1.0.1/go.mod h1:ax1aAchzC6/QMXMcyzHQGZWaW1l195+uMYIkCWPCNIo= diff --git a/pkg/exprhelpers/exprlib.go b/pkg/exprhelpers/exprlib.go index 5921b4c10..6e4081ae8 100644 --- a/pkg/exprhelpers/exprlib.go +++ b/pkg/exprhelpers/exprlib.go @@ -19,6 +19,8 @@ import ( "github.com/prometheus/client_golang/prometheus" log "github.com/sirupsen/logrus" + "github.com/umahmood/haversine" + "github.com/crowdsecurity/crowdsec/pkg/cache" "github.com/crowdsecurity/crowdsec/pkg/database" "github.com/crowdsecurity/crowdsec/pkg/types" @@ -119,6 +121,7 @@ func GetExprEnv(ctx map[string]interface{}) map[string]interface{} { "TrimPrefix": strings.TrimPrefix, "TrimSuffix": strings.TrimSuffix, "Get": Get, + "Distance": Distance, } for k, v := range ctx { ExprLib[k] = v @@ -126,6 +129,43 @@ func GetExprEnv(ctx map[string]interface{}) map[string]interface{} { return ExprLib } +func Distance(lat1 string, long1 string, lat2 string, long2 string) (float64, error) { + lat1f, err := strconv.ParseFloat(lat1, 64) + if err != nil { + log.Warningf("lat1 is not a float : %v", err) + return 0, fmt.Errorf("lat1 is not a float : %v", err) + } + long1f, err := strconv.ParseFloat(long1, 64) + if err != nil { + log.Warningf("long1 is not a float : %v", err) + return 0, fmt.Errorf("long1 is not a float : %v", err) + } + lat2f, err := strconv.ParseFloat(lat2, 64) + if err != nil { + log.Warningf("lat2 is not a float : %v", err) + + return 0, fmt.Errorf("lat2 is not a float : %v", err) + } + long2f, err := strconv.ParseFloat(long2, 64) + if err != nil { + log.Warningf("long2 is not a float : %v", err) + + return 0, fmt.Errorf("long2 is not a float : %v", err) + } + + //either set of coordinates is 0,0, return 0 to avoid FPs + if (lat1f == 0.0 && long1f == 0.0) || (lat2f == 0.0 && long2f == 0.0) { + log.Warningf("one of the coordinates is 0,0, returning 0") + return 0, nil + } + + first := haversine.Coord{Lat: lat1f, Lon: long1f} + second := haversine.Coord{Lat: lat2f, Lon: long2f} + + _, km := haversine.Distance(first, second) + return km, nil +} + func Init(databaseClient *database.Client) error { dataFile = make(map[string][]string) dataFileRegex = make(map[string][]*regexp.Regexp) diff --git a/pkg/exprhelpers/exprlib_test.go b/pkg/exprhelpers/exprlib_test.go index bba3339a6..20927a65d 100644 --- a/pkg/exprhelpers/exprlib_test.go +++ b/pkg/exprhelpers/exprlib_test.go @@ -125,6 +125,22 @@ func TestVisitor(t *testing.T) { } } +func TestDistanceHelper(t *testing.T) { + + //one set of coord is empty + ret, err := Distance("0.0", "0.0", "12.1", "12.1") + assert.NoError(t, err) + assert.Equal(t, 0.0, ret) + //those aren't even coords + ret, err = Distance("lol", "42.1", "12.1", "12.1") + assert.NotNil(t, err) + assert.Equal(t, 0.0, ret) + //real ones + ret, err = Distance("51.45", "1.15", "41.54", "12.27") + assert.NoError(t, err) + assert.Equal(t, 1389.1793118293067, ret) +} + func TestRegexpCacheBehavior(t *testing.T) { err := Init(nil) require.NoError(t, err)