Skip to content

Limiting privileges for objects such as application privileges #31559

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

Closed
jaymode opened this issue Jun 25, 2018 · 9 comments
Closed

Limiting privileges for objects such as application privileges #31559

jaymode opened this issue Jun 25, 2018 · 9 comments
Assignees
Labels
:Security/Authorization Roles, Privileges, DLS/FLS, RBAC/ABAC

Comments

@jaymode
Copy link
Member

jaymode commented Jun 25, 2018

The current permission model for security has the ability to secure the ability to perform an action. For the majority of objects, this is either a all or nothing permission; a user can be granted the ability to edit all users or not be allowed to edit any user.

As we develop new features, such as Application Privileges (#29820), the need to further restrict the permissions on objects becomes more apparent. In the case of application privileges, the idea here would be to restrict the set of privileges a user could perform CRUD operations on. In concrete terms, an example of this would be limiting the kibana user to only be able to perform CRUD operations on the kibana application privileges and not those of other applications such as Beats or Logstash.

A few options have been proposed and discussed. The first that @tvernum proposed is to re-use the DSL from the role mapping api within roles, so for example we'd have something like the following role to limit privilege management by the application that the privileges belong to:

{
  "cluster": [
    {
      "privileges": [ "manage_privileges" ],
      "rules": {
        "field": { "application": "kibana" }
      }
    }
  ]
}

Extending this to role management, we could envision something like the following to limit roles that could be managed:

{
  "cluster": [
    {
      "privileges": [ "manage_roles" ],
      "rules": {
        "field": { "name": "sales_*" }
      }
    }
  ]
}

@clintongormley proposed a slightly different syntax that is more condensed and may be clearer to the user:

{
  "cluster":     
   {
      "privileges": { 
          "manage_privileges": { "application": "kibana" },
          "other_priv": {}
      }
    }
}

Alternatively, we could make application privileges a top level item within a role akin to cluster, indices, and run_as. This would look something like:

{
  "application": {
     "manage_privileges": {
         "applications": [ "kibana" ]
      }
  },
  "roles": {
    "manage": { "names": [ "sales_*" ] }
  }
}

This issue's purpose is to continue discussion and come to a conclusion for how we want to define and secure specific objects like application privileges.

@jaymode jaymode added :Security/Authorization Roles, Privileges, DLS/FLS, RBAC/ABAC team-discuss labels Jun 25, 2018
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-security

@jaymode
Copy link
Member Author

jaymode commented Jun 27, 2018

We discussed this briefly in our team meeting. No one really had opinions on the way to go, so I asked @tvernum to start with trying the format where application privileges is a top level item within roles.

{
  "application": {
     "manage_privileges": {
         "applications": [ "kibana" ]
      }
  }
}

@albertzaharovits
Copy link
Contributor

I just got this digested. I also favor the last option which @jaymode suggested we turn into a POC. IMO the other syntax options are confusing outside the role mapping API.

There are a few things that I have found difficult to grasp fully, which I want to pass through other's mind:
Given a role with the previous partial definition:

{
  "application": {
     "manage": {
         "applications": [ "kibana" ]
      }
  },
  "roles": {
    "manage": {
       "names": [ "sales_*" ]
    }
  }
}

it allows for the users that are mapped under it:

  1. to define privileges only under the kibana application and, for the sales_* roles that it can manage, assigning privileges only for the kibana application? Custom privilege definition on roles #29820 (comment)
  2. while defining those sales_* roles, their application manage and role manage privileges be a subset of the ones for this role?
    This effectively also binds roles to applications, so not sure if this is how it's supposed to work...

@jaymode
Copy link
Member Author

jaymode commented Jun 27, 2018

@albertzaharovits the roles top level item was just an example of another object; there is no relationship between that item and the application item. For now, I would just leave off the roles item when thinking about this and just look at the example I used in my last comment.

@albertzaharovits
Copy link
Contributor

@jaymode understood, thanks. It might come as if I am trying to complicate things, but that's not the case.
The whole thing unfolded when thinking about this application manage privilege that you considered in isolation in #31559 (comment) as just another privilege that must have been granted by some role, and how would that role look like.

@tvernum
Copy link
Contributor

tvernum commented Jun 28, 2018

It's a minor detail, but it's also the first issue I ran into while trying to implement this.
Right now on the application privileges branch the application privileges themselves are in application (*) field.

An example from the rest test

            {
              "cluster": [],
              "indices": [
                {
                  "names": "engineering-*",
                  "privileges": ["read"]
                }
              ],
              "applications": [
                {
                  "application": "myapp",
                  "privileges": ["user"],
                  "resources": ["*"]
                },
                {
                  "application": "myapp",
                  "privileges": ["read"],
                  "resources": ["engineering/*"]
                }
              ]
            }

(*) OK, technically it's applications, but that's because indices is plural as well.

I'm going to move ahead by putting this new stuff under a "security" field, for example

 {
  "security": {
    "application": {
      "manage": {
        "applications": [
          "kibana"
        ]
      }
    },
    "roles": {
      "manage": {
        "names": [
          "sales_*"
        ]
      }
    }
  }
}

but it will be simple enough to change.

@tvernum
Copy link
Contributor

tvernum commented Jul 4, 2018

This has evolved a little in implementation, to the point where the role descriptor now looks like this:

{
  "cluster": [ "monitor", "manage_ml" ],
  "policy": {
    "application": {
      "manage": {
        "applications": [ "app1", "app2" ]
      }
    }
  },
  "index": [{
      "names": [ "idx1", "idx2" ],
      "privileges": [ "read", "write" ],
  }],
  "applications": [ {
      "application": "app1"
      "resources": [ "object-123", "object-456" ],
      "privileges": [ "read", "delete" ],
  }]
}

The privileges under policy are always cluster level privileges, so it could make sense to combine them with the "cluster" key. If we weren't concerned with BWC then we could go with something like one of these options:

{
  "cluster": {
    "global" : [ "monitor", "manage_ml" ],
    "application": {
      "manage": {
        "applications": [ "app1", "app2" ]
      }
    }
  }
}
{
  "cluster": {
    "monitor" :  "*",
    "ml" : {
      "manage" : "*"
    },
    "application": {
      "manage": {
        "applications": [ "app1", "app2" ]
      }
    }
  }
}

(I'm ignoring index and application privileges for these examples)

But that's not really an option for a minor - for the Get Role API, users expect "cluster" to be a string array.

So either:

  1. We leave the "limited privileges" as a separate entry in the role, and find a better name than "policy". (Any ideas??)
  2. We create a new key ("cluster_v2" for example's sake, but we'd need something better) in the role definition that supports a structure like the above but lives longside the existing "cluster" key.

From a simplicity point of view option 1 is easier.
Option 2 requires having special handling in the Put Role API to know what to do if the old and new keys are both present, and to translate the new object into the old object as part of the Get Role API.

But, we do need to work out what key to use for the object field, and I don't have any good ideas...

@albertzaharovits
Copy link
Contributor

I prefer option 1. Option 2 sounds too much of a contraption to me. How would you translate the cluster privileges that have been put with the new api, but need to be get in the old format so as not to break bwc?

I have another suggestion though. We already support explicit privileges in the form of cluster:* values. Could we add manage:* as a pattern? That is:

{
  "cluster": [ "monitor", "manage_ml", "manage:app1", "manage:app2" ],
  "index": [{
      "names": [ "idx1", "idx2" ],
      "privileges": [ "read", "write" ],
  }],
  "applications": [ {
      "application": "app1"
      "resources": [ "object-123", "object-456" ],
      "privileges": [ "read", "delete" ],
  }]
}

@clintongormley
Copy link
Contributor

This naming thing is hard... Ideally, I think we will need to move to something like this in the longer term, as it will enable us to be more fine grained with cluster perms:

{
  "cluster": {
    "monitor" :  "*",
    "ml" : {
      "manage" : "*"
    },
    "application": {
      "manage": {
        "applications": [ "app1", "app2" ]
      }
    }
  }
}

But there is no bwc way i can see for how to get there. So option 1 seems to be the only route. Better names than policy? Hmmm, maybe global would work?

jaymode pushed a commit that referenced this issue Jul 24, 2018
This commit introduces "Application Privileges" to the X-Pack security
model.

Application Privileges are managed within Elasticsearch, and can be
tested with the _has_privileges API, but do not grant access to any
actions or resources within Elasticsearch. Their purpose is to allow
applications outside of Elasticsearch to represent and store their own
privileges model within Elasticsearch roles.

Access to manage application privileges is handled in a new way that
grants permission to specific application names only. This lays the
foundation for more OLS on cluster privileges, which is implemented by
allowing a cluster permission to inspect not just the action being
executed, but also the request to which the action is applied.
To support this, a "conditional cluster privilege" is introduced, which
is like the existing cluster privilege, except that it has a Predicate
over the request as well as over the action name.

Specifically, this adds
- GET/PUT/DELETE actions for defining application level privileges
- application privileges in role definitions
- application privileges in the has_privileges API
- changes to the cluster permission class to support checking of request
  objects
- a new "global" element on role definition to provide cluster object
  level security (only for manage application privileges)
- changes to `kibana_user`, `kibana_dashboard_only_user` and
  `kibana_system` roles to use and manage application privileges

Closes #29820
Closes #31559
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Security/Authorization Roles, Privileges, DLS/FLS, RBAC/ABAC
Projects
None yet
Development

No branches or pull requests

5 participants