Objective: Establish the core HTTP gateway, environment variable configuration, and routing middleware for RustStack.
Timeline: Weeks 1-2
Ensure the configuration manager properly parses and enforces all required environment variables. The current implementation has partial support but needs enhancement.
| Variable | Type | Default | Description |
|---|---|---|---|
SERVICES |
Comma-delimited | All enabled | Comma-delimited list. If present, only boot listed modules |
DEBUG / LS_LOG |
String | "info" | Map to tracing log levels (trace, debug, info, warn, error) |
PERSISTENCE / RUSTSTACK_PERSISTENCE |
Boolean | false | If 1, initialize SQLite/File I/O; otherwise, use volatile memory |
LOCALSTACK_HOST |
String | localhost.localstack.cloud:4566 | Host used in mock URLs |
USE_SSL |
Boolean | false | Toggle for returning https in mock URLs |
-
Read existing config implementation:
- Read
ruststack/src/config.rs - Read
ruststack/src/main.rsto see current CLI args
- Read
-
Add missing environment variables:
- Edit
ruststack/src/config.rsto add:SERVICESparsing that filters which services startLOCALSTACK_HOSTfor mock URL generationUSE_SSLtoggle- Update log level handling to support
DEBUGandLS_LOG
- Edit
-
Create config module for environment variable parsing:
// Add to config.rs #[derive(Debug, Clone)] pub struct EnvConfig { pub services: Vec<String>, pub log_level: tracing::Level, pub persistence: bool, pub localstack_host: String, pub use_ssl: bool, } impl EnvConfig { pub fn from_env() -> Self { ... } }
-
Update main.rs to use new config:
- Parse env vars at startup
- Pass configuration to service initialization
- Print enabled services at startup
-
Acceptance Test:
- Run
RUSTSTACK_S3=false RUSTSTACK_LOG_LEVEL=debug cargo run -- -p 4566 - Verify S3 is disabled and debug logging works
- Run
The router already exists and implements intelligent request multiplexing. This task focuses on improving it and adding protocol decoding middleware.
- Router binds to
0.0.0.0:4566✓ - Multiplexing via
X-Amz-Targetheader ✓ - Host header routing for S3 virtual-hosted styles - needs enhancement
-
Read current router implementation:
- Read
ruststack/src/router.rsfully
- Read
-
Enhance protocol detection middleware:
a. Create
ruststack/src/middleware.rs:use axum::{ extract::Request, middleware::Next, response::Response, }; /// AWS Protocol types #[derive(Debug, Clone, Copy)] pub enum AwsProtocol { RestJson, // aws.rest-json-1.1 Query, // aws.query Json, // aws.json-1.0 Unknown, } impl AwsProtocol { pub fn from_content_type(ct: &str) -> Self { // Parse Content-Type header for protocol } }
b. Add middleware to router in
router.rs:Router::new() .layer(middleware::from_fn(extract_aws_protocol)) // ... existing routes
-
Enhance S3 virtual-hosted style routing:
The router should detect
bucket.host:4566style requests:async fn extract_bucket_from_host( headers: &HeaderMap, uri: &Uri, ) -> Option<String> { // Check Host header for bucket.subdomain pattern }
-
Test routing:
- Start server with
cargo run - Test DynamoDB:
curl -H "X-Amz-Target: DynamoDB_20120810.ListTables" ... - Test S3 path-style:
curl http://localhost:4566/bucket/key - Test S3 virtual-hosted:
curl http://bucket.localhost:4566/key
- Start server with
-
Acceptance Test:
aws s3 ls --endpoint-url http://localhost:4566returns proper response- S3 operations work with both path and virtual-hosted styles
Implement a middleware that validates the structural presence of AWS Signature Version 4 headers. This prevents official SDKs from throwing pre-flight errors.
-
Read existing auth implementation:
- Read
ruststack-auth/src/lib.rs - Read
ruststack-auth/src/sigv4.rs
- Read
-
Understand SigV4 structure:
- Required headers:
Authorization,X-Amz-Date,X-Amz-Credential,X-Amz-SignedHeaders - The middleware should validate presence (not cryptographic correctness)
- Required headers:
-
Create SigV4 validation middleware:
Create
ruststack-auth/src/middleware.rs:use axum::{ extract::Request, http::{header, HeaderName, HeaderValue}, middleware::Next, response::Response, body::Body, }; /// Validates SigV4 headers are present (structural validation only) pub async fn validate_sigv4(request: Request<Body>, next: Next) -> Response { let headers = request.headers(); // Check for SigV4 indicators let has_authorization = headers.contains_key("authorization"); let has_date = headers.contains_key("x-amz-date"); if has_authorization || has_date { // Continue to actual handler return next.run(request).await; } // For non-signed requests, continue without modification next.run(request).await }
-
Add to router: In
ruststack/src/router.rs:use ruststack_auth::middleware::validate_sigv4; Router::new() .layer(middleware::from_fn(validate_sigv4)) // ... rest of router
-
Handle SigV4 errors properly:
When SigV4 is present but invalid, return proper AWS error:
if has_authorization && !is_valid_sigv4(headers) { return Response::builder() .status(StatusCode::FORBIDDEN) .header(header::CONTENT_TYPE, "application/json") .body(Body::from(r#"{"__type":"InvalidSignatureException"}"#)) .unwrap(); }
-
Test with AWS CLI:
aws configure set aws_access_key_id test aws configure set aws_secret_access_key test aws s3 ls --endpoint-url http://localhost:4566 # Should NOT return SignatureDoesNotMatch error
-
Acceptance Test:
- AWS SDK requests with SigV4 headers return 200 (or proper service error)
- Requests without SigV4 continue normally
- Invalid SigV4 returns
InvalidSignatureExceptionnot generic 500
| Criterion | Test Command | Expected Result |
|---|---|---|
| Router binds to port 4566 | cargo run |
Server starts on 0.0.0.0:4566 |
| Environment config works | RUSTSTACK_S3=false cargo run |
S3 service disabled in output |
| DynamoDB routing | curl -H "X-Amz-Target: DynamoDB_20120810.ListTables" -X POST localhost:4566 |
Returns DynamoDB response |
| S3 path-style routing | curl localhost:4566/my-bucket/my-key |
Routes to S3 handler |
| SigV4 validation | AWS CLI commands | No SigV4 errors |
| Logging works | RUSTSTACK_LOG_LEVEL=debug cargo run |
Debug logs visible |
-
File locations: All new code should go in appropriate crates:
- Core config:
ruststack/src/config.rs - Router:
ruststack/src/router.rs - Auth middleware:
ruststack-auth/src/middleware.rs
- Core config:
-
Testing approach:
- Use
cargo testto run existing tests - Manual testing with
curland AWS CLI - Add unit tests for new middleware
- Use
-
Dependencies already available:
- axum, tower, tower-http
- tokio, tracing
- All AWS-related crates already in workspace