-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
THREESCALE-10843: Audit user sessions #3885
THREESCALE-10843: Audit user sessions #3885
Conversation
app/controllers/provider/admin/user/personal_details_controller.rb
Outdated
Show resolved
Hide resolved
@@ -19,7 +19,10 @@ def show | |||
def update | |||
resource.validate_fields! | |||
if resource.errors.empty? && resource.update(user_params) | |||
resource.kill_user_sessions(user_session) if resource.just_changed_password? | |||
if resource.just_changed_password? | |||
AuditLogService.call("User changed password: #{resource.id}/#{resource.username}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we audit the whatever object stores the password already?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the user
model. I'd say the corresponding attribute is password_digest
, and we don't audit it:
Lines 35 to 36 in 07e52fe
audited except: %i[salt posts_count janrain_identifier cas_identifier password_digest | |
authentication_id open_id last_login_at last_login_ip crypted_password].freeze |
Anyway, since the jira description explicitly mentions Audit logs, I assumed that was the thing to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes sense to start auditing that field. Just redact the value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we should remove the audit logs then? or should we have both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the logs here: dd3665a
@@ -31,19 +31,29 @@ def create | |||
self.current_user = @user | |||
create_user_session! | |||
flash[:notice] = @strategy.new_user_created? ? 'Signed up successfully' : 'Signed in successfully' | |||
|
|||
AuditLogService.call("Signed in: #{current_user.id}/#{current_user.username} #{current_user.first_name} #{current_user.last_name}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't full name a little bit too much logging?
Also, provided that we audit UserSession, why do we need a separate log message that a user logged in? Maybe one can watch the sessions creation audits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't full name a little bit too much logging?
Maybe, I copied this from what we do in the admin portal:
AuditLogService.call("Signed in: #{current_user.id}/#{current_user.username} #{current_user.first_name} #{current_user.last_name}") |
Also, provided that we audit UserSession, why do we need a separate log message that a user logged in? Maybe one can watch the sessions creation audits.
Maybe it's not required. I added the log because that's what the issue description says. But I'm open to remove this traces if you think they are not needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think we should add redundant logging carefully as our logs are huge already. I see no value in this log. But if you see that it adds something useful, that might be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And what about the audit log already existing in the admin portal, should we remove it also? It's not required anymore now we are auditing UserSession
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, with a note in the release notes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aternatively we may stop auditing session and keep only the log 😎
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the logs: dd3665a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also added some release notes to the issue.
lib/developer_portal/app/controllers/developer_portal/login_controller.rb
Show resolved
Hide resolved
lib/developer_portal/app/controllers/developer_portal/login_controller.rb
Outdated
Show resolved
Hide resolved
@@ -28,12 +28,12 @@ def create | |||
create_user_session!(strategy&.authentication_provider_id) | |||
flash[:notice] = 'Signed in successfully' | |||
|
|||
AuditLogService.call("Signed in: #{current_user.id}/#{current_user.username} #{current_user.first_name} #{current_user.last_name}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this log removed because now there are audit logs for the "UserSession" model?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly. Now we audit UserSession
and also User#password_digest
, so we don't need augit logs for login/logout and user password change
redirect_back_or_default provider_admin_path | ||
else | ||
new | ||
flash.now[:error] ||= strategy&.error_message | ||
attempted_cred = auth_params.fetch(:username, 'SSO') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the fallback is "SSO"? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I want here is to provide useful information about which user tried to login. When the auth strategy is user/password, then we can log the usename, but when the strategy is SSO, then I was initially logging the given token. @akostadinov was concerned about how safe was to log that, so I just log SSO
now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, I am not quite sure about the SSO flow, I'd need to check, but would there potentially be some value in logging the system_name
of the auth provider instead?... just thinking out loud.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, that would allow admins to know which auth provider was being used when it failed to log in. Probably that's better than just print SSO
resource.kill_user_sessions(user_session) if resource.just_changed_password? | ||
if resource.just_changed_password? | ||
resource.kill_user_sessions(user_session) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this change? Seems like rubocop prefers single line :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But actually wasn't password_digest
attr important now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this change? Seems like rubocop prefers single line :)
Yeah, it was single line before but I made it complete form because I was also adding the audit log here. But then I removed the audit log and forgot to make it single line again.
But actually wasn't password_digest attr important now?
password
is a field in the form, not the DB column, that is called password_digest
since we don't save passwords in plain text. In fact, look how is just_changed_password
implemented:
porta/app/lib/authentication/by_password.rb
Lines 41 to 43 in 843f799
def just_changed_password? | |
saved_change_to_password_digest? || super | |
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed the if
: df2fa19
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a line question that is probably irrelevant. And would suggest adding a test for the password change audit unless I missed one existing.
Approved in case its just my oversight.
login_as @buyer.admins.first | ||
assert_difference(Audited.audit_class.method(:count)) do | ||
User.with_synchronous_auditing do | ||
put :update, params: { user: {current_password: 'supersecret', password: 'new_password', password_confirmation: 'new_password'} } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also asserting that the value of old and new password in audit is [REDACTED]
could be useful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmmm, actually...
[27] pry(main)> user.audits.last
=> #<Audited::Audit:0x000000004247d5a0
id: 1454,
auditable_id: 2,
auditable_type: "User",
user_id: 2,
user_type: "User",
username: nil,
action: "update",
version: 2,
created_at: Thu, 19 Sep 2024 12:02:25.000000000 UTC +00:00,
tenant_id: 2,
provider_id: 2,
kind: "User",
audited_changes: {"password_digest"=>"[FILTERED]"},
comment: nil,
associated_id: nil,
associated_type: nil,
remote_address: "127.0.0.1",
request_uuid: "d97ee5f5-ccf1-4dc8-a39a-e4e2aec767e3">
[28] pry(main)> user.audits.last.audited_changes
=> {"password_digest"=>
["$2a$12$TshOAone/WSVbXsCmOB1JuLGBQI698CButPpA2F7hw1jEb2db4YWi",
"$2a$12$.0G4VigmmeE1cjozQbXPkuyYF5iBjcfIwtjqcqJCPomceKUr7REkS"]}
Is that expected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shit. It was actually not redacting the value. I'll fix it and add the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added that test for provider and developer portals: 7607ae0 So please, approve or die. |
expected = [Audited::Auditor::AuditedInstanceMethods::REDACTED] * 2 | ||
assert_equal expected,user.audits.last.audited_changes['password_digest'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why it is *2
but better than the actual value :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Audited::Auditor::AuditedInstanceMethods::REDACTED] * 2
is a cool way to do
[Audited::Auditor::AuditedInstanceMethods::REDACTED, Audited::Auditor::AuditedInstanceMethods::REDACTED]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, now I saw the []
5f93b2c
to
d09a4dd
Compare
What this PR does / why we need it:
This PR adds audits for
UserSession
. In particular fot:create
and:revoke
operationsThe Jira issue also mentions auditing when a
User
is locked. I'm not sure what "locked" means but I assume it means "suspended". If that's the case, then that was already done.Besides, the issue also asks to add some audit logs for some operations:
In both admin and developer portals.
The PR also adds some tests for the new functionality.
Which issue(s) this PR fixes
https://issues.redhat.com/browse/THREESCALE-10843
Verification steps
Just perform the operations above and check the audits appear.