--- layout: docs page_title: Permissions description: |- Boundary's permissions model --- # Permissions in Boundary ## Overview Boundary's permissions model is a composable, RBAC, allow-only model that attempts to marry flexibility with usability. This page discusses the permission model's fundamental concepts, provides examples of the specific forms of allowed grants, and contains a table that acts as an easy cheat sheet to help those new to its grant syntax with crafting roles. Boundary's [domain model](/docs/concepts/domain-model) is based on resource types. These can be implemented directly, such as with targets, or they can be abstract types that are implemented by concrete types within the system. As an example of the latter, a host catalog is an abstract type and a Static host catalog is a concrete type. From a permissions standpoint, all actions take place against directly implemented or abstract types. There may be actions that are only implemented by some concrete types (e.g., not all `auth-method` implementations will support a `change-password` action), but the permissions model still defines these capabilities at the abstract type level. This helps keep the overall system relatively simple and predictable. At a very high level, permissions within Boundary are declared via grant strings and mapped to users via roles. ### Grant Strings A grant string has a form similar to: `id=;type=;actions=;output_fields=` Each grant string is a mapping that describes a resource or set of resources and the permissions that should be granted on them. There are currently two types of selectors: - An `id` field that indicates a specific resource or a wildcard to match all - A `type` field that indicates a specific resource type or a wildcard to match all; this might also be used to grant permissions on collections of resources Selectors are used to indicate which resources on which the grant should apply, using specific IDs or wildcard IDs and type selectors. (The acceptable grant string formats are detailed later on this page.) Additionally, there are two types of assigned permissions: - An `actions` field indicating which actions to allow the client to perform on the resources matched by `id` and `type` - An `output_fields` field indicating which top-level fields to return in the response (0.2.1+) Grant strings can be supplied via a human-friendly string syntax or via JSON. ### Roles Roles map grant strings to _principals_, currently users and groups. Every role assigns grants within a specific scope: either the scope in which the role exists, or a scope that is a child of the scope in which the role exists, controlled by the role's "grant scope ID" value When a request is made, the scope in which to discover grants is either provided by the client (if against a resource collection itself) or is looked up using the resource's ID. This scope ID, along with the user's ID and the IDs of the groups the user belongs to, controls which roles are fetched to provide grants for the request. A role provides grants for a request if the grant scope ID matches the request's scope ID and one or more of the following are true: - The user's ID is contained in the principal IDs set on the role - A group the user belongs to is contained in the principal IDs set on the role - The user is logged in and the `u_auth` user is contained in the principal IDs set on the role - The role contains the `u_anon` user in the in the principal IDs set on the role Roles are composable; a user's final set of grants will be composed of grants that originate from all matching roles.a ## Assignable Permissions Resources identified by the ID/Type selectors have permissions granted to the user in the form of actions and visibility (via `output_fields`). Each of these is detailed in the subsections below. ### Actions Actions convey the ability to perform some action against a resource or collection. Many of these are common CRUD actions (`create`, `read`, `update`, `delete`) but many resources also specify actions specific to their type; for instance, a `target` has an `authorize-session` action to allow you to request making a connection to that target, and `auth-method` resources have an `authenticate` action to allow you to authenticate to Boundary. For the most part these are straightforward, however there are a couple of special cases to know. #### Subactions Starting in Boundary 0.1.6, some subactions are supported. These actions have a format `top_level_action:subaction`, such as `read:self`. Being granted the top level action infers being granted all subactions. Thus, if a grant conveys `read`, it also matches the API actions `read` and `read:self`. However, if a grant conveys `read:self`, it will match the API action `read:self` but will not match `read`. #### The `no-op` Action Starting in Boundary 0.2.1 there is an action that can be granted called `no-op`. As might be apparent, `no-op` is not used for any real action in Boundary; the purpose of this action is for listing visibility. Boundary only shows resources in the output of a `list` action for which a user has at least one granted action. Thus, without `no-op`, in order for a resource to be visible in a `list` action, a different action such as `read` would have to be granted to a user. This could result in exposing more information than desired, especially in the case of listing scopes and authentication methods so that users can perform initial authentication to Boundary (that is, granting access to `u_anon`). By granting the `no-op` action to users, they can see the resources in the output of a list command without needing other capability grants as well. ### Output Fields Starting in Boundary 0.2.1, grant strings can contain an `output_fields` field. This allows fine-grained control over visibility of data returned to users. In many cases, `output_fields` will not need to be set directly. However, an example in the form of some history helps provide some context as to when this might be useful. In Boundary 0.2.0, we restricted the set of fields returned for some `list` calls (those on the `scopes` and `auth-methods` collections) to a small set if the user was the anonymous user `u_anon`. Although default behavior in Boundary was to display all resource fields when listing, because the default was also to allow anonymous access to perform `list` on scopes and auth methods (in order to discover auth methods and then authenticate to them), returning all configuration information for all scopes and auth methods felt like it was publicly disclosing more information to users than might be desired. At the same time, this was not an ideal solution for two reasons: 1. There is no one-size-fits-all security policy, and what we thought were reasonable defaults may not work in all situations 2. It made the scopes and auth methods listing behavior work differently from any other `list` action, which is not ideal As a result, we decided to approach this problem the same way we normally try to within Boundary: set resonable defaults, but give the administrator ultimate control. The resulting behavior is as follows: `output_fields` references the field names of the JSON object response, composes just like other parts of the RBAC model, and are action-specific. That is, a grant like: `id=*;type=auth-methods;actions=list,no-op;output_fields=scope_id,name,description` will, if all by itself, result in those three identified output fields applying to `list` (and `no-op`) actions for all auth methods in the scope. Thus when performing a `list`, each item returned will have only those three fields populated. Any other actions (like `read` or `update`) are unaffected and will use defaults. A grant like: `id=*;type=auth-methods;output_fields=id` will, if all by itself, result in _any_ action against auth methods in the scope having only `id` returned. However, if both of the above grants are included, since grants are composable the final set of output fields will be `id,scope_id,name,description` for `list` (and `no-op`) actions, and `id` for all other actions. If, after the grants are composed for a given request, none of the grants applicable to the resource/action contain `output_fields` definitions, the defaults are used. These defaults are implemented using internal values for `output_fields` and vary based on whether the user is the anonymous user: - If the user is the anonymous user, a useful but restricted set of fields is returned. This includes `id`, `scope_id`, `scope`, `name`, `description`, and a few more. - If the user is any authenticated user, the full set of fields is returned To think about it a different way, empty `output_fields`, after grant composition, is equivalent to using Boundary's default; however the moment that grants start specifying output fields, it is composed from an empty set and thus nothing is contained unless explicitly specified. (An actual empty set is not currently supported, as we don't perform validation on the values given. However, this means setting `output_fields=none` is functionally equivalent!) #### Output Fields and Monitoring As another example, it's possible to get creative and use `output_fields` to allow services to keep tabs on various aspects of the system for monitoring purposes without needing to provision Boundary tokens to those services. For instance, by allowing access to list users to `u_anon` but restrict the set of fields to `id` only, a monitoring system could watch and alert if more users than expected are showing up in the system, while the IDs themselves are not really meaningful to any other caller that accesses the same endpoint. This will be especially useful once we introduce the ability to have CIDR restrictions against roles and/or grants, which are planned but not currently scheduled, as you can only have these grants apply to specific internal services, along with restricting the data that is returned for those services that do match. ## Permission Grant Formats Because of the aforementioned properties of the permissions model, grants are relatively simple. All grants take one of four forms. These examples use the canonical string syntax; the JSON equivalents are simply an object with a string `id` value, a string `type` value, a string array `actions` value, and a string array `output_fields` value. ~> `output_fields` is omitted in most example below for brevity but are valid in all of them. It is also valid in each case to omit `actions` and specify _only_ `output_fields`. ### ID Only This is the simplest form: for a given specific resource, allow these actions. Example: `id=hsst_1234567890;actions=read,update` This grants `read` and `update` actions to that single resource. It is invalid to specify `create` or `list` as actions in this format, as this format explicitly identifies a resource, whereas those actions operate exclusively on collections. ### Type Only For a given type, allow these actions. Example: `type=host-catalog;actions=create,list` Because type specifies only a collection as opposed to specific resources within that collection, only collection actions are allowed in this format. Currently, this is `create` and `list`. There is one additional restriction: this is only valid against "top-level" resource types, which currently are: - Auth Methods - Auth Tokens - Groups - Host Catalogs - Roles - Scopes - Sessions - Targets - Users The reason for this is that other types of resources are contained within one of these resource types; for instance, accounts are instantiated within an auth method. To specify actions against those, you must also specify to which specific containing resource you want the grants to apply. This can be done with the pinned format shown below. ### Pinned ID This form "pins" actions to a non-top-level type within a specific ID. It's easiest to explain with an example: `id=hcst_1234567890;type=host-set;actions=create,read,update` In this example, the user is able to create, read, or update host sets within the scope, but _only the host sets belonging to host catalog hcst_1234567890_. Pinning is essentially a way to use top-level resources to create mini permission boundaries for their subordinate resources. ### Wildcard ID Various wildcard possibilities are allowed: #### Wildcard ID When just the ID is `*`, it matches all IDs of the given type. This can be used with both top-level resource types and not. Example: `id=*;type=host-set;actions=create,read,update,set-hosts` #### Wildcard Type For non-top-level resources with pinned IDs, the `type` can be a wildcard: `id=hcst_1234567890;type=*;actions=create,read,update` This would allow `create`, `read`, and `update` actions for all types of subordinate resources (in this case host sets and hosts) underneath the host catalog with ID `hcst_1234567890`. #### Wildcard ID and Type If ID and type are both a wildcard, the grant is essentially a catch-all that will match any resource of any type within the scope and allow the given actions. `id=*;type=*;actions=read,list` #### Wildcard ID, Type, and Actions Finally, ID, type, and actions can all be wildcards: `id=*;type=*;actions=*` Such a grant is essentially a full administrator grant for a scope. ### Templates A few template possibilities exist, which will at grant evaluation time substitute the given value into the ID field of the grant string: - `{{account.id}}`: The substituted value is the account ID associated with the token used to perform the action. As an example, `id={{account.id}};actions=read,change-password"` is one of Boundary's default grants to allow users that have authenticated with the Password auth method to change their own password. - `{{user.id}}`: The substituted value is the user ID associated with the token used to perform the action. ## Resource Table The following table works as a quick cheat-sheet to help you manage your permissions. Note that it's not exhaustive; for brevity it does _not_ show wildcard or templated grant strings. Additionally, this does not include available output fields; see the [service documentation](https://www.boundaryproject.io/api-docs) for guidance.
Resource Type Applicable Scopes API Endpoint Parameters into Permissions Engine Available Actions / Examples
Account
  • Global
  • Org
/accounts
  • Type
    • account
  • create: Create an account
    • type=<type>;actions=create
  • list: List accounts
    • type=<type>;actions=list
/accounts/<id>
  • ID
    • <id>
  • Pin
    • <auth-method-id>
  • Type
    • account
  • read: Read an account
    • id=<id>;actions=read
    • id=<pin>;type=<type>;actions=read
  • update: Update an account
    • id=<id>;actions=update
    • id=<pin>;type=<type>;actions=update
  • delete: Delete an account
    • id=<id>;actions=delete
    • id=<pin>;type=<type>;actions=delete
  • set-password: Set a password on an account, without requiring the current password
    • id=<id>;actions=set-password
    • id=<pin>;type=<type>;actions=set-password
  • change-password: Change a password on an account given the current password
    • id=<id>;actions=change-password
    • id=<pin>;type=<type>;actions=change-password
Auth Method
  • Global
  • Org
/auth-methods
  • Type
    • auth-method
  • create: Create an auth method
    • type=<type>;actions=create
  • list: List auth methods
    • type=<type>;actions=list
/auth-methods/<id>
  • ID
    • <id>
  • Type
    • auth-method
  • read: Read an auth method
    • id=<id>;actions=read
  • update: Update an auth method
    • id=<id>;actions=update
  • delete: Delete an auth method
    • id=<id>;actions=delete
  • authenticate: Authenticate to an auth method
    • id=<id>;actions=authenticate
