-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Security - remove auth scope provider #36998
Conversation
return h.continue; | ||
} | ||
|
||
const user = auth.credentials; |
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.
Logic copied from dashboard_mode_auth_scope
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
💔 Build Failed |
💔 Build Failed |
💔 Build Failed |
💔 Build Failed |
💔 Build Failed |
retest |
💚 Build Succeeded |
Pinging @elastic/kibana-security |
@@ -25,9 +27,27 @@ export function createDashboardModeRequestInterceptor(dashboardViewerApp) { | |||
type: 'onPostAuth', | |||
async method(request, h) { | |||
const { auth, url } = request; | |||
const user = auth.credentials; |
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.
As you can tell from the commit history in this PR, the ordering of operations in this function is rather fragile.
Previously, this logic was part of dashboard_mode_auth_scope
, which ran after a successful authentication. Now, this runs as part of "onPostAuth", which runs after auth, but also runs when security is disabled completely.
The existing (and current) logic uses the UI Settings service to retrieve the list of dashboard-only-mode roles. The act of retrieving this setting ends up creating the config
document if it doesn't already exist. Various functional tests have come to indirectly rely on this behavior, so I've opted to maintain that in this PR. I had originally hoped to optimize the existing implementation by not querying the UI Settings Service unless strictly necessary, but I wasn't able to do so without also revisiting all of the existing functional tests. I vote to work in that when we remove dashboard-only-mode altogether.
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.
The act of retrieving this setting ends up creating the config document if it doesn't already exist. Various functional tests have come to indirectly rely on this behavior, so I've opted to maintain that in this PR. I had originally hoped to optimize the existing implementation by not querying the UI Settings Service unless strictly necessary, but I wasn't able to do so without also revisiting all of the existing functional tests. I vote to work in that when we remove dashboard-only-mode altogether.
That's a bummer :/ How many (approximately) of such weird tests we have? I'm fine with leaving it as is, just curious.
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.
How many (approximately) of such weird tests we have? I'm fine with leaving it as is, just curious.
It's hard to quantify this since the FTR doesn't run test suites to completion once it finds a test failure. I know we had failures in infra and canvas, but I'm sure there are a number of other impacted suites.
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.
Okay, thanks, that's what I wanted to know. I was just curious whether tests were failing within one "area" or not.
ACK: started to review, planning to finish today or tomorrow at the latest. |
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.
LGTM, just a couple of minor nits. Thanks for doing this, I always wanted to get rid of auth scopes ^feature^ 🙂
@@ -133,11 +132,7 @@ class Authenticator { | |||
* @param authScope AuthScopeService instance. |
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: please remove authScope
from JSDoc as well.
// Complement user returned from the provider with scopes. | ||
scope: await this.authScope.getForRequestAndUser(request, authenticationResult.user!), | ||
} as any); | ||
return AuthenticationResult.succeeded(authenticationResult.user as any); |
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: authenticationResult.user as any
---> authenticationResult.user!
would be more appropriate.
const user = auth.credentials; | ||
const roles = user ? user.roles : []; | ||
|
||
if (!user) { |
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.
suggestion: since we create roles
even if user
isn't defined, can't we just do something like this instead and use our roles
list below instead of user.roles
?
// Clarifying comment goes here ....
const roles = (auth.credentials && auth.credentials.roles) || [];
if (roles.length === 0) {
return h.continue;
}
Or the way it's done also related to these weird functional tests that depend on config
object? If so, feel free to ignore this suggestion.
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.
Or the way it's done also related to these weird functional tests that depend on config object? If so, feel free to ignore this suggestion.
Yep, it was done this way because of the weird functional tests
const isSuperUser = user.roles.find(role => role === superuserRole); | ||
|
||
const enforceDashboardOnlyMode = isDashboardOnlyModeUser && !isSuperUser; | ||
if (enforceDashboardOnlyMode) { | ||
if (url.path.startsWith('/app/kibana')) { | ||
// If the user is in "Dashboard only mode" they should only be allowed to see | ||
// that app and none others. Here we are intercepting all other routing and ensuring the viewer |
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.
uh oh: we have a link to x-pack-kibana
repo :)
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.
ha, good catch, will remove
@@ -7,12 +7,14 @@ | |||
import Boom from 'boom'; | |||
|
|||
import { | |||
AUTH_SCOPE_DASHBORD_ONLY_MODE |
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: can you please also get rid of AUTH_SCOPE_DASHBORD_ONLY_MODE
in x-pack/plugins/dashboard_mode/common/constants.js
?
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 can't believe I missed that! will do!
@@ -108,11 +105,11 @@ describe('DashboardOnlyModeRequestInterceptor', () => { | |||
describe('request has correct auth scope scope', () => { |
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: test title is outdated
not related: I've noticed we also reference to auth scope from comment in x-pack/plugins/spaces/server/lib/request_inteceptors/on_post_auth_interceptor.ts
, probably some left over.
@@ -25,9 +27,27 @@ export function createDashboardModeRequestInterceptor(dashboardViewerApp) { | |||
type: 'onPostAuth', | |||
async method(request, h) { | |||
const { auth, url } = request; | |||
const user = auth.credentials; |
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.
The act of retrieving this setting ends up creating the config document if it doesn't already exist. Various functional tests have come to indirectly rely on this behavior, so I've opted to maintain that in this PR. I had originally hoped to optimize the existing implementation by not querying the UI Settings Service unless strictly necessary, but I wasn't able to do so without also revisiting all of the existing functional tests. I vote to work in that when we remove dashboard-only-mode altogether.
That's a bummer :/ How many (approximately) of such weird tests we have? I'm fine with leaving it as is, just curious.
const uiSettings = request.getUiSettingsService(); | ||
const dashboardOnlyModeRoles = await uiSettings.get(CONFIG_DASHBOARD_ONLY_MODE_ROLES); | ||
|
||
if (!isAppRequest || !dashboardOnlyModeRoles || !roles || roles.length === 0) { |
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.
optional nit: I'd say the perf impact of find
on roles
is negligible comparing to async uiSettings.get
call, so maybe there is no need to have this additional return path (and assuming we'll do roles check in the if
above) and always treat this advanced setting a defined array.
const dashboardOnlyModeRoles = await uiSettings.get(CONFIG_DASHBOARD_ONLY_MODE_ROLES) || [];
nit: also can you please leave a comment in code explaining why we always call uiSettings.get
, so that we don't forget that?
💔 Build Failed |
💚 Build Succeeded |
* remove auth scope provider * handle missing roles * guard for unauthenticated calls * update functional tests to not expect a scope property * there's always money in the banana stand * revert interceptor optimizations * protect against missing roles * address pr feedback * remove scope as expected property on kerberos auth response
* remove auth scope provider * handle missing roles * guard for unauthenticated calls * update functional tests to not expect a scope property * there's always money in the banana stand * revert interceptor optimizations * protect against missing roles * address pr feedback * remove scope as expected property on kerberos auth response
* remove auth scope provider * handle missing roles * guard for unauthenticated calls * update functional tests to not expect a scope property * there's always money in the banana stand * revert interceptor optimizations * protect against missing roles * address pr feedback * remove scope as expected property on kerberos auth response
Summary
The security plugin provides a way for other plugins to append "scopes" to the authenticated user. Based on a conversation here, this is not something we want to migrate to the new platform.
This PR removes the auth scope provider, and replaces its usage within the Dashboard Only Mode plugin with a slightly more straightforward implementation.