mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-08-30 22:10:13 +03:00
622 lines
23 KiB
Markdown
622 lines
23 KiB
Markdown
# RBAC User Isolation Roadmap
|
||
|
||
## Overview
|
||
|
||
GNS3 3.0 ships with a complete RBAC framework (ACE + Role + Privilege models), but the user isolation layer is incomplete. Users can see resources they should not have access to because:
|
||
|
||
- Resource creation does not auto-grant the creator an ACE
|
||
- List endpoints return unfiltered results
|
||
- Two GET endpoints have RBAC checks bypassed via FIXME
|
||
|
||
**This document has been updated to reflect the implemented solution in `feature/simple-user-isolation` branch.**
|
||
|
||
## Current State
|
||
|
||
| Resource | Route Check | List Filtering | Auto-ACE on Create | ACE Cleanup on Delete |
|
||
|---|---|---|---|---|
|
||
| Project | `Project.Audit/Modify/Allocate` | **Implemented** — Three-step filtering | **Not needed** | Done |
|
||
| Template | `Template.Audit` **FIXME** | None — all templates returned | **Missing** | Done |
|
||
| 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 |
|
||
| Drawing | `Drawing.Audit/Modify/Allocate` | N/A (inherits project) | Inherits project | N/A |
|
||
| Snapshot | `Snapshot.Audit/Allocate/Restore` | N/A (inherits project) | Inherits project | N/A |
|
||
| Image | `Image.Audit/Allocate` | None — all images returned | **Missing** | Missing |
|
||
| Compute | `Compute.Audit` **FIXME** | None — all computes returned | N/A (shared infra) | Done |
|
||
| 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 |
|
||
|
||
## 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
|
||
graph TD
|
||
subgraph Client
|
||
WebUI
|
||
CLI
|
||
end
|
||
|
||
subgraph "Controller API"
|
||
Auth[get_current_active_user]
|
||
Routes[Resource Routes]
|
||
ACE_Check[Step 1: ACE Check]
|
||
Owner_Filter[Step 2: Filter by created_by]
|
||
Pool_Check[Step 3: Resource Pools]
|
||
end
|
||
|
||
subgraph "RBAC Engine"
|
||
ACE[(ACE table)]
|
||
Role[(Role table)]
|
||
Privilege[(Privilege table)]
|
||
Checker[check_user_has_privilege]
|
||
end
|
||
|
||
WebUI --> Auth
|
||
CLI --> Auth
|
||
Auth --> Routes
|
||
Routes --> ACE_Check
|
||
ACE_Check --> Checker
|
||
ACE_Check --> Owner_Filter
|
||
Owner_Filter --> Pool_Check
|
||
Pool_Check --> Checker
|
||
Checker --> ACE
|
||
Checker --> Role
|
||
Role --> Privilege
|
||
```
|
||
|
||
## Business Process
|
||
|
||
### Project listing with three-step filtering
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
actor U as User
|
||
participant API as GET /projects
|
||
participant Controller as Controller
|
||
participant RBAC as RBAC Engine
|
||
|
||
U->>API: List projects
|
||
API->>API: get_current_active_user (not superadmin)
|
||
|
||
API->>RBAC: Step 1: ACE check on each project
|
||
loop Each project
|
||
RBAC-->>API: ACE results
|
||
end
|
||
|
||
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)
|
||
```
|
||
|
||
## Updated Phased Plan
|
||
|
||
### ✅ Phase 1 — MVP: Project isolation (COMPLETED)
|
||
|
||
**Goal**: Users only see projects they created or were granted access to through resource pools.
|
||
|
||
| Task | Files | Status | Detail |
|
||
|---|---|---|---|
|
||
| Fix project list filtering | `projects.py` — `get_projects()` | ✅ **Implemented** | Three-step filtering: ACE check → created_by filter → resource pools |
|
||
|
||
**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
|
||
|
||
**Goal**: Users see their own templates + builtin templates only.
|
||
|
||
| Task | Files | Detail |
|
||
|---|---|---|
|
||
| Apply same pattern to templates | `templates.py` — `get_templates()` | Use same three-step filtering as projects |
|
||
| Uncomment `Template.Audit` | `templates.py` | Restore `has_privilege("Template.Audit")` checks |
|
||
|
||
**Dependency**: Web UI must handle 403 from `GET /templates/{id}`. Mitigation: keep builtin templates unconditionally visible so the UI always has data.
|
||
|
||
### Phase 3 — Image isolation (optional)
|
||
|
||
**Goal**: Users see only images they uploaded.
|
||
|
||
| Task | Files |
|
||
|---|---|
|
||
| Apply same pattern to images | `images.py` — `get_images()` |
|
||
| Fix image list filtering | `images.py` |
|
||
| ACE cleanup on delete | `images.py` — `delete_image()` |
|
||
|
||
### Phase 4 — Default ACE for "Users" group (optional)
|
||
|
||
**Goal**: Users in "Users" group can create/list resources without admin ACE intervention.
|
||
|
||
| Task | Detail |
|
||
|---|---|
|
||
| Default ACE on `/projects` | Grant "Users" group → User role → `/projects` (propagate=False) |
|
||
| Default ACE on `/templates` | Grant "Users" group → User role → `/templates` (propagate=False) |
|
||
|
||
## API Endpoints Changed
|
||
|
||
### Phase 1 (Implemented)
|
||
|
||
| Method | Path | Change |
|
||
|---|---|---|
|
||
| `GET` | `/v3/projects` | Three-step filtering: ACE → created_by → resource pools |
|
||
|
||
### Phase 2 (Planned)
|
||
|
||
| Method | Path | Change |
|
||
|---|---|---|
|
||
| `GET` | `/v3/templates` | Apply same three-step filtering |
|
||
| `GET` | `/v3/templates/{id}` | Restore `Template.Audit` check |
|
||
|
||
## Key Design Decisions
|
||
|
||
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 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. **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. **No DB migration required**: Uses existing ACE/role/privilege tables and created_by field. No schema changes needed.
|
||
|
||
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.
|
||
|
||
## Updated References
|
||
|
||
- **Implementation**: `gns3server/api/routes/controller/projects.py` (feature/simple-user-isolation branch)
|
||
- **Discussion**: https://github.com/GNS3/gns3-server/discussions/1949
|
||
- **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.
|
||
|
||
## Phase 5 — ACE Architecture Refactoring (Future)
|
||
|
||
**Goal**: Improve ACE manageability by supporting multiple paths and resource pools in a single ACE entry.
|
||
|
||
### Current Problem
|
||
|
||
With the current design where one ACE = one path:
|
||
- **ACE explosion**: 5 user groups × 10 resource pools = 50 ACE entries
|
||
- **Management complexity**: Difficult to maintain and understand ACE purpose
|
||
- **Performance impact**: Permission checking must iterate through many ACE entries
|
||
|
||
### Proposed Solution
|
||
|
||
Redesign ACE structure to support multiple paths and resource pools in a single ACE entry:
|
||
|
||
```json
|
||
{
|
||
"name": "Development Team Access",
|
||
"description": "Full access for development team",
|
||
"ace_type": "group",
|
||
"group_id": "...",
|
||
"role_id": "...",
|
||
"paths": ["/projects", "/templates", "/images"],
|
||
"resource_pools": ["pool-id-1", "pool-id-2"],
|
||
"propagate": true,
|
||
"allowed": true
|
||
}
|
||
```
|
||
|
||
### Database Changes Required
|
||
|
||
1. **Add name and description to ACE table**:
|
||
```sql
|
||
ALTER TABLE acl ADD COLUMN name VARCHAR;
|
||
ALTER TABLE acl ADD COLUMN description TEXT;
|
||
```
|
||
|
||
2. **Create association tables**:
|
||
```sql
|
||
CREATE TABLE ace_paths (
|
||
ace_id UUID REFERENCES acl(ace_id),
|
||
path VARCHAR,
|
||
PRIMARY KEY (ace_id, path)
|
||
);
|
||
|
||
CREATE TABLE ace_pools (
|
||
ace_id UUID REFERENCES acl(ace_id),
|
||
resource_pool_id UUID REFERENCES resource_pools(resource_pool_id),
|
||
PRIMARY KEY (ace_id, resource_pool_id)
|
||
);
|
||
```
|
||
|
||
3. **Update permission checking logic** to check both paths and resource_pools tables
|
||
|
||
### Benefits
|
||
|
||
- ✅ **Reduced ACE entries**: One ACE covers multiple related paths/pools
|
||
- ✅ **Better organization**: Logical grouping with clear names and descriptions
|
||
- ✅ **Easier management**: Edit one ACE instead of multiple related entries
|
||
- ✅ **Improved performance**: Fewer ACE entries to check during permission validation
|
||
|
||
### Implementation Considerations
|
||
|
||
- **Migration path**: Need to migrate existing single-path ACEs to new structure
|
||
- **Backward compatibility**: API should support both old and new formats during transition
|
||
- **UI updates**: ACE management interface needs to support multi-path/pool selection
|
||
- **Permission checking**: Update `check_user_has_privilege` to check association tables
|
||
|
||
## Phase 6 — Frontend Permission Query API (Future)
|
||
|
||
**Goal**: Provide an API endpoint for the Web UI to query the current user's permissions, enabling dynamic UI rendering based on role and ACE configuration.
|
||
|
||
### Problem
|
||
|
||
Currently the Web UI cannot determine what the authenticated user is allowed to see or do:
|
||
|
||
- ❌ Users see menu items and buttons they don't have permission to use
|
||
- ❌ Clicking a forbidden action results in a 403 error (unexpected UX)
|
||
- ❌ No way to hide/show UI elements based on actual permissions
|
||
|
||
### Proposed Solution
|
||
|
||
Create a `GET /v3/me/permissions` endpoint that returns the current user's effective permissions:
|
||
|
||
```json
|
||
{
|
||
"user_id": "uuid",
|
||
"is_superadmin": false,
|
||
"permissions": [
|
||
{"path": "/projects", "privileges": ["Project.Audit", "Project.Allocate"]},
|
||
{"path": "/projects/{id}", "privileges": ["Project.Audit", "Project.Modify"]},
|
||
{"path": "/templates", "privileges": ["Template.Audit"]}
|
||
],
|
||
"pools": [
|
||
{"path": "/pools/{id}", "name": "Team Projects", "privileges": ["Pool.Audit"]}
|
||
]
|
||
}
|
||
```
|
||
|
||
### Benefits
|
||
|
||
- ✅ **Dynamic UI**: Frontend can hide inaccessible menus/buttons
|
||
- ✅ **Better UX**: Users only see what they can actually use
|
||
- ✅ **Reduced errors**: Fewer 403 responses from hidden operations
|
||
- ✅ **Faster feedback**: Permission checks happen at render time, not request time
|
||
|
||
### Dependencies
|
||
|
||
- **Phase 5 (ACE refactoring)** may change how permissions are stored, which would affect this API's implementation
|
||
|
||
## Phase 7 — Resource Pool Renaming (Future)
|
||
|
||
**Goal**: Rename "Resource Pool" to a more descriptive name that better reflects its actual purpose.
|
||
|
||
### Problem
|
||
|
||
The current name "Resource Pool" is too generic and doesn't clearly convey its actual function:
|
||
|
||
- ❌ **Ambiguous name**: "Resource Pool" could refer to compute pools, connection pools, etc.
|
||
- ❌ **Unclear purpose**: Users don't understand it's primarily for sharing projects
|
||
- ❌ **Discoverability**: Hard to find the right feature when looking for project sharing
|
||
|
||
### Actual Function
|
||
|
||
Resource pools in GNS3 are used for:
|
||
- **Project sharing**: Allow users to access projects created by other users
|
||
- **Team collaboration**: Enable team members to work on shared projects
|
||
- **Access control**: Provide fine-grained permissions for project access through three-step filtering (ACE check → created_by filter → resource pools)
|
||
|
||
### Proposed Name Options
|
||
|
||
| Option | Pros | Cons |
|
||
|--------|-------|-------|
|
||
| **Project Pool** | More explicit, indicates it contains projects | Still uses "pool" terminology |
|
||
| **Shared Projects** | Directly describes the function | Loses the "collection" concept |
|
||
| **Team Projects** | Emphasizes collaboration use case | Doesn't cover non-team sharing scenarios |
|
||
|
||
**Recommended**: **Project Pool** - strikes a balance between clarity and consistency with existing terminology.
|
||
|
||
### Implementation Scope
|
||
|
||
Renaming would require changes to:
|
||
- Database tables: `resource_pools` → `project_pools`
|
||
- API routes: `/v3/pools` → `/v3/project_pools`
|
||
- Schema classes and field names throughout the codebase
|
||
- All documentation and help text
|
||
- Migration script to preserve existing data
|
||
|
||
### Benefits
|
||
|
||
- ✅ **Improved discoverability**: Users can easily find the project sharing feature
|
||
- ✅ **Better onboarding**: New users understand the purpose without confusion
|
||
- ✅ **Clearer API**: API endpoints and schemas more self-documenting
|
||
|
||
### Implementation Considerations
|
||
|
||
- **Breaking change**: Requires API version bump or backward compatibility layer
|
||
- **Data migration**: Existing resource pools must be preserved during table rename
|
||
- **Documentation updates**: All references in docs, tutorials, and API specs need updating
|
||
- **UI changes**: Frontend labels and navigation menus need to match new terminology
|
||
|
||
## Phase 8 — Per-User Project Namespace (Future)
|
||
|
||
**Goal**: Allow project names to be unique per user instead of globally unique, enabling better user experience.
|
||
|
||
### Current Problem
|
||
|
||
Although Phase 1 implements user isolation (users only see projects they created or have access to through resource pools), project names remain globally unique:
|
||
|
||
- ❌ **Naming conflicts**: Alice and Bob cannot both create a project named "My Project"
|
||
- ❌ **Unnecessary restrictions**: Even though projects are isolated, users must coordinate globally unique names
|
||
- ❌ **Poor user experience**: Users get confusing error messages when trying to use common names like "Test Project"
|
||
|
||
### Proposed Solution
|
||
|
||
Change project uniqueness from global to per-user:
|
||
|
||
**Current:**
|
||
```sql
|
||
UNIQUE(name) -- Project names must be globally unique
|
||
```
|
||
|
||
**Proposed:**
|
||
```sql
|
||
UNIQUE(user_id, name) -- Project names unique per user
|
||
```
|
||
|
||
### Benefits
|
||
|
||
- ✅ **Better UX**: Users can name projects whatever they want without worrying about global conflicts
|
||
- ✅ **Natural naming**: Common names like "Test Project" or "Demo" can coexist between users
|
||
- ✅ **No coordination needed**: Teams don't need to maintain a shared project naming registry
|
||
- ✅ **Consistent isolation**: Projects are isolated both in visibility AND naming
|
||
|
||
### Implementation Scope
|
||
|
||
Changes required:
|
||
- **Database schema**: Modify Project table unique constraint from `(name)` to `(user_id, name)`
|
||
- **Migration script**: Handle existing projects with conflicting names
|
||
- **API validation**: Update project creation validation logic
|
||
- **Frontend**: Remove global name uniqueness checks from UI
|
||
|
||
### Migration Considerations
|
||
|
||
**Handling existing name conflicts:**
|
||
If the database already has projects with the same name but different users:
|
||
- Option 1: Keep existing names, only enforce uniqueness for new projects
|
||
- Option 2: Append suffixes to duplicates (e.g., "My Project (alice)", "My Project (bob)")
|
||
- Option 3: Require admin resolution for conflicts before enabling new constraint
|
||
|
||
**Recommended**: Option 1 (grandfather existing projects) for minimal disruption.
|
||
|
||
### Dependencies
|
||
|
||
- **Phase 1 (User isolation)**: Must be completed first
|
||
- Database migration required to modify unique constraint
|
||
|
||
## Phase 9 — User Self-Registration (Future)
|
||
|
||
**Goal**: Allow users to register their own accounts without requiring manual admin creation.
|
||
|
||
### Current State
|
||
|
||
Currently, user accounts can only be created by administrators or through direct database operations:
|
||
- ❌ **Admin burden**: Every new user requires manual account creation
|
||
- ❌ **Poor scalability**: Not suitable for public deployments or large organizations
|
||
- ❌ **Friction**: Users cannot immediately start using the system
|
||
|
||
### Proposed Features
|
||
|
||
**Self-Registration Flow:**
|
||
1. User provides email, username, and password
|
||
2. System validates input and creates account
|
||
3. Optional email verification to confirm email address
|
||
4. Account created with default role (typically "User" role)
|
||
5. User can immediately log in and start creating projects
|
||
|
||
**Email Verification (Optional):**
|
||
- Send verification email with confirmation link/code
|
||
- Verify email address before granting full access
|
||
- Prevent spam account creation
|
||
- Require SMTP server configuration
|
||
|
||
### Implementation Components
|
||
|
||
1. **New API endpoint**: `POST /v3/access/register` (public, no authentication required)
|
||
2. **Email service**: Integration with SMTP server for sending emails
|
||
3. **Configuration**: SMTP settings (host, port, credentials, encryption)
|
||
4. **Rate limiting**: Prevent abuse of self-registration
|
||
5. **Captcha integration**: Optional bot protection
|
||
|
||
### Configuration
|
||
|
||
```yaml
|
||
Server:
|
||
email:
|
||
enabled: true
|
||
smtp_host: smtp.example.com
|
||
smtp_port: 587
|
||
smtp_username: noreply@example.com
|
||
smtp_password: secret
|
||
use_tls: true
|
||
registration:
|
||
require_email_verification: true
|
||
default_role: "User"
|
||
allow_public_registration: true
|
||
```
|
||
|
||
### Security Considerations
|
||
|
||
- ✅ **Rate limiting**: Prevent spam account creation
|
||
- ✅ **Email verification**: Confirm email ownership
|
||
- ✅ **Default permissions**: New users get limited default role
|
||
- ✅ **Admin approval** (optional): Require admin approval before account activation
|
||
- ❌ **Superadmin creation**: Never allow self-registration as superadmin
|
||
|
||
### Dependencies
|
||
|
||
- **Phase 10 (Email service)**: SMTP integration required for email verification
|
||
|
||
## Phase 10 — Email Service Integration (Future)
|
||
|
||
**Goal**: Implement email sending capability for notifications, verification, and alerts.
|
||
|
||
### Use Cases
|
||
|
||
1. **User registration**: Email verification links/codes
|
||
2. **Password reset**: Secure password reset emails
|
||
3. **System alerts**: Error notifications, system updates
|
||
4. **Project sharing**: Notify users when projects are shared via resource pools
|
||
5. **Usage reports**: Periodic usage summaries or quota alerts
|
||
|
||
### Proposed Implementation
|
||
|
||
**Email Service Architecture:**
|
||
- Abstract email service interface
|
||
- Support multiple email providers (SMTP, SendGrid, AWS SES, etc.)
|
||
- Email templates with Jinja2 for customization
|
||
- Async email sending to avoid blocking API responses
|
||
- Email queue for retry logic on failures
|
||
|
||
**Email Templates:**
|
||
- Registration verification
|
||
- Password reset
|
||
- Project shared notification
|
||
- System alerts
|
||
- Usage reports
|
||
|
||
**API Endpoints:**
|
||
```python
|
||
# Configuration (admin only)
|
||
POST /v3/access/config/email
|
||
GET /v3/access/config/email
|
||
PUT /v3/access/config/email
|
||
|
||
# Test email (admin only)
|
||
POST /v3/access/config/email/test
|
||
|
||
# Password reset (public)
|
||
POST /v3/access/users/password/reset/request
|
||
POST /v3/access/users/password/reset/confirm
|
||
|
||
# Email verification (public)
|
||
POST /v3/access/users/verify/email
|
||
POST /v3/access/users/verify/confirm
|
||
```
|
||
|
||
### Database Schema
|
||
|
||
New table for email tracking:
|
||
```sql
|
||
CREATE TABLE email_verification_tokens (
|
||
token_id UUID PRIMARY KEY,
|
||
user_id UUID REFERENCES users(user_id) ON DELETE CASCADE,
|
||
token VARCHAR(255), # Verification code
|
||
purpose VARCHAR(50), # 'registration', 'password_reset', etc.
|
||
expires_at DATETIME,
|
||
created_at DATETIME,
|
||
used BOOLEAN DEFAULT FALSE
|
||
);
|
||
```
|
||
|
||
### Configuration
|
||
|
||
```yaml
|
||
Server:
|
||
email:
|
||
enabled: true
|
||
provider: "smtp" # or "sendgrid", "aws_ses", etc.
|
||
from_address: "noreply@example.com"
|
||
from_name: "GNS3 Server"
|
||
reply_to: "support@example.com"
|
||
smtp:
|
||
host: smtp.example.com
|
||
port: 587
|
||
username: noreply@example.com
|
||
password: encrypted_password
|
||
use_tls: true
|
||
templates_dir: /etc/gns3/email_templates
|
||
```
|
||
|
||
### Security Considerations
|
||
|
||
- ✅ **Encrypted credentials**: SMTP passwords stored encrypted in database
|
||
- ✅ **Token expiration**: Verification tokens expire after configurable time
|
||
- ✅ **Rate limiting**: Prevent email spamming
|
||
- ✅ **Async sending**: Don't block API responses on email operations
|
||
- ✅ **Retry logic**: Handle temporary email service failures
|
||
- ✅ **Privacy**: Don't expose user information in error messages
|
||
|
||
### Dependencies
|
||
|
||
- **Phase 9 (Self-registration)**: User self-registration requires email verification
|
||
- Encryption utilities for storing SMTP credentials securely
|