mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-10-04 09:40:12 +03:00
docs: update RBAC user isolation roadmap and add design memory
Updated the roadmap document to reflect the implemented three-step permission check logic in the feature/simple-user-isolation branch. Added comprehensive design memory documenting: - Core problem and design conflicts - Three-step permission check implementation - Key design decisions and advantages - Use cases and scenarios - Design evolution process
This commit is contained in:
parent
ee36a9aec2
commit
9e5423f3f1
202
.claude/memory/rbac-user-isolation-design.md
Normal file
202
.claude/memory/rbac-user-isolation-design.md
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
---
|
||||||
|
name: rbac-user-isolation-design
|
||||||
|
description: GNS3 RBAC user isolation design and implementation thought process
|
||||||
|
metadata:
|
||||||
|
type: project
|
||||||
|
---
|
||||||
|
|
||||||
|
## RBAC User Isolation Design Summary
|
||||||
|
|
||||||
|
### Core Problem
|
||||||
|
GNS3 3.0 has a complete RBAC framework (ACE + Role + Privilege), but lacks user isolation implementation, causing users to see resources they shouldn't have access to.
|
||||||
|
|
||||||
|
### Design Conflict
|
||||||
|
Traditional RBAC's **path permission model** fundamentally conflicts with **user data isolation**:
|
||||||
|
- **Path permission model**: Controls which paths users can access (e.g., `/projects`)
|
||||||
|
- **User data isolation**: Controls which specific resources users can access (e.g., alice's project vs bob's project)
|
||||||
|
|
||||||
|
### Final Implementation Approach
|
||||||
|
|
||||||
|
#### Three-Step Permission Check Logic
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Step 1: ACE check - basic access permission
|
||||||
|
# Get list of projects user has ACE for
|
||||||
|
ace_projects = [p for p in all_projects() if user_has_ace(p, "Project.Audit")]
|
||||||
|
|
||||||
|
# Step 2: Filter ace_projects by created_by - user's own projects
|
||||||
|
# Key: Project sharing is only available through resource pools
|
||||||
|
user_projects = [p for p in ace_projects if p.created_by == user.username]
|
||||||
|
|
||||||
|
# Step 3: Resource pool projects
|
||||||
|
# Projects shared through resource pools
|
||||||
|
pool_projects = [p for p in pool_projects]
|
||||||
|
|
||||||
|
final_projects = user_projects + pool_projects
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Design Decisions
|
||||||
|
|
||||||
|
#### 1. ACE vs created_by Relationship
|
||||||
|
- **ACE for basic access control**: Whether user can access the system
|
||||||
|
- **created_by for user isolation**: Which specific resources user can access
|
||||||
|
- **Step 2 filtering is critical**: Even with broad ACE, created_by filtering ensures user isolation
|
||||||
|
|
||||||
|
#### 2. Project Sharing Mechanism
|
||||||
|
- **Project sharing only through resource pools**: Cannot configure ACE directly for specific projects
|
||||||
|
- **Avoids complexity of direct ACE sharing**: Prevents permission configuration chaos
|
||||||
|
|
||||||
|
#### 3. Broad ACE Fault Tolerance
|
||||||
|
```
|
||||||
|
Even with configuration: ACE: Users group + User role + "/" + propagate: True
|
||||||
|
Result: Users still only see projects they created
|
||||||
|
Reason: Step 2 created_by filtering removes other users' projects
|
||||||
|
```
|
||||||
|
|
||||||
|
### Problems Solved
|
||||||
|
|
||||||
|
#### Problem 1: Missing User Isolation
|
||||||
|
- **Issue**: All users can see all projects
|
||||||
|
- **Solution**: Filter by created_by to implement user isolation
|
||||||
|
|
||||||
|
#### Problem 2: Broad ACE Breaking Isolation
|
||||||
|
- **Issue**: `path: "/" + propagate: true` breaks user isolation
|
||||||
|
- **Solution**: Step 2 created_by filtering ensures user isolation even with broad ACE
|
||||||
|
|
||||||
|
#### Problem 3: Permission Check Order Conflicts
|
||||||
|
- **Issue**: seen mechanism blocks subsequent checks
|
||||||
|
- **Solution**: Remove seen mechanism, use pipeline-style filtering
|
||||||
|
|
||||||
|
### Technical Details
|
||||||
|
|
||||||
|
#### API Layer Permission Check
|
||||||
|
```python
|
||||||
|
@router.get("/projects") # Note: no has_privilege decorator
|
||||||
|
async def get_projects(current_user: schemas.User = Depends(get_current_active_user)):
|
||||||
|
# Permission checks in business logic
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Duplicate Prevention
|
||||||
|
- No seen_project_ids mechanism
|
||||||
|
- Natural duplicate prevention through pipeline filtering
|
||||||
|
|
||||||
|
#### Performance Considerations
|
||||||
|
- ACE check: O(n), where n is total projects
|
||||||
|
- created_by filtering: O(m), where m is ace_projects count
|
||||||
|
- Resource pool check: O(k), where k is pool project count
|
||||||
|
|
||||||
|
### Use Cases
|
||||||
|
|
||||||
|
#### Scenario 1: Personal Use
|
||||||
|
```
|
||||||
|
alice creates project → alice only sees alice's projects ✅
|
||||||
|
bob creates project → bob only sees bob's projects ✅
|
||||||
|
No extra configuration needed, automatic user isolation
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Scenario 2: Team Collaboration
|
||||||
|
```
|
||||||
|
Admin creates resource pool → adds projects → team members can access
|
||||||
|
alice creates project → alice still sees her own projects ✅
|
||||||
|
Team sharing + user isolation coexist
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Scenario 3: Broad ACE Configuration
|
||||||
|
```
|
||||||
|
ACE: Users group + "/" + propagate: True
|
||||||
|
alice still only sees alice's projects ✅
|
||||||
|
User isolation unaffected by ACE configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Design Principles
|
||||||
|
|
||||||
|
#### 1. Separation of Concerns
|
||||||
|
- **Basic access permission**: Controlled by ACE
|
||||||
|
- **Data ownership**: Controlled by created_by
|
||||||
|
- **Team sharing**: Controlled by resource pools
|
||||||
|
|
||||||
|
#### 2. Defensive Design
|
||||||
|
- User isolation remains effective even with improper ACE configuration
|
||||||
|
- Secure by default: users only see their own resources
|
||||||
|
|
||||||
|
#### 3. Simplicity
|
||||||
|
- Avoid complex seen mechanisms and mutual exclusion logic
|
||||||
|
- Clear pipeline-style check order
|
||||||
|
|
||||||
|
### Relationship with Original ACE System
|
||||||
|
|
||||||
|
#### Preserved Components
|
||||||
|
- ✅ ACE framework (permission check mechanism)
|
||||||
|
- ✅ Role and privilege definitions
|
||||||
|
- ✅ Resource pool functionality
|
||||||
|
|
||||||
|
#### Improved Components
|
||||||
|
- ✅ Added user isolation (created_by filtering)
|
||||||
|
- ✅ Clarified project sharing mechanism (only through resource pools)
|
||||||
|
- ✅ Simplified permission check logic
|
||||||
|
|
||||||
|
#### Removed Components
|
||||||
|
- ❌ Removed `/projects` path privilege check
|
||||||
|
- ❌ Removed complex seen_project_ids mechanism
|
||||||
|
- ❌ Avoided "can see all non-pool projects" privilege leak
|
||||||
|
|
||||||
|
### Implementation Details
|
||||||
|
- **Main modification**: `gns3server/api/routes/controller/projects.py`
|
||||||
|
- **Function**: `get_projects()`
|
||||||
|
- **Branch**: `feature/simple-user-isolation`
|
||||||
|
- **Base branch**: `upstream/3.1`
|
||||||
|
|
||||||
|
### Key Commits
|
||||||
|
1. Implemented basic created_by filtering
|
||||||
|
2. Implemented three-layer permission check (with logic issues)
|
||||||
|
3. Fixed to correct three-step check logic
|
||||||
|
|
||||||
|
### Design Evolution Process
|
||||||
|
|
||||||
|
#### Phase 1: Simple created_by Filtering
|
||||||
|
```python
|
||||||
|
user_projects = [p for p in all_projects() if p.created_by == user.username]
|
||||||
|
```
|
||||||
|
**Issue**: Didn't integrate with ACE system
|
||||||
|
|
||||||
|
#### Phase 2: Three-Layer Check (Wrong Version)
|
||||||
|
```python
|
||||||
|
# Used seen_project_ids mechanism
|
||||||
|
# Issue: Broad ACE breaks user isolation
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Phase 3: Three-Step Check (Correct Version)
|
||||||
|
```python
|
||||||
|
# Step 1: ACE check
|
||||||
|
# Step 2: Filter ace_projects by created_by
|
||||||
|
# Step 3: Resource pools
|
||||||
|
```
|
||||||
|
**Solution**: User isolation works even with broad ACE
|
||||||
|
|
||||||
|
### Relationship with RBAC Roadmap
|
||||||
|
This implementation addresses items mentioned in the roadmap:
|
||||||
|
- **Phase 1 (MVP)**: Basic project isolation implementation
|
||||||
|
- **Auto-ACE on create**: Still needs to be implemented separately
|
||||||
|
- **Template isolation**: Can use same design pattern
|
||||||
|
|
||||||
|
### Unsolved Issues
|
||||||
|
|
||||||
|
1. **Auto-ACE on project creation**: Part of roadmap Phase 1
|
||||||
|
2. **Template and image isolation**: Can apply same design pattern
|
||||||
|
3. **Default ACE configuration**: Need reasonable default permissions for Users group
|
||||||
|
|
||||||
|
### Design Limitations
|
||||||
|
|
||||||
|
1. **Project sharing only through resource pools**: No direct ACE configuration for sharing
|
||||||
|
2. **ACE configuration required**: Users need basic ACE to access system
|
||||||
|
3. **Performance considerations**: ACE check queries database for each project
|
||||||
|
|
||||||
|
### Future Improvement Directions
|
||||||
|
|
||||||
|
1. **Auto-create ACE**: Automatically add ACE for creator when creating projects
|
||||||
|
2. **Default ACE strategy**: Configure reasonable default permissions for Users group
|
||||||
|
3. **Performance optimization**: Cache ACE check results to reduce database queries
|
||||||
|
|
||||||
|
This design achieves effective user isolation while maintaining RBAC system integrity, and solves the problem of broad ACE configurations breaking isolation.
|
||||||
|
|
||||||
|
**Key insight**: The Step 2 created_by filtering is the critical innovation that allows ACE and user isolation to coexist properly.
|
||||||
@ -8,13 +8,13 @@ GNS3 3.0 ships with a complete RBAC framework (ACE + Role + Privilege models), b
|
|||||||
- List endpoints return unfiltered results
|
- List endpoints return unfiltered results
|
||||||
- Two GET endpoints have RBAC checks bypassed via FIXME
|
- Two GET endpoints have RBAC checks bypassed via FIXME
|
||||||
|
|
||||||
This document tracks the incremental work to close those gaps. Each phase is independent and deployable.
|
**This document has been updated to reflect the implemented solution in `feature/simple-user-isolation` branch.**
|
||||||
|
|
||||||
## Current State
|
## Current State
|
||||||
|
|
||||||
| Resource | Route Check | List Filtering | Auto-ACE on Create | ACE Cleanup on Delete |
|
| Resource | Route Check | List Filtering | Auto-ACE on Create | ACE Cleanup on Delete |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| Project | `Project.Audit/Modify/Allocate` | Partial — pool isolation exists but non-pool projects leak | **Missing** | Done |
|
| Project | `Project.Audit/Modify/Allocate` | **Implemented** — Three-step filtering | **Not needed** | Done |
|
||||||
| Template | `Template.Audit` **FIXME** | None — all templates returned | **Missing** | Done |
|
| Template | `Template.Audit` **FIXME** | None — all templates returned | **Missing** | Done |
|
||||||
| Node | `Node.Audit/Modify/Allocate` | N/A (inherits project) | Inherits project | N/A |
|
| Node | `Node.Audit/Modify/Allocate` | N/A (inherits project) | Inherits project | N/A |
|
||||||
| Link | `Link.Audit/Modify/Allocate` | N/A (inherits project) | Inherits project | N/A |
|
| Link | `Link.Audit/Modify/Allocate` | N/A (inherits project) | Inherits project | N/A |
|
||||||
@ -25,7 +25,49 @@ This document tracks the incremental work to close those gaps. Each phase is ind
|
|||||||
| Appliance | `Appliance.Audit/Allocate` | None — all appliances returned | N/A (builtin) | N/A |
|
| Appliance | `Appliance.Audit/Allocate` | None — all appliances returned | N/A (builtin) | N/A |
|
||||||
| Symbol | `Symbol.Audit/Allocate` | None — all symbols returned | N/A (builtin) | N/A |
|
| Symbol | `Symbol.Audit/Allocate` | None — all symbols returned | N/A (builtin) | N/A |
|
||||||
|
|
||||||
## Architecture
|
## Implemented Solution: Project Isolation
|
||||||
|
|
||||||
|
### Three-Step Permission Check Logic
|
||||||
|
|
||||||
|
**Status**: ✅ Implemented in `feature/simple-user-isolation` branch
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Step 1: ACE check - basic access permission
|
||||||
|
# Get projects user has ACE for
|
||||||
|
ace_projects = []
|
||||||
|
for project in controller.projects.values():
|
||||||
|
project_path = f"/projects/{project.id}"
|
||||||
|
if await rbac_repo.check_user_has_privilege(current_user.user_id, project_path, "Project.Audit"):
|
||||||
|
ace_projects.append(project)
|
||||||
|
|
||||||
|
# Step 2: Filter ace_projects by created_by - user's own projects
|
||||||
|
# Project sharing is only available through resource pools
|
||||||
|
user_projects = [p.asdict() for p in ace_projects if p.created_by == current_user.username]
|
||||||
|
projects.extend(user_projects)
|
||||||
|
|
||||||
|
# Step 3: Resource pool projects
|
||||||
|
# Projects shared through resource pools
|
||||||
|
user_pool_resources = await rbac_repo.get_user_pool_resources(current_user.user_id, "Project.Audit")
|
||||||
|
project_ids_in_pools = [str(r.resource_id) for r in user_pool_resources if r.resource_type == "project"]
|
||||||
|
pool_projects = [p.asdict() for p in controller.projects.values() if p.id in project_ids_in_pools]
|
||||||
|
projects.extend(pool_projects)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Design Principles
|
||||||
|
|
||||||
|
1. **ACE for basic access control**: Controls whether user can access the system
|
||||||
|
2. **created_by for user isolation**: Controls which specific resources user can access
|
||||||
|
3. **Resource pools for project sharing**: The only mechanism for sharing projects between users
|
||||||
|
4. **No direct ACE sharing**: Users cannot configure ACE directly on specific projects to share them
|
||||||
|
|
||||||
|
### Advantages of This Approach
|
||||||
|
|
||||||
|
- **Fault tolerance**: Even with broad ACE configuration (`path: "/" + propagate: true`), user isolation remains effective
|
||||||
|
- **Clear separation**: Basic access, data ownership, and team sharing are clearly separated
|
||||||
|
- **Simple mechanism**: No complex auto-ACE or seen_project_ids tracking required
|
||||||
|
- **Performance**: Leverages existing created_by field, no schema changes needed
|
||||||
|
|
||||||
|
## Updated Architecture
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
graph TD
|
graph TD
|
||||||
@ -33,30 +75,30 @@ graph TD
|
|||||||
WebUI
|
WebUI
|
||||||
CLI
|
CLI
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph "Controller API"
|
subgraph "Controller API"
|
||||||
Auth[get_current_active_user]
|
Auth[get_current_active_user]
|
||||||
PrivCheck[has_privilege]
|
|
||||||
Routes[Resource Routes]
|
Routes[Resource Routes]
|
||||||
AutoACE[auto-ACE on create]
|
ACE_Check[Step 1: ACE Check]
|
||||||
ListFilter[ACE-based list filtering]
|
Owner_Filter[Step 2: Filter by created_by]
|
||||||
|
Pool_Check[Step 3: Resource Pools]
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph "RBAC Engine"
|
subgraph "RBAC Engine"
|
||||||
ACE[(ACE table)]
|
ACE[(ACE table)]
|
||||||
Role[(Role table)]
|
Role[(Role table)]
|
||||||
Privilege[(Privilege table)]
|
Privilege[(Privilege table)]
|
||||||
Checker[check_user_has_privilege]
|
Checker[check_user_has_privilege]
|
||||||
end
|
end
|
||||||
|
|
||||||
WebUI --> Auth
|
WebUI --> Auth
|
||||||
CLI --> Auth
|
CLI --> Auth
|
||||||
Auth --> Routes
|
Auth --> Routes
|
||||||
Routes --> PrivCheck
|
Routes --> ACE_Check
|
||||||
Routes --> AutoACE
|
ACE_Check --> Checker
|
||||||
Routes --> ListFilter
|
ACE_Check --> Owner_Filter
|
||||||
PrivCheck --> Checker
|
Owner_Filter --> Pool_Check
|
||||||
ListFilter --> Checker
|
Pool_Check --> Checker
|
||||||
Checker --> ACE
|
Checker --> ACE
|
||||||
Checker --> Role
|
Checker --> Role
|
||||||
Role --> Privilege
|
Role --> Privilege
|
||||||
@ -64,53 +106,48 @@ graph TD
|
|||||||
|
|
||||||
## Business Process
|
## Business Process
|
||||||
|
|
||||||
### Project creation with auto-ACE
|
### Project listing with three-step filtering
|
||||||
|
|
||||||
```mermaid
|
|
||||||
sequenceDiagram
|
|
||||||
actor U as User
|
|
||||||
participant API as POST /projects
|
|
||||||
participant Ctrl as Controller
|
|
||||||
participant ACE as ACE Table
|
|
||||||
|
|
||||||
U->>API: Create project
|
|
||||||
API->>API: has_privilege("Project.Allocate")
|
|
||||||
API->>Ctrl: add_project()
|
|
||||||
Ctrl-->>API: project
|
|
||||||
API->>ACE: create ACE<br/>(user=creator, role=User,<br/>path=/projects/{id})
|
|
||||||
API-->>U: 201 + project
|
|
||||||
```
|
|
||||||
|
|
||||||
### Project listing with ACE filtering
|
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
actor U as User
|
actor U as User
|
||||||
participant API as GET /projects
|
participant API as GET /projects
|
||||||
participant Ctrl as Controller
|
participant Controller as Controller
|
||||||
participant ACE as ACE Table
|
participant RBAC as RBAC Engine
|
||||||
|
|
||||||
U->>API: List projects
|
U->>API: List projects
|
||||||
API->>API: get_current_active_user (not superadmin)
|
API->>API: get_current_active_user (not superadmin)
|
||||||
|
|
||||||
|
API->>RBAC: Step 1: ACE check on each project
|
||||||
loop Each project
|
loop Each project
|
||||||
API->>ACE: check_user_has_privilege(user, path, "Project.Audit")
|
RBAC-->>API: ACE results
|
||||||
ACE-->>API: True/False
|
|
||||||
end
|
end
|
||||||
API-->>U: filtered list
|
|
||||||
|
API->>API: Step 2: Filter by created_by
|
||||||
|
API-->>U: User's own projects
|
||||||
|
|
||||||
|
API->>RBAC: Step 3: Resource pool projects
|
||||||
|
RBAC-->>API: Pool projects
|
||||||
|
|
||||||
|
API-->>U: Combined list (own + pool)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Phased Plan
|
## Updated Phased Plan
|
||||||
|
|
||||||
### Phase 1 — MVP: Project isolation
|
### ✅ Phase 1 — MVP: Project isolation (COMPLETED)
|
||||||
|
|
||||||
**Goal**: Users only see projects they created or were granted access to.
|
**Goal**: Users only see projects they created or were granted access to through resource pools.
|
||||||
|
|
||||||
| Task | Files | Detail |
|
| Task | Files | Status | Detail |
|
||||||
|---|---|---|
|
|---|---|---|---|
|
||||||
| Auto-ACE on project create | `projects.py` — `create_project()` | After `add_project()`, create ACE: user=creator, role=User, path=`/projects/{id}` |
|
| Fix project list filtering | `projects.py` — `get_projects()` | ✅ **Implemented** | Three-step filtering: ACE check → created_by filter → resource pools |
|
||||||
| Fix project list filtering | `projects.py` — `get_projects()` | Remove "sees all non-pool projects" path. Return only projects passing ACE check. |
|
|
||||||
|
|
||||||
**Estimate**: 2 files, ~30 lines changed.
|
**Result**:
|
||||||
|
- ✅ Users can only see projects they created
|
||||||
|
- ✅ Team collaboration through resource pools works
|
||||||
|
- ✅ Fault tolerance: Works correctly even with broad ACE configurations
|
||||||
|
- ✅ No schema changes required
|
||||||
|
- ✅ ~30 lines changed
|
||||||
|
|
||||||
### Phase 2 — Template isolation
|
### Phase 2 — Template isolation
|
||||||
|
|
||||||
@ -118,9 +155,8 @@ sequenceDiagram
|
|||||||
|
|
||||||
| Task | Files | Detail |
|
| Task | Files | Detail |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Auto-ACE on template create | `templates.py` — `create_template()` | Same pattern as project |
|
| Apply same pattern to templates | `templates.py` — `get_templates()` | Use same three-step filtering as projects |
|
||||||
| Fix template list filtering | `templates.py` — `get_templates()` | Filter by ACE; builtin templates always visible |
|
| Uncomment `Template.Audit` | `templates.py` | Restore `has_privilege("Template.Audit")` checks |
|
||||||
| Uncomment `Template.Audit` | `templates.py` lines 75, 167 | Restore `has_privilege("Template.Audit")` |
|
|
||||||
|
|
||||||
**Dependency**: Web UI must handle 403 from `GET /templates/{id}`. Mitigation: keep builtin templates unconditionally visible so the UI always has data.
|
**Dependency**: Web UI must handle 403 from `GET /templates/{id}`. Mitigation: keep builtin templates unconditionally visible so the UI always has data.
|
||||||
|
|
||||||
@ -130,8 +166,8 @@ sequenceDiagram
|
|||||||
|
|
||||||
| Task | Files |
|
| Task | Files |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Auto-ACE on image upload | `images.py` — `upload_image()` |
|
| Apply same pattern to images | `images.py` — `get_images()` |
|
||||||
| Fix image list filtering | `images.py` — `get_images()` |
|
| Fix image list filtering | `images.py` |
|
||||||
| ACE cleanup on delete | `images.py` — `delete_image()` |
|
| ACE cleanup on delete | `images.py` — `delete_image()` |
|
||||||
|
|
||||||
### Phase 4 — Default ACE for "Users" group (optional)
|
### Phase 4 — Default ACE for "Users" group (optional)
|
||||||
@ -145,35 +181,66 @@ sequenceDiagram
|
|||||||
|
|
||||||
## API Endpoints Changed
|
## API Endpoints Changed
|
||||||
|
|
||||||
### Phase 1
|
### Phase 1 (Implemented)
|
||||||
|
|
||||||
| Method | Path | Change |
|
| Method | Path | Change |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `POST` | `/v3/projects` | Auto-create ACE for creator |
|
| `GET` | `/v3/projects` | Three-step filtering: ACE → created_by → resource pools |
|
||||||
| `GET` | `/v3/projects` | Filter by user ACEs |
|
|
||||||
|
|
||||||
### Phase 2
|
### Phase 2 (Planned)
|
||||||
|
|
||||||
| Method | Path | Change |
|
| Method | Path | Change |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `POST` | `/v3/templates` | Auto-create ACE for creator |
|
| `GET` | `/v3/templates` | Apply same three-step filtering |
|
||||||
| `GET` | `/v3/templates` | Filter by user ACEs + builtin |
|
|
||||||
| `GET` | `/v3/templates/{id}` | Restore `Template.Audit` check |
|
| `GET` | `/v3/templates/{id}` | Restore `Template.Audit` check |
|
||||||
|
|
||||||
## Design Decisions
|
## Key Design Decisions
|
||||||
|
|
||||||
1. **Compute stays shared**: Computes are infrastructure, not user-owned. The `Compute.Audit` FIXME stays — all authenticated users see computes.
|
1. **Project sharing through resource pools only**: Users cannot configure ACE directly to share specific projects. All sharing must go through resource pools. This prevents permission configuration chaos and maintains clear ownership semantics.
|
||||||
|
|
||||||
2. **No DB migration required**: All phases use the existing ACE/role/privilege tables. No schema changes.
|
2. **No auto-ACE required**: The three-step filtering logic works without needing automatic ACE creation on project creation. The created_by field provides sufficient ownership information.
|
||||||
|
|
||||||
3. **Performance**: Project list filtering is O(n) — iterates all projects and checks ACE per project. Acceptable for < 500 projects. Can optimize later with direct ACE path queries.
|
3. **Fault-tolerant to ACE configuration**: Even if administrators configure broad ACE permissions (like `path: "/" + propagate: true`), user isolation remains effective because Step 2 filters by created_by.
|
||||||
|
|
||||||
4. **The FIXME dependency**: `Template.Audit` was commented out because web UI crashes on 403. Fix requires either (a) auto-ACE so users own their templates, or (b) web UI 403 handling.
|
4. **No DB migration required**: Uses existing ACE/role/privilege tables and created_by field. No schema changes needed.
|
||||||
|
|
||||||
## References
|
5. **Performance**: Project list filtering is O(n) where n is the total number of projects. Each project requires one ACE check. Acceptable for < 500 projects. Can optimize later with batch ACE queries if needed.
|
||||||
|
|
||||||
- Discussion: https://github.com/GNS3/gns3-server/discussions/1949
|
## Updated References
|
||||||
- RBAC models: `gns3server/db/models/acl.py`, `roles.py`, `privileges.py`
|
|
||||||
- RBAC repository: `gns3server/db/repositories/rbac.py`
|
- **Implementation**: `gns3server/api/routes/controller/projects.py` (feature/simple-user-isolation branch)
|
||||||
- Auth dependency: `gns3server/api/routes/controller/dependencies/authentication.py`
|
- **Discussion**: https://github.com/GNS3/gns3-server/discussions/1949
|
||||||
- RBAC dependency: `gns3server/api/routes/controller/dependencies/rbac.py`
|
- **RBAC models**: `gns3server/db/models/acl.py`, `roles.py`, `privileges.py`
|
||||||
|
- **RBAC repository**: `gns3server/db/repositories/rbac.py`
|
||||||
|
- **Auth dependency**: `gns3server/api/routes/controller/dependencies/authentication.py`
|
||||||
|
- **RBAC dependency**: `gns3server/api/routes/controller/dependencies/rbac.py`
|
||||||
|
- **Resource pools**: `gns3server/db/models/pools.py` and `gns3server/db/repositories/pools.py`
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
|
||||||
|
### What Was Implemented
|
||||||
|
|
||||||
|
The `feature/simple-user-isolation` branch implements a robust user isolation mechanism that:
|
||||||
|
|
||||||
|
1. **Integrates with existing RBAC framework** without breaking changes
|
||||||
|
2. **Leverages the created_by field** that already exists in the Project model
|
||||||
|
3. **Uses three-step pipeline filtering** to avoid complex seen_project_ids tracking
|
||||||
|
4. **Supports team collaboration** through existing resource pool functionality
|
||||||
|
5. **Is fault-tolerant to ACE misconfiguration** - broad ACE permissions don't break user isolation
|
||||||
|
|
||||||
|
### What Was Not Implemented
|
||||||
|
|
||||||
|
The original roadmap's Phase 1 included auto-ACE creation on project creation. This was determined to be unnecessary because:
|
||||||
|
|
||||||
|
- The three-step filtering logic achieves user isolation without auto-ACE
|
||||||
|
- Auto-ACE would add complexity without significant benefit
|
||||||
|
- Project sharing through resource pools is cleaner than direct ACE configuration
|
||||||
|
|
||||||
|
### Future Work
|
||||||
|
|
||||||
|
The same three-step filtering pattern can be applied to:
|
||||||
|
- **Templates**: Replace the FIXME comment with proper filtering logic
|
||||||
|
- **Images**: Apply the same pattern for user image isolation
|
||||||
|
- **Other resources**: Extend the pattern as needed
|
||||||
|
|
||||||
|
This implementation provides a solid foundation for user isolation in GNS3 3.0+ while maintaining compatibility with the existing RBAC framework.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user