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

POC to migrate Code to use Feature Controls #35093

Closed
wants to merge 4 commits into from

Conversation

legrego
Copy link
Member

@legrego legrego commented Apr 15, 2019

Summary

This is a rough POC which removes Code's custom security handling in favor of Feature Controls:

  1. Added Code as a feature via xpack_main feature registry
    a) Defined all privilege as the existing "Code Admin"
    b) Defined read privilege as the existing "Code User"

  2. Removed explicit role checks:
    a) Rather than checking for code_admin or code_user roles, each route that needs securing is now tagged with one of two access tags: access:code_user or access:code_admin. These tags are used by the security plugin to automatically authorize access to these routes. These tags are registered as part of the feature registry in step 1, which is how the security plugin knows how to authorize them.

  3. Updated client-side state to use uiCapabilities
    Previously, the client-side state was requesting the details of the authenticated user, and determining if they were a code admin or a code user. Now, this logic is automatically handled by uiCapabilities, so the state was updated to read from these capabilities instead.

  4. Replaced callWithRequest with callWithInternalUser
    Now that Code is using Feature Controls, the end-users should not be calling Elasticsearch directly when interacting with the .code* indices. Instead, the Kibana server should be connecting on their behalf.

Note: This will need additional work by the Code team. I'll point out areas that I'm aware of that need attention, but there may be other areas too.

@legrego legrego marked this pull request as ready for review April 15, 2019 19:19
@legrego legrego added :Code Feature:Security/Feature Controls Platform Security - Spaces & Role Mgmt feature controls labels Apr 15, 2019
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-security

isCodeAdmin: false,
isCodeUser: false,
isCodeAdmin: Boolean(uiCapabilities.code.admin),
isCodeUser: Boolean(uiCapabilities.code.user),
};

export const userProfile = handleActions(
Copy link
Member Author

Choose a reason for hiding this comment

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

It's likely that you don't need any of these userProfile actions anymore. I left it in place because I didn't feel comfortable refactoring. All you essentially need is the initialState above, however you wish to incorporate that into the application.

icon: 'codeApp',
navLinkId: 'code',
app: ['code', 'kibana'],
catalogue: [],
Copy link
Member Author

Choose a reason for hiding this comment

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

If you add an entry to the Feature Catalogue, then you should add the ID of that entry to this array. This catalogue is what populates the Kibana Home page with the various features that users can enjoy.

catalogue: [],
privileges: {
all: {
api: ['code_user', 'code_admin'],
Copy link
Member Author

Choose a reason for hiding this comment

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

This grants users with the all privilege the ability to execute any API endpoints that are tagged with either access:code_user or access:code_admin

ui: ['show', 'user', 'admin'],
},
read: {
api: ['code_user'],
Copy link
Member Author

Choose a reason for hiding this comment

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

This grants users with the all privilege the ability to execute any API endpoints that are tagged with access:code_user.

@@ -66,7 +62,7 @@ async function checkWithRoles(server: any, roles: any) {
return response;
}

it('should response 403 when roles check failed', async () => {
it.skip('should response 403 when roles check failed', async () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

Skipping this test, but this entire suite should be revisited.

const routeOptions: RouteOptions = (route.options || {}) as RouteOptions;
routeOptions.tags = [
...(routeOptions.tags || []),
`access:code_${route.requireAdmin ? 'admin' : 'user'}`,
Copy link
Member Author

Choose a reason for hiding this comment

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

Tags the route with either access:code_user or access:code_admin depending on if requireAdmin is set on the route.

.callWithRequest.bind(null, req);
// FIXME: I swapped out `callWithRequest` for `callWithInternalUser` to test and verify functionality, but you'll want to refactor this since
// the names no longer make sense.
this.callWithRequest = req.server.plugins.elasticsearch.getCluster('data').callWithInternalUser;
Copy link
Member Author

Choose a reason for hiding this comment

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

Important

In order to test my changes, I simply changed the call being made here from callWithRequest to callWithInternalUser. I assume that we want this in most places, but I'm not sure if there are legitimate cases for callWithRequest -- Do you need to query any user indices, or are you only querying .code* indices?

Either way, this will need refactoring, since it is no longer "WithRequest".

A couple other notes:

  1. The kibana_system role has access to .code-*. Are there any other indices it needs access to in order for Code to function correctly?
  2. The code_admin and code_user roles that were introduced here will need to be removed. They are no longer needed, and we shouldn't confuse users with those options.

Copy link
Member Author

Choose a reason for hiding this comment

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

Update: We should not blindly use callWithInternalUser. Instead, Code should check if the Kibana security plugin is available, and if it is, use its exposed authorization mode to determine what to do:

const securityPlugin = server.plugins.security;
if (securityPlugin) {
  const useRbac = securityPlugin.authorization.mode.useRbacForRequest(request);
  if (useRbac) {
    // use `callWithInternalUser`
  } else {
    // use `callWithRequest`
  }
}

@elasticmachine
Copy link
Contributor

💔 Build Failed

@elasticmachine
Copy link
Contributor

💔 Build Failed

@elasticmachine
Copy link
Contributor

💔 Build Failed

@zfy0701
Copy link
Contributor

zfy0701 commented Apr 15, 2019

I'm going to continue the work here: #35115

@legrego
Copy link
Member Author

legrego commented Apr 16, 2019

Sounds good, thanks! I’ll close this then.

@legrego legrego closed this Apr 16, 2019
@legrego legrego deleted the fc/code branch April 29, 2019 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Security/Feature Controls Platform Security - Spaces & Role Mgmt feature controls
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants