Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions docs/apps/rbac/for_app_developers.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,35 @@

These instructions are intended for someone applying this system to an existing Django app.
Start with `docs/Installation.md` for the core ansible_base setup.
The app name is dab_rbac, INSTALLED_APPS path is "ansible_base.rbac".

You can choose to use this entirely at the Django model level
- you use roles to delegate permissions to users and teams
- this system will efficiently filter querysets to a certain permission level for a certain user
The 2 main things to enable DAB RBAC are:
1. Add to INSTALLED_APPS in settings, path is "ansible_base.rbac"
2. Register your models with the DAB RBAC `permission_registry`

### DAB Models vs Django Models

DAB RBAC uses specialized models that mirror Django's built-in auth models but are purpose-built for the RBAC system:

- **`DABPermission`** - Mirrors Django's `Permission` model but only tracks permissions for RBAC-registered models and supports remote models
- **`DABContentType`** - Mirrors Django's `ContentType` but with enhanced caching and support for remote models
- **User/Team/Organization Models** - Configurable through settings, defaults to Django or DAB default models

The custom permission and content type models provide:
- Better performance through aggressive caching
- Support for tracking permissions to remote services
- Clean separation from Django's built-in auth system, avoiding conflicts with other apps

### Terminology for Developers

When working with DAB RBAC code, use precise terminology:

- **Role Definition** - Always use "role definition", never just "role" (which could refer to object roles or other concepts)
- **Object Role** - The instantiation of a role definition for a specific object
- **Role Assignment** - The record linking a user/team to a role definition for an object or globally
- **Permission** - An action on a model type (e.g., "change_inventory")
- **Access** - Avoid this term in code; used for AWX `awx/main/access.py` module, overlay logic on top of RBAC evaluations

User-facing interfaces may simplify "role definition" to "role" for usability, but internal code should maintain precision.

### Migrations

Expand Down
189 changes: 133 additions & 56 deletions docs/apps/rbac/for_clients.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,83 @@
## Using DAB RBAC as an API Client

This section tells how to use the API endpoints as a client;
what requests to make and how to build request data.
This section explains how to use the RBAC API endpoints to manage permissions.

You need a server running a Django project that uses this system.
Use test_app in this repo for a demo, see `test_app/README.md` for bootstrap.
The server runs at http://127.0.0.1:8000, and links within that will be referenced here.
Default password for admin user is "admin".
### Prerequisites

### Create Custom Role (Definition)
You need a server running a Django project that uses DAB RBAC.
Use test_app in this repo for a demo (see `test_app/README.md` for setup).
The server runs at http://127.0.0.1:8000, and examples reference this base URL.
Default admin password is "admin".

After logging in to test_app/, you can visit this endpoint to get the role definition API.
### API Workflow Overview

http://127.0.0.1:8000/api/v1/role_definitions/
The RBAC API follows standard REST practices where models have relational dependencies. The typical order for establishing permissions:

Perform an OPTIONS request, and you will find this gives choices for `content_type`.
Out of the choices a single `content_type` needs to be chosen for a role definition.
1. **Types** (`/api/v1/role_metadata/`) - Read-only, managed by app developers
2. **Permissions** - Read-only, created when models are registered
3. **Role Definitions** (`/api/v1/role_definitions/`) - Managed and custom roles
4. **Role Assignments** - User assignments (`/api/v1/role_user_assignments/`) and team assignments (`/api/v1/role_team_assignments/`)

Multiple permissions can be selected, and are accepted in the form of a list.
To find out what permissions are valid for a role definition for a given `content_type`
make a GET to `/api/v1/role_metadata/` and look up the type under "allowed_permissions".
Users interact primarily with steps 3 and 4, while steps 1 and 2 are controlled by the application configuration.

A POST to this endpoint will create a new role definition, example data:
## Step 1: Understanding Available Types and Permissions

### View Available Content Types

Get the available content types and their permissions:

```
GET /api/v1/role_metadata/
```

This returns read-only information configured by app developers:
- Available content types (e.g., "aap.inventory", "shared.organization")
- Permissions allowed for each content type
- No user interaction required with this data

## Step 2: Creating Role Definitions

### Create a Custom Role Definition

```
POST /api/v1/role_definitions/
```

Example request body:

```json
{
"permissions": ["view_inventory"],
"content_type": "aap.inventory",
"name": "View a single inventory",
"description": "custom role"
"description": "Custom role for inventory viewing"
}
```

Name can be any string that's not blank. Description can be any string.
Required fields:
- `permissions`: List of permission codenames (from step 1)
- `content_type`: Content type string (from step 1)
- `name`: Display name for the role definition

Optional fields:
- `description`: Additional context about the role definition

### Managed vs Custom Role Definitions

- **Managed roles**: Created by app developers, cannot be modified via API
- **Custom roles**: Created by users, fully manageable via API

