Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
2b05562c
Commit
2b05562c
authored
Aug 01, 2018
by
Grzegorz Bizon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify blocked user tracking during authentication
parent
4bcf72e7
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
35 additions
and
119 deletions
+35
-119
config/initializers/warden.rb
config/initializers/warden.rb
+8
-10
lib/gitlab/auth/activity.rb
lib/gitlab/auth/activity.rb
+1
-2
lib/gitlab/auth/blocked_user_tracker.rb
lib/gitlab/auth/blocked_user_tracker.rb
+9
-45
spec/lib/gitlab/auth/blocked_user_tracker_spec.rb
spec/lib/gitlab/auth/blocked_user_tracker_spec.rb
+17
-62
No files found.
config/initializers/warden.rb
View file @
2b05562c
...
...
@@ -2,7 +2,7 @@ Rails.application.configure do |config|
Warden
::
Manager
.
after_set_user
(
scope: :user
)
do
|
user
,
auth
,
opts
|
Gitlab
::
Auth
::
UniqueIpsLimiter
.
limit_user!
(
user
)
activity
=
Gitlab
::
Auth
::
Activity
.
new
(
user
,
opts
)
activity
=
Gitlab
::
Auth
::
Activity
.
new
(
opts
)
case
opts
[
:event
]
when
:authentication
...
...
@@ -26,20 +26,18 @@ Rails.application.configure do |config|
end
Warden
::
Manager
.
before_failure
(
scope: :user
)
do
|
env
,
opts
|
tracker
=
Gitlab
::
Auth
::
BlockedUserTracker
.
new
(
env
)
tracker
.
log_blocked_user_activity!
if
tracker
.
user_blocked?
Gitlab
::
Auth
::
Activity
.
new
(
tracker
.
user
,
opts
).
user_authentication_failed!
Gitlab
::
Auth
::
Activity
.
new
(
opts
).
user_authentication_failed!
end
Warden
::
Manager
.
before_logout
(
scope: :user
)
do
|
user
_warden
,
auth
,
opts
|
user
=
user_warden
||
auth
.
user
Warden
::
Manager
.
before_logout
(
scope: :user
)
do
|
user
,
auth
,
opts
|
user
||=
auth
.
user
Gitlab
::
Auth
::
Activity
.
new
(
user
,
opts
).
tap
do
|
activity
|
activity
.
user_blocked!
if
user
.
blocked?
activity
.
user_session_destroyed
!
if
user
.
blocked?
Gitlab
::
Auth
::
Activity
.
new
(
opts
).
user_blocked!
BlockedUserTracker
.
new
(
user
,
auth
).
log_blocked_user_activity
!
end
Gitlab
::
Auth
::
Activity
.
new
(
opts
).
user_session_destroyed!
ActiveSession
.
destroy
(
user
,
auth
.
request
.
session
.
id
)
end
end
lib/gitlab/auth/activity.rb
View file @
2b05562c
...
...
@@ -18,8 +18,7 @@ module Gitlab
user_blocked:
'Counter of sign in attempts when user is blocked'
}.
freeze
def
initialize
(
user
,
opts
)
@user
=
user
def
initialize
(
opts
)
@opts
=
opts
end
...
...
lib/gitlab/auth/blocked_user_tracker.rb
View file @
2b05562c
...
...
@@ -2,57 +2,21 @@
module
Gitlab
module
Auth
class
BlockedUserTracker
include
Gitlab
::
Utils
::
StrongMemoize
ACTIVE_RECORD_REQUEST_PARAMS
=
'action_dispatch.request.request_parameters'
def
initialize
(
env
)
@env
=
env
end
def
user_blocked?
user
&
.
blocked?
end
def
user
return
unless
has_user_blocked_message?
strong_memoize
(
:user
)
do
# Check for either LDAP or regular GitLab account logins
login
=
@env
.
dig
(
ACTIVE_RECORD_REQUEST_PARAMS
,
'username'
)
||
@env
.
dig
(
ACTIVE_RECORD_REQUEST_PARAMS
,
'user'
,
'login'
)
User
.
by_login
(
login
)
if
login
.
present?
end
rescue
TypeError
def
initialize
(
user
,
auth
)
@user
=
user
@auth
=
auth
end
def
log_blocked_user_activity!
return
unless
user_blocked?
Gitlab
::
AppLogger
.
info
(
"Failed login for blocked user: user=
#{
user
.
username
}
ip=
#{
@env
[
'REMOTE_ADDR'
]
}
"
)
SystemHooksService
.
new
.
execute_hooks_for
(
user
,
:failed_login
)
true
rescue
TypeError
end
return
unless
@user
.
blocked?
private
Gitlab
::
AppLogger
.
info
<<~
INFO
"Failed login for blocked user: user=
#{
@user
.
username
}
ip=
#{
@auth
.
request
.
ip
}
")
INFO
##
# Devise calls User#active_for_authentication? on the User model and then
# throws an exception to Warden with User#inactive_message:
# https://github.com/plataformatec/devise/blob/v4.2.1/lib/devise/hooks/activatable.rb#L8
#
# Since Warden doesn't pass the user record to the failure handler, we
# need to do a database lookup with the username. We can limit the
# lookups to happen when the user was blocked by checking the inactive
# message passed along by Warden.
#
def
has_user_blocked_message?
strong_memoize
(
:user_blocked_message
)
do
message
=
@env
.
dig
(
'warden.options'
,
:message
)
message
==
User
::
BLOCKED_MESSAGE
end
SystemHooksService
.
new
.
execute_hooks_for
(
@user
,
:failed_login
)
rescue
TypeError
end
end
end
...
...
spec/lib/gitlab/auth/blocked_user_tracker_spec.rb
View file @
2b05562c
require
'spec_helper'
describe
Gitlab
::
Auth
::
BlockedUserTracker
do
set
(
:user
)
{
create
(
:user
)
}
describe
'#log_blocked_user_activity!'
do
it
'does not log if user failed to login due to undefined reason'
do
expect_any_instance_of
(
SystemHooksService
).
not_to
receive
(
:execute_hooks_for
)
tracker
=
described_class
.
new
({})
context
'when user is not blocked'
do
it
'does not blocked user activity'
do
expect_any_instance_of
(
SystemHooksService
)
.
not_to
receive
(
:execute_hooks_for
)
expect
(
Gitlab
::
AppLogger
).
not_to
receive
(
:info
)
expect
(
tracker
.
user
).
to
be_nil
expect
(
tracker
.
user_blocked?
).
to
be_falsey
expect
(
tracker
.
log_blocked_user_activity!
).
to
be_nil
end
user
=
create
(
:user
)
it
'gracefully handles malformed environment variables'
do
tracker
=
described_class
.
new
({
'warden.options'
=>
'test'
})
expect
(
tracker
.
user
).
to
be_nil
expect
(
tracker
.
user_blocked?
).
to
be_falsey
expect
(
tracker
.
log_blocked_user_activity!
).
to
be_nil
end
context
'failed login due to blocked user'
do
let
(
:base_env
)
{
{
'warden.options'
=>
{
message:
User
::
BLOCKED_MESSAGE
}
}
}
let
(
:env
)
{
base_env
.
merge
(
request_env
)
}
subject
{
described_class
.
new
(
env
)
}
before
do
expect_any_instance_of
(
SystemHooksService
).
to
receive
(
:execute_hooks_for
).
with
(
user
,
:failed_login
)
described_class
.
new
(
user
,
spy
(
'auth'
)).
log_blocked_user_activity!
end
end
context
'via GitLab login'
do
let
(
:request_env
)
{
{
described_class
::
ACTIVE_RECORD_REQUEST_PARAMS
=>
{
'user'
=>
{
'login'
=>
user
.
username
}
}
}
}
it
'logs a blocked user'
do
user
.
block!
expect
(
subject
.
user
).
to
be_blocked
expect
(
subject
.
user_blocked?
).
to
be
true
expect
(
subject
.
log_blocked_user_activity!
).
to
be_truthy
end
it
'logs a blocked user by e-mail'
do
user
.
block!
env
[
described_class
::
ACTIVE_RECORD_REQUEST_PARAMS
][
'user'
][
'login'
]
=
user
.
email
expect
(
subject
.
user
).
to
be_blocked
expect
(
subject
.
log_blocked_user_activity!
).
to
be_truthy
end
end
context
'via LDAP login'
do
let
(
:request_env
)
{
{
described_class
::
ACTIVE_RECORD_REQUEST_PARAMS
=>
{
'username'
=>
user
.
username
}
}
}
it
'logs a blocked user'
do
user
.
block!
expect
(
subject
.
user
).
to
be_blocked
expect
(
subject
.
user_blocked?
).
to
be
true
expect
(
subject
.
log_blocked_user_activity!
).
to
be_truthy
end
context
'when user is not blocked'
do
it
'logs blocked user activity'
do
user
=
create
(
:user
,
:blocked
)
it
'logs a LDAP blocked user'
do
user
.
ldap_block!
expect_any_instance_of
(
SystemHooksService
)
.
to
receive
(
:execute_hooks_for
)
.
with
(
user
,
:failed_login
)
expect
(
Gitlab
::
AppLogger
).
to
receive
(
:info
)
.
with
(
/Failed login for blocked user/
)
expect
(
subject
.
user
).
to
be_blocked
expect
(
subject
.
user_blocked?
).
to
be
true
expect
(
subject
.
log_blocked_user_activity!
).
to
be_truthy
end
described_class
.
new
(
user
,
spy
(
'auth'
)).
log_blocked_user_activity!
end
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment