Transparent S3 Access Grants for fsspec/s3fs — per-grant scoped credentials, no Access Grants logic in application code.
Project description
s3fs-access-grants
Transparent S3 Access Grants for fsspec / s3fs.
Register the implementation for s3:// once and every fsspec consumer —
pandas, polars, universal-pathlib, fsspec.open, ... — routes each call
through a credential scoped to the matching grant. No Access Grants logic leaks
into application code.
How it works
ScopedS3FileSystem subclasses s3fs.S3FileSystem. On construction it
enumerates the caller's grants (ListCallerAccessGrants) and builds a
longest-prefix routing table. Each S3 operation is matched to a grant scope and
served by a per-scope aiobotocore client whose credentials come from
GetDataAccess and auto-refresh on expiry. Calls that match no grant fall
through to the default IAM client (fail-closed), and cross-scope copies are
rejected.
If the caller has no grants (or no permission to list them), register()
installs nothing and plain s3fs handles s3:// with zero added overhead.
Install
pip install s3fs-access-grants
# or
uv add s3fs-access-grants
Usage
Registration is explicit — importing the package does no AWS I/O.
import s3fs_access_grants
# Install the s3:// handler for the calling identity's grants.
s3fs_access_grants.register()
import polars as pl
df = pl.read_parquet("s3://bucket/teamA/data.parquet") # scoped automatically
Pass the grants-instance account/region explicitly (e.g. in a notebook, or when the grants instance lives in a different account than your role):
import s3fs_access_grants
s3fs_access_grants.register(account_id="123456789012", region="eu-west-1")
register() is the only entry point and returns nothing — it's a one-time setup
call. It resolves the account/region, then binds them into the handler it
registers, so a later argless fsspec.filesystem("s3") (what pandas / polars use
under the hood) builds the filesystem with the right values. After calling it,
just use fsspec / pandas / polars as normal.
Configuration
register() resolves the grants-instance account and region in this order:
| Setting | Resolution order |
|---|---|
| Account ID | explicit arg → S3FS_ACCESS_GRANTS_ACCOUNT_ID → STS caller |
| Region | explicit arg → S3FS_ACCESS_GRANTS_REGION → session default |
The grants instance may live in a different account than the caller's role, so the explicit arg / env is authoritative; the STS caller account is only a same-account fallback.
Advanced: manual construction
register() covers the common case. To build a scoped filesystem by hand —
e.g. pointing at a different grants account without touching the global s3://
registration — construct ScopedS3FileSystem directly:
from s3fs_access_grants import ScopedS3FileSystem
fs = ScopedS3FileSystem(grants_account_id="123456789012", grants_region="eu-west-1")
Compatibility
This subclass depends on s3fs internals (_call_s3 and _iterdir resolving
their client via get_s3()). Validated against s3fs 2026.6.0 / aiobotocore
2.25.1. Re-check on any s3fs major bump.
Development
bun install # installs JS tooling + runs uv sync + lefthook install
bun run check # lint + typecheck (ruff, ty, editorconfig)
bun run test # pytest with coverage
bun run build # uv build (wheel + sdist)
Releases are managed with changesets:
add one with bun run changeset:add, and merging the generated "version
packages" PR bumps the version, syncs it into pyproject.toml, and publishes to
PyPI.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file s3fs_access_grants-0.1.0.tar.gz.
File metadata
- Download URL: s3fs_access_grants-0.1.0.tar.gz
- Upload date:
- Size: 118.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4ffb30e6a07456039551b44042613d87bb49f4832644e7252c76acadc4d31ce
|
|
| MD5 |
9baa5a3cf50e34bd745e19dd65277657
|
|
| BLAKE2b-256 |
6a71c169caf9ab1fa27d405c228caabc38a9d89dbd0b29f4402e3180eb81756d
|
Provenance
The following attestation bundles were made for s3fs_access_grants-0.1.0.tar.gz:
Publisher:
release.yaml on undeadpixel/s3fs-access-grants
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
s3fs_access_grants-0.1.0.tar.gz -
Subject digest:
a4ffb30e6a07456039551b44042613d87bb49f4832644e7252c76acadc4d31ce - Sigstore transparency entry: 1914058229
- Sigstore integration time:
-
Permalink:
undeadpixel/s3fs-access-grants@a689ad52685b66ed335d1e80e405fdeb6ca6bd8b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/undeadpixel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@a689ad52685b66ed335d1e80e405fdeb6ca6bd8b -
Trigger Event:
push
-
Statement type:
File details
Details for the file s3fs_access_grants-0.1.0-py3-none-any.whl.
File metadata
- Download URL: s3fs_access_grants-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
284e99925a887f45eb96705bd555206848f2d7519415d1ab2a4e981ea0730f5f
|
|
| MD5 |
1949744f064da5912f7af91d076f11b0
|
|
| BLAKE2b-256 |
10a273812e44e8f0ea1bb7a881108239c4a3398f8541b936e83beb8547929515
|
Provenance
The following attestation bundles were made for s3fs_access_grants-0.1.0-py3-none-any.whl:
Publisher:
release.yaml on undeadpixel/s3fs-access-grants
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
s3fs_access_grants-0.1.0-py3-none-any.whl -
Subject digest:
284e99925a887f45eb96705bd555206848f2d7519415d1ab2a4e981ea0730f5f - Sigstore transparency entry: 1914058602
- Sigstore integration time:
-
Permalink:
undeadpixel/s3fs-access-grants@a689ad52685b66ed335d1e80e405fdeb6ca6bd8b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/undeadpixel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@a689ad52685b66ed335d1e80e405fdeb6ca6bd8b -
Trigger Event:
push
-
Statement type: