mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-15 10:25:11 +00:00
Merge commit from fork
* fix: respect lockout policy on password change (with old password) * add tarpitting * cleanup
This commit is contained in:
@@ -2,7 +2,7 @@ package systemdefaults
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
)
|
||||
|
||||
@@ -11,6 +11,7 @@ type SystemDefaults struct {
|
||||
PasswordHasher crypto.HashConfig
|
||||
SecretHasher crypto.HashConfig
|
||||
Multifactors MultifactorConfig
|
||||
Tarpit TarpitConfig
|
||||
DomainVerification DomainVerification
|
||||
Notifications Notifications
|
||||
KeyConfig KeyConfig
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package systemdefaults
|
||||
|
||||
import "time"
|
||||
|
||||
type TarpitConfig struct {
|
||||
// After how many failed attempts, the tarpit should start.
|
||||
MinFailedAttempts uint64
|
||||
// The seconds that will be added per step.
|
||||
StepDuration time.Duration
|
||||
// The failed attempts that are needed to increase the tarpit by one step.
|
||||
StepSize uint64
|
||||
// The maximum duration the tarpit can reach.
|
||||
MaxDuration time.Duration
|
||||
}
|
||||
|
||||
func (t *TarpitConfig) Tarpit() func(failedCount uint64) {
|
||||
return func(failedCount uint64) {
|
||||
time.Sleep(t.duration(failedCount))
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TarpitConfig) duration(failedCount uint64) time.Duration {
|
||||
if failedCount < t.MinFailedAttempts {
|
||||
return 0
|
||||
}
|
||||
// calculate the step we are at
|
||||
// every StepSize failed attempts increase the step by one
|
||||
step := (failedCount - t.MinFailedAttempts) / t.StepSize
|
||||
duration := time.Duration(step) * t.StepDuration
|
||||
if duration < t.MaxDuration {
|
||||
return duration
|
||||
}
|
||||
return t.MaxDuration
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package systemdefaults
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTarpitConfig_duration(t *testing.T) {
|
||||
type fields struct {
|
||||
MinFailedAttempts uint64
|
||||
StepDuration time.Duration
|
||||
StepSize uint64
|
||||
MaxDuration time.Duration
|
||||
}
|
||||
type args struct {
|
||||
failedCount uint64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want time.Duration
|
||||
}{
|
||||
{
|
||||
"no tarpit",
|
||||
fields{
|
||||
MinFailedAttempts: 2,
|
||||
StepDuration: time.Second,
|
||||
StepSize: 1,
|
||||
MaxDuration: 5 * time.Second,
|
||||
},
|
||||
args{failedCount: 1},
|
||||
0,
|
||||
},
|
||||
{
|
||||
"first step",
|
||||
fields{
|
||||
MinFailedAttempts: 2,
|
||||
StepDuration: time.Second,
|
||||
StepSize: 1,
|
||||
MaxDuration: 5 * time.Second,
|
||||
},
|
||||
args{failedCount: 3},
|
||||
time.Second,
|
||||
},
|
||||
{
|
||||
"second step",
|
||||
fields{
|
||||
MinFailedAttempts: 2,
|
||||
StepDuration: time.Second,
|
||||
StepSize: 1,
|
||||
MaxDuration: 5 * time.Second,
|
||||
},
|
||||
args{failedCount: 4},
|
||||
2 * time.Second,
|
||||
},
|
||||
{
|
||||
"exceeding max duration",
|
||||
fields{
|
||||
MinFailedAttempts: 2,
|
||||
StepDuration: time.Second,
|
||||
StepSize: 1,
|
||||
MaxDuration: 5 * time.Second,
|
||||
},
|
||||
args{failedCount: 20},
|
||||
5 * time.Second,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &TarpitConfig{
|
||||
MinFailedAttempts: tt.fields.MinFailedAttempts,
|
||||
StepDuration: tt.fields.StepDuration,
|
||||
StepSize: tt.fields.StepSize,
|
||||
MaxDuration: tt.fields.MaxDuration,
|
||||
}
|
||||
got := c.duration(tt.args.failedCount)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user