Separate TLS conf for LAPI and Appsec (#293)

*   Separate TLS conf for LAPI and Appsec

* 🍱 fix lint

* 🍱 fix test

* 🍱 fix lint

* 🍱 fix lint

* 🍱 fix lint

* 🍱 fix lint ?

* 🍱 fix lint

* 🍱 Add default for traceCustomHeaders
This commit is contained in:
maxlerebourg
2025-12-11 07:58:12 +01:00
committed by GitHub
parent e20ccc5d0c
commit a9d83f2097
5 changed files with 175 additions and 122 deletions
+1
View File
@@ -554,6 +554,7 @@ http:
httpTimeoutSeconds: 10 httpTimeoutSeconds: 10
crowdsecMode: live crowdsecMode: live
crowdsecAppsecEnabled: false crowdsecAppsecEnabled: false
crowdsecAppsecScheme: ""
crowdsecAppsecHost: crowdsec:7422 crowdsecAppsecHost: crowdsec:7422
crowdsecAppsecPath: "/" crowdsecAppsecPath: "/"
crowdsecAppsecFailureBlock: true crowdsecAppsecFailureBlock: true
+33 -9
View File
@@ -85,8 +85,10 @@ type Bouncer struct {
enabled bool enabled bool
appsecEnabled bool appsecEnabled bool
appsecScheme string
appsecHost string appsecHost string
appsecPath string appsecPath string
appsecKey string
appsecFailureBlock bool appsecFailureBlock bool
appsecUnreachableBlock bool appsecUnreachableBlock bool
appsecBodyLimit int64 appsecBodyLimit int64
@@ -112,6 +114,7 @@ type Bouncer struct {
clientPoolStrategy *ip.PoolStrategy clientPoolStrategy *ip.PoolStrategy
serverPoolStrategy *ip.PoolStrategy serverPoolStrategy *ip.PoolStrategy
httpClient *http.Client httpClient *http.Client
httpAppsecClient *http.Client
cacheClient *cache.Client cacheClient *cache.Client
captchaClient *captcha.Client captchaClient *captcha.Client
log *logger.Log log *logger.Log
@@ -131,6 +134,17 @@ func New(_ context.Context, next http.Handler, config *configuration.Config, nam
serverChecker, _ := ip.NewChecker(log, config.ForwardedHeadersTrustedIPs) serverChecker, _ := ip.NewChecker(log, config.ForwardedHeadersTrustedIPs)
clientChecker, _ := ip.NewChecker(log, config.ClientTrustedIPs) clientChecker, _ := ip.NewChecker(log, config.ClientTrustedIPs)
tlsAppsecConfig, err := configuration.GetTLSConfigCrowdsec(config, log, true)
if err != nil {
log.Error("New:getTLSConfigCrowdsec fail to get tlsAppsecConfig " + err.Error())
return nil, err
}
apiAppsecKey, errAppsecKey := configuration.GetVariable(config, "CrowdsecAppsecKey")
if errAppsecKey != nil && len(tlsAppsecConfig.Certificates) == 0 {
log.Error("New:crowdsecLapiKey fail to get CrowdsecAppsecKey and no client certificate setup " + errAppsecKey.Error())
return nil, errAppsecKey
}
config.CrowdsecAppsecKey = apiAppsecKey
var tlsConfig *tls.Config var tlsConfig *tls.Config
crowdsecStreamRoute := "" crowdsecStreamRoute := ""
@@ -141,22 +155,22 @@ func New(_ context.Context, next http.Handler, config *configuration.Config, nam
config.CrowdsecLapiScheme = configuration.HTTPS config.CrowdsecLapiScheme = configuration.HTTPS
config.CrowdsecLapiHost = crowdsecCapiHost config.CrowdsecLapiHost = crowdsecCapiHost
config.CrowdsecLapiPath = "/" config.CrowdsecLapiPath = "/"
config.CrowdsecAppsecEnabled = false config.CrowdsecAppsecEnabled = config.CrowdsecAppsecEnabled && config.CrowdsecAppsecScheme != ""
config.UpdateIntervalSeconds = 7200 // 2 hours config.UpdateIntervalSeconds = 7200 // 2 hours
crowdsecStreamRoute = crowdsecCapiStreamRoute crowdsecStreamRoute = crowdsecCapiStreamRoute
crowdsecHeader = crowdsecCapiHeader crowdsecHeader = crowdsecCapiHeader
} else { } else {
crowdsecStreamRoute = crowdsecLapiStreamRoute crowdsecStreamRoute = crowdsecLapiStreamRoute
crowdsecHeader = crowdsecLapiHeader crowdsecHeader = crowdsecLapiHeader
tlsConfig, err = configuration.GetTLSConfigCrowdsec(config, log) tlsConfig, err = configuration.GetTLSConfigCrowdsec(config, log, false)
if err != nil { if err != nil {
log.Error("New:getTLSConfigCrowdsec fail to get tlsConfig " + err.Error()) log.Error("New:getTLSConfigCrowdsec fail to get tlsConfig " + err.Error())
return nil, err return nil, err
} }
apiKey, errAPIKey := configuration.GetVariable(config, "CrowdsecLapiKey") apiKey, errKey := configuration.GetVariable(config, "CrowdsecLapiKey")
if errAPIKey != nil && len(tlsConfig.Certificates) == 0 { if errKey != nil && len(tlsConfig.Certificates) == 0 {
log.Error("New:crowdsecLapiKey fail to get CrowdsecLapiKey and no client certificate setup " + errAPIKey.Error()) log.Error("New:crowdsecLapiKey fail to get CrowdsecLapiKey and no client certificate setup " + errKey.Error())
return nil, errAPIKey return nil, errKey
} }
config.CrowdsecLapiKey = apiKey config.CrowdsecLapiKey = apiKey
} }
@@ -174,8 +188,10 @@ func New(_ context.Context, next http.Handler, config *configuration.Config, nam
enabled: config.Enabled, enabled: config.Enabled,
crowdsecMode: config.CrowdsecMode, crowdsecMode: config.CrowdsecMode,
appsecEnabled: config.CrowdsecAppsecEnabled, appsecEnabled: config.CrowdsecAppsecEnabled,
appsecScheme: config.CrowdsecAppsecScheme,
appsecHost: config.CrowdsecAppsecHost, appsecHost: config.CrowdsecAppsecHost,
appsecPath: config.CrowdsecAppsecPath, appsecPath: config.CrowdsecAppsecPath,
appsecKey: config.CrowdsecAppsecKey,
appsecFailureBlock: config.CrowdsecAppsecFailureBlock, appsecFailureBlock: config.CrowdsecAppsecFailureBlock,
appsecUnreachableBlock: config.CrowdsecAppsecUnreachableBlock, appsecUnreachableBlock: config.CrowdsecAppsecUnreachableBlock,
appsecBodyLimit: config.CrowdsecAppsecBodyLimit, appsecBodyLimit: config.CrowdsecAppsecBodyLimit,
@@ -212,6 +228,14 @@ func New(_ context.Context, next http.Handler, config *configuration.Config, nam
}, },
Timeout: time.Duration(config.HTTPTimeoutSeconds) * time.Second, Timeout: time.Duration(config.HTTPTimeoutSeconds) * time.Second,
}, },
httpAppsecClient: &http.Client{
Transport: &http.Transport{
MaxIdleConns: 10,
IdleConnTimeout: 30 * time.Second,
TLSClientConfig: tlsAppsecConfig,
},
Timeout: time.Duration(config.HTTPTimeoutSeconds) * time.Second,
},
cacheClient: &cache.Client{}, cacheClient: &cache.Client{},
captchaClient: &captcha.Client{}, captchaClient: &captcha.Client{},
} }
@@ -672,7 +696,7 @@ func crowdsecQuery(bouncer *Bouncer, stringURL string, data []byte) ([]byte, err
func appsecQuery(bouncer *Bouncer, ip string, httpReq *http.Request) error { func appsecQuery(bouncer *Bouncer, ip string, httpReq *http.Request) error {
routeURL := url.URL{ routeURL := url.URL{
Scheme: bouncer.crowdsecScheme, Scheme: bouncer.appsecScheme,
Host: bouncer.appsecHost, Host: bouncer.appsecHost,
Path: bouncer.appsecPath, Path: bouncer.appsecPath,
} }
@@ -697,14 +721,14 @@ func appsecQuery(bouncer *Bouncer, ip string, httpReq *http.Request) error {
req.Header.Add(key, value) req.Header.Add(key, value)
} }
} }
req.Header.Set(crowdsecAppsecHeader, bouncer.crowdsecKey) req.Header.Set(crowdsecAppsecHeader, bouncer.appsecKey)
req.Header.Set(crowdsecAppsecIPHeader, ip) req.Header.Set(crowdsecAppsecIPHeader, ip)
req.Header.Set(crowdsecAppsecVerbHeader, httpReq.Method) req.Header.Set(crowdsecAppsecVerbHeader, httpReq.Method)
req.Header.Set(crowdsecAppsecHostHeader, httpReq.Host) req.Header.Set(crowdsecAppsecHostHeader, httpReq.Host)
req.Header.Set(crowdsecAppsecURIHeader, httpReq.URL.String()) req.Header.Set(crowdsecAppsecURIHeader, httpReq.URL.String())
req.Header.Set(crowdsecAppsecUserAgent, httpReq.Header.Get("User-Agent")) req.Header.Set(crowdsecAppsecUserAgent, httpReq.Header.Get("User-Agent"))
res, err := bouncer.httpClient.Do(req) res, err := bouncer.httpAppsecClient.Do(req)
if err != nil { if err != nil {
bouncer.log.Error("appsecQuery:unreachable") bouncer.log.Error("appsecQuery:unreachable")
if bouncer.appsecUnreachableBlock { if bouncer.appsecUnreachableBlock {
+5 -1
View File
@@ -89,4 +89,8 @@ make run_tlsauth
``` ```
Note: Note:
> Traefik need to be restart if certificates are regenerated after his launch > Traefik need to be restarted if certificates are regenerated after his launch
## Separate LAPI and Appsec HTTP/S config
To separate TLS config for LAPI and Appsec, you can use all the TLS LAPI variable beginning with `CrowdsecLapi...` into `CrowdsecAppsec...`.
Don't forget to set `CrowdsecAppsecScheme: HTTP` or `HTTPS` to trigger the separate setup.
+135 -111
View File
@@ -42,62 +42,71 @@ const (
// Config the plugin configuration. // Config the plugin configuration.
type Config struct { type Config struct {
Enabled bool `json:"enabled,omitempty"` Enabled bool `json:"enabled,omitempty"`
LogLevel string `json:"logLevel,omitempty"` LogLevel string `json:"logLevel,omitempty"`
LogFilePath string `json:"logFilePath,omitempty"` LogFilePath string `json:"logFilePath,omitempty"`
CrowdsecMode string `json:"crowdsecMode,omitempty"` CrowdsecMode string `json:"crowdsecMode,omitempty"`
CrowdsecAppsecEnabled bool `json:"crowdsecAppsecEnabled,omitempty"` CrowdsecAppsecEnabled bool `json:"crowdsecAppsecEnabled,omitempty"`
CrowdsecAppsecHost string `json:"crowdsecAppsecHost,omitempty"` CrowdsecAppsecScheme string `json:"crowdsecAppsecScheme,omitempty"`
CrowdsecAppsecPath string `json:"crowdsecAppsecPath,omitempty"` CrowdsecAppsecHost string `json:"crowdsecAppsecHost,omitempty"`
CrowdsecAppsecFailureBlock bool `json:"crowdsecAppsecFailureBlock,omitempty"` CrowdsecAppsecPath string `json:"crowdsecAppsecPath,omitempty"`
CrowdsecAppsecUnreachableBlock bool `json:"crowdsecAppsecUnreachableBlock,omitempty"` CrowdsecAppsecKey string `json:"crowdsecAppsecKey,omitempty"`
CrowdsecAppsecBodyLimit int64 `json:"crowdsecAppsecBodyLimit,omitempty"` CrowdsecAppsecKeyFile string `json:"crowdsecAppsecKeyFile,omitempty"`
CrowdsecLapiScheme string `json:"crowdsecLapiScheme,omitempty"` CrowdsecAppsecTLSInsecureVerify bool `json:"crowdsecAppsecTlsInsecureVerify,omitempty"`
CrowdsecLapiHost string `json:"crowdsecLapiHost,omitempty"` CrowdsecAppsecTLSCertificateAuthority string `json:"crowdsecAppsecTlsCertificateAuthority,omitempty"`
CrowdsecLapiPath string `json:"crowdsecLapiPath,omitempty"` CrowdsecAppsecTLSCertificateAuthorityFile string `json:"crowdsecAppsecTlsCertificateAuthorityFile,omitempty"`
CrowdsecLapiKey string `json:"crowdsecLapiKey,omitempty"` CrowdsecAppsecTLSCertificateBouncer string `json:"crowdsecAppsecTlsCertificateBouncer,omitempty"`
CrowdsecLapiKeyFile string `json:"crowdsecLapiKeyFile,omitempty"` CrowdsecAppsecTLSCertificateBouncerFile string `json:"crowdsecAppsecTlsCertificateBouncerFile,omitempty"`
CrowdsecLapiTLSInsecureVerify bool `json:"crowdsecLapiTlsInsecureVerify,omitempty"` CrowdsecAppsecTLSCertificateBouncerKey string `json:"crowdsecAppsecTlsCertificateBouncerKey,omitempty"`
CrowdsecLapiTLSCertificateAuthority string `json:"crowdsecLapiTlsCertificateAuthority,omitempty"` CrowdsecAppsecFailureBlock bool `json:"crowdsecAppsecFailureBlock,omitempty"`
CrowdsecLapiTLSCertificateAuthorityFile string `json:"crowdsecLapiTlsCertificateAuthorityFile,omitempty"` CrowdsecAppsecUnreachableBlock bool `json:"crowdsecAppsecUnreachableBlock,omitempty"`
CrowdsecLapiTLSCertificateBouncer string `json:"crowdsecLapiTlsCertificateBouncer,omitempty"` CrowdsecAppsecBodyLimit int64 `json:"crowdsecAppsecBodyLimit,omitempty"`
CrowdsecLapiTLSCertificateBouncerFile string `json:"crowdsecLapiTlsCertificateBouncerFile,omitempty"` CrowdsecLapiScheme string `json:"crowdsecLapiScheme,omitempty"`
CrowdsecLapiTLSCertificateBouncerKey string `json:"crowdsecLapiTlsCertificateBouncerKey,omitempty"` CrowdsecLapiHost string `json:"crowdsecLapiHost,omitempty"`
CrowdsecLapiTLSCertificateBouncerKeyFile string `json:"crowdsecLapiTlsCertificateBouncerKeyFile,omitempty"` CrowdsecLapiPath string `json:"crowdsecLapiPath,omitempty"`
CrowdsecCapiMachineID string `json:"crowdsecCapiMachineId,omitempty"` CrowdsecLapiKey string `json:"crowdsecLapiKey,omitempty"`
CrowdsecCapiMachineIDFile string `json:"crowdsecCapiMachineIdFile,omitempty"` CrowdsecLapiKeyFile string `json:"crowdsecLapiKeyFile,omitempty"`
CrowdsecCapiPassword string `json:"crowdsecCapiPassword,omitempty"` CrowdsecLapiTLSInsecureVerify bool `json:"crowdsecLapiTlsInsecureVerify,omitempty"`
CrowdsecCapiPasswordFile string `json:"crowdsecCapiPasswordFile,omitempty"` CrowdsecLapiTLSCertificateAuthority string `json:"crowdsecLapiTlsCertificateAuthority,omitempty"`
CrowdsecCapiScenarios []string `json:"crowdsecCapiScenarios,omitempty"` CrowdsecLapiTLSCertificateAuthorityFile string `json:"crowdsecLapiTlsCertificateAuthorityFile,omitempty"`
UpdateIntervalSeconds int64 `json:"updateIntervalSeconds,omitempty"` CrowdsecLapiTLSCertificateBouncer string `json:"crowdsecLapiTlsCertificateBouncer,omitempty"`
MetricsUpdateIntervalSeconds int64 `json:"metricsUpdateIntervalSeconds,omitempty"` CrowdsecLapiTLSCertificateBouncerFile string `json:"crowdsecLapiTlsCertificateBouncerFile,omitempty"`
UpdateMaxFailure int64 `json:"updateMaxFailure,omitempty"` CrowdsecLapiTLSCertificateBouncerKey string `json:"crowdsecLapiTlsCertificateBouncerKey,omitempty"`
DefaultDecisionSeconds int64 `json:"defaultDecisionSeconds,omitempty"` CrowdsecLapiTLSCertificateBouncerKeyFile string `json:"crowdsecLapiTlsCertificateBouncerKeyFile,omitempty"`
RemediationStatusCode int `json:"remediationStatusCode,omitempty"` CrowdsecCapiMachineID string `json:"crowdsecCapiMachineId,omitempty"`
HTTPTimeoutSeconds int64 `json:"httpTimeoutSeconds,omitempty"` CrowdsecCapiMachineIDFile string `json:"crowdsecCapiMachineIdFile,omitempty"`
RemediationHeadersCustomName string `json:"remediationHeadersCustomName,omitempty"` CrowdsecCapiPassword string `json:"crowdsecCapiPassword,omitempty"`
ForwardedHeadersCustomName string `json:"forwardedHeadersCustomName,omitempty"` CrowdsecCapiPasswordFile string `json:"crowdsecCapiPasswordFile,omitempty"`
ForwardedHeadersTrustedIPs []string `json:"forwardedHeadersTrustedIps,omitempty"` CrowdsecCapiScenarios []string `json:"crowdsecCapiScenarios,omitempty"`
ClientTrustedIPs []string `json:"clientTrustedIps,omitempty"` UpdateIntervalSeconds int64 `json:"updateIntervalSeconds,omitempty"`
RedisCacheEnabled bool `json:"redisCacheEnabled,omitempty"` MetricsUpdateIntervalSeconds int64 `json:"metricsUpdateIntervalSeconds,omitempty"`
RedisCacheHost string `json:"redisCacheHost,omitempty"` UpdateMaxFailure int64 `json:"updateMaxFailure,omitempty"`
RedisCachePassword string `json:"redisCachePassword,omitempty"` DefaultDecisionSeconds int64 `json:"defaultDecisionSeconds,omitempty"`
RedisCachePasswordFile string `json:"redisCachePasswordFile,omitempty"` RemediationStatusCode int `json:"remediationStatusCode,omitempty"`
RedisCacheDatabase string `json:"redisCacheDatabase,omitempty"` HTTPTimeoutSeconds int64 `json:"httpTimeoutSeconds,omitempty"`
RedisCacheUnreachableBlock bool `json:"redisCacheUnreachableBlock,omitempty"` TraceHeadersCustomName string `json:"traceHeadersCustomName,omitempty"`
BanHTMLFilePath string `json:"banHtmlFilePath,omitempty"` RemediationHeadersCustomName string `json:"remediationHeadersCustomName,omitempty"`
TraceHeadersCustomName string `json:"traceHeadersCustomName,omitempty"` ForwardedHeadersCustomName string `json:"forwardedHeadersCustomName,omitempty"`
CaptchaHTMLFilePath string `json:"captchaHtmlFilePath,omitempty"` ForwardedHeadersTrustedIPs []string `json:"forwardedHeadersTrustedIps,omitempty"`
CaptchaProvider string `json:"captchaProvider,omitempty"` ClientTrustedIPs []string `json:"clientTrustedIps,omitempty"`
CaptchaCustomJsURL string `json:"captchaCustomJsUrl,omitempty"` RedisCacheEnabled bool `json:"redisCacheEnabled,omitempty"`
CaptchaCustomValidateURL string `json:"captchaCustomValidateUrl,omitempty"` RedisCacheHost string `json:"redisCacheHost,omitempty"`
CaptchaCustomKey string `json:"captchaCustomKey,omitempty"` RedisCachePassword string `json:"redisCachePassword,omitempty"`
CaptchaCustomResponse string `json:"captchaCustomResponse,omitempty"` RedisCachePasswordFile string `json:"redisCachePasswordFile,omitempty"`
CaptchaSiteKey string `json:"captchaSiteKey,omitempty"` RedisCacheDatabase string `json:"redisCacheDatabase,omitempty"`
CaptchaSiteKeyFile string `json:"captchaSiteKeyFile,omitempty"` RedisCacheUnreachableBlock bool `json:"redisCacheUnreachableBlock,omitempty"`
CaptchaSecretKey string `json:"captchaSecretKey,omitempty"` BanHTMLFilePath string `json:"banHtmlFilePath,omitempty"`
CaptchaSecretKeyFile string `json:"captchaSecretKeyFile,omitempty"` CaptchaHTMLFilePath string `json:"captchaHtmlFilePath,omitempty"`
CaptchaGracePeriodSeconds int64 `json:"captchaGracePeriodSeconds,omitempty"` CaptchaProvider string `json:"captchaProvider,omitempty"`
CaptchaCustomJsURL string `json:"captchaCustomJsUrl,omitempty"`
CaptchaCustomValidateURL string `json:"captchaCustomValidateUrl,omitempty"`
CaptchaCustomKey string `json:"captchaCustomKey,omitempty"`
CaptchaCustomResponse string `json:"captchaCustomResponse,omitempty"`
CaptchaSiteKey string `json:"captchaSiteKey,omitempty"`
CaptchaSiteKeyFile string `json:"captchaSiteKeyFile,omitempty"`
CaptchaSecretKey string `json:"captchaSecretKey,omitempty"`
CaptchaSecretKeyFile string `json:"captchaSecretKeyFile,omitempty"`
CaptchaGracePeriodSeconds int64 `json:"captchaGracePeriodSeconds,omitempty"`
} }
func contains(source []string, target string) bool { func contains(source []string, target string) bool {
@@ -112,46 +121,50 @@ func contains(source []string, target string) bool {
// New creates the default plugin configuration. // New creates the default plugin configuration.
func New() *Config { func New() *Config {
return &Config{ return &Config{
Enabled: false, Enabled: false,
LogLevel: LogINFO, LogLevel: LogINFO,
LogFilePath: "", LogFilePath: "",
CrowdsecMode: LiveMode, CrowdsecMode: LiveMode,
CrowdsecAppsecEnabled: false, CrowdsecAppsecEnabled: false,
CrowdsecAppsecHost: "crowdsec:7422", CrowdsecAppsecFailureBlock: true,
CrowdsecAppsecPath: "/", CrowdsecAppsecUnreachableBlock: true,
CrowdsecAppsecFailureBlock: true, CrowdsecAppsecBodyLimit: 10485760,
CrowdsecAppsecUnreachableBlock: true, CrowdsecAppsecScheme: "",
CrowdsecAppsecBodyLimit: 10485760, CrowdsecAppsecHost: "crowdsec:7422",
CrowdsecLapiScheme: HTTP, CrowdsecAppsecPath: "/",
CrowdsecLapiHost: "crowdsec:8080", CrowdsecAppsecKey: "",
CrowdsecLapiPath: "/", CrowdsecAppsecTLSInsecureVerify: false,
CrowdsecLapiKey: "", CrowdsecLapiScheme: HTTP,
CrowdsecLapiTLSInsecureVerify: false, CrowdsecLapiHost: "crowdsec:8080",
UpdateIntervalSeconds: 60, CrowdsecLapiPath: "/",
MetricsUpdateIntervalSeconds: 600, CrowdsecLapiKey: "",
UpdateMaxFailure: 0, CrowdsecLapiTLSInsecureVerify: false,
DefaultDecisionSeconds: 60, UpdateIntervalSeconds: 60,
RemediationStatusCode: http.StatusForbidden, MetricsUpdateIntervalSeconds: 600,
HTTPTimeoutSeconds: 10, UpdateMaxFailure: 0,
CaptchaProvider: "", DefaultDecisionSeconds: 60,
CaptchaCustomJsURL: "", RemediationStatusCode: http.StatusForbidden,
CaptchaCustomValidateURL: "", HTTPTimeoutSeconds: 10,
CaptchaCustomKey: "", CaptchaProvider: "",
CaptchaCustomResponse: "", CaptchaCustomJsURL: "",
CaptchaSiteKey: "", CaptchaCustomValidateURL: "",
CaptchaSecretKey: "", CaptchaCustomKey: "",
CaptchaGracePeriodSeconds: 1800, CaptchaCustomResponse: "",
CaptchaHTMLFilePath: "/captcha.html", CaptchaSiteKey: "",
BanHTMLFilePath: "", CaptchaSecretKey: "",
RemediationHeadersCustomName: "", CaptchaGracePeriodSeconds: 1800,
ForwardedHeadersCustomName: "X-Forwarded-For", CaptchaHTMLFilePath: "/captcha.html",
ForwardedHeadersTrustedIPs: []string{}, BanHTMLFilePath: "",
ClientTrustedIPs: []string{}, TraceHeadersCustomName: "",
RedisCacheEnabled: false, RemediationHeadersCustomName: "",
RedisCacheHost: "redis:6379", ForwardedHeadersCustomName: "X-Forwarded-For",
RedisCachePassword: "", ForwardedHeadersTrustedIPs: []string{},
RedisCacheDatabase: "", ClientTrustedIPs: []string{},
RedisCacheUnreachableBlock: true, RedisCacheEnabled: false,
RedisCacheHost: "redis:6379",
RedisCachePassword: "",
RedisCacheDatabase: "",
RedisCacheUnreachableBlock: true,
} }
} }
@@ -413,26 +426,27 @@ func validateParamsRequired(config *Config) error {
if !contains([]string{HTTP, HTTPS}, config.CrowdsecLapiScheme) { if !contains([]string{HTTP, HTTPS}, config.CrowdsecLapiScheme) {
return errors.New("CrowdsecLapiScheme: must be one of 'http' or 'https'") return errors.New("CrowdsecLapiScheme: must be one of 'http' or 'https'")
} }
if !contains([]string{HTTP, HTTPS, ""}, config.CrowdsecAppsecScheme) {
return errors.New("CrowdsecAppsecScheme: must be one of 'http' or 'https'")
}
return nil return nil
} }
// GetTLSConfigCrowdsec get TLS config from Config. func getTLSConfig(config *Config, log *logger.Log, prefix, scheme string, insecureVerify bool) (*tls.Config, error) {
//
//nolint:nestif
func GetTLSConfigCrowdsec(config *Config, log *logger.Log) (*tls.Config, error) {
tlsConfig := new(tls.Config) tlsConfig := new(tls.Config)
tlsConfig.RootCAs = x509.NewCertPool() tlsConfig.RootCAs = x509.NewCertPool()
//nolint:gocritic if scheme != HTTPS {
if config.CrowdsecLapiScheme != HTTPS { log.Debug("getTLSConfigCrowdsec:" + prefix + "Scheme https:no")
log.Debug("getTLSConfigCrowdsec:CrowdsecLapiScheme https:no")
return tlsConfig, nil return tlsConfig, nil
} else if config.CrowdsecLapiTLSInsecureVerify { }
//nolint:nestif
if insecureVerify {
tlsConfig.InsecureSkipVerify = true tlsConfig.InsecureSkipVerify = true
log.Debug("getTLSConfigCrowdsec:CrowdsecLapiTLSInsecureVerify tlsInsecure:true") log.Debug("getTLSConfigCrowdsec:" + prefix + "TLSInsecureVerify tlsInsecure:true")
// If we return here and still want to use client auth this won't work // If we return here and still want to use client auth this won't work
// return tlsConfig, nil // return tlsConfig, nil
} else { } else {
certAuthority, err := GetVariable(config, "CrowdsecLapiTLSCertificateAuthority") certAuthority, err := GetVariable(config, prefix+"TLSCertificateAuthority")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -440,17 +454,16 @@ func GetTLSConfigCrowdsec(config *Config, log *logger.Log) (*tls.Config, error)
if !tlsConfig.RootCAs.AppendCertsFromPEM([]byte(certAuthority)) { if !tlsConfig.RootCAs.AppendCertsFromPEM([]byte(certAuthority)) {
// here we return because if CrowdsecLapiTLSInsecureVerify is false // here we return because if CrowdsecLapiTLSInsecureVerify is false
// and CA not load, we can't communicate with https // and CA not load, we can't communicate with https
return nil, errors.New("getTLSConfigCrowdsec:cannot load CA and verify cert is enabled") return nil, errors.New("getTLSConfigCrowdsec:" + prefix + "cannot load CA and verify cert is enabled")
} }
log.Debug("getTLSConfigCrowdsec:CrowdsecLapiTLSCertificateAuthority CA added successfully") log.Debug("getTLSConfigCrowdsec:" + prefix + "TLSCertificateAuthority CA added successfully")
} }
} }
certBouncer, err := GetVariable(config, prefix+"TLSCertificateBouncer")
certBouncer, err := GetVariable(config, "CrowdsecLapiTLSCertificateBouncer")
if err != nil { if err != nil {
return nil, err return nil, err
} }
certBouncerKey, err := GetVariable(config, "CrowdsecLapiTLSCertificateBouncerKey") certBouncerKey, err := GetVariable(config, prefix+"TLSCertificateBouncerKey")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -465,3 +478,14 @@ func GetTLSConfigCrowdsec(config *Config, log *logger.Log) (*tls.Config, error)
return tlsConfig, nil return tlsConfig, nil
} }
// GetTLSConfigCrowdsec get TLS config from Config.
func GetTLSConfigCrowdsec(config *Config, log *logger.Log, isAppsec bool) (*tls.Config, error) {
var prefix string
if isAppsec && config.CrowdsecAppsecScheme != "" {
prefix = "CrowdsecAppsec"
return getTLSConfig(config, log, prefix, config.CrowdsecAppsecScheme, config.CrowdsecAppsecTLSInsecureVerify)
}
prefix = "CrowdsecLapi"
return getTLSConfig(config, log, prefix, config.CrowdsecLapiScheme, config.CrowdsecLapiTLSInsecureVerify)
}
+1 -1
View File
@@ -242,7 +242,7 @@ func Test_GetTLSConfigCrowdsec(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := GetTLSConfigCrowdsec(tt.args.config, logger.New("INFO", "")) got, err := GetTLSConfigCrowdsec(tt.args.config, logger.New("INFO", ""), false)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("getTLSConfigCrowdsec() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("getTLSConfigCrowdsec() error = %v, wantErr %v", err, tt.wantErr)
return return