Platform-agnostic processing gateway. Point any S3 client at Maskura to filter, redact, encrypt, or convert supported object content with your Wasm plugins.
Quick Start
# Get an API key from the dashboard or use demo mode
# Upload — data runs through the plugin pipeline
curl -X PUT http://localhost:9000/ingest/data.jsonl \
-H "x-maskura-access-key: YOUR_KEY_ID" \
-H "x-maskura-secret-key: YOUR_SECRET" \
--data-binary @data.jsonl
# Read — filtered data comes back
curl http://localhost:9000/ingest/data.jsonl \
-H "x-maskura-access-key: YOUR_KEY_ID" \
-H "x-maskura-secret-key: YOUR_SECRET"
Features
Everything you need to process data in transit
☁
Multi-cloud storage
Maskura Service Storage distributes objects across AWS, R2, and B2 using consistent hashing. Dual-write to primary + replica. Cross-cloud resilience by default.
📁
Full S3 API
PUT, GET, DELETE, HEAD, LIST — standard S3 operations run through the plugin pipeline. Drop-in compatible with AWS SDK, boto3, and any S3 tool.
🔑
Simple ACL
Maskura API keys (maskura_xxx / maskura_secret_xxx) authenticate S3 requests. Create, revoke, set expiry per key. No IAM policy complexity.
🌐
Cloud agnostic
Presigned URL proxy works with S3, R2, B2, MinIO, or any S3-compatible storage. Bring your own backend or use Maskura's managed buckets.
🧩
Plugin system
Wasm filter plugins: import, enable, disable, reorder at runtime. Ordered pipeline processes data through multiple plugins — ship custom transforms without redeploying.
🛡
Zero trust
IAM Role assumption (Fivetran/Airbyte model). No long-lived credentials stored. Unique External ID per workspace prevents confused deputy attacks.
Get Started
Create an account or sign in
or with email
Get started
Create your first API key
S3-compatible credentials. Works with AWS SDK, CLI, or any S3 tool.
Key label
Expiry
Backend storage
Where should Maskura write filtered data?
Maskura uses the Fivetran/Airbyte model: you create an IAM role (or API token) granting Maskura access to your bucket. No long-lived credentials stored.
Step 1: Create an IAM role for Maskura
Run this in your AWS account. Maskura will assume this role to write filtered data to your bucket.
Copy the Role ARN from the output above and paste it below, together with the region and an external ID for confused-deputy protection.
Role ARN
Region
External ID (optional)
Create an R2 API Token
In the Cloudflare dashboard: R2 → Manage R2 API Tokens → Create API Token → select your bucket → grant Read + Write.
# Get your Account ID from the Cloudflare dashboard
ACCOUNT_ID="your-account-id"
BUCKET="your-bucket"
# The endpoint is always:
echo "https://${ACCOUNT_ID}.r2.cloudflarestorage.com"
R2 Endpoint
R2 API Token
Create a B2 Application Key
In the B2 console: App Keys → Add a New Application Key → select your bucket → grant Read + Write.
use aws_sdk_s3::{Client, presigning::PresigningConfig};
// Generate presigned URL
let config = aws_config::load_from_env().await;
let s3 = Client::new(&config);
let presigned = s3.put_object()
.bucket("my-bucket")
.key("uploads/data.jsonl")
.presigned(PresigningConfig::expires_in(
std::time::Duration::from_secs(604800)
)).await?;
// Send through Maskura
let client = reqwest::Client::new();
let resp = client.put("http://localhost:9000/my-bucket/uploads/data.jsonl")
.header("x-maskura-access-key", "maskura_YOUR_KEY_ID")
.header("x-maskura-secret-key", "maskura_secret_YOUR_SECRET")
.header("x-maskura-backend-url", presigned.uri())
.body(std::fs::read("data.jsonl")?)
.send().await?;
// Generate presigned URL
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import java.net.http.*;
var presigner = S3Presigner.create();
var req = PutObjectRequest.builder()
.bucket("my-bucket").key("uploads/data.jsonl").build();
var presigned = presigner.presignPutObject(p -> p
.putObjectRequest(req)
.signatureDuration(java.time.Duration.ofDays(7))
);
// Send through Maskura
var client = HttpClient.newHttpClient();
var httpReq = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:9000/my-bucket/uploads/data.jsonl"))
.header("x-maskura-access-key", "maskura_YOUR_KEY_ID")
.header("x-maskura-secret-key", "maskura_secret_YOUR_SECRET")
.header("x-maskura-backend-url", presigned.url().toString())
.PUT(HttpRequest.BodyPublishers.ofFile(Path.of("data.jsonl")))
.build();
client.send(httpReq, HttpResponse.BodyHandlers.ofString());
Envelope encryption
Hybrid wire format; client packaging in progress
Current gateways accept Maskura hybrid X25519 + ML-KEM-768 public keys for new encrypted writes. The released Python and TypeScript high-level encryption helpers still implement the legacy RSA envelope and cannot provision a key on this gateway. Redaction and ordinary SDK object operations are unaffected. See the current client compatibility boundary.
Storage
Objects in memory
Objects flowing through the gateway. Upload more via S3 API.