Sharing Settings (ACL Management) in Synapse¶
Access Control Lists (ACLs) in Synapse determine who can access your data and what actions they can perform. By default, entities inherit permissions from their parent container, but you can create local sharing settings to provide more granular control over access to specific folders and files.
This tutorial demonstrates how to use the Python client to manage permissions and sharing settings for your Synapse entities using the new object-oriented models.
Read more about Access Control
Tutorial Purpose¶
In this tutorial you will:
- Retrieve an existing project or create a new one
- Create a main folder to set custom sharing settings
- Examine current permissions using
get_permissions()
andget_acl()
- Get ACL for specific principal using
get_acl()
- Set specific permissions using
set_permissions()
- Create a sub-folder with different permissions than its parent
- List all ACLs in a hierarchy using
list_acl()
- Manage permissions with advanced options
- Remove permissions and delete ACLs using
delete_permissions()
Prerequisites¶
- Make sure that you have completed the Installation and Authentication setup.
- IMPORTANT: You must set a valid
PRINCIPAL_ID
in the tutorial script before running it. This should be a Synapse user ID or team ID that you want to grant permissions to. - You must have a Project created and replace the one used in this tutorial.
Understanding Permission Types¶
Before we begin, it's important to understand the different permission types available in Synapse:
- READ: View entity metadata and download files
- DOWNLOAD: Download files (requires READ)
- UPDATE: Modify entity metadata and upload new file versions
- CREATE: Create new entities within containers
- DELETE: Delete entities
- CHANGE_PERMISSIONS: Modify ACL permissions
- CHANGE_SETTINGS: Modify entity settings
- MODERATE: Moderate forum discussions (for projects)
Special Principal IDs¶
- 273948: All authenticated Synapse users
- 273949: Public access (anyone on the internet)
- Specific user ID: Individual Synapse user (e.g., 123456)
- Team ID: Synapse team
Permission Inheritance and Benefactors¶
Understanding how permissions work in Synapse is crucial for effective ACL management:
Benefactor Concept¶
Every entity in Synapse has a benefactor - the entity from which it inherits its permissions. When checking permissions for an entity:
- Start at the current entity: Check if it has local sharing settings (its own ACL)
- Traverse up the hierarchy: If no local ACL exists, continue checking parent containers
- Find the benefactor: The search continues up the tree until an entity with permissions/ACL is found, or until reaching the Project level
- Inherit permissions: The entity inherits all permissions from its benefactor
Default Inheritance Behavior¶
- New Projects: Become their own benefactor with default permissions
- New Folders/Files: Initially inherit from their containing Project or parent Folder
- Local ACLs: When you set local sharing settings, the entity becomes its own benefactor
Applying Permissions to Other Entities¶
While this tutorial focuses on Folders, you can apply the same permission management methods (get_permissions()
, get_acl()
, set_permissions()
, list_acl()
, and delete_permissions()
) to other Synapse entities including:
- Projects: Top-level containers that are typically their own benefactors
- Files: Individual data files that can have their own sharing settings
- Tables: Structured data entities with their own permission requirements
- Views: Query-based entities that can have custom access controls
The inheritance and benefactor concepts apply consistently across all entity types in Synapse.
1. Set Up and Get Project¶
⚠️ IMPORTANT: Before running the tutorial, you MUST edit the script to set a valid PRINCIPAL_ID
.
import synapseclient
from synapseclient.models import Folder, Project
# REQUIRED: Set this to the Synapse user ID or team ID you want to grant permissions to
# Do NOT leave this as None - the script will not work properly
PRINCIPAL_ID = None # Replace with actual user/team ID
if PRINCIPAL_ID is None:
raise ValueError(
"You must set PRINCIPAL_ID to a valid Synapse user ID or team ID before running this script. "
"Examples: ###### (user ID), 273948 (authenticated users), 273949 (public)"
)
syn = synapseclient.login()
# Step 1: Get or create a project for this tutorial
print("=== Step 1: Getting project ===")
project = Project(name="My uniquely named project about Alzheimer's Disease").get()
2. Create a main folder to set custom sharing settings¶
# Step 2: Create a main folder to set custom sharing settings
print("\n=== Step 2: Creating main to set custom permissions ===")
main_folder = Folder(
name="Research Data",
description="Main folder for research data with custom sharing settings",
parent_id=project.id,
)
main_folder = main_folder.store()
print(f"Created main folder: {main_folder.name} (ID: {main_folder.id})")
3. Examine Current Permissions¶
The get_permissions()
method returns the permissions that the current user has on an entity
# Step 3: Demonstrate get_permissions() - Get current user's permissions
print("\n=== Step 3: Getting current user's permissions ===")
permissions = main_folder.get_permissions()
print(f"Current user permissions on main folder: {permissions.access_types}")
You'll notice the output looks like:
=== Step 3: Getting current user's permissions ===
Current user permissions on main folder: ['READ', 'UPDATE', 'CREATE', 'DELETE', 'DOWNLOAD', 'MODERATE', 'CHANGE_PERMISSIONS', 'CHANGE_SETTINGS']
4. Get ACL for Specific Principal¶
The get_acl()
method gets the specific permissions for a given principal (user or team):
# Step 4: Demonstrate get_acl() - Get ACL for specific principal
print("\n=== Step 4: Getting ACL for specific principal ===")
# First check what permissions the principal currently has (likely inherited from project)
current_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID, check_benefactor=True)
print(
f"Principal {PRINCIPAL_ID} current permissions (including inherited): {current_acl}"
)
# Check ACL only on the folder itself (not inherited)
folder_only_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID, check_benefactor=False)
print(f"Principal {PRINCIPAL_ID} permissions on folder only: {folder_only_acl}")
Depending on if you've already given permissions to given user/team your may see different results in the output.
You'll notice the output looks like:
=== Step 4: Getting ACL for specific principal ===
Principal ######## current permissions (including inherited): []
Principal ######## permissions on folder only: []
5. Set Custom Permissions¶
Use set_permissions()
to grant specific permissions to a user or team:
# Step 5: Demonstrate set_permissions() - Set specific permissions for the main folder
print("\n=== Step 5: Setting permissions on main folder ===")
main_folder_permissions = ["READ", "DOWNLOAD"]
main_folder.set_permissions(
principal_id=PRINCIPAL_ID,
access_type=main_folder_permissions,
modify_benefactor=False, # Create local ACL for this folder
overwrite=True,
)
print(
f"Set permissions for principal {PRINCIPAL_ID} on main folder: {main_folder_permissions}"
)
# Verify the permissions were set
new_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID, check_benefactor=False)
print(f"Verified new permissions: {new_acl}")
You'll notice the output looks like:
=== Step 5: Setting permissions on main folder ===
[WARNING] Creating an ACL for entity syn#######, which formerly inherited access control from a benefactor entity, "My uniquely named project about Alzheimer's Disease" (syn########).
Set permissions for principal ####### on main folder: ['READ', 'DOWNLOAD']
Verified new permissions: ['DOWNLOAD', 'READ']
6. Create Sub-folder with Different Permissions¶
Create a sub-folder and give it more restrictive permissions than its parent:
# Step 6: Create a sub-folder with different sharing settings
print("\n=== Step 6: Creating sub-folder with different permissions ===")
sub_folder = Folder(
name="Sensitive Analysis",
description="Sub-folder with more restrictive permissions",
parent_id=main_folder.id,
)
sub_folder = sub_folder.store()
print(f"Created sub-folder: {sub_folder.name} (ID: {sub_folder.id})")
# Set more restrictive permissions on the sub-folder
sub_folder_permissions = ["READ"] # More restrictive - only read access
sub_folder.set_permissions(
principal_id=PRINCIPAL_ID,
access_type=sub_folder_permissions,
modify_benefactor=False,
overwrite=True,
)
print(
f"Set more restrictive permissions for principal {PRINCIPAL_ID} on sub-folder: {sub_folder_permissions}"
)
You'll notice the output looks like:
=== Step 6: Creating sub-folder with different permissions ===
Created sub-folder: Sensitive Analysis (ID: syn#######)
[WARNING] Creating an ACL for entity syn#######, which formerly inherited access control from a benefactor entity, "Research Data" (syn#######).
Set more restrictive permissions for principal ####### on sub-folder: ['READ']
7. List All ACLs¶
Use list_acl()
to see all the permissions in your hierarchy. By specifying
the log_tree=True
argument for the method we can get an ascii tree representation of
the ACLs on the project. Alternatively you will also be able to loop over the data.
# Step 7: Demonstrate list_acl() - List all ACLs
print("\n=== Step 7: Listing ACLs ===")
# List ACLs recursively for main folder and all contents
print("Folder ACL:")
recursive_acl_result = main_folder.list_acl(
recursive=True,
include_container_content=True,
log_tree=True, # This will also log the tree structure
)
print(f"Folder ({main_folder.id}) ACL entries:")
for entity_acl in recursive_acl_result.all_entity_acls:
print(f"\nEntity {entity_acl.entity_id} ACL:")
for acl_entry in entity_acl.acl_entries:
print(f" Principal {acl_entry.principal_id}: {acl_entry.permissions}")
You'll notice the output looks like:
=== Step 7: Listing ACLs ===
ACL Tree Structure:
🔍 Legend:
🔒 = No local ACL (inherits from parent)
🔑 = Local ACL (custom permissions)
└── 🔑 Research Data (syn#######) [Folder]
└── user_name_1 (#######): CHANGE_PERMISSIONS, DOWNLOAD, CHANGE_SETTINGS, MODERATE, READ, DELETE, CREATE, UPDATE
└── team_name_1 (#######): DOWNLOAD, READ
└── 🔑 Sensitive Analysis (syn#######) [Folder]
└── user_name_1 (#######): CHANGE_PERMISSIONS, UPDATE, READ, DELETE, MODERATE, CHANGE_SETTINGS, DOWNLOAD, CREATE
└── team_name_1 (#######): READ
Folder (syn#######) ACL entries:
Entity syn####### ACL:
Principal #######: ['CHANGE_PERMISSIONS', 'DOWNLOAD', 'CHANGE_SETTINGS', 'MODERATE', 'READ', 'DELETE', 'CREATE', 'UPDATE']
Principal #######: ['DOWNLOAD', 'READ']
Entity syn####### ACL:
Principal #######: ['CHANGE_PERMISSIONS', 'UPDATE', 'READ', 'DELETE', 'MODERATE', 'CHANGE_SETTINGS', 'DOWNLOAD', 'CREATE']
Principal #######: ['READ']
8. Advanced Permission Management¶
Using overwrite=False
will allow you to add Permissions Non-destructively.
Note: The default behavior is overwrite=True
which will replace the permissions for the given Principal.
# Step 8: Demonstrate additional set_permissions() options
print("\n=== Step 8: Demonstrating additional permission options ===")
# Add permissions non-destructively (overwrite=False)
print("Adding additional permissions non-destructively...")
main_folder.set_permissions(
principal_id=PRINCIPAL_ID,
access_type=["UPDATE"], # Add UPDATE permission
overwrite=False, # Don't overwrite existing permissions
)
# Verify the permissions were added
updated_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID)
print(f"Updated permissions after adding UPDATE: {updated_acl}")
You'll notice the output looks like:
=== Step 8: Demonstrating additional permission options ===
Adding additional permissions non-destructively...
Updated permissions after adding UPDATE: ['READ', 'DOWNLOAD', 'UPDATE']
9. Remove Permissions¶
Remove permissions for a specific principal by setting an empty access type list:
# Step 9: Demonstrate permission removal using set_permissions with empty list
print("\n=== Step 9: Removing specific permissions ===")
print(
f"Before removal - Principal {PRINCIPAL_ID} permissions: {main_folder.get_acl(principal_id=PRINCIPAL_ID)}"
)
# Remove permissions for specific principal by setting empty access_type
main_folder.set_permissions(
principal_id=PRINCIPAL_ID,
access_type=[], # Empty list removes all permissions for this principal
overwrite=True,
)
removed_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID)
print(f"After removal - Principal {PRINCIPAL_ID} permissions: {removed_acl}")
You'll notice the output looks like:
=== Step 9: Removing specific permissions ===
Before removal - Principal ####### permissions: ['READ', 'DOWNLOAD', 'UPDATE']
After removal - Principal ####### permissions: []
10. Delete Entire ACLs¶
Use delete_permissions()
to remove entire ACLs and revert to inheritance:
# Step 10: Demonstrate delete_permissions() with dry run
print("\n=== Step 10: Demonstrating delete_permissions() ===")
# First, let's set some permissions back so we have something to delete
sub_folder.set_permissions(principal_id=PRINCIPAL_ID, access_type=["READ", "UPDATE"])
print("Re-added permissions to sub-folder for demonstration")
# Dry run - see what would be deleted without actually deleting
print("\nDry run - showing what would be deleted:")
sub_folder.delete_permissions(dry_run=True, show_acl_details=True)
# Actually delete the permissions (this will make the sub-folder inherit from parent)
print("\nActually deleting ACL from sub-folder:")
sub_folder.delete_permissions(include_self=True)
# Verify inheritance
inherited_acl = sub_folder.get_acl(principal_id=PRINCIPAL_ID)
print(f"Sub-folder now inherits permissions: {inherited_acl}")
You'll notice the output looks like:
=== Step 10: Demonstrating delete_permissions() ===
Re-added permissions to sub-folder for demonstration
Dry run - showing what would be deleted:
=== DRY RUN: Permission Deletion Impact Analysis ===
📊 Summary: 1 entities with local ACLs to delete, 1 entities will change inheritance
🔍 Legend:
⚠️ = Local ACL will be deleted
🚫 = Local ACL will NOT be deleted
↗️ = Currently inherits permissions
🔒 = No local ACL (inherits from parent)
🔑 = Permission that will be removed
📍 = New inheritance after deletion
Sensitive Analysis (syn#######) [Folder] ⚠️ WILL DELETE LOCAL ACL → Will inherit from syn#######
├── 🔑 user_name_1 (#######): ['CHANGE_SETTINGS', 'MODERATE', 'DELETE', 'READ', 'DOWNLOAD', 'UPDATE', 'CHANGE_PERMISSIONS', 'CREATE'] → WILL BE REMOVED
└── 🔑 team_name_1 (#######): ['READ', 'UPDATE'] → WILL BE REMOVED
=== End of Dry Run Analysis ===
Actually deleting ACL from sub-folder:
Sub-folder now inherits permissions: []
11. Final Overview¶
Get a complete view of your permission structure:
# Step 11: Final ACL overview
print("\n=== Step 11: Final ACL overview ===")
final_overview = main_folder.list_acl(
recursive=True, include_container_content=True, log_tree=True
)
You'll notice the output looks like:
=== Step 11: Final ACL overview ===
ACL Tree Structure:
🔍 Legend:
🔒 = No local ACL (inherits from parent)
🔑 = Local ACL (custom permissions)
└── 🔑 Research Data (syn#######) [Folder]
└── user_name_1 (#######): CHANGE_PERMISSIONS, DOWNLOAD, CHANGE_SETTINGS, MODERATE, READ, DELETE, CREATE, UPDATE
Key Concepts Covered¶
Inheritance vs Local ACLs¶
- Inheritance: Entities inherit permissions from their parent by default
- Local ACLs: Create specific permissions that override inheritance
- Benefactor: The entity from which permissions are inherited
Permission Management Functions¶
get_permissions()
: Get current user's effective permissionsget_acl()
: Get specific principal's permissions on an entityset_permissions()
: Set permissions for a principallist_acl()
: List all ACLs in a hierarchydelete_permissions()
: Remove ACLs and revert to inheritance
Best Practices¶
- Use inheritance when possible for easier management
- Create local ACLs only when you need different permissions than the parent
- Use teams for managing group permissions
- Test with
dry_run=True
before deleting permissions - Use
list_acl()
to audit your permission structure
Common Use Cases¶
Research Collaboration¶
- Give collaborators READ/DOWNLOAD on data folders
- Restrict UPDATE/DELETE to data owners
- Use teams for lab group permissions
Data Sharing¶
- Use authenticated users (273948) for internal sharing
- Use public access (273949) for open data
- Create different permission levels for different data sensitivity
Hierarchical Access¶
- Set broad permissions at project level
- Override with restrictive permissions for sensitive sub-folders
- Use
delete_permissions()
to revert to parent permissions when needed
Source code for this tutorial¶
Click to show me
"""
Here is where you'll find the code for the Sharing Settings tutorial.
This tutorial demonstrates how to manage ACL (Access Control List) permissions
for entities in Synapse, including folders and their contents.
IMPORTANT: Before running this script, you MUST set the PRINCIPAL_ID variable
below to a valid Synapse user ID or team ID. You can find user IDs by looking
at their profile page in Synapse, or by using syn.getUserProfile().
Examples of principal IDs:
- A specific user ID (e.g., 123456)
- Authenticated users: 273948
- Public access: 273949
"""
import synapseclient
from synapseclient.models import Folder, Project
# REQUIRED: Set this to the Synapse user ID or team ID you want to grant permissions to
# Do NOT leave this as None - the script will not work properly
PRINCIPAL_ID = None # Replace with actual user/team ID
if PRINCIPAL_ID is None:
raise ValueError(
"You must set PRINCIPAL_ID to a valid Synapse user ID or team ID before running this script. "
"Examples: ###### (user ID), 273948 (authenticated users), 273949 (public)"
)
syn = synapseclient.login()
# Step 1: Get or create a project for this tutorial
print("=== Step 1: Getting project ===")
project = Project(name="My uniquely named project about Alzheimer's Disease").get()
# Step 2: Create a main folder to set custom sharing settings
print("\n=== Step 2: Creating main to set custom permissions ===")
main_folder = Folder(
name="Research Data",
description="Main folder for research data with custom sharing settings",
parent_id=project.id,
)
main_folder = main_folder.store()
print(f"Created main folder: {main_folder.name} (ID: {main_folder.id})")
# Step 3: Demonstrate get_permissions() - Get current user's permissions
print("\n=== Step 3: Getting current user's permissions ===")
permissions = main_folder.get_permissions()
print(f"Current user permissions on main folder: {permissions.access_types}")
# Step 4: Demonstrate get_acl() - Get ACL for specific principal
print("\n=== Step 4: Getting ACL for specific principal ===")
# First check what permissions the principal currently has (likely inherited from project)
current_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID, check_benefactor=True)
print(
f"Principal {PRINCIPAL_ID} current permissions (including inherited): {current_acl}"
)
# Check ACL only on the folder itself (not inherited)
folder_only_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID, check_benefactor=False)
print(f"Principal {PRINCIPAL_ID} permissions on folder only: {folder_only_acl}")
# Step 5: Demonstrate set_permissions() - Set specific permissions for the main folder
print("\n=== Step 5: Setting permissions on main folder ===")
main_folder_permissions = ["READ", "DOWNLOAD"]
main_folder.set_permissions(
principal_id=PRINCIPAL_ID,
access_type=main_folder_permissions,
modify_benefactor=False, # Create local ACL for this folder
overwrite=True,
)
print(
f"Set permissions for principal {PRINCIPAL_ID} on main folder: {main_folder_permissions}"
)
# Verify the permissions were set
new_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID, check_benefactor=False)
print(f"Verified new permissions: {new_acl}")
# Step 6: Create a sub-folder with different sharing settings
print("\n=== Step 6: Creating sub-folder with different permissions ===")
sub_folder = Folder(
name="Sensitive Analysis",
description="Sub-folder with more restrictive permissions",
parent_id=main_folder.id,
)
sub_folder = sub_folder.store()
print(f"Created sub-folder: {sub_folder.name} (ID: {sub_folder.id})")
# Set more restrictive permissions on the sub-folder
sub_folder_permissions = ["READ"] # More restrictive - only read access
sub_folder.set_permissions(
principal_id=PRINCIPAL_ID,
access_type=sub_folder_permissions,
modify_benefactor=False,
overwrite=True,
)
print(
f"Set more restrictive permissions for principal {PRINCIPAL_ID} on sub-folder: {sub_folder_permissions}"
)
# Step 7: Demonstrate list_acl() - List all ACLs
print("\n=== Step 7: Listing ACLs ===")
# List ACLs recursively for main folder and all contents
print("Folder ACL:")
recursive_acl_result = main_folder.list_acl(
recursive=True,
include_container_content=True,
log_tree=True, # This will also log the tree structure
)
print(f"Folder ({main_folder.id}) ACL entries:")
for entity_acl in recursive_acl_result.all_entity_acls:
print(f"\nEntity {entity_acl.entity_id} ACL:")
for acl_entry in entity_acl.acl_entries:
print(f" Principal {acl_entry.principal_id}: {acl_entry.permissions}")
# Step 8: Demonstrate additional set_permissions() options
print("\n=== Step 8: Demonstrating additional permission options ===")
# Add permissions non-destructively (overwrite=False)
print("Adding additional permissions non-destructively...")
main_folder.set_permissions(
principal_id=PRINCIPAL_ID,
access_type=["UPDATE"], # Add UPDATE permission
overwrite=False, # Don't overwrite existing permissions
)
# Verify the permissions were added
updated_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID)
print(f"Updated permissions after adding UPDATE: {updated_acl}")
# Step 9: Demonstrate permission removal using set_permissions with empty list
print("\n=== Step 9: Removing specific permissions ===")
print(
f"Before removal - Principal {PRINCIPAL_ID} permissions: {main_folder.get_acl(principal_id=PRINCIPAL_ID)}"
)
# Remove permissions for specific principal by setting empty access_type
main_folder.set_permissions(
principal_id=PRINCIPAL_ID,
access_type=[], # Empty list removes all permissions for this principal
overwrite=True,
)
removed_acl = main_folder.get_acl(principal_id=PRINCIPAL_ID)
print(f"After removal - Principal {PRINCIPAL_ID} permissions: {removed_acl}")
# Step 10: Demonstrate delete_permissions() with dry run
print("\n=== Step 10: Demonstrating delete_permissions() ===")
# First, let's set some permissions back so we have something to delete
sub_folder.set_permissions(principal_id=PRINCIPAL_ID, access_type=["READ", "UPDATE"])
print("Re-added permissions to sub-folder for demonstration")
# Dry run - see what would be deleted without actually deleting
print("\nDry run - showing what would be deleted:")
sub_folder.delete_permissions(dry_run=True, show_acl_details=True)
# Actually delete the permissions (this will make the sub-folder inherit from parent)
print("\nActually deleting ACL from sub-folder:")
sub_folder.delete_permissions(include_self=True)
# Verify inheritance
inherited_acl = sub_folder.get_acl(principal_id=PRINCIPAL_ID)
print(f"Sub-folder now inherits permissions: {inherited_acl}")
# Step 11: Final ACL overview
print("\n=== Step 11: Final ACL overview ===")
final_overview = main_folder.list_acl(
recursive=True, include_container_content=True, log_tree=True
)