Auth Token
  • Global
  • Org
/auth-tokens
  • Type
    • auth-token
  • list: List auth tokens
    • type=<type>;actions=list
/auth-tokens/<id>
  • ID
    • <id>
  • Type
    • auth-token
  • read: Read an auth token
    • id=<id>;actions=read
  • delete: Delete an auth token
    • id=<id>;actions=delete
Group
  • Global
  • Org
  • Project
/groups
  • Type
    • group
  • create: Create a group
    • type=<type>;actions=create
  • list: List groups
    • type=<type>;actions=list
/groups/<id>
  • ID
    • <id>
  • Type
    • group
  • read: Read a group
    • id=<id>;actions=read
  • update: Update a group
    • id=<id>;actions=update
  • delete: Delete a group
    • id=<id>;actions=delete
  • add-members: Add members to a group
    • id=<id>;actions=add-members
  • set-members: Set the full set of members on a group
    • id=<id>;actions=set-members
  • remove-members: Remove members from a group
    • id=<id>;actions=remove-members
Host
  • Project
/hosts
  • Type
    • host
  • create: Create a host
    • type=<type>;actions=create
  • list: List hosts
    • type=<type>;actions=list
/hosts/<id>
  • ID
    • <id>
  • Pin
    • <host-catalog-id>
  • Type
    • host
  • read: Read a host
    • id=<id>;actions=read
    • id=<pin>;type=<type>;actions=read
  • update: Update a host
    • id=<id>;actions=update
    • id=<pin>;type=<type>;actions=update
  • delete: Delete a host
    • id=<id>;actions=delete
    • id=<pin>;type=<type>;actions=delete
Host Catalog
  • Project
/host-catalogs
  • Type
    • host-catalog
  • create: Create a host catalog
    • type=<type>;actions=create
  • list: List host catalogs
    • type=<type>;actions=list
