diff options
author | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2015-07-06 10:09:53 +0000 |
---|---|---|
committer | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2015-07-06 10:09:53 +0000 |
commit | f3590c83ea52971f2c30534952ea4d1fd6fc1b81 (patch) | |
tree | 00609053c12c960dd645ecad45dcaae2f58d5f9d /app | |
parent | 5f52d6a038dc64db42d137aa83b3c104766c7098 (diff) | |
parent | 411829fdb5f24f97ce17e05f5fd018d47075b216 (diff) | |
download | gitlab-ce-f3590c83ea52971f2c30534952ea4d1fd6fc1b81.tar.gz |
Merge branch 'audit_log' into 'master'
Audit log for user authentication
https://dev.gitlab.org/gitlab/gitlabhq/issues/2318
See merge request !931
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/omniauth_callbacks_controller.rb | 8 | ||||
-rw-r--r-- | app/controllers/profiles_controller.rb | 7 | ||||
-rw-r--r-- | app/controllers/sessions_controller.rb | 7 | ||||
-rw-r--r-- | app/models/audit_event.rb | 19 | ||||
-rw-r--r-- | app/models/security_event.rb | 2 | ||||
-rw-r--r-- | app/services/audit_event_service.rb | 25 | ||||
-rw-r--r-- | app/views/layouts/nav/_profile.html.haml | 6 | ||||
-rw-r--r-- | app/views/profiles/_event_table.html.haml | 16 | ||||
-rw-r--r-- | app/views/profiles/audit_log.html.haml | 5 | ||||
-rw-r--r-- | app/views/profiles/history.html.haml | 11 |
10 files changed, 90 insertions, 16 deletions
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index 765adaf2128..fd51b380da2 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -28,6 +28,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController # Do additional LDAP checks for the user filter and EE features if @user.allowed? + log_audit_event(gl_user, with: :ldap) sign_in_and_redirect(gl_user) else flash[:alert] = "Access denied for your LDAP account." @@ -47,6 +48,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController if current_user # Add new authentication method current_user.identities.find_or_create_by(extern_uid: oauth['uid'], provider: oauth['provider']) + log_audit_event(current_user, with: oauth['provider']) redirect_to profile_account_path, notice: 'Authentication method updated' else @user = Gitlab::OAuth::User.new(oauth) @@ -54,6 +56,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController # Only allow properly saved users to login. if @user.persisted? && @user.valid? + log_audit_event(@user.gl_user, with: oauth['provider']) sign_in_and_redirect(@user.gl_user) else error_message = @@ -83,4 +86,9 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController def oauth @oauth ||= request.env['omniauth.auth'] end + + def log_audit_event(user, options = {}) + AuditEventService.new(user, user, options). + for_authentication.security_event + end end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 5382a6cf6ac..26a4de15462 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -38,8 +38,11 @@ class ProfilesController < Profiles::ApplicationController redirect_to profile_account_path end - def history - @events = current_user.recent_events.page(params[:page]).per(PER_PAGE) + def audit_log + @events = AuditEvent.where(entity_type: "User", entity_id: current_user.id). + order("created_at DESC"). + page(params[:page]). + per(PER_PAGE) end def update_username diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 7577fc96d6d..89629bc0581 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -37,6 +37,8 @@ class SessionsController < Devise::SessionsController resource.update_attributes(reset_password_token: nil, reset_password_sent_at: nil) end + authenticated_with = user_params[:otp_attempt] ? "two-factor" : "standard" + log_audit_event(current_user, with: authenticated_with) end end @@ -95,4 +97,9 @@ class SessionsController < Devise::SessionsController user.valid_otp?(user_params[:otp_attempt]) || user.invalidate_otp_backup_code!(user_params[:otp_attempt]) end + + def log_audit_event(user, options = {}) + AuditEventService.new(user, user, options). + for_authentication.security_event + end end diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb new file mode 100644 index 00000000000..967ffd46db0 --- /dev/null +++ b/app/models/audit_event.rb @@ -0,0 +1,19 @@ +class AuditEvent < ActiveRecord::Base + serialize :details, Hash + + belongs_to :user, foreign_key: :author_id + + validates :author_id, presence: true + validates :entity_id, presence: true + validates :entity_type, presence: true + + after_initialize :initialize_details + + def initialize_details + self.details = {} if details.nil? + end + + def author_name + self.user.name + end +end diff --git a/app/models/security_event.rb b/app/models/security_event.rb new file mode 100644 index 00000000000..d131c11cb6c --- /dev/null +++ b/app/models/security_event.rb @@ -0,0 +1,2 @@ +class SecurityEvent < AuditEvent +end diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb new file mode 100644 index 00000000000..a7f090655e1 --- /dev/null +++ b/app/services/audit_event_service.rb @@ -0,0 +1,25 @@ +class AuditEventService + def initialize(author, entity, details = {}) + @author, @entity, @details = author, entity, details + end + + def for_authentication + @details = { + with: @details[:with], + target_id: @author.id, + target_type: "User", + target_details: @author.name, + } + + self + end + + def security_event + SecurityEvent.create( + author_id: @author.id, + entity_id: @entity.id, + entity_type: @entity.class.name, + details: @details + ) + end +end diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index 914e1b83d1f..de5544268a1 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -44,8 +44,8 @@ = icon('image fw') %span Preferences - = nav_link(path: 'profiles#history') do - = link_to history_profile_path, title: 'History', data: {placement: 'right'} do + = nav_link(path: 'profiles#audit_log') do + = link_to audit_log_profile_path, title: 'Audit Log', data: {placement: 'right'} do = icon('history fw') %span - History + Audit Log diff --git a/app/views/profiles/_event_table.html.haml b/app/views/profiles/_event_table.html.haml new file mode 100644 index 00000000000..c19ac429d52 --- /dev/null +++ b/app/views/profiles/_event_table.html.haml @@ -0,0 +1,16 @@ +%table.table#audits + %thead + %tr + %th Action + %th When + + %tbody + - events.each do |event| + %tr + %td + %span + Signed in with + %b= event.details[:with] + authentication + %td #{time_ago_in_words event.created_at} ago += paginate events, theme: "gitlab" diff --git a/app/views/profiles/audit_log.html.haml b/app/views/profiles/audit_log.html.haml new file mode 100644 index 00000000000..698d6037428 --- /dev/null +++ b/app/views/profiles/audit_log.html.haml @@ -0,0 +1,5 @@ +- page_title "Audit Log" +%h3.page-title Audit Log +%p.light History of authentications + += render 'event_table', events: @events
\ No newline at end of file diff --git a/app/views/profiles/history.html.haml b/app/views/profiles/history.html.haml deleted file mode 100644 index b414fb69f4e..00000000000 --- a/app/views/profiles/history.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -- page_title "History" -%h3.page-title - Your Account History -%p.light - All events created by your account are listed below. -%hr -.profile_history - = render @events -%hr -= paginate @events, theme: "gitlab" - |