Repository navigation
Local POSIX Access Design Strategies #1618
chirayupatel9
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
DataFed Local POSIX Access Design Strategies Overview
This document provides a comprehensive and detailed overview of five different design strategies for enabling local POSIX access to DataFed repositories. Each strategy represents a distinct architectural approach to balancing security, performance, usability, and operational complexity in high-performance computing (HPC) environments.
The strategies address the fundamental challenge of providing secure, efficient access to repository data while maintaining the performance characteristics that HPC workflows demand. They range from simple file linking approaches to complex namespace isolation systems, each offering different trade-offs that must be carefully considered based on specific use case requirements.
Design Strategy 1: Temporary POSIX User Mapping with ACLs
Overview: Create temporary POSIX users on the repository systems that map to application users, using Access Control Lists (ACLs) to grant read/write permissions without changing file ownership.
Implementation:
Approach: Creates temporary POSIX user accounts with file-specific ACLs for direct repository access. This strategy leverages the native Linux user management and access control systems to provide secure, isolated access to repository files.
Key Components
Temporary POSIX Accounts
df_tmp_007,df_tmp_008, etc.) are created on-demand when users request accessPOSIX ACLs (Access Control Lists)
setfaclto grant read, write, or execute permissions on specific filesSSH Key-based Authentication
Automatic Cleanup Mechanisms
Implementation Flow
Repository Side Setup
User Side Access
Pros
Cons
Use Cases
Security Considerations
User Sequence Diagram
sequenceDiagram participant Bob as Bob (User) participant DataFed as DataFed Client participant Hub as DataFed Hub participant Repo as Repository Service participant KDC as Kerberos Service participant POSIX as POSIX Filesystem Bob ->> DataFed: Login to DataFed (datafed login) DataFed ->> Hub: Verify User Hub -->> DataFed: ACK Bob ->> DataFed: User requests Repo addr (datafed connect $repo_id) DataFed ->> Hub: datafed connect $repo_id Hub -->> DataFed: Return Repo Addr DataFed ->> Repo: Tries to connect alt unable to connect Repo -> Bob: Timeout. end Repo -->> DataFed: Acknowledge connected, return Auth Addr DataFed ->> DataFed: Check Ticket alt no Ticket Bob ->> DataFed: enter username/password DataFed ->> KDC: New Ticket request KDC -->> DataFed: User Ticket DataFed ->> DataFed: Cache Ticket end DataFed ->> Repo: TGT + datafed token Repo ->> Hub: Verifies Datafed User and User logged in with kerberos is same Hub ->> Hub: Add Lock flag with username Hub ->> Repo: Ack, Lock Flag, RW Perm Repo ->> POSIX: setfacl -m u:bob:r /mnt/data/file.txt alt Session expires or logout Note over Repo, POSIX: Monitor session or token expiry Repo -->> DataFed: returns: /mnt/data/file.txt DataFed -->> Bob: cat: /mnt/data/file.txt Repo ->> POSIX: setfacl -x u:bob /mnt/data/file.txt endSteps:
Bob logs into DataFed using the CLI command datafed login. The DataFed client contacts the Hub to verify the user.
Once authenticated, Bob requests access to a file by calling datafed connect $repo_id.
The Hub resolves the address of the repository holding the file and returns it to the DataFed client.
The DataFed client attempts to connect to the Repo service. If unsuccessful, a timeout is returned.
Upon successful connection, the Repo checks whether Bob has a valid Kerberos ticket.
If no valid ticket is found:
The client prompts Bob to enter credentials.
A Kerberos Ticket Granting Ticket (TGT) is requested from the Kerberos Service (KDC).
The TGT is cached locally.
A session monitor is launched on the Repo side, watching for the Kerberos ticket’s expiration.
When the Kerberos session ends (via kdestroy or timeout), the Repo revokes Bob’s access:
Here is a simple implementation
Repository / Admin Side
(executed by the “repo‑controller” service running as root)
Allocate POSIX permission to an user for a file.txt.
u: User permissions (named user, other than owner)
:rw Read / Write on the file
Set Permissions for a Specific Group
g: Group permissions (named group, other than owning group)
:r Grants group read permission
Set Default ACL on a Directory
New files in /data/shared will grant alice rwx.
Set Multiple ACLs at Once
Sets permissions for user and group simultaneously.
Remove All ACLs (reset to basic permissions)
Clears all extended ACLs (restores chmod-based permissions).
View Current ACLs
Sample output:
Grant ACLs only on authorised paths
Generate short‑lived SSH key + drop into Hub
Audit logging
User / Client Side (Bob)
Download / save the temp SSH private key
SSH to the repository host as df_tmp_007
Prompt now shows:
Read or copy the authorised file (RO example)
Optional: keep session running during HPC job
Bob can launch the HPC job from this shell or simply leave the shell open while the job reads the file under the temp UID.
Early exit
exit ends SSH sessionACL remains valid until TTL timer fires (unless Bob presses “Revoke now” in Hub).
What happens if Milly tries to delete while Bob is reading?
Bob (temp UID) has the file open.
Milly requests DELETE via Hub; repo controller checks lsof +D file or fuser and sees an open FD under df_tmp_007.
Hub responds “File is currently in use by Bob – try later.”
After Bob’s FD closes (shell exit or job close()), Milly’s next DELETE will succeed.
(Kernel enforces the lock: inode can’t be deleted while a link count > 0 and FD open.)
How every commitment is met
setfacl -m u:df_tmp_xxxgives precise per‑file perms.repo_svc, but Bob accesses via ACL.revoke_acl.shremoves ACLs & account.Design Strategy 2: FUSE-based Virtual Filesystem
Overview: Implement a FUSE (Filesystem in Userspace) layer that presents authorized files to users while maintaining the underlying service account ownership.
Implementation:
Approach: Uses FUSE (Filesystem in Userspace) to create virtual filesystem mounts with JWT token authentication. This strategy provides a transparent filesystem interface while maintaining centralized access control through token validation.
Key Components
FUSE Daemon (
df-fuse)JWT Token Authentication
Automatic Token Refresh
File Locking Mechanisms
Implementation Flow
Token Request and Mount
File Operations
Token Refresh Process
Pros
Cons
Use Cases
Performance Characteristics
User sequence Diagram
sequenceDiagram participant Bob as HPC User (Bob) participant DataFed as DataFed Client participant Hub as DataFed Hub participant Repo as Repo + Mount Manager participant FUSE as FUSE or bindfs Mountpoint participant FS as POSIX Filesystem participant KDC as Kerberos Server participant DB as Metadata Database Bob ->> DataFed: Login to DataFed (datafed login) DataFed ->> Hub: Verify User Hub -->> DataFed: ACK Bob ->> DataFed: User requests Repo addr (datafed connect $repo_id) DataFed ->> Hub: datafed connect $repo_id Hub -->> DataFed: Return Repo Addr DataFed ->> Repo: Tries to connect alt unable to connect Repo -> Bob: Timeout. end Repo -->> DataFed: Acknowledge connected, return Auth Addr DataFed ->> DataFed: Check Ticket alt no Ticket Bob ->> DataFed: enter username/password DataFed ->> KDC: New Ticket request KDC -->> DataFed: User Ticket DataFed ->> DataFed: Cache Ticket end DataFed ->> Repo: TGT + datafed token Repo ->> Hub: Verifies Datafed User and User logged in with kerberos is same Hub ->> Hub: Add Lock flag with username Hub ->> Repo: Ack, Lock Flag, RW Perm %% ---------- Authorization + Access Setup ---------- DataFed ->> DataFed: datafed access d/456 --lock DataFed ->> Hub: Check permissions for Bob on d/456 Hub -->> DataFed: Access granted DataFed ->> Repo: Request hard link for Bob to d/456 with lock Repo ->> FS: ln /mnt/shared/master/file_456.txt /mnt/shared/bob/file_bob.txt FS -->> Repo: Hard link created Repo ->> DB: Record lock (locked=true, locked_by=Bob) DB -->> Repo: Lock recorded Repo -->> DataFed: ACK - file_bob.txt ready %% ---------- File Access Phase with Lock ---------- DataFed ->> DataFed: file_bob.txt ready in /mnt/shared/bob %% ---------- Bob Opens File (Implicit Locking) ---------- DataFed ->> FUSE: open("/mnt/shared/bob/file_bob.txt", O_RDWR) FUSE ->> Repo: Check write permission Repo ->> DB: Check if file is already locked alt Not locked Repo ->> DB: Set locked=true, locked_by=Bob DB -->> Repo: Lock set Repo -->> FUSE: Allow open FUSE -->> Bob: File opened for writing else Locked by another user Repo -->> FUSE: Deny write (EACCES) FUSE -->> Bob: Permission denied end %% ---------- Session Completion + Cleanup ---------- Bob ->> DataFed: file access complete DataFed ->> Repo: Dispose hard link /mnt/shared/bob/file_bob.txt Repo ->> DB: Clear lock Repo ->> FS: unlink /mnt/shared/bob/file_bob.txt FS -->> Repo: Link removed Repo -->> DataFed: Cleanup doneSteps:
User Login: Bob (the HPC User) initiates a login to the DataFed Client using the command datafed login.
Verification: The DataFed Client contacts the DataFed Hub to verify Bob's identity. The Hub acknowledges the verification.
Repo Connection: Bob requests to connect to a specific repository (datafed connect $repo_id).
Address Retrieval: The DataFed Client asks the Hub for the repository's network address, and the Hub provides it.
Direct Connection & Auth: The DataFed Client connects to the Repo. The Repo acknowledges the connection and provides an authentication address.
Kerberos Ticket Check: The DataFed Client checks for a cached Kerberos authentication ticket.
If no ticket exists: Bob is prompted for his username/password, which the client uses to request a new ticket from the Kerberos Server (KDC). The client then caches this new ticket.
Authentication: The DataFed Client sends the Kerberos ticket (TGT) and a DataFed token to the Repo.
Final Verification: The Repo contacts the Hub to ensure the DataFed user and the Kerberos user are the same. The Hub confirms this, adds a lock flag for the user's session, and grants Read/Write permissions to the Repo.
Access Request: Through the client, Bob requests locked access to a data object (e.g., datafed access d/456 --lock).
Permission Check: The DataFed Client asks the Hub if Bob has permission to access d/456. The Hub grants access.
Hard Link Creation: The client requests that the Repo create a locked hard link to the data for Bob.
Filesystem Operation: The Repo instructs the POSIX Filesystem (FS) to create a hard link from the master file to a file in Bob's personal directory (e.g., ln /mnt/shared/master/file_456.txt /mnt/shared/bob/file_bob.txt).
Database Update: After the FS confirms the link is created, the Repo records the lock in the Metadata Database (DB), marking it as locked by Bob.
Confirmation: The Repo notifies the DataFed Client that the personal, locked file (file_bob.txt) is ready for use.
File Open Request: Bob attempts to open his personal file (file_bob.txt) for writing. This request is intercepted by the FUSE mountpoint.
Permission Check: FUSE asks the Repo to verify write permissions.
Lock Verification: The Repo checks the DB to see if the file is locked.
If not locked: The Repo immediately sets the lock for Bob in the DB and tells FUSE to allow the file to be opened. Bob can now write to the file.
If locked by another user: The Repo tells FUSE to deny the request, and Bob receives a "Permission denied" error.
Access Complete: Bob signals that he is finished with the file.
Cleanup Request: The DataFed Client tells the Repo to dispose of the hard link.
Lock Release: The Repo updates the DB to clear the lock on the file.
File Unlink: The Repo instructs the FS to remove the hard link from Bob's directory.
Final Confirmation: After the FS confirms the removal, the Repo notifies the DataFed Client that the cleanup is complete.
Here is a simple scenario
Use case scenario
Don is a scientist, fuse mounting few directories in to his local computer with the help of sshfs.
Susie is a grad student who wants to have access to those directories as she needs to read those files for some research purposes.
Later Don gives Susie access to those files by creating a fuseaccess group so other users in the system doesn't get access those files.
Create fuseaccess group
Add Don and Susie to the fuseaccess group
Verify group membership
Create a secure mount point
Additional security hardening
To get id's
To Mount
Basic mount with security options
Enhanced mount with additional security and performance options
somepath can be anything in don's local directory /home/don/code
uid = user id
gid = group id
umask=007: sets permission to 770 on files/dirs (owner/group full, others none)
Mount option explanations:
allow_other: Allows users other than the mounting user to access the filesystemdefault_permissions: Enables permission checking on the client sidecompression=no: Disables compression for better performance on fast networkslarge_read,large_write: Enables larger read/write operations for better performanceServerAliveInterval=60: Sends keep-alive packets every 60 secondsServerAliveCountMax=3: Maximum number of unacknowledged keep-alive packetsIdentityFile: Specifies the private key file for authenticationStrictHostKeyChecking=yes: Ensures host key verificationUserKnownHostsFile: Specifies the known hosts fileError Handling and Troubleshooting
Check if mount was successful
mount | grep fuse df -h /mnt/shared_securedataCommon issues and solutions
Debug SSHFS issues
To unmount
Monitoring and Maintenance
Check mount status and performance
Security monitoring
Regular maintenance tasks
Summary of sshfs
sshfsis not parallel or pipelined❌ Not recommended for large file access in HPC. SSHFS is convenient but slow and not scalable.
Design Strategy 3: Bind Mount with Namespace Isolation
Overview: Use Linux namespaces and bind mounts to give users isolated views of authorized files.
Implementation:
Approach: Creates isolated Linux namespaces with bind-mounted repository files for secure, jailed access. This strategy provides the highest level of security by completely isolating user processes from the host system while maintaining native filesystem performance.
Key Components
User Namespace Isolation
Mount Namespace Isolation
PID Namespace Isolation
UID/GID Remapping
Implementation Flow
Repository Side Namespace Creation
User Side Access
Automatic Cleanup
Pros
Cons
Use Cases
Security Features
User Sequence Diagram
sequenceDiagram participant Bob as HPC User (Bob) participant DataFed as DataFed Client participant Hub as DataFed Hub participant Repo as Repo + Mount Manager participant FUSE as FUSE or bindfs Mountpoint participant DB as Metadata DB participant FS as POSIX Filesystem participant KDC as Kerberos Service Bob ->> DataFed: Login to DataFed (datafed login) DataFed ->> Hub: Verify User Hub -->> DataFed: ACK Bob ->> DataFed: User requests Repo addr (datafed connect $repo_id) DataFed ->> Hub: datafed connect $repo_id Hub -->> DataFed: Return Repo Addr DataFed ->> Repo: Tries to connect alt unable to connect Repo -> Bob: Timeout. end Repo -->> DataFed: Acknowledge connected, return Auth Addr DataFed ->> DataFed: Check Ticket alt no Ticket Bob ->> DataFed: enter username/password DataFed ->> KDC: New Ticket request KDC -->> DataFed: User Ticket DataFed ->> DataFed: Cache Ticket end DataFed ->> Repo: TGT + datafed token Repo ->> Hub: Verifies Datafed User and User logged in with kerberos is same Hub ->> Hub: Add Lock flag with username Hub ->> Repo: Ack, Lock Flag, RW Perm Repo ->> DB: Locks the file Repo ->> FS: Resolve path for /d/abc123 FS -->> Repo: /repo/data/abc123.txt %% Create namespace for user access Repo ->> Repo: unshare --user --mount --map-root-user --fork Repo ->> Repo: mount --make-private / Repo ->> Repo: mkdir /mnt/view %% Mount only authorized file Repo ->> Repo: mount --bind /repo/data/abc123.txt /mnt/view/abc123.txt Repo ->> Repo: mount -o remount,bind,ro /mnt/view/abc123.txt %% UID/GID remapping for user namespace Repo ->> Repo: newuidmap/newgidmap to map Bob's UID/GID %% Start jailed shell or session Repo ->> Bob: Namespace shell with /mnt/view/abc123.txt mounted Bob ->> FS: Reads file /mnt/view/abc123.txt FS -->> Bob: File content %% Bob exits jail Bob ->> Repo: Exit Repo ->> Repo: umount /mnt/view/abc123.txt Repo ->> DB: Resets Lock flag Repo ->> Hub: Release Lock Flag Hub -->> Repo: ACK Repo ->> DataFed: Operation complete DataFed -->> Bob: Session endedSteps:
User Login: Bob (the HPC User) logs into the DataFed Client with datafed login.
Verification: The client contacts the DataFed Hub to verify Bob's credentials.
Repo Connection: Bob requests a connection to a specific repository via the client (datafed connect $repo_id). The client gets the repository's address from the Hub.
Authentication Handshake: The client connects to the Repo, which acknowledges the connection.
Kerberos Ticket: The client checks for a valid Kerberos ticket. If one isn't found, it prompts Bob for his credentials to get a new ticket from the Kerberos Service (KDC).
Token Submission: The client sends the Kerberos ticket and a DataFed token to the Repo.
Final Permission Grant: The Repo confirms with the Hub that the Kerberos and DataFed users match. The Hub applies a session lock for the user and grants the Repo read/write permissions for the session.
File Lock: The Repo immediately locks the requested file in the Metadata DB to prevent conflicts.
Path Resolution: The Repo asks the POSIX Filesystem (FS) for the true, physical path of the requested data object (e.g., /d/abc123 resolves to /repo/data/abc123.txt).
Create Sandbox: The Repo creates a new, isolated user and mount namespace (unshare). This is a lightweight container or "jail" that separates the user's session from the main system.
Create View: Inside this sandbox, the Repo creates a new mount point (e.g., /mnt/view).
Mount File: The Repo uses a bind mount to make the specific data file (abc123.txt) appear inside the user's sandboxed view. It then remounts this file as read-only to ensure data integrity.
Map User ID: The system maps Bob's user/group ID into the namespace so file ownership and permissions appear correct to him.
Start Jailed Session: The Repo provides Bob with a shell session that is locked inside this secure namespace. From Bob's perspective, the filesystem only contains the single file he requested.
Read File: Bob reads the file from its path inside his isolated view (/mnt/view/abc123.txt).
Content Served: The FS provides the file's content to Bob.
Exit: Bob exits the jailed shell session.
Unmount: The Repo automatically unmounts the file from the sandboxed view.
Release Locks: The Repo resets the lock flag in the Metadata DB and notifies the Hub to release the session lock.
Complete: The Repo signals to the DataFed Client that the operation is complete, and the client informs Bob that his session has ended.
Here is a simple implementation
Scenario
Create a test file
repo_host$ nano ~/mytest.txtGive permissions to the files
Copy the file to tmp location
Creating the namespace with unshare
isolates the entire filesystem namespace from any other namespaces on the system
Read only file path
$# RO_SRC=/tmp/mytest.txtFile path in mount
$# LANDING=/mnt/view/mytest.txtCreate a directory in namespace with the landing path
Create a bind mount in the namespace (add comments )
Mount the created bind mount
Check if it has mounted or not
Unmount
$# umount -R /mnt/view/mytest.txtRetrying without sudo
This tells us definitively that:
An AppArmor security profile is blocking the action.
The profile is named unprivileged_userns.
It is specifically denying the unshare command the sys_admin capability, which is required to create the user namespace mapping, even though it's a "fake" root inside the namespace.
This command installs the app armor utils and allow unprivileged users to create and interact with user namespaces.
Log any actions within those namespaces that would normally violate the associated AppArmor profile for "unprivileged userns".
$ sudo apt-get update && sudo apt-get install apparmor-utils $ sudo aa-complain unprivileged_usernsLet's create the files we will use to test our jail's isolation.
Create a working directory
Create a file that we WILL allow into the jail
Create a file that should NOT be visible from the jail
This is the core command. We use unshare to launch a new bash shell inside a new set of namespaces, mapping our user to root within them.
Prevent any mount changes from propagating back to the host system
$# mount --make-private /Create the directory for our jail in a location you have write access to
Create a directory inside the jail to hold our authorized content
Create an empty placeholder file that will serve as the mount point
Use a bind mount to make ONLY the authorized file visible inside the jail
Verify that the unauthorized file is NOT in our prepared jail
Create a 'bin' directory in the jail
Copy the bash executable
Create directories for the necessary librarie
Copy the libraries that bash depends on
Enter the chroot jail
Check the contents of your new root directory.
Confirm you can read the authorized file.
Confirm you CANNOT see anything from the host filesystem.
Exit the Environment
Design Strategy 4: Capability-Based Token System
Overview: Implement a capability token system where the hub issues time-limited tokens that can be exchanged for temporary file access.
Implementation:
Approach: Creates hard links to repository files in private directories, controlled by JWT capability tokens. This strategy provides a simple, efficient way to grant access to repository files while maintaining security through token validation.
Key Components
Hard Link Creation
JWT Capability Tokens
Private Directory Structure
/tmp/datafed/File Access Control
Implementation Flow
Token Request and Link Creation
File Access and Usage
Automatic Cleanup
Pros
Cons
Use Cases
Security Considerations
User Sequence Diagram
sequenceDiagram participant Bob as HPC User (Bob) participant DataFed as DataFed Client participant Hub as DataFed Hub participant KDC as Kerberos Server participant Repo as Repo participant FUSE as FUSE or bindfs Mountpoint participant FS as POSIX Filesystem Bob ->> DataFed: Login to DataFed (datafed login) DataFed ->> Hub: Verify User Hub -->> DataFed: ACK Bob ->> DataFed: User requests Repo addr (datafed connect $repo_id) DataFed ->> Hub: datafed connect $repo_id Hub -->> DataFed: Return Repo Addr DataFed ->> Repo: Tries to connect alt unable to connect Repo -> Bob: Timeout. end Repo -->> DataFed: Acknowledge connected, return Auth Addr DataFed ->> DataFed: Check Ticket alt no Ticket Bob ->> DataFed: enter username/password DataFed ->> KDC: New Ticket request KDC -->> DataFed: User Ticket DataFed ->> DataFed: Cache Ticket end DataFed ->> Repo: TGT + datafed token Repo ->> Hub: Verifies Datafed User and User logged in with kerberos is same Hub ->> Hub: Add Lock flag with username Hub ->> Repo: Ack, Lock Flag, RW Perm %% ---------- Authorization + Access Setup ---------- Bob ->> DataFed: datafed access d/456 DataFed ->> Hub: Check permissions for Bob on d/456 Hub -->> DataFed: Access granted DataFed ->> Repo: Request hard link for Bob to d/456 Repo ->> FS: ln /mnt/shared/master/file_456.txt /mnt/shared/bob/file_bob.txt FS -->> Repo: Hard link created Repo -->> DataFed: ACK - file_bob.txt ready %% ---------- File Access Phase ---------- DataFed ->> DataFed: file_bob.txt ready in /mnt/shared/bob DataFed ->> FUSE: Open /mnt/shared/bob/file_bob.txt FUSE ->> FS: Read/write access FS -->> FUSE: File data FUSE -->> Bob: File read/write complete %% ---------- Session Completion + Cleanup ---------- Bob ->> DataFed: File access / Session complete DataFed ->> Repo: Dispose hard link /mnt/shared/bob/file_bob.txt Repo ->> FS: unlink /mnt/shared/bob/file_bob.txt FS -->> Repo: Link removed Repo -->> DataFed: Cleanup doneSteps:
User Login: Bob (the HPC User) initiates a login to the DataFed Client using the command datafed login.
Verification: The DataFed Client contacts the DataFed Hub to verify Bob's identity. The Hub acknowledges the verification.
Repo Connection: Bob requests a connection to a specific repository (datafed connect $repo_id). The client asks the Hub for the repository's network address and receives it.
Authentication Handshake: The DataFed Client connects to the Repo, which acknowledges the connection and returns its authentication address.
Kerberos Ticket Check: The client checks for a cached Kerberos authentication ticket. If one is not found, it prompts Bob for his credentials and requests a new ticket from the Kerberos Server (KDC).
Token Submission: The client sends the Kerberos ticket (TGT) and a DataFed token to the Repo.
Final Permission Grant: The Repo confirms with the Hub that the Kerberos user and DataFed user are the same. The Hub applies a session lock for the user and grants the Repo read/write permissions for the session.
Access Request: Bob, through the client, requests access to a data object (datafed access d/456).
Permission Check: The DataFed Client checks with the Hub to confirm Bob has permission to access d/456. The Hub grants access.
Hard Link Creation: The DataFed Client requests that the Repo create a hard link to the file for Bob.
Filesystem Operation: The Repo instructs the POSIX Filesystem (FS) to create a hard link from the master file to a file in Bob's personal directory (e.g., ln /mnt/shared/master/file_456.txt /mnt/shared/bob/file_bob.txt).
Confirmation: The FS confirms the link is created, and the Repo notifies the DataFed Client that the file is ready for use at the new path (file_bob.txt).
File Open: Bob opens the file for reading or writing. This request goes through the FUSE layer.
Direct Access: The FUSE layer forwards the read or write request directly to the underlying Filesystem.
Data Transfer: The Filesystem performs the requested operation and returns the file data to FUSE, which then passes it back to Bob. There is no file-level lock check performed at this stage.
Access Complete: Bob signals that he is finished with the file or that his session is complete.
Cleanup Request: The DataFed Client instructs the Repo to dispose of the hard link.
File Unlink: The Repo tells the FS to remove the hard link (unlink /mnt/shared/bob/file_bob.txt).
Complete: After the FS confirms the link is removed, the Repo notifies the DataFed Client that cleanup is complete.
Here is a simple implementation
If user does not own the file
$ sudo chown username: file1 $ ln file1 file2 # ln sourceFile destFileTo check hard link is created
Deleting a hardlink
Other way around deleting all the hard links
Alternatively we can manage the file remove functionality in DataFed Client
OR
When deleting from Client Web, the raw data can deleted without removing the metadata.
This will go into the shell/bash and look for the file, get the inum of the file, find all the hard links user has created.
The user can create hard link anywhere from /mnt/(Allocation spaces) and ~/
But the process of finding all the hard links is costlier
find+stattimeOnce the user's session is ended, the datafed client has the file and knows where the hardlink is created or atleast the datafed client has the inum and it can find all the hardlinks related to that inum
Some limitations
Cannot Cross Filesystems
Cannot Link to Directories (by default)
Indistinguishable from the Original
All hard links to a file are equal — there is no "original".
This makes it hard to track down which filename created the content.
Breaks When Files Are Replaced (Not Edited)
If a file is edited, all hard links reflect the change (they share content).
But if a file is replaced (e.g., echo "x" > file), a new inode is created, and old links are unaffected — now pointing to stale data.
Here is a simple implementation
Scenario
Repo, bob and gray are three regular users in the same group. Bob and gray wants to access a file which is owned by Repo via hard-link. Bob has to update the file and gray will use the different file for a task. Once they are done with the file the hard-link should be removed. The file bob has access, should not able to accessible by gray and vice versa.
SudoRequired commandsFor adding users in the group
bob
cd /mnt/shared/acl
repo
cd
Add file to the sharedaccess
Repohas a shared directory in/mnt/sharedBobandGrayhave their own directories in/mntasaccess_bobandaccess_grayrespectively.All the directories in
/mnt/sharedhas the same group assharedaccessRepoCreates an Hardlink for bob.bobUpdates the file.$ nano /mnt/shared/access_bob/newdata.txt # Result Repo created file Bob was herebobends his sessionReporevokes hard-link for bobRepocreates an Hard-link for grayGrayreads the filemore /mnt/shared/access_tester/newdata.txt # Result Repo created file Bob was hereGraylater updates the filenano /mnt/shared/access_tester/newdata.txt # Result Repo created file Bob was here Gray modified the fileReporevokes the permission forGraywhen session exits.Design Strategy 5: WebDAV/SFTP Gateway with Authorization Proxy
Overview: Deploy protocol gateways that authenticate users and proxy authorized file operations.
Implementation:
Approach: Provides SFTP access to repository files through a gateway service with token-based authentication. This strategy offers a familiar interface for many users while maintaining security through centralized token validation.
Key Components
SFTP Gateway Service
Token Validation System
Service Account Operations
Session-based Access Control
Implementation Flow
Gateway Setup and Configuration
User Authentication and Access
File Operation Processing
Pros
Cons
Use Cases
Performance Characteristics
User sequence Diagram for webdav
sequenceDiagram %% PARTICIPANTS actor BobBrowser as Bob – browser actor BobShell as Bob – shell / CLI participant Hub as DataFed Hub participant Client as WebDAV client participant Gateway as NGINX + mod_dav participant Proxy as Auth‑proxy participant FS as POSIX FS %% 0. Bob logs in to the Hub UI BobBrowser->>Hub: OAuth login Hub-->>BobBrowser: Session cookie %% 1. Bob requests WebDAV token BobBrowser->>Hub: "Get WebDAV token"<br/>path=/project42/inputs/config.json<br/>mode=RO ttl=1 h Hub-->>BobBrowser: token tk‑9a12 (download)<br/>file saved as ~/token.jwt %% 2. Bob mounts the share from his shell BobBrowser-->>BobShell: info (URL + token file path) BobShell->>Client: mount -t davfs https://repo.example/dav ~/repo42 \\ -o token=/home/bob/token.jwt %% 3. TLS connection & auth Client->>Gateway: PROPFIND /dav/… (Authorization: Bearer tk‑9a12) Gateway->>Proxy: /auth_dav token=tk‑9a12 Proxy->>Hub: POST /introspect tk‑9a12 (cache miss) Hub-->>Proxy: 200 OK user=bob scope=/project42 cache=15 min Proxy-->>Gateway: 200 allow %% 4. Data request Client->>Gateway: GET /dav/project42/inputs/config.json Gateway->>Proxy: /auth_dav (cache hit) → allow Gateway->>FS: open RO /repo/project42/inputs/config.json (svc UID) FS-->>Gateway: fd → data Gateway-->>Client: 200 OK (stream file) Client-->>BobShell: file delivered to ~/repo42/… %% 5. Hub pushes revoke before TTL Hub-->>Proxy: PUSH revoke user=bob Proxy->>Proxy: purge bob cache %% 6. Next client request is denied Client->>Gateway: GET /dav/project42/inputs/config.json Gateway->>Proxy: /auth_dav (cache miss → deny) Proxy-->>Gateway: 403 Forbidden Gateway-->>Client: 403 Forbidden Client-->>BobShell: I/O error (access revoked)Steps:
Web Login: Bob logs into the DataFed Hub via his web browser, likely using a standard method like OAuth. The Hub responds by giving his browser a session cookie.
Token Request: Within the Hub's web UI, Bob requests a WebDAV token. He specifies the exact path he needs access to (/project42/inputs/config.json), the access mode (Read-Only), and a time-to-live (1 hour).
Token Download: The Hub generates a unique token (tk‑9a12) and provides it to Bob's browser as a downloadable file, which he saves as ~/token.jwt.
Mount Command: Bob switches to his shell and uses a WebDAV client (like davfs) to execute a mount command.
Authentication: He provides the repository URL and specifies the path to the downloaded token file, which will be used for authentication instead of a password.
First Request: The WebDAV client sends an initial request (PROPFIND to list directory properties) to the NGINX Gateway. It includes the token in the Authorization: Bearer header.
Auth Check: The Gateway passes the token to the Auth-proxy for validation.
Token Introspection: Since the Auth-proxy has never seen this token before (cache miss), it contacts the DataFed Hub to validate it.
Hub Validation: The Hub confirms the token is valid for user "bob" and the requested scope (/project42). It tells the proxy this validation can be cached for 15 minutes.
Access Granted: The Auth-proxy gives the Gateway the green light to proceed.
File Request: The WebDAV client sends a GET request to read the config.json file.
Cached Auth: The Gateway checks with the Auth-proxy again. This time, the proxy finds the valid token in its cache (cache hit) and immediately allows the request without contacting the Hub.
File Retrieval: The Gateway reads the file from the POSIX Filesystem.
File Delivery: The Gateway streams the file's content back to the WebDAV client, which makes it available to Bob in his local mount point (~/repo42).
Revoke Command: For security or administrative reasons, the Hub pushes a command to the Auth-proxy to revoke all access for user "bob".
Cache Purge: The Auth-proxy immediately purges its cache, deleting the stored validation for Bob's token.
New Request: The WebDAV client sends another request for the file.
Auth Failure: The Gateway checks with the Auth-proxy. The proxy can't find the token in its cache and now denies the request (cache miss → deny).
Forbidden Error: The proxy returns a 403 Forbidden error to the Gateway, which forwards it to the WebDAV client.
I/O Error: The client reports an "I/O error" to Bob's shell, indicating that his access has been revoked and the mount is no longer functional.
User sequence Diagram for SFTP
sequenceDiagram %% PARTICIPANTS actor Bob as Bob participant Hub as DataFed Hub participant Gateway as sshd (+ sftp‑subsystem) participant Proxy as Auth‑proxy (path authoriser) participant FS as POSIX FS %% 0. Bob asks the Hub for an ephemeral SFTP certificate Bob->>Hub: Request SSH cert (TTL 2 h) for /project42 scope Hub-->>Bob: hub_bob_cert.pub (signed OpenSSH certificate) %% 1. Bob starts the SFTP session Bob->>Gateway: SSH handshake (cert=hub_bob_cert.pub, user=bob) %% 2. sshd validates the certificate Gateway->>Hub: AuthorizedPrincipalsCommand check (bob, cert sig) Hub-->>Gateway: OK expires=2 h Gateway-->>Bob: SSH success (opens SFTP subsystem) %% 3. Bob downloads a file (READ) Bob->>Gateway: SFTP: OPEN /project42/inputs/config.json flags=READ Gateway->>Proxy: /authorize user=bob path=/project42/inputs/config.json mode=RO Proxy-->>Gateway: allow (cached 15 min) Gateway->>FS: open RO /repo/project42/inputs/config.json (svc UID) FS-->>Gateway: fd ➜ data Gateway-->>Bob: SFTP: DATA %% 4. Bob uploads scratch output (WRITE) Bob->>Gateway: SFTP: OPEN /project42/scratch/bob_tmp/out.dat flags=WRITE Gateway->>Proxy: /authorize (cached miss → ask Hub) Proxy-->>Gateway: allow Gateway->>FS: open RW /repo/project42/scratch/bob_tmp/out.dat FS-->>Gateway: fd Gateway-->>Bob: SFTP: OK (Bob sends DATA packets) %% 5. Hub revokes Bob before TTL expires Hub-->>Proxy: PUSH revoke user=bob Proxy->>Proxy: purge bob cache %% 6. Next Bob operation is denied, channel closes Bob->>Gateway: SFTP: OPEN /project42/inputs/config.json flags=READ Gateway->>Proxy: /authorize (cache miss, revoked) Proxy-->>Gateway: deny Gateway-->>Bob: SFTP: STATUS = PERMISSION DENIED Bob-->>Gateway: SSH disconnectSteps:
Request Certificate: Bob asks the DataFed Hub for an ephemeral (short-lived) SSH certificate. He specifies the scope of his access (e.g., /project42) and a Time-To-Live (TTL) of 2 hours.
Receive Certificate: The Hub generates a unique, signed OpenSSH certificate and sends the file (hub_bob_cert.pub) back to Bob.
SSH Handshake: Bob initiates an SFTP connection to the Gateway (sshd server), presenting the certificate as his method of authentication.
Certificate Validation: The Gateway uses a command (AuthorizedPrincipalsCommand) to ask the DataFed Hub if the certificate is valid for the user "bob".
Hub Confirmation: The Hub verifies the certificate's signature, confirms it's valid, and notes its 2-hour expiration.
Connection Success: The Gateway authenticates Bob and opens the SFTP subsystem, establishing the session.
Open Request: Bob sends a command to open a file for reading (/project42/inputs/config.json).
Authorize Path: The Gateway forwards the request details (user, path, and read-only mode) to the Auth-proxy.
Permission Granted: The Auth-proxy confirms Bob is allowed to read this file, allows the request, and caches this permission for 15 minutes.
File Retrieval: The Gateway opens the file on the POSIX Filesystem and streams its data back to Bob.
Write Request: Bob attempts to open a different file for writing in his scratch directory.
Authorize Path (Cache Miss): The Gateway again asks the Auth-proxy for permission. Since this is a new path, it's a cache miss, forcing the proxy to re-evaluate permissions (likely by consulting the Hub or its own policies).
Permission Granted: The Auth-proxy allows the write operation.
File Creation: The Gateway creates the file on the Filesystem and sends an "OK" back to Bob, who can now begin sending the file's data packets.
Push Revocation: The Hub sends a PUSH notification to the Auth-proxy, instructing it to immediately revoke all access for user "bob".
Purge Cache: The Auth-proxy purges all of Bob's cached permissions.
New Request: Within the same SFTP session, Bob attempts another file operation.
Authorization Denied: The Gateway checks with the Auth-proxy. Because the cache was purged and the user is marked as revoked, the proxy denies the request.
Permission Denied Error: The Gateway sends a PERMISSION DENIED status to Bob's client.
Disconnect: The session can no longer proceed, and Bob disconnects.
Here is a simple implementation for SFTP
User / Client Side (Bob)
Get an ephemeral SFTP certificate from the Hub
Start SFTP session using that cert
Do normal file work
What happens on revoke / expiry
If the Hub revokes Bob early, his next SFTP command returns:
Permission denied.
When TTL (2 h) is reached, the certificate is invalid; the session closes and Bob must request a fresh cert.
End-to-End Picture
Strategy Comparison Matrix
The following matrix provides a detailed comparison of all five strategies across key dimensions:
(Temp Users + ACLs)
(FUSE + Tokens)
(Namespaces)
(Hard Links)
(SFTP Gateway)
No virtualization overhead
Direct kernel I/O
Userspace filesystem layer
Context switching overhead
Direct kernel access
No virtualization overhead
Direct inode access
No performance penalty
SFTP protocol overhead
Serial file operations
POSIX ACL enforcement
SSH key authentication
FUSE-level permission checking
Session isolation
Namespace boundaries
No privilege escalation paths
Permission inheritance
Token-based access control
Token validation
Service account separation
User account management
ACL configuration
SSH key handling
FUSE daemon management
Token refresh logic
Mount point handling
Namespace setup
UID/GID mapping
Mount propagation
Simple link creation
Token validation
Basic cleanup
Standard SFTP setup
Token integration
Session management
Native filesystem access
Full POSIX support
MPI and Slurm integration
FUSE mount points
Most HPC tools work
Some edge cases
Native filesystem access
Full POSIX support
Complete tool integration
Native filesystem access
Full POSIX support
Seamless workflow integration
File transfer only
No in-place processing
Not suitable for compute jobs
flock() and fcntl() support
Concurrent access control
HPC workflow support
Application-level coordination
Concurrent access management
Cross-mount coordination
flock() and fcntl() support
Complete isolation
Secure concurrent access
flock() and fcntl() support
Standard POSIX semantics
HPC workflow support
Transfer-based access
No concurrent access control
Not applicable
SSH key generation
ACL configuration
Systemd timer setup
FUSE daemon deployment
Mount point configuration
Token refresh logic
Namespace support
Kernel configuration
Complex setup scripts
Simple link creation
Directory management
Basic cleanup scripts
SSH configuration
User group management
Token integration
Systemd timers
ACL revocation
User account removal
Mount point unmounting
Session termination
Resource cleanup
Mount unmounting
Process termination
Resource cleanup
Directory cleanup
Token expiry
Simple unlink operations
Connection termination
Resource cleanup
Token invalidation
Conclusion
Each design strategy offers different trade-offs between performance, security, complexity, and operational requirements. The choice depends on specific requirements and constraints:
Strategy 1 — Temp POSIX users + per-file ACLs
Strategy 2 — Token-validated FUSE mount (df-fuse)
Strategy 3 — Namespace “view jail” (bind-mounts)
Strategy 4 — Hard-link “view dirs” (token-gated)
Strategy 5 — SFTP/WebDAV gateway
Key trade-offs
The key to successful implementation is understanding the specific requirements of the environment and choosing the strategy (or combination of strategies) that best balances performance, security, complexity, and operational requirements.
All reactions