Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,15 @@ COPY --from=frontend-builder /app/docs/out ./docs/out/
# Fetch model catalog (embedded at compile time via include_str!)
RUN mkdir -p data && curl -sSL https://models.dev/api.json -o data/models-dev-catalog.json

# Touch main.rs to invalidate the dummy build
RUN touch src/main.rs
# Force fresh build of the main crate by removing cached artifacts.
# The --mount=type=cache for target/ persists across builds, but fingerprints
# may not detect all source changes. Removing the crate's artifacts ensures
# a full recompile of application code (dependencies remain cached).
RUN touch src/main.rs && \
rm -rf target/release/.fingerprint/hadrian-* \
target/release/deps/hadrian-* \
target/release/deps/libhadrian-* \
target/release/hadrian

# Build the actual application
RUN --mount=type=cache,target=/usr/local/cargo/registry \
Expand Down
7 changes: 2 additions & 5 deletions deploy/config/hadrian.dlq.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@ path = "/app/data/hadrian.db"
type = "redis"
url = "${REDIS_URL}"

[auth.gateway]
type = "api_key"
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300
[auth.mode]
type = "none"

[providers]
default_provider = "test"
Expand Down
28 changes: 17 additions & 11 deletions deploy/config/hadrian.keycloak.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
# Development setup with Keycloak for per-org OIDC authentication
# OIDC SSO is configured via Admin API, not in this config file

[server]
# Allow Docker-internal private IPs for OIDC discovery (Keycloak runs in Docker)
allow_private_urls = true
# Keycloak advertises issuer as http://localhost:8080 (host-mapped port)
allow_loopback_urls = true

[ui]
enabled = true

Expand All @@ -15,13 +21,19 @@ enabled = true
api_key = "gw_test_bootstrap_key_for_e2e"

# ==============================================================================
# Session Configuration (for per-org SSO)
# Auth Mode: IdP (per-org SSO + API keys)
# ==============================================================================
# OIDC authentication is configured per-organization via the Admin API.
# This section only configures session management for authenticated users.
# The test setup creates the SSO connection with OIDC settings.
[auth.admin]
type = "session"
# Session management for authenticated users is configured below.
[auth.mode]
type = "idp"

[auth.api_key]
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300

[auth.session]
secure = false # For local dev over HTTP

[database]
Expand All @@ -32,12 +44,6 @@ path = "/app/data/hadrian.db"
type = "redis"
url = "${REDIS_URL}"

[auth.gateway]
type = "api_key"
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300

# RBAC is disabled for this basic keycloak test to allow unauthenticated admin API access.
# For comprehensive RBAC testing with OIDC authentication, see the university deployment tests.

Expand Down
7 changes: 2 additions & 5 deletions deploy/config/hadrian.observability.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@ path = "/app/data/hadrian.db"
type = "redis"
url = "${REDIS_URL}"

[auth.gateway]
type = "api_key"
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300
[auth.mode]
type = "none"

[providers]
default_provider = "test"
Expand Down
7 changes: 2 additions & 5 deletions deploy/config/hadrian.postgres-ha.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ read_url = "${DATABASE_READ_URL}"
type = "redis"
url = "${REDIS_URL}"

[auth.gateway]
type = "api_key"
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300
[auth.mode]
type = "none"
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PostgreSQL HA production configuration sets auth.mode.type to "none", fully disabling authentication. Deploying this file as-is would expose all gateway and admin endpoints without any access control, enabling unauthorized access to data and model operations. Update the default to a secure mode like "api_key", "idp", or "iap", and ensure "none" is only used in explicitly development/test configurations.

Suggested change
type = "none"
type = "api_key"

Copilot uses AI. Check for mistakes.

[providers]
default_provider = "test"
Expand Down
13 changes: 5 additions & 8 deletions deploy/config/hadrian.postgres.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,14 @@ url = "${DATABASE_URL}"
type = "redis"
url = "${REDIS_URL}"

[auth.gateway]
type = "api_key"
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300 # 5 minutes with Redis
[auth.mode]
type = "none"

Comment on lines +13 to 14
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This production configuration sets auth.mode.type to "none", which disables all authentication for both API and admin endpoints. If an operator uses this file as-is, the gateway will run in production with completely unauthenticated access, allowing any unauthenticated user to invoke models and access admin functionality. Change auth.mode.type to a secure mode such as "api_key", "idp", or "iap" by default, and reserve "none" strictly for clearly-labeled development-only configs.

Suggested change
type = "none"
type = "api_key"
# Note: Do NOT use auth.mode.type = "none" in production. Reserve it for clearly-marked
# development-only configs if you need to disable authentication locally.

Copilot uses AI. Check for mistakes.
# Optional: Reverse proxy authentication for UI
# Optional: IAP (Identity-Aware Proxy) authentication
# Trusts identity headers from an authenticating proxy (Cloudflare Access, oauth2-proxy, etc.)
# IMPORTANT: Configure [server.trusted_proxies] to prevent header spoofing
# [auth.admin]
# type = "proxy_auth"
# [auth.mode]
# type = "iap"
# identity_header = "Cf-Access-Authenticated-User-Email"
# email_header = "Cf-Access-Authenticated-User-Email"
# name_header = "X-Forwarded-User"
Expand Down
4 changes: 3 additions & 1 deletion deploy/config/hadrian.production.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ url = "${DATABASE_URL}"
type = "redis"
url = "${REDIS_URL}"

[auth.gateway]
[auth.mode]
type = "api_key"

