Skip to content

Security: hscale/duradx-oss

Security

docs/security.md

Security

Reference for API authentication, RBAC, and step sandboxing in DuraDX.

Overview

DuraDX provides security features for production deployments:

  • API Authentication — Bearer token authentication for admin API endpoints.
  • Workflow RBAC — Role-based access control for workflow operations.
  • Step Sandboxing — Configuration flag for restricting shell step execution.

API Authentication

Configuration

Set the api_auth field in your Config:

use duradx::security::ApiAuth;

let mut config = Config::new("my-app", "postgres://localhost/mydb");
config.api_auth = ApiAuth::BearerToken("my-secret-token".to_string());

ApiAuth Enum

Variant Description
ApiAuth::None No authentication (default). All endpoints are open.
ApiAuth::BearerToken(String) Require Authorization: Bearer <token> header on all admin API requests.

How It Works

When ApiAuth::BearerToken is configured, every admin API request must include:

Authorization: Bearer my-secret-token

Requests without a valid token receive 401 Unauthorized.

The health check endpoint (GET /) is exempt from authentication.

Middleware

The auth middleware is implemented as an Axum layer in src/security/auth.rs. It extracts the Authorization header, validates the bearer token, and passes through on match.

use duradx::security::auth::auth_middleware;
use axum::middleware;

// Applied automatically when api_auth is configured
let app = Router::new()
    .route("/workflows", post(list_workflows))
    .layer(middleware::from_fn(auth_middleware));

Workflow RBAC

Role-based access control restricts who can execute, read, cancel, or administer workflows.

Permission Model

Permissions are stored in the workflow_permissions table:

Column Type Description
workflow_name TEXT Workflow name this permission applies to.
principal TEXT User ID, team name, or role.
permission TEXT Permission type: execute, read, cancel, admin.
created_at BIGINT When the permission was created.

Primary key: (workflow_name, principal, permission).

Managing Permissions

use duradx::security::rbac::{SetPermissionInput, DeletePermissionInput};

// Grant permission
ctx.system_db().set_permission(&SetPermissionInput {
    workflow_name: "process_order".to_string(),
    principal: "team-backend".to_string(),
    permission: "execute".to_string(),
}).await?;

// Check permission
let allowed = ctx.system_db().check_permission(
    "process_order",
    "team-backend",
    "execute",
).await?;

// List permissions
let perms = ctx.system_db().list_permissions("process_order").await?;

// Revoke permission
ctx.system_db().delete_permission(&DeletePermissionInput {
    workflow_name: "process_order".to_string(),
    principal: "team-backend".to_string(),
    permission: "execute".to_string(),
}).await?;

Permission Types

Permission Description
execute Can start/enqueue the workflow.
read Can view workflow status and steps.
cancel Can cancel the workflow.
admin Full control (execute + read + cancel + manage permissions).

Production Recommendations

  1. Always set ApiAuth::BearerToken in production. Use a strong, randomly generated token.
  2. Bind admin port to localhost or internal network. Use a reverse proxy for external access.
  3. Use RBAC to restrict workflow operations to authorized teams/users.
  4. Rotate tokens periodically. Update the config and restart the application.
  5. Use HTTPS via a reverse proxy (nginx, Caddy) — the admin API is HTTP-only.

Related

There aren't any published security advisories