Skip to content
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

Merged
merged 3 commits into from
Mar 25, 2021
Merged

Make error messages specific #6108

merged 3 commits into from
Mar 25, 2021

Conversation

kimlisa
Copy link
Contributor

@kimlisa kimlisa commented Mar 23, 2021

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:

  • emit audit events when there are failures from creating sso auth requests
  • since we no longer expose any specific errors when users fail to login from UI, returned error messages are more specific so that it is clear what the error is when viewing audit logs
  • return generic 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

@kimlisa kimlisa marked this pull request as draft March 23, 2021 09:04
@kimlisa kimlisa force-pushed the lisa/emit-sso-login-failures branch 2 times, most recently from 5dce855 to 99a651a Compare March 23, 2021 09:44
mockE := &events.MockEmitter{}

emitSSOLoginFailureEvent(context.Background(), mockE, "test", trace.BadParameter("some error"))
event := mockE.LastEvent().(*events.UserLogin)
Copy link
Contributor

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.

Copy link
Contributor Author

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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.
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

@kimlisa kimlisa Mar 24, 2021

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

@kimlisa kimlisa force-pushed the lisa/emit-sso-login-failures branch 2 times, most recently from 246a96d to 50078d3 Compare March 24, 2021 04:59
@kimlisa kimlisa marked this pull request as ready for review March 24, 2021 04:59
@kimlisa kimlisa requested a review from alex-kovoy as a code owner March 24, 2021 04:59
Comment on lines -106 to -124
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())
Copy link
Contributor Author

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)

@kimlisa kimlisa force-pushed the lisa/emit-sso-login-failures branch from 50078d3 to 0c10acf Compare March 24, 2021 16:38
}

if err := a.emitter.EmitAuditEvent(a.closeCtx, event); err != nil {
log.WithError(err).Warn("Failed to emit OIDC login failed event.")
Copy link
Contributor

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.

Copy link
Contributor Author

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

logger := h.log.WithField("auth", "github")
logger.Debug("Console login start.")

generalErr := trace.AccessDenied(ssoLoginConsoleErr)
Copy link
Contributor

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.

Copy link
Contributor Author

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

Copy link
Contributor

@russjones russjones left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot.

@kimlisa kimlisa force-pushed the lisa/emit-sso-login-failures branch from 0c10acf to b352f18 Compare March 25, 2021 17:02
kimlisa added 3 commits March 25, 2021 10:05
- Remove inner emit event for createOIDCClient to prevent double emits
  on error.
- Return generic error message for console login errors
@kimlisa kimlisa force-pushed the lisa/emit-sso-login-failures branch from b352f18 to 342d4b2 Compare March 25, 2021 17:05
@kimlisa kimlisa merged commit 940c83c into master Mar 25, 2021
@kimlisa kimlisa deleted the lisa/emit-sso-login-failures branch March 25, 2021 17:36
kimlisa added a commit that referenced this pull request Mar 29, 2021
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.
kimlisa added a commit that referenced this pull request Mar 29, 2021
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Teleport should emit "Audit Events" on SSO login errors
4 participants