Only add cloud-specific links for superusers#97870
Conversation
|
@elasticmachine merge upstream |
|
|
||
| interface CloudSetupDependencies { | ||
| home?: HomePublicPluginSetup; | ||
| security?: Pick<SecurityPluginSetup, 'authc'>; |
There was a problem hiding this comment.
NIT: as you're using the whole type in the tests via securityMock anyhow, any reason to use a Pick here?
There was a problem hiding this comment.
I leave that to Larry, but I personally like the fact that we explicitly outline the part of the dependency contract we really need (too bad we don't have a more expressive syntax to do that). This can make the life much easier if you're changing/fixing the behavior of a certain portion of your public contract and want to quickly know what plugins may be affected without following all the paths where the contract is passed to.
There was a problem hiding this comment.
Yeah I did this mostly out of habit for the reasons Aleh mentioned. I don't mind reverting if you'd prefer the original approach
| this.checkIfAuthorizedForLinks().then((authorized) => { | ||
| if (authorized && baseUrl && deploymentUrl) { | ||
| coreStart.chrome.setCustomNavLink({ | ||
| title: i18n.translate('xpack.cloud.deploymentLinkLabel', { |
There was a problem hiding this comment.
NIT: I know checkIfAuthorizedForLinks cannot likely throw, but we may still want to add a catch handler, just to follow the best practices against UnhandledPromiseRejection, wdyt?
azasypkin
left a comment
There was a problem hiding this comment.
Test locally, LGTM, thanks!
| const coreSetup = coreMock.createSetup(); | ||
| const homeSetup = homePluginMock.createSetupContract(); | ||
| const securitySetup = securityMock.createSetup(); | ||
| securitySetup.authc.getCurrentUser.mockResolvedValue({ |
There was a problem hiding this comment.
optional nit: wondering if it's time to expose existing mockAuthenticatedUser from security/common/mocks? Not a big deal, up to you.
There was a problem hiding this comment.
Good idea, will do! I forgot about this mock
| // Otherwise check roles. If user is not defined due to an unexpected error, then fail *open*. | ||
| // Cloud admin console will always perform the actual authorization checks. | ||
| const user = await this.authenticatedUserPromise; | ||
| return user?.roles.includes('superuser') ?? true; |
There was a problem hiding this comment.
question: sorry if I missed that in #97308, but for how long we expect this workaround to exist? If we're not sure, I'm wondering if we may want to leave an escape hatch and expose something like xpack.cloud.roles: schema.arrayOf(schema.string(), { defaultValue: ['superuser'] }) config value, so that in the worst case users could create an empty "marker" role if they need to.... I don't have a strong opinion on that, so feel free to ignore.
There was a problem hiding this comment.
This workaround will likely exist for a while - it's really up to the cloud team's roadmap to prioritize an API or similar mechanism for us to leverage.
I think it's premature to add an escape hatch, because we don't know what it would look like just yet. It's possible that we would instead want something under cloud's control, such as inspecting the user's metadata that their SSO realm attaches
There was a problem hiding this comment.
I think it's premature to add an escape hatch, because we don't know what it would look like just yet. It's possible that we would instead want something under cloud's control, such as inspecting the user's metadata that their SSO realm attaches
That makes sense, thanks. Works for me as long as it works for Cloud.
|
|
||
| interface CloudSetupDependencies { | ||
| home?: HomePublicPluginSetup; | ||
| security?: Pick<SecurityPluginSetup, 'authc'>; |
There was a problem hiding this comment.
I leave that to Larry, but I personally like the fact that we explicitly outline the part of the dependency contract we really need (too bad we don't have a more expressive syntax to do that). This can make the life much easier if you're changing/fixing the behavior of a certain portion of your public contract and want to quickly know what plugins may be affected without following all the paths where the contract is passed to.
| import { securityMock } from '../../security/public/mocks'; | ||
| import { CloudPlugin } from './plugin'; | ||
|
|
||
| const nextTick = async () => await new Promise<void>((resolve) => setTimeout(() => resolve(), 1)); |
There was a problem hiding this comment.
question: can we use import { nextTick } from '@kbn/test/jest'; instead?
| this.checkIfAuthorizedForLinks().then((authorized) => { | ||
| if (authorized && baseUrl && deploymentUrl) { | ||
| coreStart.chrome.setCustomNavLink({ | ||
| title: i18n.translate('xpack.cloud.deploymentLinkLabel', { |
…kibana into cloud/user-links-for-superusers
| createSetup: createSetupMock, | ||
| createStart: createStartMock, | ||
| createApiResponse: createApiResponseMock, | ||
| createMockAuthenticatedUser: (props: MockAuthenticatedUserProps = {}) => |
There was a problem hiding this comment.
I didn't have to expose this from the server mock, but I felt like this was a good way to ensure consistency between the client and server mock contracts
There was a problem hiding this comment.
Any reason why not just createMockAuthenticatedUser: mockAuthenticatedUser? No need to change anything, just curious.
There was a problem hiding this comment.
I debated exposing mockAuthenticatedUser, but prefixing it with create was more consistent with the other mock functions (createSetup, createStart, ...), and it felt more correct. When I first imported mockAuthenticatedUser, I assumed based on the name that it was an object with a create property or similar on it (mockAuthenticatedUser.create())
There was a problem hiding this comment.
Yeah, I like the createMockAuthenticatedUser name, I was mostly curious if we need this additional arrow function or we can just assign mockAuthenticatedUser driectly to createMockAuthenticatedUser.
There was a problem hiding this comment.
Ah sorry I should have read your comment a little closer 🙈
We don't need the additional arrow function, I added that so my IDE would give me type information as I wrote it out 😬
Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com>
💚 Build SucceededMetrics [docs]Page load bundle
History
To update your PR or re-run it, just comment with: |
Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Larry Gregory <larry.gregory@elastic.co> Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com>
Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Larry Gregory <larry.gregory@elastic.co> Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com>
Summary
Adds cloud specific links for users who are likely authorized to view them. In this first iteration, we are checking if the current user is a superuser.
Link examples
Manage this deployment for Cloud users with superuser privileges

Profile and Account & Billing with Cloud links for superuser privileges

Profile link for self managed, or Cloud w/o superuser privileges

Resolves #97308