mirror of
https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin.git
synced 2026-09-02 20:28:50 +02:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2bbc4dac5 | ||
|
|
889c5b55fe | ||
|
|
efb3a67019 | ||
|
|
0780027252 |
@@ -1,5 +1,8 @@
|
||||
name: Main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Release Version Update
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
update-version:
|
||||
name: Update version in source
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: main
|
||||
|
||||
- name: Extract version from tag
|
||||
id: get_version
|
||||
run: |
|
||||
TAG="${{ github.event.release.tag_name }}"
|
||||
VERSION="${TAG#v}"
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Update version in version.go
|
||||
run: |
|
||||
sed -i 's/pluginVersion = "[^"]*"/pluginVersion = "'"${{ steps.get_version.outputs.version }}"'"/' version.go
|
||||
cat version.go
|
||||
|
||||
- name: Commit, push, and retag
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add version.go
|
||||
if git diff --cached --quiet; then
|
||||
echo "Version already up to date, nothing to commit"
|
||||
exit 0
|
||||
fi
|
||||
git commit -m "⬆️ chore: bump version to ${{ steps.get_version.outputs.version }}"
|
||||
git push origin main
|
||||
# Move the release tag to include the version update
|
||||
git tag -f "${{ steps.get_version.outputs.tag }}"
|
||||
git push -f origin "${{ steps.get_version.outputs.tag }}"
|
||||
@@ -420,7 +420,7 @@ make run
|
||||
- RemediationHeadersCustomName
|
||||
- string
|
||||
- default: ""
|
||||
- Name of the header you want in response when request are cancelled (possible value of the header `ban` or `captcha`)
|
||||
- Name of the header you want in response when request are handled by plugin (possible value of the header `ban`, `captcha` or `solved-captcha`)
|
||||
- ForwardedHeadersCustomName
|
||||
- string
|
||||
- default: "X-Forwarded-For"
|
||||
|
||||
+2
-2
@@ -674,7 +674,7 @@ func crowdsecQuery(bouncer *Bouncer, stringURL string, data []byte) ([]byte, err
|
||||
req, _ = http.NewRequest(http.MethodGet, stringURL, nil)
|
||||
}
|
||||
req.Header.Add(bouncer.crowdsecHeader, bouncer.crowdsecKey)
|
||||
req.Header.Add("User-Agent", "Crowdsec-Bouncer-Traefik-Plugin/1.X.X")
|
||||
req.Header.Add("User-Agent", "Crowdsec-Bouncer-Traefik-Plugin/"+pluginVersion)
|
||||
|
||||
res, err := bouncer.httpClient.Do(req)
|
||||
if err != nil {
|
||||
@@ -779,7 +779,7 @@ func reportMetrics(bouncer *Bouncer) error {
|
||||
metrics := map[string]interface{}{
|
||||
"remediation_components": []map[string]interface{}{
|
||||
{
|
||||
"version": "1.X.X",
|
||||
"version": pluginVersion,
|
||||
"type": "bouncer",
|
||||
"name": "traefik_plugin",
|
||||
"metrics": []map[string]interface{}{
|
||||
|
||||
@@ -94,6 +94,9 @@ func (c *Client) ServeHTTP(rw http.ResponseWriter, r *http.Request, remoteIP str
|
||||
if valid {
|
||||
c.log.Debug("captcha:ServeHTTP captcha:valid")
|
||||
c.cacheClient.Set(remoteIP+"_captcha", cache.CaptchaDoneValue, c.gracePeriodSeconds)
|
||||
if c.remediationCustomHeader != "" {
|
||||
rw.Header().Set(c.remediationCustomHeader, "solved-captcha")
|
||||
}
|
||||
http.Redirect(rw, r, r.URL.String(), http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -277,6 +277,10 @@ func ValidateParams(config *Config) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
appsecKey, err := GetVariable(config, "CrowdsecAppsecKey")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certBouncer, err := GetVariable(config, "CrowdsecLapiTLSCertificateBouncer")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -285,12 +289,21 @@ func ValidateParams(config *Config) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We need to either have crowdsecLapiKey defined or the BouncerCert and Bouncerkey
|
||||
if lapiKey == "" && (certBouncer == "" || certBouncerKey == "") {
|
||||
if lapiKey == "" && (certBouncer == "" || certBouncerKey == "") && config.CrowdsecMode != AppsecMode {
|
||||
return errors.New("CrowdsecLapiKey || (CrowdsecLapiTLSCertificateBouncer && CrowdsecLapiTLSCertificateBouncerKey): cannot be all empty")
|
||||
} else if lapiKey != "" && (certBouncer == "" || certBouncerKey == "") {
|
||||
lapiKey = strings.TrimSpace(lapiKey)
|
||||
if err = validateParamsAPIKey(lapiKey); err != nil {
|
||||
if err = validateParamsAPIKey(lapiKey, "CrowdsecLapiKey"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Validate CrowdsecAppsecKey if provided
|
||||
if appsecKey != "" {
|
||||
appsecKey = strings.TrimSpace(appsecKey)
|
||||
if err = validateParamsAPIKey(appsecKey, "CrowdsecAppsecKey"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -329,10 +342,10 @@ func validateURL(variable, scheme, host, path string) error {
|
||||
// field name. RFC 7230 says:
|
||||
// valid ! # $ % & ' * + - . ^ _ ` | ~ DIGIT ALPHA
|
||||
// See https://httpwg.github.io/specs/rfc7230.html#rule.token.separators
|
||||
func validateParamsAPIKey(lapiKey string) error {
|
||||
func validateParamsAPIKey(key string, paramName string) error {
|
||||
reg := regexp.MustCompile("^[a-zA-Z0-9 !#$%&'*+-.^_`|~=/]*$")
|
||||
if !reg.MatchString(lapiKey) {
|
||||
return fmt.Errorf("CrowdsecLapiKey doesn't valid this regexp: '/%s/'", reg.String())
|
||||
if !reg.MatchString(key) {
|
||||
return fmt.Errorf("%s doesn't validate this regexp: '/%s/'", paramName, reg.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -205,23 +205,24 @@ func Test_validateParamsRequired(t *testing.T) {
|
||||
|
||||
func Test_validateParamsAPIKey(t *testing.T) {
|
||||
type args struct {
|
||||
lapiKey string
|
||||
lapiKey string
|
||||
paramName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "Validate all the valid characters", args: args{lapiKey: "test!#$%&'*+-.^_`|~"}, wantErr: false},
|
||||
{name: "Not validate a @", args: args{lapiKey: "test@"}, wantErr: true},
|
||||
{name: "Not validate a (", args: args{lapiKey: "test("}, wantErr: true},
|
||||
{name: "Not validate a [", args: args{lapiKey: "test["}, wantErr: true},
|
||||
{name: "Not validate a ?", args: args{lapiKey: "test?"}, wantErr: true},
|
||||
{name: "Not validate a \\n, (must be trimed before)", args: args{lapiKey: "test\n"}, wantErr: true},
|
||||
{name: "Validate all the valid characters", args: args{lapiKey: "test!#$%&'*+-.^_`|~", paramName: "CrowdsecParamName"}, wantErr: false},
|
||||
{name: "Not validate a @", args: args{lapiKey: "test@", paramName: "CrowdsecParamName"}, wantErr: true},
|
||||
{name: "Not validate a (", args: args{lapiKey: "test(", paramName: "CrowdsecParamName"}, wantErr: true},
|
||||
{name: "Not validate a [", args: args{lapiKey: "test[", paramName: "CrowdsecParamName"}, wantErr: true},
|
||||
{name: "Not validate a ?", args: args{lapiKey: "test?", paramName: "CrowdsecParamName"}, wantErr: true},
|
||||
{name: "Not validate a \\n, (must be trimed before)", args: args{lapiKey: "test\n", paramName: "CrowdsecParamName"}, wantErr: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := validateParamsAPIKey(tt.args.lapiKey); (err != nil) != tt.wantErr {
|
||||
if err := validateParamsAPIKey(tt.args.lapiKey, tt.args.paramName); (err != nil) != tt.wantErr {
|
||||
t.Errorf("validateParamsAPIKey() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
package crowdsec_bouncer_traefik_plugin //nolint:revive,stylecheck
|
||||
|
||||
// pluginVersion is updated automatically by the release workflow.
|
||||
var pluginVersion = "1.5.0" //nolint:gochecknoglobals
|
||||
Reference in New Issue
Block a user