-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Make error messages specific #6108
Conversation
5dce855
to
99a651a
Compare
lib/auth/auth_test.go
Outdated
mockE := &events.MockEmitter{} | ||
|
||
emitSSOLoginFailureEvent(context.Background(), mockE, "test", trace.BadParameter("some error")) | ||
event := mockE.LastEvent().(*events.UserLogin) |
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.
Instead of type assertion (which might potentially trigger a panic), assert the equivalence with require
, e.g. it should suffice to:
require.Equal(t, mockE.LastEvent(), &events.UserLogin{
Metadata: events.Metadata{
Type: events.UserLoginEvent,
Code: events.UserSSOLoginFailureCode,
},
Method: "test",
Status: events.Status{
Success: false,
Error: "some error",
UserMessage: "some error",
},
})
and matching on Method
will not be necessary since it's also part of the expectation.
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.
revised
lib/auth/oidc.go
Outdated
} | ||
if idsub != uisub { | ||
log.Debugf("OIDC claim subjects don't match '%v' != '%v'.", idsub, uisub) | ||
return nil, trace.BadParameter("invalid subject in UserInfo") | ||
log.Debugf("OIDC claim subjects does not match '%v' != '%v'.", idsub, uisub) |
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 was grammatically correct before?
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.
reverted
@@ -196,8 +197,15 @@ func UserMessageFromError(err error) string { | |||
} | |||
fmt.Fprintln(&buf, AllowNewlines(trace.Unwrap(er).Error())) | |||
} else { | |||
fmt.Fprintln(&buf, AllowNewlines(err.Error())) | |||
strErr := err.Error() | |||
// Error can be of type trace.proxyError where error message didn't get captured. |
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.
This is somewhat misleading. Did you have a specific error that did not transport the message over the wire? All errors coming from the server over HTTP will be of type trace.proxyError and it's supposed to transport the message with it - if that's not the case here, it's probably a bug to be fixed.
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 was trying to purposely cause errors when logging in with sso through CLI and I found errors came back as empty strings. I traced into it and I thought maybe it was by design to prevent sensitive error messages from auth from being exposed?
This is how errors get marshalled: https://github.com/gravitational/trace/blob/master/httplib.go#L87
And this is how errors get unmarshalled: https://github.com/gravitational/trace/blob/master/httplib.go#L59
And this is how requests are made in both client and proxy: https://github.com/gravitational/teleport/blob/master/lib/auth/clt.go#L251
Given tsh client -> proxy -> auth make request
First marshal/unmarshal auth to proxy: when error from auth gets marshalled, the error is of type TraceErr
, and when it gets unmarshalled, error is unmarshaled into TraceErr
and wrapped in proxyErr
Second marshal/unmarshal proxy to client: When this proxyErr gets marshalled, b/c it is not a type of TraceErr
, everything gets stripped except error field, and when this gets unmarshalled it gets unmarshalled into trace error struct that only has message
as its field, so the error field never gets saved and message is empty.
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.
Ok, I see. This a bug in trace and should be definitely fixed so it's possible to send errors over the wire multiple times. I'll see how complicated this would be.
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.
Since this is a bug, I went back to all console logins github
, oidc
, saml
, in the webapi layer and made sure to return a generic error message for all errors to hide sensitive data. This is what we did for UI dashboard login failures (and validating auth callbacks): 50078d3
246a96d
to
50078d3
Compare
if err := a.emitter.EmitAuditEvent(ctx, &events.UserLogin{ | ||
Metadata: events.Metadata{ | ||
Type: events.UserLoginEvent, | ||
Code: events.UserSSOLoginFailureCode, | ||
}, | ||
Method: events.LoginMethodOIDC, | ||
Status: events.Status{ | ||
Success: false, | ||
Error: trace.Unwrap(ctx.Err()).Error(), | ||
UserMessage: err.Error(), | ||
}, | ||
}); err != nil { | ||
log.WithError(err).Warn("Failed to emit OIDC login failure event.") | ||
} | ||
// return user-friendly error hiding the actual error in the event | ||
// logs for security purposes | ||
return nil, trace.ConnectionProblem(nil, | ||
"failed to login with %v", | ||
conn.GetDisplay()) |
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.
Since we no longer show the users the actual login errors (but a generic login failed msg), I didn't think it was necessary to hide this error and simply return the actual error for the outer caller to emit the events (also removes double emitting)
50078d3
to
0c10acf
Compare
} | ||
|
||
if err := a.emitter.EmitAuditEvent(a.closeCtx, event); err != nil { | ||
log.WithError(err).Warn("Failed to emit OIDC login failed event.") |
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.
nit: log these at Debug
if these aren't critical.
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 constructed these to be consistent with others (others use warn), i think it also makes sense to use warn here b/c missing an event for auditing should stand out
lib/web/apiserver.go
Outdated
logger := h.log.WithField("auth", "github") | ||
logger.Debug("Console login start.") | ||
|
||
generalErr := trace.AccessDenied(ssoLoginConsoleErr) |
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.
Even though this seems to reduce the error handling (if that's the intent), it will obscure the actual point of error emission and might complicate analysis as several places would be likely candidates as the error source - it's better to emit the error at each point with the corresponding trace
error constructor.
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.
Revised so that each error returns its own trace err so tracing is closer to origin of actual error
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.
Bot.
0c10acf
to
b352f18
Compare
- Remove inner emit event for createOIDCClient to prevent double emits on error. - Return generic error message for console login errors
b352f18
to
342d4b2
Compare
Purpose is to allow users with admin privilege that are able to view audit logs, to be able to debug SSO login failures from the UI as much as possible * Return generic error message for sso console login failures to hide sensitive data from reaching client. Previously errors were returning as empty messages b/c of a trace bug. * Remove emit event for createOIDCClient to allow outer caller to emit event and prevent double emits on error. * Temporarily direct users to check teleports log on errors that come back empty to tsh client.
…6204) Purpose is to allow users with admin privilege that are able to view audit logs, to be able to debug SSO login failures from the UI as much as possible * Return generic error message for sso console login failures to hide sensitive data from reaching client. Previously errors were returning as empty messages b/c of a trace bug. * Remove emit event for createOIDCClient to allow outer caller to emit event and prevent double emits on error. * Temporarily direct users to check teleports log on errors that come back empty to tsh client.
resolves #6046
Description
Note: there is a bug with trace marshalling proxyErr: #6108 (comment)
Purpose is to allow users with admin privilege that are able to view audit logs, to be able to debug SSO login failures from the UI as much as possible:
login failed
message for sso CLI login failures (which are errors from creating an auth request) similar in the UI dashbaord where we also display generic error message