<object-storage-proxy ⚡> Yet Another Object Storage Proxy
Project description
** <object-storage-proxy ⚡> Yet Another Object Storage Reverse Proxy**
📌 Note: This project is still under heavy development, and its APIs are subject to change.
Introduction
secrets
IBM COS Storage is built in a way where buckets are grouped by a cos (Cloud Object Storage) instance. Access to a bucket is managed by either an api key or hmac secrets, configured on the cos instance.
endpoint
Each bucket has its own endpoint: <bucket_name>.s3..cloud-object-storage.appdomain.cloud:.
The port is not always different, though, but it might be. Depends on your implementation.
You can imagine managing multiple buckets across instances can become quite cumbersome, even with aws profiles etc.
solution
There are two ways to access a bucket: through virtual addressing style (bucket.ibm-cos-host:port) and path style (ibm-cos-host/bucket).
your client (aws s3 compatible) -> http(s)://this-proxy/bucket01 -> https://bucket01.s3.eu-de.cloud-object-storage.appdomain.cloud:443
- translate path style to virtual style
- abstract authentication & authorization
Pass in a function which maps bucket to instance (credentials), and a function to map bucket to port (endpoint)
┌──────┐ ┌────────────┐ ┌───────────┐ ┌───────┐
│Client│ │ReverseProxy│ │IAM_Service│ │IBM_COS│
└───┬──┘ └──────┬─────┘ └─────┬─────┘ └───┬───┘
│Path-style Request ┌┴┐ │ │
│──────────────────> │ │ │ │
│ │ │ │ │
│ │ │ ────┐ │ │
│ │ │ │ Extract credentials from request │ │
│ │ │ <───┘ │ │
│ │ │ │ │
│ │ │ ────┐ │ │
│ │ │ │ Check cache for valid credentials │ │
│ │ │ <───┘ │ │
│ │ │ │ │
│ │ │ │ │
│ ╔══════╤════════╪═╪═════════════════════════════════════════════════════════╪═══════════════╗ │
│ ║ ALT │ Credentials Not Found or Expired │ ║ │
│ ╟──────┘ │ │ │ ║ │
│ ║ │ │ Request IAM Verification ┌┴┐ ║ │
│ ║ │ │ ──────────────────────────────────────────────────────>│ │ ║ │
│ ║ │ │ └┬┘ ║ │
│ ║ │ │ Return Verified Credentials │ ║ │
│ ║ │ │ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│ ║ │
│ ║ │ │ │ ║ │
│ ║ │ │ ────┐ │ ║ │
│ ║ │ │ │ Cache credentials │ ║ │
│ ║ │ │ <───┘ │ ║ │
│ ╠═══════════════╪═╪═════════════════════════════════════════════════════════╪═══════════════╣ │
│ ║ [Credentials Valid] │ ║ │
│ ║ │ │ ────┐ │ ║ │
│ ║ │ │ │ Use Cached Credentials │ ║ │
│ ║ │ │ <───┘ │ ║ │
│ ╚═══════════════╪═╪═════════════════════════════════════════════════════════╪═══════════════╝ │
│ │ │ │ │
│ │ │ ────┐ │ │
│ │ │ │ Translate path-style to virtual-style request │ │
│ │ │ <───┘ │ │
│ │ │ │ │
│ │ │ ────┐ │ │
│ │ │ │ Handle secrets and endpoint (incl. port) │ │
│ │ │ <───┘ │ │
│ │ │ │ │
│ │ │ Forward Virtual-style Request │ ┌┴┐
│ │ │ ───────────────────────────────────────────────────────────────────────────>│ │
│ │ │ │ │ │
│ │ │ Response │ │ │
│ │ │ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│ │
│ └┬┘ │ └┬┘
│ Return Response │ │ │
│<─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ │ │
┌───┴──┐ ┌──────┴─────┐ ┌─────┴─────┐ ┌───┴───┐
│Client│ │ReverseProxy│ │IAM_Service│ │IBM_COS│
└──────┘ └────────────┘ └───────────┘ └───────┘
authentication & authorization
The advantage is we can plug in a python authentication function and another function for authorization, allowing for fine-grained control.
authentication
We use the standard aws hmac header.
authorization
Pass in a callable from python which will be called from rust. This will be cached (ttl) for consequtive requests.
Examples
With local configuration.
~/.aws/config
[profile osp]
region = eu-west-3
output = json
services = pingora-services
s3 =
addressing_style = path
[services osp-services]
s3 =
endpoint_url = http://localhost:6190
~/.aws/credentials
[osp]
aws_access_key_id = MYLOCAL123
aws_secret_access_key = nothingmeaningful
Set up a minimal server implementation:
from object_storage_proxy import start_server, ProxyServerConfig
from dotenv import load_dotenv
import os
import random
load_dotenv()
def docreds(bucket):
apikey = os.getenv("COS_API_KEY")
if not apikey:
raise ValueError("COS_API_KEY environment variable not set")
print(f"Fetching credentials for {bucket}...")
return apikey
def do_validation(token: str, bucket: str) -> bool:
print(f"PYTHON: Validating headers: {token} for {bucket}...")
return random.choice([True, False])
def main():
apikey = os.getenv("COS_API_KEY")
if not apikey:
raise ValueError("COS_API_KEY environment variable not set")
cos_mapping = [
("bucket1", "s3.eu-de.cloud-object-storage.appdomain.cloud", 443, "instance1", apikey),
("bucket2", "s3.eu-de.cloud-object-storage.appdomain.cloud", 443, "instance2", apikey),
("proxy-bucket01", "s3.eu-de.cloud-object-storage.appdomain.cloud", 443, "instance3", apikey),
]
ra = ProxyServerConfig(
bucket_creds_fetcher=docreds,
validator=do_validation,
cos_map=cos_mapping,
port=6190
)
start_server(ra)
if __name__ == "__main__":
main()
run with aws-cli (but could be anything compatible with the aws s3 api like polars, spark, presto, ...):
$ aws s3 ls s3://proxy-bucket01/ --recursive --summarize --human-readable --profile osp
2025-04-17 17:45:30 33 Bytes README.md
2025-04-17 17:48:04 33 Bytes README2.md
Total Objects: 2
Total Size: 66 Bytes
$
Status
- pingora proxy implementation
- pass in credentials handler
- cache credentials
- pass in bucket/instance and bucket/port config
-
split in workspace crate with core, cli and python crates(too many specifics for python) - config mgmt
- cache authorization (with optional ttl)
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 Distributions
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 object_storage_proxy-0.1.1.tar.gz.
File metadata
- Download URL: object_storage_proxy-0.1.1.tar.gz
- Upload date:
- Size: 42.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eed0e821f23d54722a7fe9c98885f90bc7a4638c3ee9b5e582ed521aa59af504
|
|
| MD5 |
b806fd2f3468909a1d62bbf74eb2011b
|
|
| BLAKE2b-256 |
ca6cad08864cca0105902cf7a58bd359554a8f8a97c6a9d0127901c5e6d7a18a
|
File details
Details for the file object_storage_proxy-0.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: object_storage_proxy-0.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 8.8 MB
- Tags: PyPy, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d20f7463fad7f1149436c1e86ff49ff0ba613296ac1e72357f1892c2afd4b7d
|
|
| MD5 |
82ae63ac8efe504453dbeb97d4c3edb3
|
|
| BLAKE2b-256 |
24e6d1ed1001bde579030ea5bb854a1f267a104b427a5c43f74bf9d83a1491ed
|
File details
Details for the file object_storage_proxy-0.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: object_storage_proxy-0.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 8.8 MB
- Tags: PyPy, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1550d88711cbcac21f5e5cbc8ae9677f3161e1eb7d336578cc4c284d2ab46505
|
|
| MD5 |
f831d772f1598e2c8f72a243792a3ef3
|
|
| BLAKE2b-256 |
fa454f097fbcc031e32b309958bd5dc6500031dd064170786e3ead6c383abc49
|
File details
Details for the file object_storage_proxy-0.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: object_storage_proxy-0.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 8.8 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a46e8ca3388aa88ee7e1e8f8897407afcb2c8f76d61172528f8531379648202
|
|
| MD5 |
b4f9062febe2c407bdba50f26232c8ed
|
|
| BLAKE2b-256 |
ab617a274fc2c74587d0d60304fa7bf90b9ea94e81b33efd9a09622e627f128d
|
File details
Details for the file object_storage_proxy-0.1.1-cp313-cp313-macosx_10_12_x86_64.whl.
File metadata
- Download URL: object_storage_proxy-0.1.1-cp313-cp313-macosx_10_12_x86_64.whl
- Upload date:
- Size: 6.4 MB
- Tags: CPython 3.13, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3d38991813914096886473237150e41212d324fdd45b08ec89c111a36b2cf94
|
|
| MD5 |
6a5ce4459575e7df0f4c7959f894507b
|
|
| BLAKE2b-256 |
ef436c2f2a0cbec76a3a623f7dbc6bdcedb31562f411c0ec45c8bcd75828245c
|
File details
Details for the file object_storage_proxy-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: object_storage_proxy-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 8.8 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
87c7a0306fe3c407373a334571d670050e33032665fb053e5b54899a4c620540
|
|
| MD5 |
d08f18780937c2123068d6cd75e58f67
|
|
| BLAKE2b-256 |
21edab47c04594f3949e9f6a5b8a1bd774a236b591b709d5466974ec5abb50db
|
File details
Details for the file object_storage_proxy-0.1.1-cp312-cp312-macosx_10_12_x86_64.whl.
File metadata
- Download URL: object_storage_proxy-0.1.1-cp312-cp312-macosx_10_12_x86_64.whl
- Upload date:
- Size: 6.4 MB
- Tags: CPython 3.12, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b29a98713df0ff7e31df10549634b843cb75e2bd8779e28f44f73e6aeb1c17a2
|
|
| MD5 |
0251a4a7cc4dd0a8f83b4d40e0952f89
|
|
| BLAKE2b-256 |
1751c7ff801f6025858d2d27b968a4332bf6c20c46fff4e833b19bb942764832
|
File details
Details for the file object_storage_proxy-0.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: object_storage_proxy-0.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 8.8 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8988fe779db8d89fe6482fe6badd2b8e3e198ad59149b3adcc026a184525a213
|
|
| MD5 |
40520128a27148f24ee4ab3df2e2c484
|
|
| BLAKE2b-256 |
01d41d4ad567f635153ba35232e4236a1f692bdbb0b26e5f46080bc199ea3233
|
File details
Details for the file object_storage_proxy-0.1.1-cp311-cp311-macosx_10_12_x86_64.whl.
File metadata
- Download URL: object_storage_proxy-0.1.1-cp311-cp311-macosx_10_12_x86_64.whl
- Upload date:
- Size: 6.4 MB
- Tags: CPython 3.11, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
611de879124f827b5bacb346ddfddecc58775734ae6f28d5cb30f559f978dc3c
|
|
| MD5 |
b40115d00f88cf9012b68c36c42ae181
|
|
| BLAKE2b-256 |
8a8a6425cbf636df2e9bbc8053f2431b7e2657e2d06ebd9a7dc27877e2add8ed
|
File details
Details for the file object_storage_proxy-0.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: object_storage_proxy-0.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 8.8 MB
- Tags: CPython 3.10, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e801faf91fe7e38ab43c27137eaec93e28fe71609f30270fd6b99fdc5f3cbc2
|
|
| MD5 |
53df2d584c9e0283558a9883019756f7
|
|
| BLAKE2b-256 |
09387756446174848dfc87361be52a948e34737384d4a805953c0fe94cb99a09
|