Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion internal/controller/proxy_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ func TestProxyController(t *testing.T) {
Log: log,
})

authService := service.NewAuthService(service.AuthServiceInput{
authService, err := service.NewAuthService(service.AuthServiceInput{
Log: log,
Config: &cfg,
Runtime: &runtime,
Expand All @@ -721,6 +721,8 @@ func TestProxyController(t *testing.T) {
PolicyEngine: policyEngine,
})

require.NoError(t, err)

for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
router := gin.Default()
Expand Down
1 change: 1 addition & 0 deletions internal/controller/user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func (controller *UserController) loginHandler(c *gin.Context) {

if err != nil {
if errors.Is(err, service.ErrUserNotFound) {
controller.auth.DummyPasswordCheck(req.Password)
controller.log.App.Warn().Str("username", req.Username).Msg("User not found during login attempt")
controller.auth.RecordLoginAttempt(req.Username, false)
controller.log.AuditLoginFailure(req.Username, "unknown", c.ClientIP(), "user not found")
Expand Down
5 changes: 4 additions & 1 deletion internal/controller/user_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,8 @@ func TestUserController(t *testing.T) {
Runtime: &runtime,
Ctx: ctx,
})
authService := service.NewAuthService(service.AuthServiceInput{

authService, err := service.NewAuthService(service.AuthServiceInput{
Log: log,
Config: &cfg,
Runtime: &runtime,
Expand All @@ -555,6 +556,8 @@ func TestUserController(t *testing.T) {
PolicyEngine: policyEngine,
})

require.NoError(t, err)

beforeEach := func() {
// Clear failed login attempts before each test
authService.ClearLoginAttempts()
Expand Down
4 changes: 4 additions & 0 deletions internal/middleware/context_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package middleware

import (
"context"
"errors"
"fmt"
"net/http"
"strings"
Expand Down Expand Up @@ -244,6 +245,9 @@ func (m *ContextMiddleware) basicAuth(username string, password string) (*model.
search, err := m.auth.SearchUser(username)

if err != nil {
if errors.Is(err, service.ErrUserNotFound) {
m.auth.DummyPasswordCheck(password)
}
return nil, nil, fmt.Errorf("error searching for user: %w", err)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Expand Down
5 changes: 4 additions & 1 deletion internal/middleware/context_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@ func TestContextMiddleware(t *testing.T) {
Runtime: &runtime,
Ctx: ctx,
})
authService := service.NewAuthService(service.AuthServiceInput{

authService, err := service.NewAuthService(service.AuthServiceInput{
Log: log,
Config: &cfg,
Runtime: &runtime,
Expand All @@ -277,6 +278,8 @@ func TestContextMiddleware(t *testing.T) {
PolicyEngine: policyEngine,
})

require.NoError(t, err)

contextMiddleware := NewContextMiddleware(ContextMiddlewareInput{
Log: log,
RuntimeConfig: &runtime,
Expand Down
19 changes: 17 additions & 2 deletions internal/service/auth_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ type AuthService struct {
tailscale *TailscaleService
policyEngine *PolicyEngine

dummyHash string

lockdown struct {
active bool
until time.Time
Expand Down Expand Up @@ -101,7 +103,7 @@ type AuthServiceInput struct {
PolicyEngine *PolicyEngine
}

func NewAuthService(i AuthServiceInput) *AuthService {
func NewAuthService(i AuthServiceInput) (*AuthService, error) {
Comment thread
steveiliop56 marked this conversation as resolved.
service := &AuthService{
log: i.Log,
runtime: i.Runtime,
Expand All @@ -123,6 +125,15 @@ func NewAuthService(i AuthServiceInput) *AuthService {
loginCacheSize = service.maxLoginLimits
}

// dummy hash
dummyHash, err := bcrypt.GenerateFromPassword([]byte(utils.GenerateString(8)), bcrypt.DefaultCost)

if err != nil {
return nil, fmt.Errorf("failed to generate dummy hash: %w", err)
}

service.dummyHash = string(dummyHash)

// caches setup
oauthCache := NewCacheStore[OAuthPendingSession](256)
loginCache := NewCacheStore[LoginAttempt](loginCacheSize)
Expand All @@ -148,7 +159,11 @@ func NewAuthService(i AuthServiceInput) *AuthService {
}
}, ding.RingMinor)

return service
return service, nil
}

func (auth *AuthService) DummyPasswordCheck(password string) {
bcrypt.CompareHashAndPassword([]byte(auth.dummyHash), []byte(password))
}

func (auth *AuthService) SearchUser(username string) (*model.UserSearch, error) {
Expand Down