# RBAC: Users, Roles & Policies

Starting at version 7.2.0, CloudAPI supports Role Based Access Control (RBAC), which means that [accounts](https://apidocs.joyent.com/cloudapi/#account) can have multiple users and roles associated with them.

While the behaviour of the [main account](https://apidocs.joyent.com/cloudapi/#GetAccount) remains the same, including the [SSH keys](https://apidocs.joyent.com/cloudapi/#keys) associated with it, it's now possible to have multiple [Users](https://apidocs.joyent.com/cloudapi/#users) subordinate to the main account. Each of these users have a different set of [SSH Keys](https://apidocs.joyent.com/cloudapi/#sshKeys). Both the users and their associated SSH keys have the same format as the main account object (and the keys associated with it).

It's worth mentioning that the `login` for an account's users must be different only between the users of that account, not globally. We could have an account with login *"mark"*, another account "exampleOne" with a user with login "mark", another account "exampleTwo" with another user with login "mark", and so forth.

These account users can additionally be organized using [Roles](https://apidocs.joyent.com/cloudapi/#roles):

```
{
  "id": "ff578c1f-bad5-4d3c-8880-2f76745f2511",
  "name": "devs",
  "members": [
    {
      "type": "subuser",
      "id": "985e0ed4-9994-4303-8c43-6c92b7988167",
      "login": "bob",
      "default": true
    },
    {
      "type": "subuser",
      "id": "0cc38461-787a-4c05-a3f3-352a4d55541f",
      "login": "fred",
      "default": false
    }
  ],
  "policies": [
    {
      "id": "2104c53f-2e33-4393-9320-a6521d5ef2dc",
      "name": "createMachine"
    },
    {
      "id": "e8bdd555-eef0-4c1c-83be-93c443b59e3e",
      "name": "restart instances"
    }
  ]
}
```

Each role can have an arbitrary set of [Policies](https://apidocs.joyent.com/cloudapi/#policies):

```
{
  "name": "restart instances",
  "id": "e8bdd555-eef0-4c1c-83be-93c443b59e3e",
  "rules": [
    "CAN rebootmachine if requesttime::time > 07:30:00 and requesttime::time < 18:30:00 and requesttime::day in (Mon, Tue, Wed, THu, Fri)",
    "CAN stopmachine",
    "CAN startmachine"
  ],
  "description": "This is completely optional"
}
```

The `rules` in policies are used for the access control of an account's users. These rules use [Aperture](https://github.com/joyent/node-aperture) as the policy language, and are described in detail in the next section.

Our recommendation is to limit each policy's set of rules to a very scoped collection, and then add one or more of these policies to each group. This aids easily reusing existing policies for one or more roles, allowing fine-grained definition of each role's abilities.

### Rules definition for access control <a href="#rules-definition-for-access-control" id="rules-definition-for-access-control"></a>

As mentioned earlier, the policies' rules use [Aperture Policy Language](https://github.com/joyent/node-aperture#policy-language), with the following *basic format*:

`<principals> CAN <actions> <resources> WHEN <conditions>`.

You should refer to the [Aperture documentation](https://github.com/joyent/node-aperture) for the complete details about the different possibilities when defining new rules. This section will only cover a limited set strictly related to CloudAPI's usage.

In the case of CloudAPI, `<principal>` will be always the user performing the HTTP request. Likewise, `<resource>` will always be the URL of such request, for example `/:account/machines/:instance_id`.

We add one or more roles to a resource to explicitly define the active roles a user trying to access a given resource must have. Therefore, we don't need to specify `<principal>` in our rules, since it'll always be defined by the role-tags of the resource the user is trying to get access to. For the same reason, we don't need to specify `<resource>` in our rules.

Therefore, CloudAPI's Aperture rules have the format:

```
    CAN <actions> WHEN <conditions>
```

By default, the access policy will `DENY` any attempt made by any account user to access a given resource, unless:

* that resource is tagged with a role
* that role is active
* that role has a policy
* that policy contains a rule which explicity `GRANTS` access to that resource

For example, a user with an active role `read`, which includes a policy rule like `CAN listmachines and getmachines` will not get access to resources like `/:account/machines` or `/:account/machines/:instance_id` unless these resources are *role-tagged* with the role `read` too.

Additionally, given that the `<actions>` included in the policy rule are just `listmachines` and `getmachine`, the user will be able to retrieve an instance's details provided by the [GetMachine](https://apidocs.joyent.com/cloudapi/#GetMachine) action, but will not be able to perform any other instance actions (like [StopMachine](https://apidocs.joyent.com/cloudapi/#StopMachine)). However, if the role has a rule including that `<action>` (like StopMachine), or the user has an additional role which includes that rule, then the user can invoke that action too.

As an aside, the active roles of a user are set by the `default_members` attribute in a role. If three different roles contain the "john" user (amongst others) in their default-members list, then the "john" user will have those three roles as active roles by default. This can be overridden by passing in `?as-role=<comma-separated list of role names>` as part of the URL, or adding a --role flag when using a node-smartdc command; provided that each role contains that user in their `members` list, then those roles are set as the currently-active roles for a request instead.

For more details on how Access Control works for both CloudAPI and Manta, please refer to [Role Based Access Control](https://docs.joyent.com/jpc/rbac/) documentation.

#### An important note about RBAC and certain reads after writes <a href="#an-important-note-about-rbac-and-certain-reads-after-writes" id="an-important-note-about-rbac-and-certain-reads-after-writes"></a>

CloudAPI uses replication and caching behind the scenes for user, role and policy data. This implies that API reads after a write on these particular objects can be up to several seconds out of date.

For example, when a user is created, CloudAPI returns both a user object (which is up to date), and a location header indicating where that new user object actually lives. Following that location header may result in a 404 for a short period.

As another example, if a policy is updated, the API call will return a policy object (which is up to date), but GETing that URL again may temporarily return a outdated object with old object details.

For the time being, please keep in mind that user, role and policy creation/updates/deletion may potentially take several seconds to settle. They have eventual consistency, not read-after-write.<br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mnx.io/cloudapi/rbac-users-roles-and-policies.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
