diff --git a/config/config_defaults.go b/config/config_defaults.go
index 4d543523f..9f2d3157f 100755
--- a/config/config_defaults.go
+++ b/config/config_defaults.go
@@ -243,6 +243,7 @@ const CGRATES_CFG_JSON = `
"*rpc_connections": {"limit": -1, "ttl": "", "static_ttl": false, "replicate": false}, // RPC connections caching
"*uch": {"limit": -1, "ttl": "3h", "static_ttl": false, "replicate": false}, // User cache
"*stir": {"limit": -1, "ttl": "3h", "static_ttl": false, "replicate": false}, // stirShaken cache keys
+ "*apiban":{"limit": -1, "ttl": "2m", "static_ttl": false, "replicate": false},
// only for *internal database
"*versions": {"limit": -1, "ttl": "", "static_ttl": false, "replicate": false}, // for version storing
diff --git a/config/config_json_test.go b/config/config_json_test.go
index 858cce495..41c022c39 100755
--- a/config/config_json_test.go
+++ b/config/config_json_test.go
@@ -290,6 +290,9 @@ func TestCacheJsonCfg(t *testing.T) {
utils.CacheTBLTPRateProfiles: {Limit: utils.IntPointer(-1),
Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false),
Replicate: utils.BoolPointer(false)},
+ utils.MetaAPIBan: {Limit: utils.IntPointer(-1),
+ Ttl: utils.StringPointer("2m"), Static_ttl: utils.BoolPointer(false),
+ Replicate: utils.BoolPointer(false)},
},
Replication_conns: &[]string{},
}
diff --git a/config/config_test.go b/config/config_test.go
index 693e9d55d..03b47aa86 100755
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -502,79 +502,79 @@ func TestCgrCfgJSONDefaultsCacheCFG(t *testing.T) {
eCacheCfg := &CacheCfg{
Partitions: map[string]*CacheParamCfg{
utils.CacheDestinations: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheReverseDestinations: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheRatingPlans: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheRatingProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheActions: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheActionPlans: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheAccountActionPlans: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheActionTriggers: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheSharedGroups: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTimings: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheResourceProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheResources: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheEventResources: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false},
+ TTL: 0, StaticTTL: false},
utils.CacheStatQueueProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheStatQueues: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheThresholdProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheThresholds: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheFilters: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheRouteProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheAttributeProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheChargerProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheDispatcherProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheRateProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheDispatcherHosts: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheResourceFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheStatFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheThresholdFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheRouteFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheAttributeFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheChargerFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheDispatcherFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheRateProfilesFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheRateFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheReverseFilterIndexes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheDispatcherRoutes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheDispatcherLoads: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheDispatchers: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheDiameterMessages: {Limit: -1,
TTL: time.Duration(3 * time.Hour), StaticTTL: false},
utils.CacheRPCResponses: {Limit: 0,
@@ -586,64 +586,66 @@ func TestCgrCfgJSONDefaultsCacheCFG(t *testing.T) {
utils.CacheCDRIDs: {Limit: -1,
TTL: time.Duration(10 * time.Minute), StaticTTL: false},
utils.CacheLoadIDs: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheRPCConnections: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false},
+ TTL: 0, StaticTTL: false},
utils.CacheUCH: {Limit: -1,
TTL: time.Duration(3 * time.Hour), StaticTTL: false},
utils.CacheSTIR: {Limit: -1,
TTL: time.Duration(3 * time.Hour), StaticTTL: false},
utils.CacheVersions: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheAccounts: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPTimings: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPDestinations: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPRates: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPDestinationRates: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPRatingPlans: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPRatingProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPSharedGroups: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPActions: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPActionPlans: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPActionTriggers: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPAccountActions: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPResources: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPStats: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPThresholds: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPFilters: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheSessionCostsTBL: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheCDRsTBL: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPRoutes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPAttributes: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPChargers: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPDispatchers: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPDispatcherHosts: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
utils.CacheTBLTPRateProfiles: {Limit: -1,
- TTL: time.Duration(0), StaticTTL: false, Precache: false},
+ TTL: 0, StaticTTL: false, Precache: false},
+ utils.MetaAPIBan: {Limit: -1,
+ TTL: 2 * time.Minute, StaticTTL: false, Precache: false},
},
ReplicationConns: []string{},
}
@@ -1902,7 +1904,7 @@ func TestCgrCdfEventReader(t *testing.T) {
Type: utils.META_NONE,
FieldSep: ",",
HeaderDefineChar: ":",
- RunDelay: time.Duration(0),
+ RunDelay: 0,
ConcurrentReqs: 1024,
SourcePath: "/var/spool/cgrates/ers/in",
ProcessedPath: "/var/spool/cgrates/ers/out",
@@ -2198,7 +2200,7 @@ func TestCgrCfgEventReaderDefault(t *testing.T) {
Type: utils.META_NONE,
FieldSep: ",",
HeaderDefineChar: ":",
- RunDelay: time.Duration(0),
+ RunDelay: 0,
ConcurrentReqs: 1024,
SourcePath: "/var/spool/cgrates/ers/in",
ProcessedPath: "/var/spool/cgrates/ers/out",
diff --git a/engine/datamanager.go b/engine/datamanager.go
index 2f9b5bc02..46de405b5 100644
--- a/engine/datamanager.go
+++ b/engine/datamanager.go
@@ -20,6 +20,7 @@ import (
"strings"
"time"
+ "github.com/cgrates/baningo"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
"github.com/cgrates/ltcache"
@@ -73,6 +74,7 @@ var (
utils.RateProfilesFilterIndexPrfx: {},
utils.RateFilterIndexPrfx: {},
utils.FilterIndexPrfx: {},
+ utils.MetaAPIBan: {}, // not realy a prefix as this is not stored in DB
}
)
@@ -133,7 +135,8 @@ func (dm *DataManager) CacheDataFromDB(prfx string, ids []string, mustBeCached b
if dm.cacheCfg.Partitions[utils.CachePrefixToInstance[prfx]].Limit == 0 {
return
}
- if ids == nil {
+ if ids == nil &&
+ prfx != utils.MetaAPIBan { // no need for ids in this case
if mustBeCached {
ids = Cache.GetItemIDs(utils.CachePrefixToInstance[prfx], utils.EmptyString)
} else {
@@ -282,6 +285,8 @@ func (dm *DataManager) CacheDataFromDB(prfx string, ids []string, mustBeCached b
_, err = dm.GetIndexes(utils.CacheReverseFilterIndexes, dataID[:idx], dataID[idx+1:], false, true)
case utils.LoadIDPrefix:
_, err = dm.GetItemLoadIDs(utils.EmptyString, true)
+ case utils.MetaAPIBan:
+ _, err = dm.GetAPIBan(utils.EmptyString, config.CgrConfig().APIBanCfg().Keys, false, false, true)
}
if err != nil {
if err != utils.ErrNotFound {
@@ -3359,3 +3364,42 @@ func (dm *DataManager) RemoveIndexes(idxItmType, tntCtx, idxKey string) (err err
}
return
}
+
+func (dm *DataManager) GetAPIBan(ip string, apiKeys []string, single, cacheRead, cacheWrite bool) (banned bool, err error) {
+ if cacheRead {
+ if x, ok := Cache.Get(utils.MetaAPIBan, ip); ok && x != nil { // Attempt to find in cache first
+ return x.(bool), nil
+ }
+ }
+ if single {
+ if banned, err = baningo.CheckIP(ip, apiKeys...); err != nil {
+ return
+ }
+ if cacheWrite {
+ if err = Cache.Set(utils.MetaAPIBan, ip, banned, nil, true, utils.NonTransactional); err != nil {
+ return false, err
+ }
+ }
+ return
+ }
+ var bannedIPs []string
+ if bannedIPs, err = baningo.GetBannedIPs(apiKeys...); err != nil {
+ return
+ }
+ for _, bannedIP := range bannedIPs {
+ if bannedIP == ip {
+ banned = true
+ }
+ if cacheWrite {
+ if err = Cache.Set(utils.MetaAPIBan, bannedIP, true, nil, true, utils.NonTransactional); err != nil {
+ return false, err
+ }
+ }
+ }
+ if len(ip) != 0 && !banned && cacheWrite {
+ if err = Cache.Set(utils.MetaAPIBan, ip, false, nil, true, utils.NonTransactional); err != nil {
+ return false, err
+ }
+ }
+ return
+}
diff --git a/engine/filters.go b/engine/filters.go
index 31aed967f..df99eb2cf 100644
--- a/engine/filters.go
+++ b/engine/filters.go
@@ -223,16 +223,16 @@ var supportedFiltersType utils.StringSet = utils.NewStringSet([]string{
utils.MetaTimings, utils.MetaRSR, utils.MetaDestinations,
utils.MetaEmpty, utils.MetaExists, utils.MetaLessThan, utils.MetaLessOrEqual,
utils.MetaGreaterThan, utils.MetaGreaterOrEqual, utils.MetaEqual,
- utils.MetaNotEqual, utils.MetaIPNet})
+ utils.MetaNotEqual, utils.MetaIPNet, utils.MetaAPIBan})
var needsFieldName utils.StringSet = utils.NewStringSet([]string{
utils.MetaString, utils.MetaPrefix, utils.MetaSuffix,
utils.MetaTimings, utils.MetaRSR, utils.MetaDestinations, utils.MetaLessThan,
utils.MetaEmpty, utils.MetaExists, utils.MetaLessOrEqual, utils.MetaGreaterThan,
- utils.MetaGreaterOrEqual, utils.MetaEqual, utils.MetaNotEqual, utils.MetaIPNet})
+ utils.MetaGreaterOrEqual, utils.MetaEqual, utils.MetaNotEqual, utils.MetaIPNet, utils.MetaAPIBan})
var needsValues utils.StringSet = utils.NewStringSet([]string{utils.MetaString, utils.MetaPrefix,
utils.MetaSuffix, utils.MetaTimings, utils.MetaRSR, utils.MetaDestinations,
utils.MetaLessThan, utils.MetaLessOrEqual, utils.MetaGreaterThan, utils.MetaGreaterOrEqual,
- utils.MetaEqual, utils.MetaNotEqual, utils.MetaIPNet})
+ utils.MetaEqual, utils.MetaNotEqual, utils.MetaIPNet, utils.MetaAPIBan})
// NewFilterRule returns a new filter
func NewFilterRule(rfType, fieldName string, vals []string) (*FilterRule, error) {
@@ -335,6 +335,8 @@ func (fltr *FilterRule) Pass(dDP utils.DataProvider) (result bool, err error) {
result, err = fltr.passEqualTo(dDP)
case utils.MetaIPNet, utils.MetaNotIPNet:
result, err = fltr.passIPNet(dDP)
+ case utils.MetaAPIBan, utils.MetaNotAPIBan:
+ result, err = fltr.passAPIBan(dDP)
default:
err = utils.ErrPrefixNotErrNotImplemented(fltr.Type)
}
@@ -600,6 +602,21 @@ func (fltr *FilterRule) passIPNet(dDP utils.DataProvider) (bool, error) {
return false, nil
}
+func (fltr *FilterRule) passAPIBan(dDP utils.DataProvider) (bool, error) {
+ strVal, err := fltr.rsrElement.ParseDataProvider(dDP)
+ if err != nil {
+ if err == utils.ErrNotFound {
+ return false, nil
+ }
+ return false, err
+ }
+ if fltr.Values[0] != utils.MetaAll &&
+ fltr.Values[0] != utils.MetaSingle { // force only valid values
+ return false, fmt.Errorf("invalid value for apiban filter: <%s>", fltr.Values[0])
+ }
+ return dm.GetAPIBan(strVal, config.CgrConfig().APIBanCfg().Keys, fltr.Values[0] != utils.MetaAll, true, true)
+}
+
func newDynamicDP(cfg *config.CGRConfig, connMgr *ConnManager,
tenant string, initialDP utils.DataProvider) *dynamicDP {
return &dynamicDP{
diff --git a/engine/filters_test.go b/engine/filters_test.go
index 812480327..a51ce0ed6 100644
--- a/engine/filters_test.go
+++ b/engine/filters_test.go
@@ -15,10 +15,13 @@ along with this program. If not, see
package engine
import (
+ "net/http"
+ "net/http/httptest"
"reflect"
"testing"
"time"
+ "github.com/cgrates/baningo"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
)
@@ -1457,3 +1460,106 @@ func TestFilterPassIPNet(t *testing.T) {
t.Error(err)
}
}
+
+func TestAPIBan(t *testing.T) {
+ var counter int
+ testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "GET" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+ responses := map[string]struct {
+ code int
+ body []byte
+ }{
+ "/testKey/check/1.2.3.251": {code: http.StatusOK, body: []byte(`{"ipaddress":["1.2.3.251"], "ID":"987654321"}`)},
+ "/testKey/check/1.2.3.254": {code: http.StatusBadRequest, body: []byte(`{"ipaddress":["not blocked"], "ID":"none"}`)},
+ }
+ if val, has := responses[r.URL.EscapedPath()]; has {
+ w.WriteHeader(val.code)
+ if val.body != nil {
+ w.Write(val.body)
+ }
+ return
+ }
+ counter++
+ w.WriteHeader(http.StatusOK)
+ if counter < 2 {
+ _, _ = w.Write([]byte(`{"ipaddress": ["1.2.3.251", "1.2.3.252"], "ID": "100"}`))
+ } else {
+ _, _ = w.Write([]byte(`{"ID": "none"}`))
+ counter = 0
+ }
+ }))
+ defer testServer.Close()
+ baningo.RootURL = testServer.URL + "/"
+
+ dp := utils.MapStorage{
+ utils.MetaReq: utils.MapStorage{
+ "bannedIP": "1.2.3.251",
+ "bannedIP2": "1.2.3.252",
+ "IP": "1.2.3.253",
+ "IP2": "1.2.3.254",
+ },
+ }
+ cfg, _ := config.NewDefaultCGRConfig()
+ data := NewInternalDB(nil, nil, true)
+ dmFilterPass := NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
+ filterS := FilterS{
+ cfg: cfg,
+ dm: dmFilterPass,
+ }
+ config.CgrConfig().APIBanCfg().Keys = []string{"testKey"}
+ if pass, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.IP:*all"}, dp); err != nil {
+ t.Fatal(err)
+ } else if pass {
+ t.Error("Expected not to pass")
+ }
+ // from cache
+ if pass, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.IP:*all"}, dp); err != nil {
+ t.Fatal(err)
+ } else if pass {
+ t.Error("Expected not to pass")
+ }
+ if pass, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.IP2:*single"}, dp); err != nil {
+ t.Fatal(err)
+ } else if pass {
+ t.Error("Expected not to pass")
+ }
+ Cache.Clear([]string{utils.MetaAPIBan})
+ if pass, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.bannedIP:*single"}, dp); err != nil {
+ t.Fatal(err)
+ } else if !pass {
+ t.Error("Expected to pass")
+ }
+ if pass, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.bannedIP2:*all"}, dp); err != nil {
+ t.Fatal(err)
+ } else if !pass {
+ t.Error("Expected to pass")
+ }
+
+ if pass, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.notFound:*all"}, dp); err != nil {
+ t.Fatal(err)
+ } else if pass {
+ t.Error("Expected not to pass")
+ }
+ expErr := "invalid value for apiban filter: <*any>"
+ if _, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.IP:*any"}, dp); err == nil || err.Error() != expErr {
+ t.Errorf("Expected error %s received: %v", expErr, err)
+ }
+ baningo.RootURL = "http://127.0.0.1:80/"
+
+ expErr = `Get "http://127.0.0.1:80/testKey/banned/100": dial tcp 127.0.0.1:80: connect: connection refused`
+ if _, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.IP:*all"}, dp); err == nil || err.Error() != expErr {
+ t.Errorf("Expected error %s received: %v", expErr, err)
+ }
+ expErr = `Get "http://127.0.0.1:80/testKey/check/1.2.3.253": dial tcp 127.0.0.1:80: connect: connection refused`
+ if _, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.IP:*single"}, dp); err == nil || err.Error() != expErr {
+ t.Errorf("Expected error %s received: %v", expErr, err)
+ }
+
+ expErr = `invalid converter value in string: <*>, err: unsupported converter definition: <*>`
+ if _, err := filterS.Pass("cgrates.org", []string{"*apiban:~*req.<~*req.IP>{*}:*all"}, dp); err == nil || err.Error() != expErr {
+ t.Errorf("Expected error %s received: %v", expErr, err)
+ }
+}
diff --git a/go.mod b/go.mod
index 383383f72..eecf21ae7 100644
--- a/go.mod
+++ b/go.mod
@@ -18,6 +18,7 @@ require (
github.com/cenkalti/hub v1.0.1 // indirect
github.com/cenkalti/rpc2 v0.0.0-20200203073230-5ce2854ce0fd
github.com/cgrates/aringo v0.0.0-20191121125609-d85002bd1667
+ github.com/cgrates/baningo v0.0.0-20200925111414-e65b237006c9
github.com/cgrates/cron v0.0.0-20200906113840-dd008627fdca
github.com/cgrates/fsock v0.0.0-20191107070144-e7a331109df7
github.com/cgrates/kamevapi v0.0.0-20191001125829-7dbc3ad58817
diff --git a/go.sum b/go.sum
index 53cc3231b..2a072a4ed 100644
--- a/go.sum
+++ b/go.sum
@@ -64,6 +64,10 @@ github.com/cenkalti/rpc2 v0.0.0-20200203073230-5ce2854ce0fd/go.mod h1:v2npkhrXyk
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cgrates/aringo v0.0.0-20191121125609-d85002bd1667 h1:eNku7bwLtSTpn6FQUUTnqohuGWC8jij1KNqDZ2QkGRE=
github.com/cgrates/aringo v0.0.0-20191121125609-d85002bd1667/go.mod h1:l0xi5JUVqxL4P7RZ9YitbSCiOtjMY2j7JBOCJIysRWk=
+github.com/cgrates/baningo v0.0.0-20200925101338-ccea0136bbb1 h1:MM3w9bIb8DpJ+px6BQ0CkEmn0CLneAS4VHmmdZnje14=
+github.com/cgrates/baningo v0.0.0-20200925101338-ccea0136bbb1/go.mod h1:3SwVROaS1Iml5lqEhj0gRhDRtmbBgypZpKcEkVTSleU=
+github.com/cgrates/baningo v0.0.0-20200925111414-e65b237006c9 h1:WwluddhgQoHkB72AzbC781qtB2xJLt+B9Rc2+NYy0Ts=
+github.com/cgrates/baningo v0.0.0-20200925111414-e65b237006c9/go.mod h1:3SwVROaS1Iml5lqEhj0gRhDRtmbBgypZpKcEkVTSleU=
github.com/cgrates/cron v0.0.0-20200906113840-dd008627fdca h1:neuTTEjWsM+WXRyJ+MF1OzsNc+e7DGjrNZKIEIr8x4A=
github.com/cgrates/cron v0.0.0-20200906113840-dd008627fdca/go.mod h1:I9cUDn/uzkakr0hmYTjXkQqf6wagg44L2p01gSYRRz0=
github.com/cgrates/fsock v0.0.0-20191107070144-e7a331109df7 h1:dxtBWRAr62vRRKkExmJZ0u1EbCw/y0vOkSfdFND5qXw=
diff --git a/packages/debian/changelog b/packages/debian/changelog
index ff23e4f8e..cf8b85cf2 100644
--- a/packages/debian/changelog
+++ b/packages/debian/changelog
@@ -102,6 +102,7 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium
* [ActionS] Replaced the poster action with *export that will send the event to EEs
* [AgentS] DiameterAgent return NOT_FOUND instead of "filter not passing" error and let other subsystem to handle this (e.g. FilterS)
* [StatS] Change format of metricID when specifying fields ( e.g. *sum#~*req.FieldName )
+ * [FilterS] Added *apiban filter
-- DanB Wed, 19 Feb 2020 13:25:52 +0200
diff --git a/utils/consts.go b/utils/consts.go
index 65385227c..8c71a2979 100755
--- a/utils/consts.go
+++ b/utils/consts.go
@@ -53,7 +53,7 @@ var (
CacheDispatcherRoutes, CacheDispatcherLoads, CacheDiameterMessages, CacheRPCResponses,
CacheClosedSessions, CacheCDRIDs, CacheLoadIDs, CacheRPCConnections, CacheRatingProfilesTmp,
CacheUCH, CacheSTIR, CacheEventCharges, CacheRateProfiles, CacheRateProfilesFilterIndexes,
- CacheRateFilterIndexes, CacheReverseFilterIndexes,
+ CacheRateFilterIndexes, CacheReverseFilterIndexes, MetaAPIBan,
// only internalDB
CacheVersions, CacheAccounts,
CacheTBLTPTimings, CacheTBLTPDestinations, CacheTBLTPRates, CacheTBLTPDestinationRates,
@@ -98,6 +98,7 @@ var (
CacheAccounts: ACCOUNT_PREFIX,
CacheRateFilterIndexes: RateFilterIndexPrfx,
CacheReverseFilterIndexes: FilterIndexPrfx,
+ MetaAPIBan: MetaAPIBan, // special case as it is not in a DB
}
CachePrefixToInstance map[string]string // will be built on init
CacheIndexesToPrefix = map[string]string{ // used by match index to get all the ids when index selects is disabled and for compute indexes
@@ -261,6 +262,7 @@ const (
ROUNDING_DOWN = "*down"
ANY = "*any"
MetaAll = "*all"
+ MetaSingle = "*single"
ZERO = "*zero"
ASAP = "*asap"
COMMENT_CHAR = '#'
@@ -1085,6 +1087,7 @@ const (
MetaResources = "*resources"
MetaEqual = "*eq"
MetaIPNet = "*ipnet"
+ MetaAPIBan = "*apiban"
MetaNotString = "*notstring"
MetaNotPrefix = "*notprefix"
@@ -1098,6 +1101,7 @@ const (
MetaNotResources = "*notresources"
MetaNotEqual = "*noteq"
MetaNotIPNet = "*notipnet"
+ MetaNotAPIBan = "*notapiban"
MetaEC = "*ec"
)