### Assigning a User a Role to an Object
## Step 3: User Role Assignments

Select a role definition from `/api/v1/role_definitions/`, use the id as `role_definition`
and a user from `/api/v1/users/` and use the id as `user`.
Given the type of the role definition, check the available objects of that type,
in this case `/api/v1/inventories/` and obtain the desired id, this will become `object_id`.
### Assign Role Definition to User for Object

With all 3 ids ready, POST to http://127.0.0.1:8000/api/v1/role_user_assignments/
Once you have a role definition, assign it to a user for a specific object:

```
POST /api/v1/role_user_assignments/
```

Example request body:

```json
{
Expand All @@ -51,26 +87,43 @@ With all 3 ids ready, POST to http://127.0.0.1:8000/api/v1/role_user_assignments
}
```

This will give user id=3 view permission to a single inventory id=3, assuming the role definition
referenced is what was created in the last section.
Required fields:
- `role_definition`: ID from `/api/v1/role_definitions/`
- `user`: ID from `/api/v1/users/`
- `object_id`: ID of the target object (e.g., from `/api/v1/inventories/`)

This grants the user the role definition's permissions for only the specified object.

### Assign Role Definition to User Globally

For system-wide permissions, omit the `object_id`:

```json
{
"role_definition": 5,
"user": 3
}
```

The role definition must have `content_type: null` for global assignments.

### Assigning a User as a Member of a Team
## Step 4: Team Role Assignments

While this is possible with the RBAC API, it is not covered here,
because it may come from an external source.
### Team Membership

The "member_team" permission may later be prohibited from use in custom role definitions.
Teams are used to bulk assign permissions to multiple users.

### Assigning a Team a Role to an Object
You give permissions to a team by assigning the team a role definition, usually for a specific object. A single team can be assigned many roles, to many different objects. Teams can in theory be given global roles, but this may be disabled by the application settings.

If you used the test_app bootstrap script, then you will find the user "angry_spud"
is a member of the "awx_devs" team.
If a user has the "member_team" permission to a team, that user automatically inherits all permissions assigned to the team.

Assuming the team id is 2, POST to
### Assign Role Definition to Team

http://127.0.0.1:8000/api/v1/role_team_assignments/
```
POST /api/v1/role_team_assignments/
```

with data
Example request body:

```json
{
Expand All @@ -80,36 +133,60 @@ with data
}
```

This has a similar effect to user assignments, but in this case will give
permissions to all users of a team
This grants the role definition's permissions to all members of the team for the specified object.

## Management Operations

### View Existing Assignments

List assignments for a specific object:

```
GET /api/v1/role_user_assignments/?object_id=3&content_type__model=inventory
GET /api/v1/role_team_assignments/?object_id=3&content_type__model=inventory
```

### Revoke an Assignment

### Viewing Assignments
Delete a specific assignment by ID:

For the single inventory mentioned above, it is possible to view the existing permission
assignments directly to that object.
```
DELETE /api/v1/role_user_assignments/1/
```

GET
This removes the assignment and all permissions it granted.

http://127.0.0.1:8000/api/v1/role_team_assignments/?object_id=3&content_type__model=inventory
If you remove an assignment that a team has, all members to that team will lose that permission.

http://127.0.0.1:8000/api/v1/role_user_assignments/?object_id=3&content_type__model=inventory
## Organization-Level Permissions

### Revoking an Assignment
### Assigning Organization-Wide Permissions

From any of the assignment lists, the user can select an assignment to revoke.
Follow the "url" in the serializer from either user or team assignment lists.
To grant permissions to all objects within an organization:

DELETE http://127.0.0.1:8000/api/v1/role_user_assignments/1/
1. **Create an organization-level role definition:**
```json
{
"permissions": ["view_inventory", "change_inventory"],
"content_type": "shared.organization",
"name": "Organization Inventory Manager"
}
```

Will undo everything related to that assignment.
The user or team's users will lose permission that was granted by the object-role-assignment.
2. **Assign to user/team using organization ID:**
```json
{
"role_definition": 4,
"object_id": 1, // organization ID
"user": 3
}
```

### Assigning Organization Permission
This grants the specified permissions to all inventories within organization ID 1.

In the case of inventory, its parent object is its organization.
Instead of giving permission to a single inventory, you can use roles to give
permission to all inventories inside of an organization.
## Error Handling

The difference in the above steps are that
- when creating a custom role definition the `content_type` would be "shared.organization"
- when creating the assignment, the `object_id` would be the id of an organization
Common API errors:
- **400 Bad Request**: Invalid role definition/object/user combination
- **403 Forbidden**: Insufficient permissions to create assignment (you need "change" permission to the object to create role assignments)
- **404 Not Found**: Referenced object does not exist
Loading
Loading