Overview
This page documents the core types used for access control in Syft: ACLRequest, AccessLevel, User, and Access. These types work together to define who can access what resources and at what permission level.
ACLRequest
Represents a request to access a resource with a specific permission level.
from syft_permissions import ACLRequest
Fields
Relative path within the datasite to the resource being accessed. The path is relative to the datasite root.
The level of access being requested (READ, WRITE, or ADMIN).
The user making the access request.
Example
from syft_permissions import ACLRequest, AccessLevel, User
request = ACLRequest(
path="reports/q1.csv",
level=AccessLevel.READ,
user=User(id="[email protected]")
)
Usage with ACLService
from syft_permissions import ACLService, ACLRequest, AccessLevel, User
service = ACLService(owner="[email protected]")
# ... load permissions ...
# Check if alice can read the file
request = ACLRequest(
path="reports/q1.csv",
level=AccessLevel.READ,
user=User(id="[email protected]")
)
if service.can_access(request):
# Grant access to the file
with open("reports/q1.csv") as f:
data = f.read()
else:
# Deny access
raise PermissionError("Access denied")
AccessLevel
Enumeration of permission levels, implemented as an IntEnum for hierarchical comparison.
from syft_permissions import AccessLevel
Values
Read-only access to view or download resources.
Write access to modify or upload resources. Implies READ access.
Administrative access to manage permissions and perform all operations. Implies both WRITE and READ access.
Access Hierarchy
Access levels are hierarchical:
- ADMIN implies WRITE and READ
- WRITE implies READ
- READ is the base level
This hierarchy is enforced automatically when checking permissions.
Example
from syft_permissions import AccessLevel
# Using access levels
print(AccessLevel.READ) # 1
print(AccessLevel.WRITE) # 2
print(AccessLevel.ADMIN) # 4
# Comparison (due to IntEnum)
print(AccessLevel.ADMIN > AccessLevel.WRITE) # True
print(AccessLevel.WRITE > AccessLevel.READ) # True
Permission Checking Logic
When a user has a certain access level, they automatically have all lower levels:
from syft_permissions import Rule, Access, AccessLevel
# User has ADMIN access
rule = Rule(
pattern="**",
access=Access(admin=["[email protected]"])
)
# Alice can:
# - Perform ADMIN operations ✓
# - Perform WRITE operations ✓ (implied)
# - Perform READ operations ✓ (implied)
# User has WRITE access
rule = Rule(
pattern="**",
access=Access(write=["[email protected]"])
)
# Bob can:
# - Perform ADMIN operations ✗
# - Perform WRITE operations ✓
# - Perform READ operations ✓ (implied)
# User has READ access
rule = Rule(
pattern="**",
access=Access(read=["[email protected]"])
)
# Charlie can:
# - Perform ADMIN operations ✗
# - Perform WRITE operations ✗
# - Perform READ operations ✓
User
Represents a user in the permission system.
from syft_permissions import User
Fields
User identifier, typically an email address. Used for matching against access control lists and templates.
Example
Owner vs Regular Users
The datasite owner (specified in ACLService) is a special user who bypasses all permission checks:
from syft_permissions import ACLService, ACLRequest, AccessLevel, User
service = ACLService(owner="[email protected]")
# Owner can access anything, even with no rules defined
owner_request = ACLRequest(
path="any/path/anywhere",
level=AccessLevel.ADMIN,
user=User(id="[email protected]")
)
service.can_access(owner_request) # True (owner bypass)
# Regular user cannot access without matching rules
user_request = ACLRequest(
path="any/path/anywhere",
level=AccessLevel.READ,
user=User(id="[email protected]")
)
service.can_access(user_request) # False (no rules)
Access
Defines access control lists (ACLs) specifying which users have which permissions.
from syft_permissions import Access
Fields
List of users or patterns with administrative access. Users in this list can perform all operations.
List of users or patterns with write access. Users in this list can modify resources and have implied read access.
List of users or patterns with read access. Users in this list can view resources.
Access List Patterns
Each access list supports multiple pattern types:
Exact Email
Grants access to a specific user by exact email match.
Domain Wildcard
Access(read=["*@company.com"])
Grants access to all users from a specific domain using fnmatch pattern matching.
Everyone
Grants access to all users (public access).
USER Placeholder
Special placeholder that behaves differently based on the rule pattern:
- With template patterns (
{{.UserEmail}}/**): Resolves to the requesting user’s email
- Without template patterns: Resolves to
* (any authenticated user)
This enables per-user private directories:
Examples
Public Read Access
from syft_permissions import Access
access = Access(read=["*"])
Company-Wide Access
from syft_permissions import Access
access = Access(
read=["*@company.com"],
write=["[email protected]"]
)
Multi-User Access
Per-User Directories
from syft_permissions import Rule, Access
# Users can write to their own directories
rule = Rule(
pattern="{{.UserEmail}}/**",
access=Access(write=["USER"])
)
Mixed Patterns
from syft_permissions import Access
# Combine exact emails, domain wildcards, and public access
access = Access(
admin=["[email protected]"],
write=["*@company.com", "[email protected]"],
read=["*"] # Public read
)
Empty Access Lists
Empty access lists deny all access:
from syft_permissions import Access
# No one can access (except the owner)
access = Access()
# Equivalent to:
# Access(admin=[], write=[], read=[])
Complete Example
Here’s a comprehensive example combining all access control types:
from syft_permissions import (
ACLService,
ACLRequest,
AccessLevel,
User,
RuleSet,
Rule,
Access
)
# Initialize service
service = ACLService(owner="[email protected]")
# Define a ruleset with various access patterns
ruleset = RuleSet(
path="",
rules=[
# Admin-only configuration
Rule(
pattern="config/**",
access=Access(admin=["[email protected]"])
),
# Per-user private directories
Rule(
pattern="users/{{.UserEmail}}/**",
access=Access(write=["USER"])
),
# Team collaboration space
Rule(
pattern="team/**",
access=Access(
write=["*@company.com"],
read=["*@partner.com"]
)
),
# Public reports
Rule(
pattern="reports/**/*.pdf",
access=Access(read=["*"])
),
# Default: deny all
Rule(
pattern="**",
access=Access()
)
]
)
service.add_ruleset(ruleset)
# Test access for different scenarios
test_cases = [
# Admin can access config
("[email protected]", "config/settings.yaml", AccessLevel.ADMIN, True),
# Regular employee cannot access config
("[email protected]", "config/settings.yaml", AccessLevel.READ, False),
# Users can write to their own directories
("[email protected]", "users/[email protected]/notes.txt", AccessLevel.WRITE, True),
# Users cannot access other users' directories
("[email protected]", "users/[email protected]/notes.txt", AccessLevel.READ, False),
# Company employees can write to team space
("[email protected]", "team/project.txt", AccessLevel.WRITE, True),
# Partners can read team space
("[email protected]", "team/project.txt", AccessLevel.READ, True),
# Partners cannot write to team space
("[email protected]", "team/project.txt", AccessLevel.WRITE, False),
# Anyone can read public reports
("[email protected]", "reports/2024/q1.pdf", AccessLevel.READ, True),
# No one can write public reports (no write rule)
("[email protected]", "reports/2024/q1.pdf", AccessLevel.WRITE, False),
]
for user_email, path, level, expected in test_cases:
request = ACLRequest(
path=path,
level=level,
user=User(id=user_email)
)
result = service.can_access(request)
status = "✓" if result == expected else "✗"
print(f"{status} {user_email} {level.name} {path}: {result}")
See Also
- ACLService - Use these types to check permissions
- RuleSet - Define rules using Access
- Rule - Configure access patterns