Compare commits

...
16 Commits
Author SHA1 Message Date
mathieuHa f2aea695fc 🐛 Update regex to support = in lapikey update some exemples with 1.5.3 crowdsec (#115) 2023-09-19 20:57:29 +02:00
Joseph Kavanagh 2827fef273 🐛 env values need to be string (#112)
cannot unmarshal bool into Go struct field EnvVar.spec.template.spec.containers.env.value of type string
2023-09-05 13:26:50 +02:00
mathieuHaandMax Lerebourg 07c8fae927 🔧 Add conf variable: CrowdsecStreamTimeout (#110)
* 🔧 Add conf variable: CrowdsecStreamTimeout

* 🥅 catch error from sscan

*  fix ugly code

* 🐛 clean code

*  fix type + wrong type assertion

* 🚨 fix lint go simplify

* 📝 Update readme with new variable

* 🍱 fix variable naming

* 🍱 revert vendor file

* 🍱 fix lint

---------

Co-authored-by: Max Lerebourg <maxlerebourg@gmail.com>
2023-08-20 15:49:49 +02:00
mathieuHa 13c209be3f 📝 First version of doc update with single bouncer instance (#108) 2023-08-05 16:01:50 +02:00
maxlerebourg 93340ffa55 🍱 update dependencies redisclient to reduce memory consumption (#105)
* 🍱 update dependencies to avoid memory leak

* 🍱 update dep
2023-06-20 09:22:51 +02:00
maxlerebourg 0c2668d578 add redis database selection (#100)
*  add redis database selection

* 📝 update docs

* 📝 readme
2023-05-25 17:20:14 +02:00
maxlerebourg abae7ee028 📝 update version used (#97)
* 📝 update version used

* 📝 update doc

* 📝 documentation

* 📝 documentation

* 📝 versionning
2023-04-17 09:25:57 +02:00
maxlerebourg 1fcd4f4e2f remove down at start if crowdsec unavailable (#93)
*  remove down at start if crowdsec unavailable

* 🚨 fix lint
2023-03-12 20:49:00 +01:00
mathieuHa 39fcc38980 🐛Bump simple redis to 1.0.6 to fix bug hang with password, update doc on redis (#89) 2023-03-05 14:32:43 +01:00
Max Lerebourg dd322a966a 🍱 fix lint 2023-03-04 12:11:22 +01:00
Max Lerebourg f0bb140596 🍱 fix lint 2023-03-04 12:08:03 +01:00
Max Lerebourg 46e581eca2 🍱 fix readme to add redis pass 2023-03-04 12:05:09 +01:00
maxlerebourg 50690d1ac7 handle redis password (#87)
*  handle redis password

* 🍱 fix version
2023-03-04 11:51:54 +01:00
maxlerebourg b079073ff6 handle isHealthy in the main function and log error became… (#84)
*  handle isHealthy in the main function and log error became debug

* fix: lint

* fix: lint
2023-03-01 14:18:19 +01:00
maxlerebourg 976cbb7d1f 81 bug stream mode stops blocking (#82)
*  fix isHealthy issue at startup

* 🍱 not added in first commit ?

* 🍱 remove unused import

* 🍱 fix lint

* fix: lint
2023-01-30 14:03:10 +01:00
Max Lerebourg 80726df450 🐛 fix alone mode 2023-01-25 20:43:07 +01:00
24 changed files with 362 additions and 185 deletions
+2
View File
@@ -30,4 +30,6 @@ Steps to reproduce the behavior:
3. Scroll down to '....' 3. Scroll down to '....'
4. See error 4. See error
<!---
If you like the plugin, please consider starring it, so you can get updates and we get some more visibility ✨ If you like the plugin, please consider starring it, so you can get updates and we get some more visibility ✨
-->
@@ -16,4 +16,6 @@ A clear and concise description of what you want to happen.
**Additional context** **Additional context**
Add any other context or screenshots about the feature request here. Add any other context or screenshots about the feature request here.
<!---
If you like the plugin, please consider starring it, so you can get updates and we get some more visibility ✨ If you like the plugin, please consider starring it, so you can get updates and we get some more visibility ✨
-->
+18 -1
View File
@@ -29,7 +29,7 @@ There are 4 operating modes (CrowdsecMode) for this plugin:
The `streaming mode` is recommended for performance, decisions are updated every 60 sec by default and that's the only communication between Traefik and Crowdsec. Every request that happens hits the cache for quick decisions. The `streaming mode` is recommended for performance, decisions are updated every 60 sec by default and that's the only communication between Traefik and Crowdsec. Every request that happens hits the cache for quick decisions.
The cache can be local to Traefik using the filesystem, or a separate Redis instance. The cache can be local to Traefik using the filesystem, or a separate Redis instance.
Support for Redis is currently in beta (requires version 7.0.X of Redis).
## Usage ## Usage
@@ -44,6 +44,7 @@ make run
**/!\ Cache is shared by all services** **/!\ Cache is shared by all services**
*This means if an IP is banned, all services which are protected by an instance of the plugin will deny requests from that IP* *This means if an IP is banned, all services which are protected by an instance of the plugin will deny requests from that IP*
Only one instance of the plugin is *possible*.
### Variables ### Variables
- Enabled - Enabled
@@ -103,6 +104,18 @@ make run
- string - string
- default: "redis:6379" - default: "redis:6379"
- hostname and port for the Redis service - hostname and port for the Redis service
- RedisCachePassword
- string
- default: ""
- Password for the Redis service
- RedisCacheDatabase
- string
- default: ""
- Database selection for the Redis service
- HTTPTimeoutSeconds
- int64
- default: 10
- Default timeout in seconds for contacting Crowdsec LAPI
- UpdateIntervalSeconds - UpdateIntervalSeconds
- int64 - int64
- default: 60 - default: 60
@@ -134,6 +147,7 @@ experimental:
plugins: plugins:
bouncer: bouncer:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: vX.Y.Z # To update
``` ```
```yaml ```yaml
@@ -163,6 +177,7 @@ http:
logLevel: DEBUG logLevel: DEBUG
updateIntervalSeconds: 60 updateIntervalSeconds: 60
defaultDecisionSeconds: 60 defaultDecisionSeconds: 60
httpTimeoutSeconds: 10
crowdsecMode: live crowdsecMode: live
crowdsecLapiKey: privateKey-foo crowdsecLapiKey: privateKey-foo
crowdsecLapiKeyFile: /etc/traefik/cs-privateKey-foo crowdsecLapiKeyFile: /etc/traefik/cs-privateKey-foo
@@ -183,6 +198,8 @@ http:
forwardedHeadersCustomName: X-Custom-Header forwardedHeadersCustomName: X-Custom-Header
redisCacheEnabled: false redisCacheEnabled: false
redisCacheHost: "redis:6379" redisCacheHost: "redis:6379"
redisCachePassword: password
redisCacheDatabase: "5"
crowdsecLapiTLSCertificateAuthority: |- crowdsecLapiTLSCertificateAuthority: |-
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIEBzCCAu+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT MIIEBzCCAu+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
+39 -23
View File
@@ -15,8 +15,6 @@ import (
"text/template" "text/template"
"time" "time"
simpleredis "github.com/maxlerebourg/simpleredis"
cache "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/pkg/cache" cache "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/pkg/cache"
configuration "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/pkg/configuration" configuration "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/pkg/configuration"
ip "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/pkg/ip" ip "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/pkg/ip"
@@ -35,6 +33,7 @@ const (
//nolint:gochecknoglobals //nolint:gochecknoglobals
var ( var (
isStartup = true
isCrowdsecStreamHealthy = true isCrowdsecStreamHealthy = true
ticker chan bool ticker chan bool
) )
@@ -85,7 +84,7 @@ func New(ctx context.Context, next http.Handler, config *configuration.Config, n
crowdsecStreamRoute := "" crowdsecStreamRoute := ""
crowdsecHeader := "" crowdsecHeader := ""
if config.CrowdsecMode == configuration.AloneMode { if config.CrowdsecMode == configuration.AloneMode {
config.CrowdsecCapiMachineID, _ = configuration.GetVariable(config, "CrowdsecCapiMachineId") config.CrowdsecCapiMachineID, _ = configuration.GetVariable(config, "CrowdsecCapiMachineID")
config.CrowdsecCapiPassword, _ = configuration.GetVariable(config, "CrowdsecCapiPassword") config.CrowdsecCapiPassword, _ = configuration.GetVariable(config, "CrowdsecCapiPassword")
config.CrowdsecLapiHost = "api.crowdsec.net" config.CrowdsecLapiHost = "api.crowdsec.net"
config.CrowdsecLapiScheme = "https" config.CrowdsecLapiScheme = "https"
@@ -138,24 +137,30 @@ func New(ctx context.Context, next http.Handler, config *configuration.Config, n
IdleConnTimeout: 30 * time.Second, IdleConnTimeout: 30 * time.Second,
TLSClientConfig: tlsConfig, TLSClientConfig: tlsConfig,
}, },
Timeout: 10 * time.Second, Timeout: time.Duration(config.HTTPTimeoutSeconds) * time.Second,
}, },
cacheClient: &cache.Client{}, cacheClient: &cache.Client{},
} }
bouncer.cacheClient.New(config.RedisCacheEnabled, config.RedisCacheHost) config.RedisCachePassword, _ = configuration.GetVariable(config, "RedisCachePassword")
bouncer.cacheClient.New(
config.RedisCacheEnabled,
config.RedisCacheHost,
config.RedisCachePassword,
config.RedisCacheDatabase,
)
if (config.CrowdsecMode == configuration.StreamMode || config.CrowdsecMode == configuration.AloneMode) && ticker == nil { if (config.CrowdsecMode == configuration.StreamMode || config.CrowdsecMode == configuration.AloneMode) && ticker == nil {
if config.CrowdsecMode == configuration.AloneMode { if config.CrowdsecMode == configuration.AloneMode {
err = getToken(bouncer) if err := getToken(bouncer); err != nil {
if err != nil {
logger.Error(fmt.Sprintf("New:getToken %s", err.Error())) logger.Error(fmt.Sprintf("New:getToken %s", err.Error()))
return nil, err return nil, err
} }
} }
handleStreamTicker(bouncer)
isStartup = false
ticker = startTicker(config, func() { ticker = startTicker(config, func() {
handleStreamCache(bouncer) handleStreamTicker(bouncer)
}) })
go handleStreamCache(bouncer)
} }
logger.Debug(fmt.Sprintf("New initialized mode:%s", config.CrowdsecMode)) logger.Debug(fmt.Sprintf("New initialized mode:%s", config.CrowdsecMode))
@@ -193,10 +198,12 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// TODO This should be simplified // TODO This should be simplified
if bouncer.crowdsecMode != configuration.NoneMode { if bouncer.crowdsecMode != configuration.NoneMode {
isBanned, erro := bouncer.cacheClient.GetDecision(remoteIP) isBanned, cacheErr := bouncer.cacheClient.GetDecision(remoteIP)
if erro != nil { if cacheErr != nil {
logger.Debug(fmt.Sprintf("ServeHTTP:getDecision ip:%s isBanned:true %s", remoteIP, erro.Error())) errString := cacheErr.Error()
if erro.Error() == simpleredis.RedisUnreachable { logger.Debug(fmt.Sprintf("ServeHTTP:getDecision ip:%s isBanned:false %s", remoteIP, errString))
if errString != cache.CacheMiss {
logger.Error(fmt.Sprintf("ServeHTTP:getDecision ip:%s %s", remoteIP, errString))
rw.WriteHeader(http.StatusForbidden) rw.WriteHeader(http.StatusForbidden)
return return
} }
@@ -216,7 +223,7 @@ func (bouncer *Bouncer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if isCrowdsecStreamHealthy { if isCrowdsecStreamHealthy {
bouncer.next.ServeHTTP(rw, req) bouncer.next.ServeHTTP(rw, req)
} else { } else {
logger.Error(fmt.Sprintf("ServeHTTP isCrowdsecStreamHealthy:false ip:%s", remoteIP)) logger.Debug(fmt.Sprintf("ServeHTTP isCrowdsecStreamHealthy:false ip:%s", remoteIP))
rw.WriteHeader(http.StatusForbidden) rw.WriteHeader(http.StatusForbidden)
} }
} else { } else {
@@ -259,6 +266,15 @@ type Login struct {
Expire string `json:"expire"` Expire string `json:"expire"`
} }
func handleStreamTicker(bouncer *Bouncer) {
if err := handleStreamCache(bouncer); err != nil {
isCrowdsecStreamHealthy = false
logger.Error(err.Error())
} else {
isCrowdsecStreamHealthy = true
}
}
func startTicker(config *configuration.Config, work func()) chan bool { func startTicker(config *configuration.Config, work func()) chan bool {
ticker := time.NewTicker(time.Duration(config.UpdateIntervalSeconds) * time.Second) ticker := time.NewTicker(time.Duration(config.UpdateIntervalSeconds) * time.Second)
stop := make(chan bool, 1) stop := make(chan bool, 1)
@@ -346,7 +362,7 @@ func getToken(bouncer *Bouncer) error {
return fmt.Errorf("getToken statusCode:%d", login.Code) return fmt.Errorf("getToken statusCode:%d", login.Code)
} }
func handleStreamCache(bouncer *Bouncer) { func handleStreamCache(bouncer *Bouncer) error {
// TODO clean properly on exit. // TODO clean properly on exit.
// Instead of blocking the goroutine interval for all the secondary node, // Instead of blocking the goroutine interval for all the secondary node,
// if the master service is shut down, other goroutine can take the lead // if the master service is shut down, other goroutine can take the lead
@@ -354,27 +370,26 @@ func handleStreamCache(bouncer *Bouncer) {
_, err := bouncer.cacheClient.GetDecision(cacheTimeoutKey) _, err := bouncer.cacheClient.GetDecision(cacheTimeoutKey)
if err == nil { if err == nil {
logger.Debug("handleStreamCache:alreadyUpdated") logger.Debug("handleStreamCache:alreadyUpdated")
return return nil
}
if err.Error() != cache.CacheMiss {
return err
} }
bouncer.cacheClient.SetDecision(cacheTimeoutKey, false, bouncer.updateInterval-1) bouncer.cacheClient.SetDecision(cacheTimeoutKey, false, bouncer.updateInterval-1)
streamRouteURL := url.URL{ streamRouteURL := url.URL{
Scheme: bouncer.crowdsecScheme, Scheme: bouncer.crowdsecScheme,
Host: bouncer.crowdsecHost, Host: bouncer.crowdsecHost,
Path: bouncer.crowdsecStreamRoute, Path: bouncer.crowdsecStreamRoute,
RawQuery: fmt.Sprintf("startup=%t", !isCrowdsecStreamHealthy), RawQuery: fmt.Sprintf("startup=%t", !isCrowdsecStreamHealthy || isStartup),
} }
body, err := crowdsecQuery(bouncer, streamRouteURL.String(), false) body, err := crowdsecQuery(bouncer, streamRouteURL.String(), false)
if err != nil { if err != nil {
logger.Error(err.Error()) return err
isCrowdsecStreamHealthy = false
return
} }
var stream Stream var stream Stream
err = json.Unmarshal(body, &stream) err = json.Unmarshal(body, &stream)
if err != nil { if err != nil {
logger.Error(fmt.Sprintf("handleStreamCache:parsingBody %s", err.Error())) return fmt.Errorf("handleStreamCache:parsingBody %w", err)
isCrowdsecStreamHealthy = false
return
} }
for _, decision := range stream.New { for _, decision := range stream.New {
duration, err := time.ParseDuration(decision.Duration) duration, err := time.ParseDuration(decision.Duration)
@@ -387,6 +402,7 @@ func handleStreamCache(bouncer *Bouncer) {
} }
logger.Debug("handleStreamCache:updated") logger.Debug("handleStreamCache:updated")
isCrowdsecStreamHealthy = true isCrowdsecStreamHealthy = true
return nil
} }
func crowdsecQuery(bouncer *Bouncer, stringURL string, isPost bool) ([]byte, error) { func crowdsecQuery(bouncer *Bouncer, stringURL string, isPost bool) ([]byte, error) {
+6 -1
View File
@@ -144,12 +144,17 @@ func Test_handleStreamCache(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args args args args
wantErr bool
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
handleStreamCache(tt.args.bouncer) err := handleStreamCache(tt.args.bouncer)
if (err != nil) != tt.wantErr {
t.Errorf("handleStreamCache() error = %v, wantErr %v", err, tt.wantErr)
return
}
}) })
} }
} }
+5 -6
View File
@@ -2,7 +2,7 @@ version: "3.8"
services: services:
traefik: traefik:
image: "traefik:v2.9.6" image: "traefik:v2.10.4"
container_name: "traefik" container_name: "traefik"
restart: unless-stopped restart: unless-stopped
command: command:
@@ -36,7 +36,7 @@ services:
- "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker" - "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
- "traefik.http.services.service-foo.loadbalancer.server.port=80" - "traefik.http.services.service-foo.loadbalancer.server.port=80"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5" - "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5="
whoami2: whoami2:
image: traefik/whoami image: traefik/whoami
@@ -49,17 +49,16 @@ services:
- "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker" - "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker"
- "traefik.http.services.service-bar.loadbalancer.server.port=80" - "traefik.http.services.service-bar.loadbalancer.server.port=80"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7" - "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5="
crowdsec: crowdsec:
image: crowdsecurity/crowdsec:v1.4.1 image: crowdsecurity/crowdsec:v1.5.3
container_name: "crowdsec" container_name: "crowdsec"
restart: unless-stopped restart: unless-stopped
environment: environment:
COLLECTIONS: crowdsecurity/traefik COLLECTIONS: crowdsecurity/traefik
CUSTOM_HOSTNAME: crowdsec CUSTOM_HOSTNAME: crowdsec
BOUNCER_KEY_TRAEFIK_1: 40796d93c2958f9e58345514e67740e5 BOUNCER_KEY_TRAEFIK: 40796d93c2958f9e58345514e67740e5=
BOUNCER_KEY_TRAEFIK_2: 44c36dac5c4140af9f06f397508e82c7
volumes: volumes:
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro - ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- logs-local:/var/log/traefik:ro - logs-local:/var/log/traefik:ro
+6 -7
View File
@@ -2,7 +2,7 @@ version: "3.8"
services: services:
traefik: traefik:
image: "traefik:v2.9.6" image: "traefik:v2.10.4"
container_name: "traefik" container_name: "traefik"
restart: unless-stopped restart: unless-stopped
command: command:
@@ -14,7 +14,7 @@ services:
- "--entrypoints.web.address=:80" - "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" - "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.8" - "--experimental.plugins.bouncer.version=v1.1.15"
volumes: volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro" - "/var/run/docker.sock:/var/run/docker.sock:ro"
- "logs:/var/log/traefik" - "logs:/var/log/traefik"
@@ -39,7 +39,7 @@ services:
# Definition of the middleware # Definition of the middleware
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true"
# crowdseclapikey must be unique to the middleware attached to the service # crowdseclapikey must be unique to the middleware attached to the service
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=FIXME-LAPI-KEY-1" - "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=FIXME-LAPI-KEY-1="
# forwardedheaderstrustedips should be the IP of the proxy that is in front of traefik (if any) # forwardedheaderstrustedips should be the IP of the proxy that is in front of traefik (if any)
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5" - "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
@@ -58,20 +58,19 @@ services:
# Definitin of the middleware # Definitin of the middleware
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true"
# crowdseclapikey must be unique to the middleware attached to the service # crowdseclapikey must be unique to the middleware attached to the service
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=FIXME-LAPI-KEY-2" - "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=FIXME-LAPI-KEY-1="
# forwardedheaderstrustedips should be the IP of the proxy that is in front of traefik (if any) # forwardedheaderstrustedips should be the IP of the proxy that is in front of traefik (if any)
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5" - "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
crowdsec: crowdsec:
image: crowdsecurity/crowdsec:v1.4.1 image: crowdsecurity/crowdsec:v1.5.3
container_name: "crowdsec" container_name: "crowdsec"
restart: unless-stopped restart: unless-stopped
environment: environment:
COLLECTIONS: crowdsecurity/traefik COLLECTIONS: crowdsecurity/traefik
CUSTOM_HOSTNAME: crowdsec CUSTOM_HOSTNAME: crowdsec
# We need to register one api key per service we will use # We need to register one api key per service we will use
BOUNCER_KEY_TRAEFIK_1: FIXME-LAPI-KEY-1 BOUNCER_KEY_TRAEFIK: FIXME-LAPI-KEY-1=
BOUNCER_KEY_TRAEFIK_2: FIXME-LAPI-KEY-2
volumes: volumes:
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro - ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- logs:/var/log/traefik:ro - logs:/var/log/traefik:ro
@@ -2,7 +2,7 @@ version: "3.8"
services: services:
cloudflare: cloudflare:
image: "traefik:v2.9.6" image: "traefik:v2.10.4"
container_name: "cloudflare" container_name: "cloudflare"
restart: unless-stopped restart: unless-stopped
command: command:
@@ -12,7 +12,6 @@ services:
- "--api.insecure=true" - "--api.insecure=true"
- "--entrypoints.web.address=:80" - "--entrypoints.web.address=:80"
- "--providers.file.filename=/cloud.yaml" - "--providers.file.filename=/cloud.yaml"
- "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
- ./cloudflare-exemple.yaml:/cloud.yaml:ro - ./cloudflare-exemple.yaml:/cloud.yaml:ro
@@ -22,7 +21,7 @@ services:
- 8080:8080 - 8080:8080
traefik: traefik:
image: "traefik:v2.9.6" image: "traefik:v2.10.4"
container_name: "traefik" container_name: "traefik"
restart: unless-stopped restart: unless-stopped
command: command:
@@ -36,7 +35,7 @@ services:
- "--entrypoints.web.forwardedheaders.trustedips=172.21.0.5" - "--entrypoints.web.forwardedheaders.trustedips=172.21.0.5"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" - "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7" - "--experimental.plugins.bouncer.version=v1.1.13"
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
- logs-traefik:/var/log/traefik - logs-traefik:/var/log/traefik
@@ -46,7 +45,7 @@ services:
depends_on: depends_on:
- crowdsec - crowdsec
whoami1: whoami-foo:
image: traefik/whoami image: traefik/whoami
container_name: "simple-service-foo" container_name: "simple-service-foo"
restart: unless-stopped restart: unless-stopped
@@ -58,15 +57,14 @@ services:
- "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker" - "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
# Definition of the service # Definition of the service
- "traefik.http.services.service-foo.loadbalancer.server.port=80" - "traefik.http.services.service-foo.loadbalancer.server.port=80"
# Definitin of the middleware # Definition of the middleware
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5" - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecmode=live"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdsecmode=live" - "traefik.http.middlewares.crowdsec.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5" - "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.loglevel=DEBUG"
whoami2: whoami-bar:
image: traefik/whoami image: traefik/whoami
container_name: "simple-service-bar" container_name: "simple-service-bar"
restart: unless-stopped restart: unless-stopped
@@ -78,24 +76,22 @@ services:
- "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker" - "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker"
# Definition of the service # Definition of the service
- "traefik.http.services.service-bar.loadbalancer.server.port=80" - "traefik.http.services.service-bar.loadbalancer.server.port=80"
# Definitin of the middleware # Definition of the middleware
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7" - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecmode=live"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecmode=live" - "traefik.http.middlewares.crowdsec.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.forwardedheaderstrustedips=172.21.0.5" - "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.loglevel=DEBUG"
crowdsec: crowdsec:
image: crowdsecurity/crowdsec:v1.4.3 image: crowdsecurity/crowdsec:v1.5.2
container_name: "crowdsec" container_name: "crowdsec"
restart: unless-stopped restart: unless-stopped
environment: environment:
COLLECTIONS: crowdsecurity/traefik COLLECTIONS: crowdsecurity/traefik
CUSTOM_HOSTNAME: crowdsec CUSTOM_HOSTNAME: crowdsec
BOUNCER_KEY_TRAEFIK_DEV_1: 40796d93c2958f9e58345514e67740e5 BOUNCER_KEY_TRAEFIK_DEV: 40796d93c2958f9e58345514e67740e5
BOUNCER_KEY_TRAEFIK_DEV_2: 44c36dac5c4140af9f06f397508e82c7
volumes: volumes:
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro - ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- logs-cloudflare:/var/log/traefik:ro - logs-cloudflare:/var/log/traefik:ro
@@ -2,7 +2,7 @@
DEBIAN_FRONTEND=noninteractive sudo apt-get update && sudo apt-get install wget -y DEBIAN_FRONTEND=noninteractive sudo apt-get update && sudo apt-get install wget -y
# DEBIAN_FRONTEND=noninteractive sudo apt-get upgrade -y --assume-yes # DEBIAN_FRONTEND=noninteractive sudo apt-get upgrade -y --assume-yes
wget -O traefik.tar.gz "https://github.com/traefik/traefik/releases/download/v2.9.6/traefik_v2.9.6_linux_amd64.tar.gz" wget -O traefik.tar.gz "https://github.com/traefik/traefik/releases/download/v2.10.4/traefik_v2.10.4_linux_amd64.tar.gz"
tar -zxvf traefik.tar.gz tar -zxvf traefik.tar.gz
# inspired from https://gist.github.com/ubergesundheit/7c9d875befc2d7bfd0bf43d8b3862d85 # inspired from https://gist.github.com/ubergesundheit/7c9d875befc2d7bfd0bf43d8b3862d85
sudo mv ./traefik /usr/local/bin/ sudo mv ./traefik /usr/local/bin/
+1 -1
View File
@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
DEBIAN_FRONTEND=noninteractive sudo apt-get update && apt-get install wget -y DEBIAN_FRONTEND=noninteractive sudo apt-get update && apt-get install wget -y
wget -O whoami.tar.gz "https://github.com/traefik/whoami/releases/download/v1.8.7/whoami_v1.8.7_linux_amd64.tar.gz" wget -O whoami.tar.gz "https://github.com/traefik/whoami/releases/download/v1.9.0/whoami_v1.9.0_linux_amd64.tar.gz"
tar -zxvf whoami.tar.gz tar -zxvf whoami.tar.gz
# inspired from https://gist.github.com/ubergesundheit/7c9d875befc2d7bfd0bf43d8b3862d85 # inspired from https://gist.github.com/ubergesundheit/7c9d875befc2d7bfd0bf43d8b3862d85
sudo mv ./whoami /usr/local/bin/ sudo mv ./whoami /usr/local/bin/
+2 -2
View File
@@ -1,5 +1,5 @@
image: image:
tag: v1.4.4-rc1 tag: v1.5.2
agent: agent:
acquisition: acquisition:
@@ -22,4 +22,4 @@ lapi:
value: "k8s linux test" value: "k8s linux test"
# If it's a test, we don't want to share signals with CrowdSec so disable the Online API. # If it's a test, we don't want to share signals with CrowdSec so disable the Online API.
- name: DISABLE_ONLINE_API - name: DISABLE_ONLINE_API
value: true value: "true"
+2 -2
View File
@@ -1,5 +1,5 @@
image: image:
tag: v2.9.6 tag: v2.10.4
logs: logs:
general: general:
@@ -16,4 +16,4 @@ experimental:
additionalArguments: additionalArguments:
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" - "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7-beta1" - "--experimental.plugins.bouncer.version=v1.1.13"
+52 -39
View File
@@ -2,7 +2,7 @@ version: "3.8"
services: services:
traefik: traefik:
image: "traefik:v2.9.6" image: "traefik:v2.10.4"
container_name: "traefik" container_name: "traefik"
restart: unless-stopped restart: unless-stopped
command: command:
@@ -15,7 +15,7 @@ services:
- "--entrypoints.web.address=:80" - "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" - "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7" - "--experimental.plugins.bouncer.version=v1.1.13"
# - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" # - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
@@ -26,56 +26,60 @@ services:
- 8080:8080 - 8080:8080
depends_on: depends_on:
- crowdsec - crowdsec
- redis # - redis-insecure
- redis-secure
whoami-foo: # Either use secure, or insecure but do not mix both
image: traefik/whoami # whoami-redis-insecure:
container_name: "simple-service-foo" # image: traefik/whoami
restart: unless-stopped # container_name: "simple-service-foo"
labels: # restart: unless-stopped
- "traefik.enable=true" # labels:
# Definition of the router # - "traefik.enable=true"
- "traefik.http.routers.router-foo.rule=Path(`/foo`)" # # Definition of the router
- "traefik.http.routers.router-foo.entrypoints=web" # - "traefik.http.routers.router-foo.rule=Path(`/redis-insecure`)"
- "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker" # - "traefik.http.routers.router-foo.entrypoints=web"
# Definition of the service # - "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
- "traefik.http.services.service-foo.loadbalancer.server.port=80" # # Definition of the service
# Definition of the middleware # - "traefik.http.services.service-foo.loadbalancer.server.port=80"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true" # # Definition of the middleware
# crowdseclapikey must be uniq to the middleware attached to the service # - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5" # - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.rediscacheenabled=true" # - "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscacheenabled=true"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.loglevel=DEBUG" # # Contact redis-unsecure without a password
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscachehost=redis-insecure:6379"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
whoami-bar: whoami-redis-secure:
image: traefik/whoami image: traefik/whoami
container_name: "simple-service-bar" container_name: "simple-service-bar"
restart: unless-stopped restart: unless-stopped
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
# Definition of the router # Definition of the router
- "traefik.http.routers.router-bar.rule=Path(`/bar`)" - "traefik.http.routers.router-bar.rule=Path(`/redis-secure`)"
- "traefik.http.routers.router-bar.entrypoints=web" - "traefik.http.routers.router-bar.entrypoints=web"
- "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker" - "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker"
# Definition of the service # Definition of the service
- "traefik.http.services.service-bar.loadbalancer.server.port=80" - "traefik.http.services.service-bar.loadbalancer.server.port=80"
# Definition of the middleware # Definition of the middleware
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7" - "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscacheenabled=true"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.rediscacheenabled=true" - "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscachepassword=FIXME"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.loglevel=DEBUG" # Contact redis-secure with password
- "traefik.http.middlewares.crowdsec.plugin.bouncer.rediscachehost=redis-secure:6379"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
crowdsec: crowdsec:
image: crowdsecurity/crowdsec:v1.4.3 image: crowdsecurity/crowdsec:v1.5.2
container_name: "crowdsec" container_name: "crowdsec"
restart: unless-stopped restart: unless-stopped
environment: environment:
COLLECTIONS: crowdsecurity/traefik COLLECTIONS: crowdsecurity/traefik
CUSTOM_HOSTNAME: crowdsec CUSTOM_HOSTNAME: crowdsec
BOUNCER_KEY_TRAEFIK_DEV_1: 40796d93c2958f9e58345514e67740e5 BOUNCER_KEY_TRAEFIK_DEV: 40796d93c2958f9e58345514e67740e5
BOUNCER_KEY_TRAEFIK_DEV_2: 44c36dac5c4140af9f06f397508e82c7
volumes: volumes:
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro - ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- logs-redis:/var/log/traefik:ro - logs-redis:/var/log/traefik:ro
@@ -84,18 +88,27 @@ services:
labels: labels:
- "traefik.enable=false" - "traefik.enable=false"
redis: redis-secure:
image: "redis:7.0.5-alpine" image: "redis:7.0.12-alpine"
container_name: "redis" container_name: "redis-secure"
hostname: redis-secure
restart: unless-stopped restart: unless-stopped
command: "redis-server --save 60 1" command: "redis-server --save 60 1 --loglevel debug --requirepass FIXME"
volumes: volumes:
- redis-data:/data - redis-secure-data:/data
ports:
- 6379:6379 # redis-insecure:
# image: "redis:7.0.12-alpine"
# container_name: "redis-insecure"
# hostname: redis-unsecure
# restart: unless-stopped
# command: "redis-server --save 60 1 --loglevel debug"
# volumes:
# - redis-unsecure-data:/data
volumes: volumes:
logs-redis: logs-redis:
crowdsec-db-redis: crowdsec-db-redis:
crowdsec-config-redis: crowdsec-config-redis:
redis-data: redis-unsecure-data:
redis-secure-data:
+3 -2
View File
@@ -11,10 +11,11 @@ These CAPI credentials must be set in your docker-compose.yml or in your config
... ...
whoami: whoami:
labels: labels:
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecMode=alone"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecCapiMachineId=LOGIN" - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecCapiMachineId=LOGIN"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecCapiPassword=PASSWORD" - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecCapiPassword=PASSWORD"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseccapiscenarios=crowdsecurity/http-generic-bf,crowdsecurity/http-xss-probing,..." - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecCapiScenarios=crowdsecurity/http-generic-bf,crowdsecurity/http-xss-probing,..."
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
``` ```
You can then run all the containers: You can then run all the containers:
@@ -0,0 +1,45 @@
version: "3.8"
services:
traefik:
image: "traefik:v2.10.4"
container_name: "traefik"
restart: unless-stopped
command:
# - "--log.level=DEBUG"
- "--accesslog"
- "--accesslog.filepath=/var/log/traefik/access.log"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.13"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- 80:80
- 8080:8080
whoami-foo:
image: traefik/whoami
container_name: "simple-service-foo"
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.router-foo.rule=Path(`/foo`)"
- "traefik.http.routers.router-foo.entrypoints=web"
- "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
- "traefik.http.services.service-foo.loadbalancer.server.port=80"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true"
# - "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdsecmode=alone"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.CrowdsecCapiMachineId=logincacacalfkrjebfreifgzfblezgyfoerxsqxsqxsqxsr"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.CrowdsecCapiPassword=Password2"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseccapiscenarios=crowdsecurity/sshd,crowdsecurity/asterisk_bf,crowdsecurity/asterisk_user_enum,crowdsecurity/base-http-scenarios"
volumes:
logs-local:
+27 -25
View File
@@ -2,7 +2,7 @@ version: "3.8"
services: services:
traefik: traefik:
image: "traefik:v2.9.6" image: "traefik:v2.10.4"
container_name: "traefik" container_name: "traefik"
restart: unless-stopped restart: unless-stopped
command: command:
@@ -15,14 +15,14 @@ services:
- "--entrypoints.web.address=:80" - "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" - "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7" - "--experimental.plugins.bouncer.version=v1.1.13"
# - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" # - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
- ./LAPIKEY:/etc/traefik/LAPIKEY:ro - ./LAPIKEY:/etc/traefik/LAPIKEY:ro
- logs-tls-auth:/var/log/traefik - logs-tls-auth:/var/log/traefik
- crowdsec-certs-tls-auth:/etc/traefik/crowdsec-certs - crowdsec-certs-tls-auth:/etc/traefik/crowdsec-certs
- ./../../:/plugins-local/src/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin # - ./../../:/plugins-local/src/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
ports: ports:
- 80:80 - 80:80
@@ -30,22 +30,24 @@ services:
depends_on: depends_on:
- crowdsec - crowdsec
whoami-foo: # Use HTTPS scheme but with lapikey authentication
image: traefik/whoami # whoami-foo:
container_name: "simple-service-foo" # image: traefik/whoami
restart: unless-stopped # container_name: "simple-service-foo"
labels: # restart: unless-stopped
- "traefik.enable=true" # labels:
- "traefik.http.routers.router-foo.rule=Path(`/foo`)" # - "traefik.enable=true"
- "traefik.http.routers.router-foo.entrypoints=web" # - "traefik.http.routers.router-foo.rule=Path(`/foo`)"
- "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker" # - "traefik.http.routers.router-foo.entrypoints=web"
- "traefik.http.services.service-foo.loadbalancer.server.port=80" # - "traefik.http.routers.router-foo.middlewares=crowdsec-foo@docker"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true" # - "traefik.http.services.service-foo.loadbalancer.server.port=80"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.loglevel=DEBUG" # - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5" # - "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapischeme=https" # - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdsecLapiTLSCertificateAuthorityFile=/etc/traefik/crowdsec-certs/inter.pem" # - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapischeme=https"
# - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiTLSCertificateAuthorityFile=/etc/traefik/crowdsec-certs/inter.pem"
# Use HTTPS scheme with TLS cert authentication
whoami-bar: whoami-bar:
image: traefik/whoami image: traefik/whoami
container_name: "simple-service-bar" container_name: "simple-service-bar"
@@ -56,15 +58,15 @@ services:
- "traefik.http.routers.router-bar.entrypoints=web" - "traefik.http.routers.router-bar.entrypoints=web"
- "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker" - "traefik.http.routers.router-bar.middlewares=crowdsec-bar@docker"
- "traefik.http.services.service-bar.loadbalancer.server.port=80" - "traefik.http.services.service-bar.loadbalancer.server.port=80"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.loglevel=DEBUG" - "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapischeme=https" - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapischeme=https"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecLapiTLSCertificateAuthorityFile=/etc/traefik/crowdsec-certs/inter.pem" - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiTLSCertificateAuthorityFile=/etc/traefik/crowdsec-certs/inter.pem"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecLapiTLSCertificateBouncerFile=/etc/traefik/crowdsec-certs/bouncer.pem" - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiTLSCertificateBouncerFile=/etc/traefik/crowdsec-certs/bouncer.pem"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdsecLapiTLSCertificateBouncerKeyFile=/etc/traefik/crowdsec-certs/bouncer-key.pem" - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiTLSCertificateBouncerKeyFile=/etc/traefik/crowdsec-certs/bouncer-key.pem"
crowdsec: crowdsec:
image: crowdsecurity/crowdsec:v1.4.3 image: crowdsecurity/crowdsec:v1.5.2
container_name: "crowdsec" container_name: "crowdsec"
restart: unless-stopped restart: unless-stopped
environment: environment:
+13 -16
View File
@@ -2,7 +2,7 @@ version: "3.8"
services: services:
traefik: traefik:
image: "traefik:v2.9.6" image: "traefik:v2.10.4"
container_name: "traefik" container_name: "traefik"
restart: unless-stopped restart: unless-stopped
command: command:
@@ -15,12 +15,12 @@ services:
- "--entrypoints.web.address=:80" - "--entrypoints.web.address=:80"
- "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" - "--experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.bouncer.version=v1.1.7" - "--experimental.plugins.bouncer.version=v1.1.13"
# - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" # - "--experimental.localplugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
- logs-trustedips:/var/log/traefik - logs-trustedips:/var/log/traefik
- ./../../:/plugins-local/src/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin # - ./../../:/plugins-local/src/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
ports: ports:
- 80:80 - 80:80
- 8080:8080 - 8080:8080
@@ -40,12 +40,11 @@ services:
# Definition of the service # Definition of the service
- "traefik.http.services.service-foo.loadbalancer.server.port=80" - "traefik.http.services.service-foo.loadbalancer.server.port=80"
# Definition of the middleware # Definition of the middleware
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
# Replace 10.0.10.30/32 by your IP range which is "trusted" # Replace 10.0.10.30/32 by your IP range which is "trusted"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.clienttrustedips=10.0.10.30/32" - "traefik.http.middlewares.crowdsec.plugin.bouncer.clienttrustedips=10.0.10.30/32"
- "traefik.http.middlewares.crowdsec-foo.plugin.bouncer.loglevel=DEBUG" - "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
whoami2: whoami2:
image: traefik/whoami image: traefik/whoami
@@ -60,23 +59,21 @@ services:
# Definition of the service # Definition of the service
- "traefik.http.services.service-bar.loadbalancer.server.port=80" - "traefik.http.services.service-bar.loadbalancer.server.port=80"
# Definition of the middleware # Definition of the middleware
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.enabled=true" - "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
# crowdseclapikey must be uniq to the middleware attached to the service - "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=40796d93c2958f9e58345514e67740e5"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.crowdseclapikey=44c36dac5c4140af9f06f397508e82c7"
# Replace 10.0.10.30/32 by your IP range which is "trusted" # Replace 10.0.10.30/32 by your IP range which is "trusted"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.clienttrustedips=10.0.10.30/32" - "traefik.http.middlewares.crowdsec.plugin.bouncer.clienttrustedips=10.0.10.30/32"
- "traefik.http.middlewares.crowdsec-bar.plugin.bouncer.loglevel=DEBUG" - "traefik.http.middlewares.crowdsec.plugin.bouncer.loglevel=DEBUG"
crowdsec: crowdsec:
image: crowdsecurity/crowdsec:v1.4.3 image: crowdsecurity/crowdsec:v1.5.2
container_name: "crowdsec" container_name: "crowdsec"
restart: unless-stopped restart: unless-stopped
environment: environment:
COLLECTIONS: crowdsecurity/traefik COLLECTIONS: crowdsecurity/traefik
CUSTOM_HOSTNAME: crowdsec CUSTOM_HOSTNAME: crowdsec
BOUNCER_KEY_TRAEFIK_DEV_1: 40796d93c2958f9e58345514e67740e5 BOUNCER_KEY_TRAEFIK_DEV: 40796d93c2958f9e58345514e67740e5
BOUNCER_KEY_TRAEFIK_DEV_2: 44c36dac5c4140af9f06f397508e82c7
volumes: volumes:
- ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro - ./acquis.yaml:/etc/crowdsec/acquis.yaml:ro
- logs-trustedips:/var/log/traefik:ro - logs-trustedips:/var/log/traefik:ro
+1 -1
View File
@@ -4,5 +4,5 @@ go 1.19
require ( require (
github.com/leprosus/golang-ttl-map v1.1.7 github.com/leprosus/golang-ttl-map v1.1.7
github.com/maxlerebourg/simpleredis v1.0.3 github.com/maxlerebourg/simpleredis v1.0.9
) )
+2 -2
View File
@@ -1,4 +1,4 @@
github.com/leprosus/golang-ttl-map v1.1.7 h1:cF4AAFDDnJTFSV+/42sKLhmMluvLdRlCGS2UaifH6UM= github.com/leprosus/golang-ttl-map v1.1.7 h1:cF4AAFDDnJTFSV+/42sKLhmMluvLdRlCGS2UaifH6UM=
github.com/leprosus/golang-ttl-map v1.1.7/go.mod h1:4QWHJPeVBbrkhOhXdhCv9IEiyj/YzkO04/iexy4vSe0= github.com/leprosus/golang-ttl-map v1.1.7/go.mod h1:4QWHJPeVBbrkhOhXdhCv9IEiyj/YzkO04/iexy4vSe0=
github.com/maxlerebourg/simpleredis v1.0.3 h1:VhXq9bVytWDqD/TS/GjHKayvQb/VUeEql5F+yUbdOiI= github.com/maxlerebourg/simpleredis v1.0.9 h1:aj1hKaYPeOVE4Ksu3TV/zsreUDDWOpKXBAvoFysiqII=
github.com/maxlerebourg/simpleredis v1.0.3/go.mod h1:/DH8zOK6kDskSqoX/m5CJJdNGfkIQZd/ERBJgytDDSk= github.com/maxlerebourg/simpleredis v1.0.9/go.mod h1:/DH8zOK6kDskSqoX/m5CJJdNGfkIQZd/ERBJgytDDSk=
+9 -3
View File
@@ -16,6 +16,9 @@ const (
cacheNoBannedValue = "f" cacheNoBannedValue = "f"
) )
// CacheMiss error string when cache is miss.
const CacheMiss = "cache:miss"
//nolint:gochecknoglobals //nolint:gochecknoglobals
var ( var (
redis simpleredis.SimpleRedis redis simpleredis.SimpleRedis
@@ -30,7 +33,7 @@ func (localCache) getDecision(clientIP string) (bool, error) {
if isCached && isValid && len(bannedString) > 0 { if isCached && isValid && len(bannedString) > 0 {
return bannedString == cacheBannedValue, nil return bannedString == cacheBannedValue, nil
} }
return false, fmt.Errorf("cache:miss") return false, fmt.Errorf(CacheMiss)
} }
func (localCache) setDecision(clientIP string, value string, duration int64) { func (localCache) setDecision(clientIP string, value string, duration int64) {
@@ -49,6 +52,9 @@ func (redisCache) getDecision(clientIP string) (bool, error) {
if err == nil && len(bannedString) > 0 { if err == nil && len(bannedString) > 0 {
return bannedString == cacheBannedValue, nil return bannedString == cacheBannedValue, nil
} }
if err.Error() == simpleredis.RedisMiss {
return false, fmt.Errorf(CacheMiss)
}
return false, err return false, err
} }
@@ -76,9 +82,9 @@ type Client struct {
} }
// New Initialize cache client. // New Initialize cache client.
func (client *Client) New(isRedis bool, host string) { func (client *Client) New(isRedis bool, host, pass, database string) {
if isRedis { if isRedis {
redis.Init(host) redis.Init(host, pass, database)
client.cache = &redisCache{} client.cache = &redisCache{}
} else { } else {
client.cache = &localCache{} client.cache = &localCache{}
+15 -3
View File
@@ -50,11 +50,15 @@ type Config struct {
CrowdsecCapiScenarios []string `json:"crowdsecCapiScenarios,omitempty"` CrowdsecCapiScenarios []string `json:"crowdsecCapiScenarios,omitempty"`
UpdateIntervalSeconds int64 `json:"updateIntervalSeconds,omitempty"` UpdateIntervalSeconds int64 `json:"updateIntervalSeconds,omitempty"`
DefaultDecisionSeconds int64 `json:"defaultDecisionSeconds,omitempty"` DefaultDecisionSeconds int64 `json:"defaultDecisionSeconds,omitempty"`
HTTPTimeoutSeconds int64 `json:"httpTimeoutSeconds,omitempty"`
ForwardedHeadersCustomName string `json:"forwardedheaderscustomheader,omitempty"` ForwardedHeadersCustomName string `json:"forwardedheaderscustomheader,omitempty"`
ForwardedHeadersTrustedIPs []string `json:"forwardedHeadersTrustedIps,omitempty"` ForwardedHeadersTrustedIPs []string `json:"forwardedHeadersTrustedIps,omitempty"`
ClientTrustedIPs []string `json:"clientTrustedIps,omitempty"` ClientTrustedIPs []string `json:"clientTrustedIps,omitempty"`
RedisCacheEnabled bool `json:"redisCacheEnabled,omitempty"` RedisCacheEnabled bool `json:"redisCacheEnabled,omitempty"`
RedisCacheHost string `json:"redisCacheHost,omitempty"` RedisCacheHost string `json:"redisCacheHost,omitempty"`
RedisCachePassword string `json:"redisCachePassword,omitempty"`
RedisCachePasswordFile string `json:"redisCachePasswordFile,omitempty"`
RedisCacheDatabase string `json:"redisCacheDatabase,omitempty"`
} }
func contains(source []string, target string) bool { func contains(source []string, target string) bool {
@@ -78,11 +82,14 @@ func New() *Config {
CrowdsecLapiTLSInsecureVerify: false, CrowdsecLapiTLSInsecureVerify: false,
UpdateIntervalSeconds: 60, UpdateIntervalSeconds: 60,
DefaultDecisionSeconds: 60, DefaultDecisionSeconds: 60,
HTTPTimeoutSeconds: 10,
ForwardedHeadersCustomName: "X-Forwarded-For", ForwardedHeadersCustomName: "X-Forwarded-For",
ForwardedHeadersTrustedIPs: []string{}, ForwardedHeadersTrustedIPs: []string{},
ClientTrustedIPs: []string{}, ClientTrustedIPs: []string{},
RedisCacheEnabled: false, RedisCacheEnabled: false,
RedisCacheHost: "redis:6379", RedisCacheHost: "redis:6379",
RedisCachePassword: "",
RedisCacheDatabase: "",
} }
} }
@@ -115,7 +122,7 @@ func GetVariable(config *Config, key string) (string, error) {
// ValidateParams validate all the param gave by user. // ValidateParams validate all the param gave by user.
// //
//nolint:gocyclo //nolint:gocyclo,gocognit
func ValidateParams(config *Config) error { func ValidateParams(config *Config) error {
if err := validateParamsRequired(config); err != nil { if err := validateParamsRequired(config); err != nil {
return err return err
@@ -128,8 +135,12 @@ func ValidateParams(config *Config) error {
return err return err
} }
if _, err := GetVariable(config, "RedisCachePassword"); err != nil {
return err
}
if config.CrowdsecMode == AloneMode { if config.CrowdsecMode == AloneMode {
if _, err := GetVariable(config, "CrowdsecCapiMachineId"); err != nil { if _, err := GetVariable(config, "CrowdsecCapiMachineID"); err != nil {
return err return err
} }
if _, err := GetVariable(config, "CrowdsecCapiPassword"); err != nil { if _, err := GetVariable(config, "CrowdsecCapiPassword"); err != nil {
@@ -184,7 +195,7 @@ func ValidateParams(config *Config) error {
// valid ! # $ % & ' * + - . ^ _ ` | ~ DIGIT ALPHA // valid ! # $ % & ' * + - . ^ _ ` | ~ DIGIT ALPHA
// See https://httpwg.github.io/specs/rfc7230.html#rule.token.separators // See https://httpwg.github.io/specs/rfc7230.html#rule.token.separators
func validateParamsAPIKey(lapiKey string) error { func validateParamsAPIKey(lapiKey string) error {
reg := regexp.MustCompile("^[a-zA-Z0-9 !#$%&'*+-.^_`|~]*$") reg := regexp.MustCompile("^[a-zA-Z0-9 !#$%&'*+-.^_`|~=]*$")
if !reg.Match([]byte(lapiKey)) { if !reg.Match([]byte(lapiKey)) {
return fmt.Errorf("CrowdsecLapiKey doesn't valid this regexp: '/%s/'", reg.String()) return fmt.Errorf("CrowdsecLapiKey doesn't valid this regexp: '/%s/'", reg.String())
} }
@@ -232,6 +243,7 @@ func validateParamsRequired(config *Config) error {
requiredInt := map[string]int64{ requiredInt := map[string]int64{
"UpdateIntervalSeconds": config.UpdateIntervalSeconds, "UpdateIntervalSeconds": config.UpdateIntervalSeconds,
"DefaultDecisionSeconds": config.DefaultDecisionSeconds, "DefaultDecisionSeconds": config.DefaultDecisionSeconds,
"HTTPTimeoutSeconds": config.HTTPTimeoutSeconds,
} }
for key, val := range requiredInt { for key, val := range requiredInt {
if val < 1 { if val < 1 {
+30 -1
View File
@@ -1,2 +1,31 @@
# simpleredis # simpleredis
Minimal go redis with only get, set and delete operation Minimal go redis with only `get`, `set` and `delete` operation.
It supports password authentication with redis.
With **NO** external dependencies.
## Example
```go
import simpleredis "github.com/maxlerebourg/simpleredis"
var redis simpleredis.SimpleRedis
redis.Init("redis:6379", "", "") // redisHost, redisPass, redisDatabase
err := redis.Set("test", []bytes("whatever"), 60), // Set key "test" with "whatever" for 60 seconds
if err != nil {
...
}
val, err := redis.Get("test") // get key test
if err != nil {
// err could be only redis:unreachable, redis:miss or redis:timeout available in simpleredis.RedisUnreachable
...
}
err = redis.Del("test")
if err != nil {
...
}
```
## Author
Max Lerebourg @ [Primadviz.com](https://primadviz.com)
Mathieu Hanotaux
+61 -25
View File
@@ -17,10 +17,12 @@ const (
RedisUnreachable = "redis:unreachable" RedisUnreachable = "redis:unreachable"
RedisMiss = "redis:miss" RedisMiss = "redis:miss"
RedisTimeout = "redis:timeout" RedisTimeout = "redis:timeout"
RedisNoAuth = "redis:noauth"
RedisIssue = "redis:issue?"
) )
// A RedisCmd is used to communicate with redis at low level using commands. // A redisCmd is used to communicate with redis at low level using commands.
type RedisCmd struct { type redisCmd struct {
Command string Command string
Name string Name string
Data []byte Data []byte
@@ -30,7 +32,9 @@ type RedisCmd struct {
// A SimpleRedis is used to communicate with redis. // A SimpleRedis is used to communicate with redis.
type SimpleRedis struct { type SimpleRedis struct {
redisHost string host string
pass string
database string
} }
func genRedisArray(params ...[]byte) []byte { func genRedisArray(params ...[]byte) []byte {
@@ -49,12 +53,29 @@ func send(wr *textproto.Writer, method string, data []byte) {
} }
} }
func askRedis(hostnamePort string, cmd RedisCmd, channel chan RedisCmd) { func (sr *SimpleRedis) waitRedis(reader *textproto.Reader, channel chan redisCmd) {
dialer := net.Dialer{Timeout: 2 * time.Second} for {
conn, err := dialer.Dial("tcp", hostnamePort) select {
if err != nil { case <-time.After(time.Second * 1):
channel <- RedisCmd{Error: fmt.Errorf(RedisUnreachable)} channel <- redisCmd{Error: fmt.Errorf(RedisTimeout)}
return return
default:
read, _ := reader.ReadLineBytes()
if string(read) != "+OK" {
channel <- redisCmd{Error: fmt.Errorf(RedisNoAuth)}
return
}
}
// breaks out of for
break
}
}
func (sr *SimpleRedis) askRedis(cmd redisCmd, channel chan redisCmd) redisCmd {
dialer := net.Dialer{Timeout: 2 * time.Second}
conn, err := dialer.Dial("tcp", sr.host)
if err != nil {
return redisCmd{Error: fmt.Errorf(RedisUnreachable)}
} }
defer func() { defer func() {
if err := conn.Close(); err != nil { if err := conn.Close(); err != nil {
@@ -65,6 +86,18 @@ func askRedis(hostnamePort string, cmd RedisCmd, channel chan RedisCmd) {
writer := textproto.NewWriter(bufio.NewWriter(conn)) writer := textproto.NewWriter(bufio.NewWriter(conn))
reader := textproto.NewReader(bufio.NewReader(conn)) reader := textproto.NewReader(bufio.NewReader(conn))
if sr.pass != "" {
data := genRedisArray([]byte("AUTH"), []byte(sr.pass))
send(writer, "auth", data)
sr.waitRedis(reader, channel)
}
if sr.database != "" {
data := genRedisArray([]byte("SELECT"), []byte(sr.database))
send(writer, "select", data)
sr.waitRedis(reader, channel)
}
switch cmd.Command { switch cmd.Command {
case "SET": case "SET":
data := genRedisArray([]byte("SET"), []byte(cmd.Name), cmd.Data, []byte("EX"), []byte(fmt.Sprintf("%d", cmd.Duration))) data := genRedisArray([]byte("SET"), []byte(cmd.Name), cmd.Data, []byte("EX"), []byte(fmt.Sprintf("%d", cmd.Duration)))
@@ -78,36 +111,39 @@ func askRedis(hostnamePort string, cmd RedisCmd, channel chan RedisCmd) {
for { for {
select { select {
case <-time.After(time.Second * 1): case <-time.After(time.Second * 1):
channel <- RedisCmd{Error: fmt.Errorf(RedisTimeout)} return redisCmd{Error: fmt.Errorf(RedisTimeout)}
return
default: default:
read, _ := reader.ReadLineBytes() read, _ := reader.ReadLineBytes()
if string(read) != "$1" { str := string(read)
channel <- RedisCmd{Error: fmt.Errorf(RedisMiss)} if strings.Contains(str, "-NOAUTH") {
return return redisCmd{Error: fmt.Errorf(RedisNoAuth)}
} else if str != "$1" {
return redisCmd{Error: fmt.Errorf(RedisMiss)}
} }
read, _ = reader.ReadLineBytes() read, _ = reader.ReadLineBytes()
channel <- RedisCmd{Data: read} return redisCmd{Data: read}
return
} }
} }
} }
return redisCmd{Error: fmt.Errorf(RedisIssue)}
} }
// Init sets the redisHost used to connect to redis. // Init sets the redisHost used to connect to redis.
func (sr *SimpleRedis) Init(redisHost string) { func (sr *SimpleRedis) Init(host, pass, database string) {
sr.redisHost = redisHost sr.host = host
sr.pass = pass
sr.database = database
} }
// Get fetches the value for key name in redis. // Get fetches the value for key name in redis.
func (sr *SimpleRedis) Get(name string) ([]byte, error) { func (sr *SimpleRedis) Get(name string) ([]byte, error) {
redisCmd := RedisCmd{ cmd := redisCmd{
Command: "GET", Command: "GET",
Name: name, Name: name,
} }
channel := make(chan RedisCmd) channel := make(chan redisCmd)
go askRedis(sr.redisHost, redisCmd, channel) resp := sr.askRedis(cmd, channel)
resp := <-channel
if resp.Error != nil { if resp.Error != nil {
return nil, resp.Error return nil, resp.Error
} }
@@ -116,22 +152,22 @@ func (sr *SimpleRedis) Get(name string) ([]byte, error) {
// Set updates the value for key name in redis with value data for duration. // Set updates the value for key name in redis with value data for duration.
func (sr *SimpleRedis) Set(name string, data []byte, duration int64) error { func (sr *SimpleRedis) Set(name string, data []byte, duration int64) error {
redisCmd := RedisCmd{ cmd := redisCmd{
Command: "SET", Command: "SET",
Name: name, Name: name,
Data: data, Data: data,
Duration: duration, Duration: duration,
} }
go askRedis(sr.redisHost, redisCmd, nil) sr.askRedis(cmd, nil)
return nil return nil
} }
// Del removes the key name in redis. // Del removes the key name in redis.
func (sr *SimpleRedis) Del(name string) error { func (sr *SimpleRedis) Del(name string) error {
redisCmd := RedisCmd{ cmd := redisCmd{
Command: "DEL", Command: "DEL",
Name: name, Name: name,
} }
go askRedis(sr.redisHost, redisCmd, nil) sr.askRedis(cmd, nil)
return nil return nil
} }
+1 -1
View File
@@ -1,6 +1,6 @@
# github.com/leprosus/golang-ttl-map v1.1.7 # github.com/leprosus/golang-ttl-map v1.1.7
## explicit; go 1.15 ## explicit; go 1.15
github.com/leprosus/golang-ttl-map github.com/leprosus/golang-ttl-map
# github.com/maxlerebourg/simpleredis v1.0.3 # github.com/maxlerebourg/simpleredis v1.0.9
## explicit; go 1.19 ## explicit; go 1.19
github.com/maxlerebourg/simpleredis github.com/maxlerebourg/simpleredis