Skip to main content

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

Project description

CI PyPI version PyPI downloads License: MIT Rust edition

<osp⚡> object-storage-proxy

A fast, in-process reverse proxy for AWS S3 and IBM Cloud Object Storage, built on Cloudflare's pingora. It exposes a Python interface so you can plug in your own credential fetching, request signing, and authorization logic without touching the Rust core.

Note: This project is under active development. APIs are likely to change before 1.0.

Why

Object storage backends like IBM COS assign one endpoint and one set of credentials per storage instance, which may contain many buckets. Managing credentials and endpoints across instances becomes cumbersome, especially when clients expect a single uniform endpoint.

This proxy solves that by:

  1. Translating path-style requests (http://proxy/bucket/key) to virtual-hosted-style (https://bucket.s3.region.host/key) on the way out.
  2. Re-signing requests with the correct backend credentials, so clients only need one keypair pointed at the proxy.
  3. Calling your Python functions for credential lookup and request authorization, with TTL-based caching.

Request lifecycle

Request stages

Features

  • Compatible with any AWS S3-compatible client: aws-cli, boto3, polars, spark, datafusion, presto, trino, ...
  • Decouples frontend authentication (what the client sends) from backend authentication (what the storage expects).
  • Python callables for credential fetching, HMAC key lookup, and per-request authorization.
  • TTL-based credential and authorization caching.
  • HTTP and HTTPS frontends (HTTPS supports HTTP/2).
  • Configurable thread count and per-URL request counting.
  • Presigned URL support with configurable max-usage limiting.
  • Built-in Prometheus metrics endpoint (/metrics) — on by default, opt-out via --no-default-features.

Installation

pip install object-storage-proxy

Or install from source (requires Rust stable and uv):

git clone https://github.com/opensourceworks-org/object-storage-proxy.git
cd object-storage-proxy
uv run maturin develop --release

See DEVELOP.md for full develop/build instructions including Nix and Taskfile usage.

Quick start

1. Configure your AWS client

~/.aws/config:

[profile osp]
region = eu-west-3
output = json
services = osp-services
s3 =
    addressing_style = path

[services osp-services]
s3 =
  endpoint_url = http://localhost:6190

~/.aws/credentials:

[osp]
aws_access_key_id = MYCLIENTID
aws_secret_access_key = myclientsecret

The aws_access_key_id is passed as the token argument to your Python callables. It can be any identifier meaningful to your auth system: an internal client ID, an OAuth2 subject, etc.

2. Write your server script

import json
import os
from object_storage_proxy import ProxyServerConfig, start_server

def fetch_credentials(token: str, bucket: str) -> str:
    # Return either an IBM COS API key string, or a JSON string:
    # '{"access_key": "...", "secret_key": "..."}'
    return json.dumps({
        "access_key": os.environ["BACKEND_ACCESS_KEY"],
        "secret_key": os.environ["BACKEND_SECRET_KEY"],
    })

def lookup_secret(access_key: str) -> str | None:
    # Called to verify incoming HMAC signatures.
    return os.getenv("MYCLIENTSECRET") if access_key == "MYCLIENTID" else None

def authorize(token: str, bucket: str, request: dict) -> bool:
    # Return True to allow, False to deny.
    return True

cos_map = {
    "my-bucket": {
        "host": "s3.eu-de.cloud-object-storage.appdomain.cloud",
        "region": "eu-de",
        "port": 443,
        "ttl": 300,
    },
}

config = ProxyServerConfig(
    cos_map=cos_map,
    bucket_creds_fetcher=fetch_credentials,
    hmac_fetcher=lookup_secret,
    validator=authorize,
    http_port=6190,
)

start_server(config)

3. Run it

uv run python my_server.py

4. Use it

aws s3 ls s3://my-bucket/ --profile osp
aws s3 cp file.txt s3://my-bucket/file.txt --profile osp

A fuller example with HTTPS, HMAC keystores, and IBM COS is in examples/minimal_server.py.

Configuration reference

ProxyServerConfig

Parameter Type Required Default Description
cos_map dict yes Bucket-to-backend mapping. See below.
hmac_keystore list[dict] no [] Static HMAC keypairs accepted on the frontend.
bucket_creds_fetcher callable(token, bucket) -> str no Called once per bucket to fetch backend credentials. Return an IBM COS API key string or {"access_key":...,"secret_key":...} JSON.
hmac_fetcher callable(access_key) -> str | None no Called per request to resolve a secret key from an access key, used to verify incoming signatures.
validator callable(token, bucket[, request]) -> bool no Called per request to authorize access. Cached by (token, bucket) for the bucket TTL.
http_port int one of http/https required HTTP listener port.
https_port int one of http/https required HTTPS listener port (HTTP/2 supported).
threads int no 1 Number of worker threads.
verify bool no None Disable TLS verification on upstream connections. Development only.
skip_signature_validation bool no False Skip verification of incoming request signatures. Development only.
max_presign_url_usage_attempts int no 3 Max times a presigned URL may be used before being rejected.
server_name str no "osp" Server name included in log output.
metrics_port int no None Port to expose the Prometheus /metrics scrape endpoint. When None no endpoint is started.

cos_map entries

Each key is the bucket name as the client addresses it. The value is a dict:

Field Required Description
host yes Backend hostname
port yes Backend port (typically 443)
region no AWS/COS region string
apikey no IBM COS IAM API key (mutually exclusive with access_key/secret_key)
access_key no Backend HMAC access key
secret_key no Backend HMAC secret key
ttl no Credential and auth cache TTL in seconds. Default 300. Set to 0 to disable.
addressing_style no "path" or "virtual" (default "virtual")
is_tls_enabled no Defaults to true when port is 443

Python callable signatures

# Fetch backend credentials for a bucket.
# token: the access key from the client's Authorization header.
# Return an IBM COS API key string, or JSON: '{"access_key":"...","secret_key":"..."}'
def fetch_credentials(token: str, bucket: str) -> str: ...

# Resolve the secret key for an access key (used to verify incoming signatures).
def lookup_secret(access_key: str) -> str | None: ...

# Authorize a request. request dict contains: method, path, query, headers.
def authorize(token: str, bucket: str, request: dict | None = None) -> bool: ...

Prometheus metrics

The proxy ships with a built-in Prometheus scrape endpoint. Set metrics_port to enable it:

config = ProxyServerConfig(
    cos_map=cos_map,
    http_port=6190,
    metrics_port=9090,   # exposes http://localhost:9090/metrics
)

Then scrape it:

curl http://localhost:9090/metrics

Or add a Prometheus scrape config:

scrape_configs:
  - job_name: object-storage-proxy
    static_configs:
      - targets: ["localhost:9090"]

Exposed metrics (all prefixed osp_):

Metric Type Labels Description
osp_requests_total Counter method, bucket, status Total proxied requests
osp_request_errors_total Counter method, bucket, error 4xx / 5xx responses
osp_transfer_bytes_total Counter direction (rx/tx), bucket Bytes transferred
osp_presigned_url_hits_total Counter bucket Presigned URL uses
osp_presigned_url_rejected_total Counter bucket Presigned URLs rejected (over limit)
osp_active_connections Gauge In-flight connections
osp_memory_bytes Gauge Resident set size (Linux only)
osp_build_info Gauge version, rustc Static build metadata
osp_request_duration_seconds Histogram method, bucket End-to-end request latency
osp_response_size_bytes Histogram method, bucket Response body size

To build without the metrics endpoint:

maturin develop --no-default-features

HTTPS setup

Generate a self-signed certificate for local development:

openssl req -x509 -nodes -days 365 \
  -newkey rsa:4096 \
  -keyout key.pem \
  -out cert.pem \
  -config localhost.cnf

export TLS_CERT_PATH=/path/to/cert.pem
export TLS_KEY_PATH=/path/to/key.pem

Then pass https_port=8443 to ProxyServerConfig.

Environment variables

See .env.example for the full list. Key variables:

Variable Description
COS_API_KEY IBM COS IAM API key
AWS_ACCESS_KEY / AWS_SECRET_KEY AWS backend credentials
TLS_CERT_PATH / TLS_KEY_PATH Paths to TLS certificate and key
OSP_ENABLE_REQUEST_COUNTING Set to true to enable per-URL request counting
AWS_REQUEST_CHECKSUM_CALCULATION Set to WHEN_REQUIRED to avoid checksum errors with AWS CLI v2

Build targets

Pre-built wheels are published to PyPI for the following platforms:

Platform Architecture Libc Python
Linux (ubuntu-22.04) x86_64 glibc (manylinux) 3.x
Linux (ubuntu-22.04) aarch64 glibc (manylinux) 3.x
Linux (alpine 3.18) x86_64 musl (musllinux_1_2) 3.x
macOS (macos-14) aarch64 (Apple Silicon) 3.x
Source distribution any any 3.x

Windows builds are not currently active in CI. An sdist is always published so you can build from source on any platform with Rust stable installed.

Building from source

See BUILD.md.

Roadmap

  • Pass path and method to Python callbacks; cache by (token, bucket, path, method)
  • Expose pingora server and service configuration to Python
  • Spark streaming write support
  • AWS CLI checksum workaround (aws/aws-cli#9214)

Contributing

See CONTRIBUTING.md. Bug reports and feature requests go through GitHub Issues.

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

object_storage_proxy-0.5.4.tar.gz (1.4 MB 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.5.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

object_storage_proxy-0.5.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

object_storage_proxy-0.5.4-cp314-cp314-macosx_11_0_arm64.whl (6.6 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

object_storage_proxy-0.5.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

object_storage_proxy-0.5.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

object_storage_proxy-0.5.4-cp313-cp313-macosx_11_0_arm64.whl (6.6 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

object_storage_proxy-0.5.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

object_storage_proxy-0.5.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

object_storage_proxy-0.5.4-cp312-cp312-macosx_11_0_arm64.whl (6.6 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

object_storage_proxy-0.5.4-cp311-cp311-musllinux_1_2_x86_64.whl (7.4 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ x86-64

object_storage_proxy-0.5.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

object_storage_proxy-0.5.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

object_storage_proxy-0.5.4-cp311-cp311-macosx_11_0_arm64.whl (6.6 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

object_storage_proxy-0.5.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

object_storage_proxy-0.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

File details

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

File metadata

  • Download URL: object_storage_proxy-0.5.4.tar.gz
  • Upload date:
  • Size: 1.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.13.3

File hashes

Hashes for object_storage_proxy-0.5.4.tar.gz
Algorithm Hash digest
SHA256 96d8643a797ab57097a5c095f0ab35f7946e633a0b0027af94006d7da51dd3ec
MD5 fb01d121b2611ba50559932d630e26b7
BLAKE2b-256 6067d5e75a29850a1813de68ecac6017cea607c9b055b7d77fa81ba2bc242260

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fbe5eaefebfb6d38737128dda249f87228f334f2930273262c218621241e1cf0
MD5 b47d8c62e60154595830c20d4efe96b7
BLAKE2b-256 c11cc44272af826f1a69d9df52c324a2927f5189564453877e1ab95459145736

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 77622d7d0e94c34794eb8347403a10eb66a7b2c1c5c5bfbb68a67cf6509d4647
MD5 c225ff9654986017a299d5cc3ae08b02
BLAKE2b-256 a9108aac2f0478513228607ef0cf00c4aca8d5affb94c0de0c7f323b799a11ea

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5c0134c2525da704406ae9e680e7d23a428e99d820e07535a6fd73d6cec96a31
MD5 d36522c1ace8ab5a46436071f413d4d5
BLAKE2b-256 8e3f82df978ff2a758739706cc19ea73117cff4d8900ddf5021a34250253741e

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 74fcbdbefc778937e5cc43551306ef01cbf322b3d15b327aeedcd6e15c4cd135
MD5 8ed23eb0d7cf8aa5d2f82d06264018c9
BLAKE2b-256 c4b1c4007f97ac319770b9166dacbecad604092164bf6a093f2a2b6a599ca71d

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2cf21ee5b6bf42756d23499a273ec59ac4ff640b03cb891d26df67f81892c076
MD5 88ee3b9d5c9af6658b27a4506126e5f8
BLAKE2b-256 6751adff30b4c341ff7c6f7a8e5ba4611fcab58d0aeeba7226948d5fc1b41181

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f191063cdbd05847f6eb8ebc7d30cc1d1f2ab8b6ad2d237c725f24fc9fa9f127
MD5 86f72204bc9cebf0ad69f486bc3c49f7
BLAKE2b-256 1bf7781c8c80afdb6229a5dec8b770b71acf3731ca3a54c1709a4ad77bf08684

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 8bc079ed927d430b3aa10692b489a175580861fdb788c7bdb6cc1bc178183da8
MD5 70d2e28b657e42ea7f4cd07eb52824bb
BLAKE2b-256 2e5726153865d96a56ed4c8af6b959e5535b5a64ba603de5c0d9d230b9e62417

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 05aabcea23c9ec7c71774947d13f8365ced54919ffb19f3006d0085d5c9acc0c
MD5 dc2fea7e6530740bbdd0d409350a7a52
BLAKE2b-256 4d59fcf76a8ef7b140965de29d8898a5f61500f0994c1ed919a6fd3bf159bb67

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 270dd337d111d4a491a534e9b58d71420b5da93441785529bc9f98388fa1096f
MD5 77aae2fdc37751b3656fa2b2e03020df
BLAKE2b-256 0fef7a1203743f09f6bf23cb7a89b2e1c17039f6fb2ae595f4e24aa8d7913e8d

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 1ce2d7c6994df038114ff30d7dba49a9374ca9e55e45a9e2d375472dce3298a9
MD5 325cc127eeaf11de5ef4ba742f29e6f2
BLAKE2b-256 70183c0fcd0927378adfd2005a786d2470957449e8ab90e952813b5740d045c0

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2781363fe6577a6289575facf723c97254c20a200b6ea8b298a295d2bc594f96
MD5 d89d1c0217a9cbd5d88c712d1820aa9e
BLAKE2b-256 7855209805dec4b15a01a646ae028938590506863a4e7b176ee967c6bfd3b5a1

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8fa9f007350394e252dcc4cd6fba3bbfa9f1e381e4a70445154a276909faffff
MD5 9cdc5bdd304c4030ca36ffd432844599
BLAKE2b-256 21cdea0913cadb8586f0a3864f028ec79b4c4613db3a7d2a69cef07c00edb80b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 033038180854a80546853e3acbed4b5eefcb017c6ae380fb517812b3f389900a
MD5 84b176644a9d67938be41707c3d3af62
BLAKE2b-256 d8612e8a61ae1cb3bf3da876b8486827579b35329520dd5ddd569e725bdb074d

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 cab63b8d7a803c373a9c4756218e1d3fe4f013b688b2a429e470e4eb10aeda6c
MD5 8a7e47475d35e6a14ae8bc5a339831bd
BLAKE2b-256 b0520271fb6515f361b18bb91a2544a569f6c09c788d5954157e985437d12da7

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 146452f6d237c15ca8c14dd2c6d234bd06698b341ef67c18072b83b7bfbd6c3e
MD5 1e78a8fe196b5cd32e28377320b63cc6
BLAKE2b-256 daf39901cd92f35045e622f6f1cfd400763822a42b250c265b1861311dc8b618

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 76c1e52154334773fd9ca61b1f81019d561deb7e123c1283551b4a28295f5aa6
MD5 beabe67460d17a668af1499b764685ff
BLAKE2b-256 414ca1dc4ea11d98cf31535736565e791f60256d8cbb05425389822d03b76822

See more details on using hashes here.

File details

Details for the file object_storage_proxy-0.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for object_storage_proxy-0.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 2f0621a6c8c231bf07024311c81c538ba380ea4e6457f19a32e21566eefe8f87
MD5 b81f4b9425369553979e8324e5f073a4
BLAKE2b-256 93f2cce46e0b38a349a3039f3e84dfe8399473aafe2def5e24f9cc5526c421c1

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