diff --git a/exemples/redis-cache/docker-compose.redis.yml b/exemples/redis-cache/docker-compose.redis.yml index a0d70ec..b179963 100644 --- a/exemples/redis-cache/docker-compose.redis.yml +++ b/exemples/redis-cache/docker-compose.redis.yml @@ -59,7 +59,7 @@ services: - "traefik.http.middlewares.crowdsec2.plugin.bouncer.enabled=true" # crowdseclapikey must be uniq to the middleware attached to the service - "traefik.http.middlewares.crowdsec2.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7" - - "traefik.http.middlewares.crowdsec2.plugin.bouncer.rediscacheenabled=false" + - "traefik.http.middlewares.crowdsec2.plugin.bouncer.rediscacheenabled=true" crowdsec: diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index 860ffd0..d2d43d9 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -20,7 +20,6 @@ var redis simpleredis.SimpleRedis var redisEnabled = false - func getDecisionLocalCache(clientIP string) (bool, error) { banned, isCached := cache.Get(clientIP) bannedString, isValid := banned.(string) @@ -30,29 +29,28 @@ func getDecisionLocalCache(clientIP string) (bool, error) { return false, fmt.Errorf("no cache data") } -func SetDecisionLocalCache(clientIP string, value string, duration int64) { +func setDecisionLocalCache(clientIP string, value string, duration int64) { cache.Set(clientIP, value, duration) } -func DeleteDecisionLocalCache(clientIP string) { +func deleteDecisionLocalCache(clientIP string) { cache.Del(clientIP) } func getDecisionRedisCache(clientIP string) (bool, error) { - banned, err := redis.Do("GET", clientIP, nil) + banned, err := redis.Get(clientIP) bannedString := string(banned) - logger.Info(fmt.Sprintf("%v banned", bannedString)) if err == nil && len(bannedString) > 0 { return bannedString == cacheBannedValue, nil } return false, fmt.Errorf("no cache data") } -func SetDecisionRedisCache(clientIP string, value string, duration int64) { - redis.Do("SET", clientIP, []byte(value)) +func setDecisionRedisCache(clientIP string, value string, duration int64) { + redis.Set(clientIP, []byte(value), duration) } -func DeleteDecisionRedisCache(clientIP string) { +func deleteDecisionRedisCache(clientIP string) { // err := rdb.Del(ctx, clientIP).Err() // if err != nil { // logger.Info("Error, could not delete in redis cache IP") @@ -60,16 +58,15 @@ func DeleteDecisionRedisCache(clientIP string) { // errors are not handled } - - func DeleteDecision(clientIP string) { if redisEnabled { - DeleteDecisionRedisCache(clientIP) + deleteDecisionRedisCache(clientIP) } else { - DeleteDecisionLocalCache(clientIP) + deleteDecisionLocalCache(clientIP) } } -// Get Decision check in the cache if the IP has the banned / not banned value. + +// GetDecision check in the cache if the IP has the banned / not banned value. // Otherwise return with an error to add the IP in cache if we are on. func GetDecision(clientIP string) (bool, error) { if redisEnabled { @@ -88,14 +85,14 @@ func SetDecision(clientIP string, isBanned bool, duration int64) { value = cacheNoBannedValue } if redisEnabled { - SetDecisionRedisCache(clientIP, value, duration) + setDecisionRedisCache(clientIP, value, duration) } else { - SetDecisionLocalCache(clientIP, value, duration) + setDecisionLocalCache(clientIP, value, duration) } } func InitRedisClient(host string, password string) { - logger.Debug("connect to redis") redisEnabled = true redis.Init(host) + logger.Debug("connect to redis") } diff --git a/pkg/redis/redis.go b/pkg/redis/redis.go index ea80b17..136cb4b 100644 --- a/pkg/redis/redis.go +++ b/pkg/redis/redis.go @@ -2,22 +2,20 @@ package simpleredis import ( "fmt" - "log" "net" "strconv" "strings" "time" "github.com/tehnerd/goUtils/netutils" - - logger "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/pkg/logger" ) type RedisCmd struct { - Command string - Name string - Data []byte - Error error + Command string + Name string + Data []byte + Duration int64 + Error error } type SimpleRedis struct { @@ -27,26 +25,17 @@ type SimpleRedis struct { redisCmd RedisCmd } -func GenRedisArray(params ...[]byte) []byte { - CRLF := "\r\n" +func genRedisArray(params ...[]byte) []byte { MSG := "" for cntr := 0; cntr < len(params); cntr++ { MSG = strings.Join([]string{MSG, string(params[cntr])}, " ") } MSG = strings.Trim(MSG, " ") - MSG = strings.Join([]string{MSG, CRLF}, "") + MSG = strings.Join([]string{MSG, "\r\n"}, "") return []byte(MSG) } -func RedisSet(name string, data []byte) []byte { - return GenRedisArray([]byte("SET"), []byte(name), data) -} - -func RedisGet(name string) []byte { - return GenRedisArray([]byte("GET"), []byte(name)) -} - -func ParseRedisResponse(response []byte, dataBuf []byte, Len *int) ([]byte, []byte, error) { +func parseResponse(response []byte, dataBuf []byte, Len *int) ([]byte, []byte, error) { dataBuf = append(dataBuf, response...) lenCRLF := 2 if *Len != 0 { @@ -116,7 +105,7 @@ func ParseRedisResponse(response []byte, dataBuf []byte, Len *int) ([]byte, []by return nil, dataBuf, nil } -func RedisContext(hostnamePort string, redisCmdWrite, redisCmdRead chan RedisCmd) { +func initContext(hostnamePort string, redisCmdWrite, redisCmdRead chan RedisCmd) { tcpRemoteAddress, err := net.ResolveTCPAddr("tcp", hostnamePort) if err != nil { panic("cant resolve remote redis address") @@ -131,23 +120,23 @@ func RedisContext(hostnamePort string, redisCmdWrite, redisCmdRead chan RedisCmd <-readChan dataBuf := make([]byte, 0) dataLen := 0 - for true { + for { select { case cmd := <-redisCmdWrite: switch cmd.Command { case "SET": - data := RedisSet(cmd.Name, cmd.Data) + data := genRedisArray([]byte("SET"), []byte(cmd.Name), cmd.Data, []byte("EX"), []byte(fmt.Sprintf("%v", cmd.Duration))) writeChan <- data case "GET": - data := RedisGet(cmd.Name) + data := genRedisArray([]byte("GET"), []byte(cmd.Name)) writeChan <- data } case response := <-readChan: - data, dataBuf, err := ParseRedisResponse(response, dataBuf, &dataLen) + data, dataBuf, err := parseResponse(response, dataBuf, &dataLen) if dataLen != 0 { for data == nil { response = <-readChan - data, dataBuf, err = ParseRedisResponse(response, dataBuf, &dataLen) + data, dataBuf, err = parseResponse(response, dataBuf, &dataLen) } } if err != nil { @@ -182,17 +171,30 @@ func (sr *SimpleRedis) Init(redisHost string) { sr.redisHost = redisHost sr.redisChanWrite = make(chan RedisCmd) sr.redisChanRead = make(chan RedisCmd) - go RedisContext(sr.redisHost, sr.redisChanWrite, sr.redisChanRead) + go initContext(sr.redisHost, sr.redisChanWrite, sr.redisChanRead) } -func (sr *SimpleRedis) Do(cmd, name string, data []byte) ([]byte, error) { - sr.redisCmd.Command = cmd +func (sr *SimpleRedis) Get(name string) ([]byte, error) { + sr.redisCmd.Command = "GET" sr.redisCmd.Name = name - sr.redisCmd.Data = data + sr.redisCmd.Data = nil sr.redisChanWrite <- sr.redisCmd - resp := <- sr.redisChanRead + resp := <-sr.redisChanRead if resp.Error != nil { return nil, resp.Error } return resp.Data, nil -} \ No newline at end of file +} + +func (sr *SimpleRedis) Set(name string, data []byte, duration int64) error { + sr.redisCmd.Command = "SET" + sr.redisCmd.Name = name + sr.redisCmd.Data = data + sr.redisCmd.Duration = duration + sr.redisChanWrite <- sr.redisCmd + resp := <-sr.redisChanRead + if resp.Error != nil { + return resp.Error + } + return nil +}