A Rust-based RESTful API for interacting with GCDServer data, abstracting away direct MongoDB interactions.
- RESTful API endpoints for Calibration, Geometry, Detector Status, and Configuration data
- Keycloak OAuth2 authentication - Direct token validation with RSA public keys
- Streamlined auth flow - No intermediate JWT wrapping, uses Keycloak tokens directly
- MongoDB integration with proper error handling
- Structured logging with environment-based configuration
- Actix-web framework for high performance
- Type-safe database operations with Serde serialization
- Role-based access control (RBAC) via Keycloak realm roles
- Token validation middleware for protected endpoints
src/
├── main.rs # Application entry point
├── api/ # REST API endpoints
│ ├── mod.rs
│ ├── auth.rs # Authentication endpoints (Keycloak OAuth2)
│ ├── calibration.rs # Calibration endpoints
│ ├── geometry.rs # Geometry endpoints
│ ├── detector_status.rs # Detector status endpoints
│ ├── configuration.rs # Configuration endpoints
│ └── health.rs # Health check endpoint
├── auth/ # Authentication & OAuth2
│ ├── mod.rs
│ ├── middleware.rs # Token validation middleware (RSA verification)
│ └── oauth2.rs # Keycloak OAuth2 integration
├── db.rs # MongoDB client wrapper
├── errors.rs # Error handling and API responses
└── models.rs # Data models and request/response types
GET /health- Health check endpoint
POST /auth/login- Initiate OAuth2 login (returns authorization URL)GET /auth/callback?code=...&state=...- OAuth2 callback endpoint (exchanges code for Keycloak token)GET /auth/verify- Verify Keycloak token validity (requires Bearer token)
GET /calibration- Get all calibrationsPOST /calibration- Create new calibrationGET /calibration/{dom_id}- Get calibration for DOMPUT /calibration/{dom_id}- Update calibrationDELETE /calibration/{dom_id}- Delete calibrationGET /calibration/latest/{dom_id}- Get latest calibration
GET /geometry- Get all geometry entriesPOST /geometry- Create new geometry entryGET /geometry/{string}/{position}- Get geometry by locationPUT /geometry/{string}/{position}- Update geometryDELETE /geometry/{string}/{position}- Delete geometryGET /geometry/string/{string}- Get all geometry for a string
GET /detector-status- Get all detector statusesPOST /detector-status- Create new detector statusGET /detector-status/{dom_id}- Get status for DOMPUT /detector-status/{dom_id}- Update detector statusDELETE /detector-status/{dom_id}- Delete detector statusGET /detector-status/bad-doms- Get all bad DOMs
GET /config- Get all configurationsPOST /config- Create new configurationGET /config/{key}- Get configuration by keyPUT /config/{key}- Update configurationDELETE /config/{key}- Delete configuration
POST /gcd/generate/{run_number}- Generate complete GCD collection for a run- Creates all geometry, calibration, and detector status data in a single atomic operation
- Requires valid run number and authentication
- Returns combined GCD collection with metadata
- Rust 1.70+
- MongoDB 4.0+
# Clone or navigate to the project directory
cd gcdserver_rust_api
# Build the project
cargo build --releaseThe API uses environment variables for configuration. Create a .env file in the project root:
# MongoDB
MONGODB_URI=mongodb://localhost:27017
DATABASE_NAME=gcdserver
# Keycloak OAuth2
KEYCLOAK_ISSUER_URL=http://localhost:8080/auth/realms/gcdserver
KEYCLOAK_CLIENT_ID=gcdserver-api
KEYCLOAK_CLIENT_SECRET=your-keycloak-client-secret
KEYCLOAK_REDIRECT_URI=http://localhost:8080/auth/callbackNote: The API validates Keycloak tokens using RSA public keys fetched from Keycloak's discovery endpoint. No additional JWT secret configuration is needed.
For detailed Keycloak setup instructions, see KEYCLOAK_SETUP.md.
Quick Start:
# Start Keycloak with Docker
docker run -d \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:latest \
start-dev
# Then configure client credentials in Keycloak admin console
# and update .env file# Development
cargo run
# Release build
cargo run --release
# With custom environment
MONGODB_URI=mongodb://db-server:27017 cargo runThe API will start on http://0.0.0.0:8080
# 1. Get login authorization URL
curl -X POST http://localhost:8080/auth/login
# Response includes authorization URL
{
"authorization_url": "http://localhost:8080/auth/realms/gcdserver/protocol/openid-connect/auth?...",
"state": "random-state"
}
# 2. User visits authorization_url and logs in with Keycloak
# 3. Keycloak redirects to callback: http://localhost:8080/auth/callback?code=AUTH_CODE&state=STATE
# 4. Exchange code for Keycloak token
curl -X GET "http://localhost:8080/auth/callback?code=AUTH_CODE&state=STATE"
# Response includes Keycloak access token
{
"access_token": "eyJhbGciOiJSUzI1NiI...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJIUzI1NiI...",
"user": {
"id": "user-uuid",
"email": "user@example.com",
"name": "User Name",
"username": "username",
"roles": ["user", "admin"]
}
}# Store token from OAuth2 callback response
TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
# Verify token validity
curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/auth/verify
# Response shows token validity and claims
{
"valid": true,
"user_id": "user-uuid",
"email": "user@example.com",
"roles": ["user", "admin"]
}
# Use token for authenticated API calls
curl -X POST http://localhost:8080/calibration \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"dom_id": 12345,
"domcal": {
"atwd_gain": [1.0, 1.1, 1.2, 1.3],
"atwd_freq": [50.0, 50.1, 50.2, 50.3],
"fadc_gain": 1.0,
"fadc_freq": 50.0,
"pmt_gain": 1.0,
"transit_time": 1.0,
"relative_pmt_gain": 1.0
}
}'
# Note: Token refresh is handled by Keycloak
# Use the refresh_token from callback response if token expirescurl -X POST http://localhost:8080/calibration \
-H "Content-Type: application/json" \
-d '{
"dom_id": 12345,
"domcal": {
"atwd_gain": [1.0, 1.1, 1.2, 1.3],
"atwd_freq": [50.0, 50.1, 50.2, 50.3],
"fadc_gain": 1.0,
"fadc_freq": 50.0,
"pmt_gain": 1.0,
"transit_time": 1.0,
"relative_pmt_gain": 1.0
}
}'curl http://localhost:8080/calibration/12345curl -X POST http://localhost:8080/geometry \
-H "Content-Type: application/json" \
-d '{
"string": 1,
"position": 1,
"location": {
"x": 100.0,
"y": 200.0,
"z": -500.0
}
}'curl -X POST http://localhost:8080/config \
-H "Content-Type: application/json" \
-d '{
"key": "detector_name",
"value": "IceCube"
}'The API returns structured error responses:
{
"error": "Not found: Configuration not found for key 'missing_key'",
"status": 404
}{
"error": "Missing authorization header",
"status": 401
}{
"error": "Invalid or expired token",
"status": 401
}Set RUST_LOG environment variable to control logging:
RUST_LOG=debug cargo run
RUST_LOG=info,actix_web=debug cargo run- The server uses Actix-web for high-concurrency async handling
- MongoDB connection pooling is handled by the MongoDB driver
- All database operations are async and non-blocking
The Python GCDServer client can be updated to use this REST API instead of directly accessing MongoDB:
import requests
BASE_URL = "http://localhost:8080"
# Get calibration
response = requests.get(f"{BASE_URL}/calibration/12345")
calibration = response.json()["data"]
# Create geometry
requests.post(
f"{BASE_URL}/geometry",
json={
"string": 1,
"position": 1,
"location": {"x": 100.0, "y": 200.0, "z": -500.0}
}
)- Login Request → Client requests authorization URL from
/auth/login - User Authentication → User logs in via Keycloak
- Authorization Code → Keycloak redirects with authorization code
- Token Exchange → API exchanges code for Keycloak token at
/auth/callback - Token Validation → Middleware validates RSA-signed token on protected endpoints
- Claims Extraction → Validated claims attached to request for handler access
- Keycloak tokens are RSA-256 signed
- Public keys fetched from Keycloak's JWKS endpoint
- Signature verification ensures token authenticity
- Expiration checked automatically by middleware
- Realm roles extracted from token claims
- GCD Collection Generation - Single endpoint to atomically generate complete Geometry, Calibration, and Detector Status collections for a given run number
- Token blacklisting/revocation support
- Batch operations support
- Query filtering and pagination
- Database migration tools
- Performance monitoring and metrics
- WebSocket support for real-time updates
- GraphQL interface
- API rate limiting
- Request signing for service-to-service authentication
- Multi-realm Keycloak support
See LICENSE file for details
cargo testcargo fmtcargo clippy