Authentication & Security
Lioran S3 provides two primary authentication schemes for client requests, plus temporary delegated access via cryptographically signed presigned URLs.
1. Authentication Models
┌────────────────────────────────────────┐
│ Authentication Methods │
└──────────────────┬─────────────────────┘
│
┌─────────────────────────┴─────────────────────────┐
▼ ▼
┌────────────────────────┐ ┌────────────────────────┐
│ Basic HTTP Auth │ │ Programmatic Keys │
│ (Username + Password) │ │ (AccessKey + SecretKey)│
├────────────────────────┤ ├────────────────────────┤
│ • Interactive CLI │ │ • Microservices / Apps │
│ • Web Dashboard │ │ • CI/CD Pipelines │
│ • Argon2id Hashing │ │ • Independent Secrets │
│ • Roles: admin, rw, ro │ │ • Rotatable / Scoped │
└────────────────────────┘ └────────────────────────┘
A. Basic Authentication (Username & Password)
- Standard RFC 7617 HTTP Basic authentication header:
Authorization: Basic <base64(username:password)>. - Passwords are encrypted on disk in RocksDB using Argon2id password hashing.
- Role-based authorization levels:
admin: Full system control (create/delete buckets, manage users, rotate keys, inspect metrics).readwrite: Read, upload, and delete objects in accessible buckets.readonly: Read and list objects and buckets only; mutating writes rejected.
B. Programmatic Access Keys
- Authenticated via custom headers (
x-bastion-access-keyandx-bastion-secret-key) or via Basic authorization whereusernameis Key ID andpasswordis Key Secret. - Key secrets are displayed only once upon generation and hashed before storage.
- Key IDs use the standard prefix
bk_(e.g.bk_live_0192a7b8...). - Secret keys use the standard prefix
sk_(e.g.sk_live_9f83a21b...).
2. Administrator Bootstrap & Forced Password Rotation
When initializing a fresh Lioran S3 deployment:
- The server bootstraps an initial administrator account using
BASTION_ADMIN_USERNAME(default:admin) andBASTION_ADMIN_PASSWORD. - In production (
BASTION_ENV=production), Bastion requires an explicit strong password (>= 8 characters) and rejects insecure defaults likeadmin,password, or123456. - The newly bootstrapped account is flagged with
must_change_password = true. - The first administrative or mutating call will return HTTP
403 Forbiddenwith the error code:{"code": "password_change_required","message": "You must change the bootstrap password before performing administrative or storage operations"}
Changing the Bootstrap Password via CLI
liorans3 user passwd --old admin --new "MyNewSecurePassword123!"
Changing the Bootstrap Password via SDK
import { BastionClient } from "@liorans3/driver";
const client = new BastionClient("bastion://admin:admin@127.0.0.1:27118");
// Change bootstrap password
await client.users.changePassword("admin", "MyNewSecurePassword123!");
// Reconnect with new credentials
const authClient = new BastionClient("bastion://admin:MyNewSecurePassword123!@127.0.0.1:27118");
3. Creating & Managing Access Keys
Via CLI
# Create a new access key for the authenticated user
liorans3 key create "backend-worker" --expires-days 90
# Output:
# =============================================================
# NEW ACCESS KEY CREATED
# =============================================================
# Name: backend-worker
# Key ID: bk_live_0192a7b8c9d0
# Secret Key: sk_live_8f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c
# Owner: admin
# Expires: 2026-12-30T12:00:00.000Z
# =============================================================
To automatically save the newly generated access key to a named CLI profile:
liorans3 key create "ci-pipeline" --save-to-profile ci
Rotating an Access Key
Rotating a key immediately revokes the old secret and generates a new active secret:
liorans3 key rotate bk_live_0192a7b8c9d0
4. Expiring Presigned URLs
Presigned URLs grant temporary, time-bound access to a specific object without sharing credentials. The signature is computed using HMAC-SHA256 bound to:
- HTTP Method (
GET,PUT, orHEAD) - Bucket Name
- Object Key
- Expiration Unix timestamp (
expires)
https://s3.example.com/api/v1/buckets/media/objects/sample.mp4?expires=1798765432&signature=a9f8e7d6...
Generating a Presigned Download Link (SDK)
const bucket = client.bucket("media");
// Generate link valid for 1 hour (3600 seconds)
const downloadUrl = await bucket.presignGet("videos/sample.mp4", {
expiresIn: 3600,
});
console.log("Presigned Download URL:", downloadUrl);
Generating a Presigned Upload Link (SDK)
// Authorize a browser or third-party client to upload directly via PUT
const uploadUrl = await bucket.presignPut("uploads/user-avatar.png", {
expiresIn: 900, // 15 minutes
});
Generating Presigned Links via CLI
# GET presigned URL valid for 2 hours
liorans3 object presign media videos/sample.mp4 --method GET --expires 7200
5. Zero-Leak Credential Masking
Lioran S3 enforces strict credential masking across all layers:
- Server Logs: Connection URIs containing credentials are automatically redacted as
bastion://***:***@host:port. - CLI Outputs: Command outputs and error messages sanitize passwords and secrets.
- SDK Serialization:
client.safeUri,client.toJSON(), andutil.inspectautomatically hide embedded credentials.