Tool Permissions & Access Control
Role-based access control system for tools with permission management, inheritance, and dynamic evaluation.
Features
- Role-Based Access Control: Define roles with specific permissions
- Permission Inheritance: Roles can inherit from other roles
- Dynamic Evaluation: Context-aware permission checking
- Tool Authorization: Control access to specific tools
- Audit Logging: Track permission changes and usage
- Flexible Conditions: Time-based and context-based permissions
Quick Start
from recoagent.tools import PermissionManager, Role, Permission, PermissionLevel, ResourceType
# Initialize permission manager
pm = PermissionManager()
# Create roles
admin_role = Role(
name="admin",
description="Administrator with full access",
permissions=[
Permission("*", ResourceType.TOOL, PermissionLevel.ADMIN)
]
)
user_role = Role(
name="user",
description="Standard user",
permissions=[
Permission("search_tools", ResourceType.TOOL, PermissionLevel.EXECUTE),
Permission("basic_workflows", ResourceType.WORKFLOW, PermissionLevel.EXECUTE)
]
)
# Add roles
pm.add_role(admin_role)
pm.add_role(user_role)
# Add users
pm.add_user("user123", "John Doe", roles=["user"])
pm.add_user("admin456", "Jane Admin", roles=["admin"])
# Check permissions
can_search = pm.check_permission("user123", "search_tools", PermissionLevel.EXECUTE)
print(f"Can search: {can_search}") # True
can_admin = pm.check_permission("user123", "admin_tools", PermissionLevel.ADMIN)
print(f"Can admin: {can_admin}") # False
Permission Levels
Basic Levels
from recoagent.tools import PermissionLevel
# Read-only access
Permission("view_tools", ResourceType.TOOL, PermissionLevel.READ)
# Write access
Permission("edit_tools", ResourceType.TOOL, PermissionLevel.WRITE)
# Execute access
Permission("run_tools", ResourceType.TOOL, PermissionLevel.EXECUTE)
# Administrative access
Permission("manage_tools", ResourceType.TOOL, PermissionLevel.ADMIN)
Permission Hierarchy
# Permission levels are hierarchical
# ADMIN > EXECUTE > WRITE > READ
# Admin can do everything
admin_permission = Permission("*", ResourceType.TOOL, PermissionLevel.ADMIN)
# Execute can run tools
execute_permission = Permission("search_tools", ResourceType.TOOL, PermissionLevel.EXECUTE)
# Write can modify tools
write_permission = Permission("edit_tools", ResourceType.TOOL, PermissionLevel.WRITE)
# Read can view tools
read_permission = Permission("view_tools", ResourceType.TOOL, PermissionLevel.READ)
Role Management
Creating Roles
# Basic role
basic_role = Role(
name="basic_user",
description="Basic user role",
permissions=[
Permission("search_tools", ResourceType.TOOL, PermissionLevel.EXECUTE),
Permission("view_workflows", ResourceType.WORKFLOW, PermissionLevel.READ)
]
)
# Role with inheritance
advanced_role = Role(
name="advanced_user",
description="Advanced user role",
inherits_from=["basic_user"], # Inherit from basic_user
permissions=[
Permission("edit_tools", ResourceType.TOOL, PermissionLevel.WRITE),
Permission("create_workflows", ResourceType.WORKFLOW, PermissionLevel.EXECUTE)
]
)
# Admin role
admin_role = Role(
name="admin",
description="Administrator role",
permissions=[
Permission("*", ResourceType.TOOL, PermissionLevel.ADMIN),
Permission("*", ResourceType.WORKFLOW, PermissionLevel.ADMIN),
Permission("*", ResourceType.DATA, PermissionLevel.ADMIN)
]
)
Role Inheritance
# Create role hierarchy
pm.add_role(Role(
name="base_user",
permissions=[
Permission("view_tools", ResourceType.TOOL, PermissionLevel.READ)
]
))
pm.add_role(Role(
name="power_user",
inherits_from=["base_user"], # Inherit base permissions
permissions=[
Permission("run_tools", ResourceType.TOOL, PermissionLevel.EXECUTE)
]
))
pm.add_role(Role(
name="developer",
inherits_from=["power_user"], # Inherit power user permissions
permissions=[
Permission("edit_tools", ResourceType.TOOL, PermissionLevel.WRITE)
]
))
User Management
Adding Users
# Add user with roles
pm.add_user(
user_id="user123",
username="John Doe",
roles=["basic_user", "power_user"],
metadata={"department": "engineering", "level": "senior"}
)
# Add user with specific permissions
pm.add_user(
user_id="special_user",
username="Special User",
roles=["basic_user"],
permissions=[
Permission("special_tool", ResourceType.TOOL, PermissionLevel.EXECUTE)
]
)
Assigning Roles
# Assign role to user
pm.assign_role("user123", "power_user")
# Check if user has role
user_info = pm.get_user_info("user123")
print(f"User roles: {user_info['roles']}")
# Revoke role
pm.revoke_role("user123", "power_user")
User Permissions
# Get all permissions for user
permissions = pm.get_user_permissions("user123")
for permission in permissions:
print(f"Resource: {permission.resource}")
print(f"Level: {permission.permission_level}")
print(f"Type: {permission.resource_type}")
print(f"Conditions: {permission.conditions}")
Permission Checking
Basic Permission Checks
# Check if user can execute tool
can_execute = pm.check_permission(
user_id="user123",
resource="search_tools",
permission_level=PermissionLevel.EXECUTE
)
# Check if user can admin tool
can_admin = pm.check_permission(
user_id="user123",
resource="admin_tools",
permission_level=PermissionLevel.ADMIN
)
Context-Aware Permissions
# Check permission with context
can_access = pm.check_permission(
user_id="user123",
resource="sensitive_tool",
permission_level=PermissionLevel.EXECUTE,
context={
"time_of_day": "business_hours",
"location": "office",
"department": "engineering"
}
)
Conditional Permissions
# Permission with conditions
conditional_permission = Permission(
resource="sensitive_tool",
resource_type=ResourceType.TOOL,
permission_level=PermissionLevel.EXECUTE,
conditions={
"time_of_day": "business_hours",
"location": "office"
}
)
# Check with context
context = {
"time_of_day": "business_hours",
"location": "office"
}
can_access = pm.check_permission(
user_id="user123",
resource="sensitive_tool",
permission_level=PermissionLevel.EXECUTE,
context=context
)
Tool Integration
Permission Decorators
from recoagent.tools import ToolPermissionDecorator
# Create permission decorator
permission_decorator = ToolPermissionDecorator(pm)
# Decorate tool function
@permission_decorator.require_permission(
resource="search_tool",
permission_level=PermissionLevel.EXECUTE
)
def search_tool(query, user_id=None, **kwargs):
# Tool implementation
return search_results
# Use tool
result = search_tool("test query", user_id="user123")
Tool Authorization
# Check tool access before execution
def execute_tool(tool_name, user_id, **kwargs):
# Check permission
if not pm.check_permission(user_id, tool_name, PermissionLevel.EXECUTE):
return {"error": "Permission denied"}
# Execute tool
return tool_function(**kwargs)
Dynamic Permissions
# Grant temporary permission
pm.grant_permission(
user_id="user123",
resource="temporary_tool",
resource_type=ResourceType.TOOL,
permission_level=PermissionLevel.EXECUTE,
expires_at=datetime.now() + timedelta(hours=1)
)
# Check temporary permission
can_access = pm.check_permission(
user_id="user123",
resource="temporary_tool",
permission_level=PermissionLevel.EXECUTE
)
Advanced Features
Time-Based Permissions
# Permission with expiration
expiring_permission = Permission(
resource="temporary_tool",
resource_type=ResourceType.TOOL,
permission_level=PermissionLevel.EXECUTE,
expires_at=datetime.now() + timedelta(days=7)
)
# Check if permission is still valid
if expiring_permission.expires_at > datetime.now():
print("Permission is valid")
else:
print("Permission has expired")
Resource-Specific Permissions
# Wildcard permissions
wildcard_permission = Permission(
resource="*", # All resources
resource_type=ResourceType.TOOL,
permission_level=PermissionLevel.ADMIN
)
# Specific resource permissions
specific_permission = Permission(
resource="search_tools", # Specific resource
resource_type=ResourceType.TOOL,
permission_level=PermissionLevel.EXECUTE
)
Permission Revocation
# Revoke specific permission
pm.revoke_permission(
user_id="user123",
resource="sensitive_tool",
permission_level=PermissionLevel.EXECUTE
)
# Revoke all permissions for user
pm.revoke_role("user123", "power_user")
Integration Examples
With FastAPI
from fastapi import FastAPI, Depends, HTTPException
from recoagent.tools import PermissionManager
app = FastAPI()
pm = PermissionManager()
def get_current_user():
# Get user from authentication
return "user123"
def check_permission(resource: str, level: PermissionLevel):
def permission_checker(user_id: str = Depends(get_current_user)):
if not pm.check_permission(user_id, resource, level):
raise HTTPException(status_code=403, detail="Permission denied")
return user_id
return permission_checker
@app.post("/tools/search")
async def search_tools(
query: str,
user_id: str = Depends(check_permission("search_tools", PermissionLevel.EXECUTE))
):
# Tool implementation
return {"results": "search_results"}
With Workflows
from packages.observability import trace_workflow
@trace_workflow(name="permission_controlled_workflow")
async def controlled_workflow(user_id: str, tool_name: str):
# Check permission
if not pm.check_permission(user_id, tool_name, PermissionLevel.EXECUTE):
return {"error": "Permission denied"}
# Execute workflow
result = await execute_tool(tool_name)
return result
With Tools
# Tool with permission check
def secure_tool(operation, user_id, **kwargs):
# Check permission
if not pm.check_permission(user_id, f"{operation}_tool", PermissionLevel.EXECUTE):
return {"error": "Permission denied"}
# Execute operation
return perform_operation(operation, **kwargs)
Monitoring and Auditing
Permission Statistics
# Get permission statistics
stats = pm.get_permission_stats()
print(f"Total Users: {stats['total_users']}")
print(f"Total Roles: {stats['total_roles']}")
print(f"Total Permissions: {stats['total_permissions']}")
# Get user statistics
user_stats = pm.get_user_stats("user123")
print(f"User Roles: {user_stats['roles']}")
print(f"User Permissions: {user_stats['permissions']}")
Audit Logging
# Track permission changes
pm.add_audit_log(
user_id="admin123",
action="grant_permission",
resource="sensitive_tool",
target_user="user123",
timestamp=datetime.now()
)
# Get audit logs
audit_logs = pm.get_audit_logs(user_id="user123")
for log in audit_logs:
print(f"{log['timestamp']}: {log['action']} on {log['resource']}")
Best Practices
- Principle of Least Privilege: Grant minimum required permissions
- Role Hierarchy: Use role inheritance for complex permissions
- Regular Audits: Review permissions regularly
- Time-Based Access: Use expiration for temporary permissions
- Context Awareness: Consider context in permission checks
- Documentation: Document permission policies
- Testing: Test permission scenarios thoroughly
Troubleshooting
Common Issues
- Permission Denied: Check user roles and permissions
- Role Inheritance: Verify role hierarchy
- Context Issues: Check permission conditions
- Expiration: Verify permission expiration times
Debug Mode
# Enable debug logging
import logging
logging.getLogger('recoagent.tools.permissions').setLevel(logging.DEBUG)
Permission Testing
# Test permission scenarios
def test_permissions():
# Test basic permission
assert pm.check_permission("user123", "search_tools", PermissionLevel.EXECUTE)
# Test denied permission
assert not pm.check_permission("user123", "admin_tools", PermissionLevel.ADMIN)
# Test context-based permission
context = {"time_of_day": "business_hours"}
assert pm.check_permission("user123", "sensitive_tool", PermissionLevel.EXECUTE, context)
print("All permission tests passed!")
API Reference
PermissionManager
| Method | Description |
|---|---|
add_role(role) | Add role to manager |
add_user(user_id, username, roles) | Add user with roles |
assign_role(user_id, role_name) | Assign role to user |
check_permission(user_id, resource, level, context) | Check user permission |
grant_permission(user_id, resource, level, expires_at) | Grant permission |
revoke_permission(user_id, resource, level) | Revoke permission |
PermissionLevel
| Value | Description |
|---|---|
READ | Read-only access |
WRITE | Write access |
EXECUTE | Execute access |
ADMIN | Administrative access |
ResourceType
| Value | Description |
|---|---|
TOOL | Tool resource |
WORKFLOW | Workflow resource |
DATA | Data resource |
SYSTEM | System resource |