Skip to main content

<object-storage-proxy ⚡> Yet Another Object Storage Proxy

Project description

CI

** <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

A fast and safe reverse proxy server, based on Cloudflare's pingora, to reverse proxy IBM Cloud Object Storage buckets.

  • Takes a Python validator function and cos bucket mapping list of tuples.
  • The validation is cached with optional ttl.
  • The apikey is used to authenticate against IBM's IAM endpoint and is cached and renewed on expiration.
  • If no apikey is provided, a Python function can be passed in to fetch the apikey for any given bucket.
  • HMAC support: passing in access and secret id keys, will be used to sign the request

The bucket mapping list consists of tuples: ("bucket1", "s3.eu-de.cloud-object-storage.appdomain.cloud", 443, "instance1", apikey)

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

  1. translate path style to virtual style
  2. 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
$

Server output:

$ uv run python test_server.py
2025-04-19T12:02:16.305908+02:00  INFO object_storage_proxy: Logger initialized; starting server on port 6190
2025-04-19T12:02:16.306127+02:00  INFO object_storage_proxy: Bucket creds fetcher provided: Py(0x102390680)
Fetching credentials for bucket01...
2025-04-19T12:02:16.306148+02:00  INFO object_storage_proxy: Callback returned: Kn2t...
2025-04-19T12:02:16.306760+02:00  INFO pingora_core::server: Bootstrap starting
2025-04-19T12:02:16.306768+02:00  INFO pingora_core::server: Bootstrap done
2025-04-19T12:02:16.308063+02:00  INFO pingora_core::server: Server starting
PYTHON: Validating headers: MYLOCAL123 for proxy-bucket01...
2025-04-19T12:02:24.878949+02:00  INFO object_storage_proxy::utils::validator: Callback returned: true
2025-04-19T12:02:25.147970+02:00  INFO object_storage_proxy::credentials::secrets_proxy: No cached token found for proxy-bucket01, fetching ...
2025-04-19T12:02:25.148019+02:00  INFO object_storage_proxy::credentials::secrets_proxy: Fetching bearer token for the API key
2025-04-19T12:02:25.714117+02:00  INFO object_storage_proxy::credentials::secrets_proxy: Received access token
2025-04-19T12:02:25.714208+02:00  INFO object_storage_proxy::credentials::secrets_proxy: Fetched new token for proxy-bucket01

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

object_storage_proxy-0.1.3.tar.gz (43.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

object_storage_proxy-0.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (8.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

object_storage_proxy-0.1.3-cp313-cp313-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

object_storage_proxy-0.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (8.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

object_storage_proxy-0.1.3-cp312-cp312-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

object_storage_proxy-0.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (8.8 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

object_storage_proxy-0.1.3-cp311-cp311-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.11macOS 10.12+ x86-64

object_storage_proxy-0.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (8.8 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

File details

Details for the file object_storage_proxy-0.1.3.tar.gz.

File metadata

  • Download URL: object_storage_proxy-0.1.3.tar.gz
  • Upload date:
  • Size: 43.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.8.3

File hashes

Hashes for object_storage_proxy-0.1.3.tar.gz
Algorithm Hash digest
SHA256 4de71b61a5db2647f8cc3ba856f52e8f833102e334d49d95255ea66770c56bc1
MD5 2cdc8e8cc2db1fec3473fde56abcfbbb
BLAKE2b-256 3cc69c2d80db6086d67c3b79ee378debe0aaecc7fc14607533379522c31ff8f4

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.1.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.1.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 eac017b1e9b7d1f36df4c829652f6519a71d111f65ec3792afd4d567b3dda551
MD5 e18715a6ea2e472f2684ba6a390ff8ee
BLAKE2b-256 2705823fd6edb2652a3d34b247143cd951ffc3f8c4ba1def4c6eab43db7717eb

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.1.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.1.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 defd1aa661cfd629ecfe0d41f7c9df15560fb99d5bf78d8b6ba8836bf6ebea2e
MD5 b1808b072021ca27349843111580b7b6
BLAKE2b-256 77dea37f8c4d4b3796ed01e8a304c2ce17fe242cea258e01d637a1a1ca1c2638

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2d87b19befd3a787ff603d5056da9833b073bde35b9415bc269ad1026fe6c8d2
MD5 1ffec168a578e36023c8a9d45e814323
BLAKE2b-256 caef95c7afe7bdd61295700884ded5f1b628acb3d46218005294e85691033a9c

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.1.3-cp313-cp313-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.1.3-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a1826ba1a35a32c7de03cc17f92eb497b945533618371900b45023c284ab833e
MD5 d779fa17d9a76296b64117809d46aa0e
BLAKE2b-256 2ee3ed3d475549d7f97709c26c7c11faaab5af3be48be5290df29cc088e47f8e

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 90a50f1dda6125e6cc65c983b15c301ed60ece211286888b4b6ba7943834f09f
MD5 fcc57303ed898b6094d228f24dc2fd94
BLAKE2b-256 2c2f87e173ea78fdcbb0908a43ffdab9afc67a7fe2ef42d65906f8f3b45e3ed5

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.1.3-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.1.3-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 9992116cae809552e94552d96a18ac2c56de156be1daa53265005c21846d3fcf
MD5 dbe033ebee9c49b279e5b64c04036d20
BLAKE2b-256 b2e94432134ddf1822cc4cb83da9897d5fc1af0e6153fa705ccfc0bd4b1317b7

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 cfc6e19dd95bc1a72d13200e76ff843e6fb738b5f771172fb77b5d6d72e9112c
MD5 7336a97378228448e9cfe9024eaff45f
BLAKE2b-256 410c2367f46f06be04bbc0cb9e98e220e55be4bc6a828141be2692bee5ac8b16

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.1.3-cp311-cp311-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.1.3-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 30ce3bbb99f809858d1a0d7fd6f0012b3faee3725841f6caa496b698b89b81bd
MD5 28b672e9443ae730051c2dd9c12f7d8b
BLAKE2b-256 bbb61bd9d38e6bb20a04fba51c07d2889020b2201ac69292b90e1859af4aea2b

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 41971b38ec2ad1c28e1cb8462943a98bdaec0902da7fd5624322ef5c7bc60831
MD5 09cc849d3d242d653728636b15349bc5
BLAKE2b-256 591e0dbf098a3ea4b6d1f2b5d40eed971806c6f5471d30e8ad77cade8c820161

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page