mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
a991379a74
Some tests are not fully rewritten in Go, a typescript wrapper is called instead until we remove the remaining TS tests and dependencies. Also, dockerize every components (mainly Authelia backend, frontend and kind) so that the project does not interfere with user host anymore (open ports for instance). The only remaining intrusive change is the one done during bootstrap to add entries in /etc/hosts. It will soon be avoided using authelia.com domain that I own.
256 lines
7.1 KiB
Go
256 lines
7.1 KiB
Go
package regulation_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/clems4ever/authelia/configuration/schema"
|
|
"github.com/clems4ever/authelia/mocks"
|
|
"github.com/clems4ever/authelia/models"
|
|
"github.com/clems4ever/authelia/regulation"
|
|
"github.com/golang/mock/gomock"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/suite"
|
|
)
|
|
|
|
type RegulatorSuite struct {
|
|
suite.Suite
|
|
|
|
ctrl *gomock.Controller
|
|
storageMock *mocks.MockStorageProvider
|
|
configuration schema.RegulationConfiguration
|
|
now time.Time
|
|
}
|
|
|
|
func (s *RegulatorSuite) SetupTest() {
|
|
s.ctrl = gomock.NewController(s.T())
|
|
s.storageMock = mocks.NewMockStorageProvider(s.ctrl)
|
|
|
|
s.configuration = schema.RegulationConfiguration{
|
|
MaxRetries: 3,
|
|
BanTime: 180,
|
|
FindTime: 30,
|
|
}
|
|
s.now = time.Now()
|
|
}
|
|
|
|
func (s *RegulatorSuite) TearDownTest() {
|
|
s.ctrl.Finish()
|
|
}
|
|
|
|
func (s *RegulatorSuite) TestShouldNotThrowWhenUserIsLegitimate() {
|
|
attempts := []models.AuthenticationAttempt{
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: true,
|
|
Time: s.now.Add(-4 * time.Minute),
|
|
},
|
|
}
|
|
|
|
s.storageMock.EXPECT().
|
|
LoadLatestAuthenticationLogs(gomock.Eq("john"), gomock.Any()).
|
|
Return(attempts, nil)
|
|
|
|
regulator := regulation.NewRegulator(&s.configuration, s.storageMock)
|
|
|
|
_, err := regulator.Regulate("john")
|
|
assert.NoError(s.T(), err)
|
|
}
|
|
|
|
// This test checks the case in which a user failed to authenticate many times but always
|
|
// with a certain amount of time larger than FindTime. Meaning the user should not be banned.
|
|
func (s *RegulatorSuite) TestShouldNotThrowWhenFailedAuthenticationNotInFindTime() {
|
|
attemptsInDB := []models.AuthenticationAttempt{
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-1 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-90 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-180 * time.Second),
|
|
},
|
|
}
|
|
|
|
s.storageMock.EXPECT().
|
|
LoadLatestAuthenticationLogs(gomock.Eq("john"), gomock.Any()).
|
|
Return(attemptsInDB, nil)
|
|
|
|
regulator := regulation.NewRegulator(&s.configuration, s.storageMock)
|
|
|
|
_, err := regulator.Regulate("john")
|
|
assert.NoError(s.T(), err)
|
|
}
|
|
|
|
// This test checks the case in which a user failed to authenticate many times only a few
|
|
// seconds ago (meaning we are checking from now back to now-FindTime).
|
|
func (s *RegulatorSuite) TestShouldBanUserIfLatestAttemptsAreWithinFinTime() {
|
|
attemptsInDB := []models.AuthenticationAttempt{
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-1 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-4 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-6 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-180 * time.Second),
|
|
},
|
|
}
|
|
|
|
s.storageMock.EXPECT().
|
|
LoadLatestAuthenticationLogs(gomock.Eq("john"), gomock.Any()).
|
|
Return(attemptsInDB, nil)
|
|
|
|
regulator := regulation.NewRegulator(&s.configuration, s.storageMock)
|
|
|
|
_, err := regulator.Regulate("john")
|
|
assert.Equal(s.T(), regulation.ErrUserIsBanned, err)
|
|
}
|
|
|
|
// This test checks the case in which a user failed to authenticate many times only a few
|
|
// seconds ago (meaning we are checking from now-FindTime+X back to now-2FindTime+X knowing that
|
|
// we are within now and now-BanTime). It means the user has been banned some time ago and is still
|
|
// banned right now.
|
|
func (s *RegulatorSuite) TestShouldCheckUserIsStillBanned() {
|
|
attemptsInDB := []models.AuthenticationAttempt{
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-31 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-34 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-36 * time.Second),
|
|
},
|
|
}
|
|
|
|
s.storageMock.EXPECT().
|
|
LoadLatestAuthenticationLogs(gomock.Eq("john"), gomock.Any()).
|
|
Return(attemptsInDB, nil)
|
|
|
|
regulator := regulation.NewRegulator(&s.configuration, s.storageMock)
|
|
|
|
_, err := regulator.Regulate("john")
|
|
assert.Equal(s.T(), regulation.ErrUserIsBanned, err)
|
|
}
|
|
|
|
func (s *RegulatorSuite) TestShouldCheckUserIsNotYetBanned() {
|
|
attemptsInDB := []models.AuthenticationAttempt{
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-34 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-36 * time.Second),
|
|
},
|
|
}
|
|
|
|
s.storageMock.EXPECT().
|
|
LoadLatestAuthenticationLogs(gomock.Eq("john"), gomock.Any()).
|
|
Return(attemptsInDB, nil)
|
|
|
|
regulator := regulation.NewRegulator(&s.configuration, s.storageMock)
|
|
|
|
_, err := regulator.Regulate("john")
|
|
assert.NoError(s.T(), err)
|
|
}
|
|
|
|
func (s *RegulatorSuite) TestShouldCheckUserWasAboutToBeBanned() {
|
|
attemptsInDB := []models.AuthenticationAttempt{
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-14 * time.Second),
|
|
},
|
|
// more than 30 seconds elapsed between this auth and the preceding one.
|
|
// In that case we don't need to regulate the user even though the number
|
|
// of retrieved attempts is 3.
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-94 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-96 * time.Second),
|
|
},
|
|
}
|
|
|
|
s.storageMock.EXPECT().
|
|
LoadLatestAuthenticationLogs(gomock.Eq("john"), gomock.Any()).
|
|
Return(attemptsInDB, nil)
|
|
|
|
regulator := regulation.NewRegulator(&s.configuration, s.storageMock)
|
|
|
|
_, err := regulator.Regulate("john")
|
|
assert.NoError(s.T(), err)
|
|
}
|
|
|
|
func (s *RegulatorSuite) TestShouldCheckRegulationHasBeenResetOnSuccessfulAttempt() {
|
|
attemptsInDB := []models.AuthenticationAttempt{
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-90 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: true,
|
|
Time: s.now.Add(-93 * time.Second),
|
|
},
|
|
// The user was almost banned but he did a successful attempt. Therefore, even if the next
|
|
// failure happens withing FindTime, he should not be banned.
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-94 * time.Second),
|
|
},
|
|
models.AuthenticationAttempt{
|
|
Username: "john",
|
|
Successful: false,
|
|
Time: s.now.Add(-96 * time.Second),
|
|
},
|
|
}
|
|
|
|
s.storageMock.EXPECT().
|
|
LoadLatestAuthenticationLogs(gomock.Eq("john"), gomock.Any()).
|
|
Return(attemptsInDB, nil)
|
|
|
|
regulator := regulation.NewRegulator(&s.configuration, s.storageMock)
|
|
|
|
_, err := regulator.Regulate("john")
|
|
assert.NoError(s.T(), err)
|
|
}
|
|
|
|
func TestRunRegulatorSuite(t *testing.T) {
|
|
s := new(RegulatorSuite)
|
|
suite.Run(t, s)
|
|
}
|