forked from github-starred/komodo
KL-1 Configurable CORS support
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use std::{path::PathBuf, sync::OnceLock};
|
||||
|
||||
use anyhow::Context;
|
||||
use axum::http::HeaderValue;
|
||||
use colored::Colorize;
|
||||
use config::ConfigLoader;
|
||||
use environment_file::{
|
||||
@@ -14,6 +15,7 @@ use komodo_client::entities::{
|
||||
logger::LogConfig,
|
||||
};
|
||||
use noise::key::{RotatableKeyPair, SpkiPublicKey};
|
||||
use tower_http::cors::CorsLayer;
|
||||
|
||||
/// Should call in startup to ensure Core errors without valid private key.
|
||||
pub fn core_keys() -> &'static RotatableKeyPair {
|
||||
@@ -89,6 +91,36 @@ pub fn periphery_public_keys() -> Option<&'static [SpkiPublicKey]> {
|
||||
.as_deref()
|
||||
}
|
||||
|
||||
/// Creates a CORS layer based on the Core configuration.
|
||||
///
|
||||
/// - If `cors_allowed_origins` is empty: Allows all origins (backward compatibility)
|
||||
/// - If `cors_allowed_origins` is set: Only allows the specified origins
|
||||
/// - Methods and headers are always allowed (Any)
|
||||
/// - Credentials are only allowed if `cors_allow_credentials` is true
|
||||
pub fn cors_layer() -> CorsLayer {
|
||||
let config = core_config();
|
||||
let allowed_origins = if config.cors_allowed_origins.is_empty() {
|
||||
vec![HeaderValue::from_static("*")]
|
||||
} else {
|
||||
config
|
||||
.cors_allowed_origins
|
||||
.iter()
|
||||
.filter_map(|origin| {
|
||||
HeaderValue::from_str(origin)
|
||||
.inspect_err(|e| {
|
||||
warn!("Invalid CORS allowed origin: {origin} | {e:?}")
|
||||
})
|
||||
.ok()
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
CorsLayer::new()
|
||||
.allow_origin(allowed_origins)
|
||||
.allow_methods(tower_http::cors::Any)
|
||||
.allow_headers(tower_http::cors::Any)
|
||||
.allow_credentials(config.cors_allow_credentials)
|
||||
}
|
||||
|
||||
pub fn core_config() -> &'static CoreConfig {
|
||||
static CORE_CONFIG: OnceLock<CoreConfig> = OnceLock::new();
|
||||
CORE_CONFIG.get_or_init(|| {
|
||||
@@ -281,6 +313,12 @@ pub fn core_config() -> &'static CoreConfig {
|
||||
.komodo_frontend_path
|
||||
.unwrap_or(config.frontend_path),
|
||||
jwt_ttl: env.komodo_jwt_ttl.unwrap_or(config.jwt_ttl),
|
||||
cors_allowed_origins: env
|
||||
.komodo_cors_allowed_origins
|
||||
.unwrap_or(config.cors_allowed_origins),
|
||||
cors_allow_credentials: env
|
||||
.komodo_cors_allow_credentials
|
||||
.unwrap_or(config.cors_allow_credentials),
|
||||
sync_directory: env
|
||||
.komodo_sync_directory
|
||||
.unwrap_or(config.sync_directory),
|
||||
|
||||
@@ -8,10 +8,7 @@ use std::{net::SocketAddr, str::FromStr};
|
||||
use anyhow::Context;
|
||||
use axum::{Router, routing::get};
|
||||
use axum_server::{Handle, tls_rustls::RustlsConfig};
|
||||
use tower_http::{
|
||||
cors::{Any, CorsLayer},
|
||||
services::{ServeDir, ServeFile},
|
||||
};
|
||||
use tower_http::services::{ServeDir, ServeFile};
|
||||
use tracing::Instrument;
|
||||
|
||||
use crate::config::{core_config, core_keys};
|
||||
@@ -108,12 +105,7 @@ async fn app() -> anyhow::Result<()> {
|
||||
.nest("/ws", ws::router())
|
||||
.nest("/client", ts_client::router())
|
||||
.fallback_service(serve_frontend)
|
||||
.layer(
|
||||
CorsLayer::new()
|
||||
.allow_origin(Any)
|
||||
.allow_methods(Any)
|
||||
.allow_headers(Any),
|
||||
)
|
||||
.layer(config::cors_layer())
|
||||
.into_make_service();
|
||||
|
||||
let addr =
|
||||
|
||||
@@ -218,6 +218,11 @@ pub struct Env {
|
||||
/// Override `github_oauth.secret` from file
|
||||
pub komodo_github_oauth_secret_file: Option<PathBuf>,
|
||||
|
||||
/// Override `cors_allowed_origins`
|
||||
pub komodo_cors_allowed_origins: Option<Vec<String>>,
|
||||
/// Override `cors_allow_credentials`
|
||||
pub komodo_cors_allow_credentials: Option<bool>,
|
||||
|
||||
/// Override `database.uri`
|
||||
#[serde(alias = "komodo_mongo_uri")]
|
||||
pub komodo_database_uri: Option<String>,
|
||||
@@ -511,6 +516,21 @@ pub struct CoreConfig {
|
||||
#[serde(default)]
|
||||
pub github_oauth: OauthCredentials,
|
||||
|
||||
// =======
|
||||
// = CORS =
|
||||
// =======
|
||||
/// List of CORS allowed origins.
|
||||
/// If empty, allows all origins (`*`).
|
||||
/// Production setups should configure this explicitly.
|
||||
/// Example: `["https://komodo.example.com", "https://app.example.com"]`.
|
||||
#[serde(default)]
|
||||
pub cors_allowed_origins: Vec<String>,
|
||||
|
||||
/// Tell CORS to allow credentials in requests.
|
||||
/// Used if needed for authentication proxy.
|
||||
#[serde(default)]
|
||||
pub cors_allow_credentials: bool,
|
||||
|
||||
// ============
|
||||
// = Webhooks =
|
||||
// ============
|
||||
@@ -757,6 +777,8 @@ impl Default for CoreConfig {
|
||||
oidc_additional_audiences: Default::default(),
|
||||
google_oauth: Default::default(),
|
||||
github_oauth: Default::default(),
|
||||
cors_allowed_origins: Default::default(),
|
||||
cors_allow_credentials: Default::default(),
|
||||
webhook_secret: Default::default(),
|
||||
webhook_base_url: Default::default(),
|
||||
logging: Default::default(),
|
||||
@@ -853,6 +875,8 @@ impl CoreConfig {
|
||||
id: empty_or_redacted(&config.github_oauth.id),
|
||||
secret: empty_or_redacted(&config.github_oauth.id),
|
||||
},
|
||||
cors_allowed_origins: config.cors_allowed_origins,
|
||||
cors_allow_credentials: config.cors_allow_credentials,
|
||||
webhook_secret: empty_or_redacted(&config.webhook_secret),
|
||||
webhook_base_url: config.webhook_base_url,
|
||||
database: config.database.sanitized(),
|
||||
|
||||
@@ -294,6 +294,23 @@ github_oauth.id = ""
|
||||
## Required if github_oauth is enabled.
|
||||
github_oauth.secret = ""
|
||||
|
||||
########
|
||||
# CORS #
|
||||
########
|
||||
|
||||
## Specifically set list of CORS allowed origins.
|
||||
## If empty, allows all origins (`*`).
|
||||
## Production setups should configure this explicitly.
|
||||
## Env: KOMODO_CORS_ALLOWED_ORIGINS
|
||||
## Default: empty
|
||||
cors_allowed_origins = ["*"]
|
||||
|
||||
## Tell CORS to allow credentials in requests.
|
||||
## Set true only if needed for authentication proxy.
|
||||
## Env: KOMODO_CORS_ALLOW_CREDENTIALS
|
||||
## Default: false
|
||||
cors_allow_credentials = false
|
||||
|
||||
##################
|
||||
# POLL INTERVALS #
|
||||
##################
|
||||
|
||||
Reference in New Issue
Block a user