[auth.api_key]
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300
Expand Down
6 changes: 2 additions & 4 deletions deploy/config/hadrian.provider-health.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ path = "/app/data/hadrian.db"
[cache]
type = "memory"

[auth.gateway]
type = "api_key"
header_name = "X-API-Key"
key_prefix = "gw_"
[auth.mode]
type = "none"

[providers]
default_provider = "test"
Expand Down
7 changes: 2 additions & 5 deletions deploy/config/hadrian.redis-cluster.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@ retry_delay_ms = 100
connection_timeout_secs = 5
response_timeout_secs = 1

[auth.gateway]
type = "api_key"
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300
[auth.mode]
type = "none"

[providers]
default_provider = "test"
Expand Down
24 changes: 11 additions & 13 deletions deploy/config/hadrian.saml.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
# - SAML groups are captured for the group mapping feature
# - Group mappings are configured via Admin API, not parsed from assertion attributes

[server]
# Allow Docker-internal private IPs for SAML/OIDC discovery (Authentik runs in Docker)
allow_private_urls = true

[ui]
enabled = true

Expand All @@ -31,22 +35,16 @@ api_key = "gw_test_bootstrap_key_for_e2e"
auto_verify_domains = ["university.edu"]

# ==============================================================================
# Session Configuration (for per-org SSO)
# Auth Mode: IdP (per-org SSO)
# ==============================================================================
# SAML authentication is configured per-organization via the Admin API.
# This section configures session management for authenticated users.
[auth.admin]
type = "session"
secure = false # For local dev over HTTP
# Session management for authenticated users is configured below.
# No API key requirement for this test — focuses on SAML SSO flow.
[auth.mode]
type = "idp"

# ==============================================================================
# API Authentication
# ==============================================================================
# For SAML E2E tests, we disable API authentication to allow bootstrapping.
# In production, you would use API keys for programmatic access.
# The test focuses on SAML SSO flow, not API key management.
[auth.gateway]
type = "none"
[auth.session]
secure = false # For local dev over HTTP

# ==============================================================================
# RBAC Configuration
Expand Down
7 changes: 2 additions & 5 deletions deploy/config/hadrian.sqlite-redis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@ path = "/app/data/hadrian.db"
type = "redis"
url = "${REDIS_URL}"

[auth.gateway]
type = "api_key"
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300 # 5 minutes with Redis
[auth.mode]
type = "none"

[providers]
default_provider = "test"
Expand Down
7 changes: 2 additions & 5 deletions deploy/config/hadrian.sqlite.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ path = "/app/data/hadrian.db"
[cache]
type = "memory"

[auth.gateway]
type = "api_key"
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 60
[auth.mode]
type = "none"

[providers]
default_provider = "test"
Expand Down
4 changes: 3 additions & 1 deletion deploy/config/hadrian.traefik.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ url = "${DATABASE_URL}"
type = "redis"
url = "${REDIS_URL}"

[auth.gateway]
[auth.mode]
type = "api_key"

[auth.api_key]
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300
Expand Down
35 changes: 15 additions & 20 deletions deploy/config/hadrian.university.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@
# - Single organization with department teams
#
# Key architecture points:
# - allow_private_urls is needed for Docker-internal OIDC discovery
# - OIDC SSO is configured per-organization via Admin API (not in this config file)
# - One SSO connection = One organization (all users provisioned into "university" org)
# - Departments are teams within the university org (cs-faculty, med-research, it-platform, etc.)
# - subject.org_ids and subject.team_ids come from database memberships, not JWT claims
# - IdP groups are captured for the group mapping feature (raw paths like /cs/faculty)
# - Group mappings are configured via Admin API, not parsed from group paths

[server]
# Allow Docker-internal private IPs for OIDC discovery (Keycloak runs in Docker)
allow_private_urls = true
# Keycloak advertises issuer as http://localhost:8080 (host-mapped port)
allow_loopback_urls = true

[ui]
enabled = true

Expand All @@ -31,33 +38,21 @@ api_key = "gw_test_bootstrap_key_for_e2e"
auto_verify_domains = ["university.edu"]

# ==============================================================================
# Session Configuration (for per-org SSO)
# Auth Mode: IdP (per-org SSO + API keys + JWT)
# ==============================================================================
# OIDC authentication is configured per-organization via the Admin API.
# This section only configures session management for authenticated users.
# The test setup creates the SSO connection with OIDC settings.
[auth.admin]
type = "session"
secure = false # For local dev over HTTP

# ==============================================================================
# Gateway Authentication
# ==============================================================================
# Use multi-auth to support both API keys and JWT tokens
# Gateway RBAC policies require JWT tokens (roles come from OIDC claims)
[auth.gateway]
type = "multi"
# Session management for authenticated users is configured below.
# JWT validation is handled per-org via GatewayJwtRegistry (loaded from SSO config).
[auth.mode]
type = "idp"

[auth.gateway.api_key]
[auth.api_key]
header_name = "X-API-Key"
key_prefix = "gw_"
cache_ttl_secs = 300

[auth.gateway.jwt]
issuer = "http://localhost:8080/realms/hadrian"
jwks_url = "http://keycloak:8080/realms/hadrian/protocol/openid-connect/certs"
audience = "hadrian-gateway"
identity_claim = "preferred_username"
[auth.session]
secure = false # For local dev over HTTP

# ==============================================================================
# RBAC Configuration with CEL Policies
Expand Down
Loading