/host-catalogs/<id>
  • ID
    • <id>
  • Type
    • host-catalog
  • read: Read a host catalog
    • id=<id>;actions=read
  • update: Update a host catalog
    • id=<id>;actions=update
  • delete: Delete a host catalog
    • id=<id>;actions=delete
Host Set
  • Project
/host-sets
  • Type
    • host-set
  • create: Create a host set
    • type=<type>;actions=create
  • list: List host sets
    • type=<type>;actions=list
/targets/<id>
  • ID
    • <id>
  • Pin
    • <host-catalog-id>
  • Type
    • host-set
  • read: Read a host set
    • id=<id>;actions=read
    • id=<pin>;type=<type>;actions=read
  • update: Update a host set
    • id=<id>;actions=update
    • id=<pin>;type=<type>;actions=update
  • delete: Delete a host set
    • id=<id>;actions=delete
    • id=<pin>;type=<type>;actions=delete
  • add-hosts: Add hosts to a host-set
    • id=<id>;actions=add-hosts
    • id=<pin>;type=<type>;actions=add-hosts
  • set-hosts: Set the full set of hosts on a host set
    • id=<id>;actions=set-hosts
    • id=<pin>;type=<type>;actions=set-hosts
  • remove-hosts: Remove hosts from a host set
    • id=<id>;actions=remove-hosts
    • id=<pin>;type=<type>;actions=remove-hosts
Role
  • Global
  • Org
  • Project
/roles
  • Type
    • role
  • create: Create a role
    • type=<type>;actions=create
  • list: List roles
    • type=<type>;actions=list
/roles/<id>
  • ID
    • <id>
  • Type
    • role
  • read: Read a role
    • id=<id>;actions=read
  • update: Update a role
    • id=<id>;actions=update
  • delete: Delete a role
    • id=<id>;actions=delete
  • add-principals: Add principals to a role
    • id=<id>;actions=add-principals
  • set-principals: Set the full set of principals on a role
    • id=<id>;actions=set-principals
  • remove-principals: Remove principals from a role
    • id=<id>;actions=remove-principals
  • add-grants: Add grants to a role
    • id=<id>;actions=add-grants
  • set-grants: Set the full set of grants on a role
    • id=<id>;actions=set-grants
  • remove-grants: Remove grants from a role
    • id=<id>;actions=remove-grants
Scope
  • Global
  • Org
/scopes
  • Type
    • scope
  • create: Create a scope
    • type=<type>;actions=create
  • list: List scopes
    • type=<type>;actions=list
/scopes/<id>
  • ID
    • <id>
  • Type
    • scope
  • read: Read a scope
    • id=<id>;actions=read
  • update: Update a scope
    • id=<id>;actions=update
  • delete: Delete a scope
    • id=<id>;actions=delete
Session
  • Project
/sessions
  • Type
    • session
  • list: List sessions
    • type=<type>;actions=list
/session/<id>
  • ID
    • <id>
  • Type
    • session
  • read: Read a session
    • id=<id>;actions=read
  • cancel: Cancel a session
    • id=<id>;actions=cancel
  • read:self: Read a session, which must be associated with the calling user
    • id=*;type=session;actions=read:self
  • cancel:self: Cancel a session, which must be associated with the calling user
    • id=*;type=session;actions=cancel:self
Target
  • Project
/targets
  • Type
    • target
  • create: Create a target
    • type=<type>;actions=create
  • list: List targets
    • type=<type>;actions=list
/targets/<id>
  • ID
    • <id>
  • Type
    • target
  • read: Read a target
    • id=<id>;actions=read
  • update: Update a target
    • id=<id>;actions=update
  • delete: Delete a target
    • id=<id>;actions=delete
  • add-host-sets: Add host sets to a target
    • id=<id>;actions=add-host-sets
  • set-host-sets: Set the full set of host sets on a target
    • id=<id>;actions=set-host-sets
  • remove-host-sets: Remove host sets from a target
    • id=<id>;actions=remove-host-sets
  • authorize-session: Authorize a session via the target
    • id=<id>;actions=authorize-session
User
  • Global
  • Org
/users
  • Type
    • user
  • create: Create a user
    • type=<type>;actions=create
  • list: List users
    • type=<type>;actions=list
/users/<id>
  • ID
    • <id>
  • Type
    • user
  • read: Read a user
    • id=<id>;actions=read
  • update: Update a user
    • id=<id>;actions=update
  • delete: Delete a user
    • id=<id>;actions=delete
  • add-accounts: Add accounts to a user
    • id=<id>;actions=add-accounts
  • set-accounts: Set the full set of accounts on a user
    • id=<id>;actions=set-accounts
  • remove-accounts: Remove accounts from a user
    • id=<id>;actions=remove-accounts