Merge pull request #42 from mayanayza/feat/user-auth

fix: update session cookie security to allow for non-secure contexts
This commit is contained in:
Maya
2025-10-30 19:26:47 -04:00
committed by GitHub
14 changed files with 28 additions and 13 deletions
+1
View File
@@ -223,6 +223,7 @@ The server supports the following configuration options:
| Log Level | `--log-level` | `NETVISOR_LOG_LEVEL` | `info` | Logging verbosity (`trace`, `debug`, `info`, `warn`, `error`) |
| Rust Log | `--rust-log` | `NETVISOR_RUST_LOG` | `""` | Low-level Rust framework logging |
| Database URL | `--database-url` | `NETVISOR_DATABASE_URL` | `postgresql://postgres:password@localhost:5432/netvisor` | PostgreSQL connection string |
| Use Secure Cookies | `--use-secure-session-cookies` | `NETVISOR_USE_SECURE_SESSION_COOKIES` | `false` | Set `true` when running behind HTTPS. Set `false` for HTTP/internal networks |
### UI Configuration
+5
View File
@@ -44,6 +44,10 @@ struct Cli {
/// Override integrated daemon url
#[arg(long)]
integrated_daemon_url: Option<String>,
/// Use secure session cookies (if serving UI behind HTTPS)
#[arg(long)]
use_secure_session_cookies: Option<bool>,
}
impl From<Cli> for CliArgs {
@@ -54,6 +58,7 @@ impl From<Cli> for CliArgs {
rust_log: cli.rust_log,
database_url: cli.database_url,
integrated_daemon_url: cli.integrated_daemon_url,
use_secure_session_cookies: cli.use_secure_session_cookies
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
pub mod extractor;
pub mod middleware;
pub mod handlers;
pub mod service;
pub mod types;
+9 -1
View File
@@ -17,6 +17,7 @@ pub struct CliArgs {
pub rust_log: Option<String>,
pub database_url: Option<String>,
pub integrated_daemon_url: Option<String>,
pub use_secure_session_cookies: Option<bool>
}
/// Flattened server configuration struct
@@ -40,6 +41,9 @@ pub struct ServerConfig {
/// URL for daemon running in same docker stack or in other local context
pub integrated_daemon_url: Option<String>,
/// URL for daemon running in same docker stack or in other local context
pub use_secure_session_cookies: bool,
}
impl Default for ServerConfig {
@@ -50,6 +54,7 @@ impl Default for ServerConfig {
rust_log: "".to_string(),
database_url: "postgresql://postgres:password@localhost:5432/netvisor".to_string(),
web_external_path: None,
use_secure_session_cookies: false,
integrated_daemon_url: None,
}
}
@@ -79,6 +84,9 @@ impl ServerConfig {
if let Some(integrated_daemon_url) = cli_args.integrated_daemon_url {
figment = figment.merge(("integrated_daemon_url", integrated_daemon_url));
}
if let Some(use_secure_session_cookies) = cli_args.use_secure_session_cookies {
figment = figment.merge(("use_secure_session_cookies", use_secure_session_cookies));
}
let config: ServerConfig = figment
.extract()
@@ -104,7 +112,7 @@ impl AppState {
config: ServerConfig,
discovery_manager: DiscoverySessionManager,
) -> Result<Arc<Self>, Error> {
let storage = StorageFactory::new(&config.database_url()).await?;
let storage = StorageFactory::new(&config.database_url(), config.use_secure_session_cookies).await?;
let services = ServiceFactory::new(&storage).await?;
Ok(Arc::new(Self {
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::server::{
auth::extractor::{AuthenticatedDaemon, AuthenticatedUser},
auth::middleware::{AuthenticatedDaemon, AuthenticatedUser},
config::AppState,
daemons::types::{
api::{DaemonRegistrationRequest, DaemonRegistrationResponse, GenerateKeyRequest},
+1 -1
View File
@@ -1,4 +1,4 @@
use crate::server::auth::extractor::AuthenticatedUser;
use crate::server::auth::middleware::AuthenticatedUser;
use crate::server::{
config::AppState,
groups::types::Group,
+1 -1
View File
@@ -1,4 +1,4 @@
use crate::server::auth::extractor::{AuthenticatedEntity, AuthenticatedUser};
use crate::server::auth::middleware::{AuthenticatedEntity, AuthenticatedUser};
use crate::server::{
config::AppState,
hosts::types::{api::HostWithServicesRequest, base::Host},
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::server::{
auth::extractor::AuthenticatedUser,
auth::middleware::AuthenticatedUser,
config::AppState,
networks::types::Network,
shared::types::api::{ApiError, ApiResponse, ApiResult},
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::server::{
auth::extractor::AuthenticatedUser,
auth::middleware::AuthenticatedUser,
config::AppState,
services::types::base::Service,
shared::types::api::{ApiResponse, ApiResult},
+4 -3
View File
@@ -26,7 +26,7 @@ pub struct StorageFactory {
}
pub async fn create_session_store(
db_pool: Pool<Postgres>,
db_pool: Pool<Postgres>, use_secure: bool
) -> Result<SessionManagerLayer<PostgresStore>> {
let session_store = PostgresStore::new(db_pool.clone());
@@ -35,17 +35,18 @@ pub async fn create_session_store(
Ok(SessionManagerLayer::new(session_store)
.with_expiry(Expiry::OnInactivity(time::Duration::days(30))) // 30 days
.with_name("session_id")
.with_secure(use_secure)
.with_http_only(true)
.with_same_site(tower_sessions::cookie::SameSite::Lax))
}
impl StorageFactory {
pub async fn new(database_url: &str) -> Result<Self> {
pub async fn new(database_url: &str, use_secure_session_cookies: bool) -> Result<Self> {
let pool = PgPool::connect(database_url).await?;
sqlx::migrate!("./migrations").run(&pool).await?;
let sessions = create_session_store(pool.clone()).await?;
let sessions = create_session_store(pool.clone(), use_secure_session_cookies).await?;
Ok(Self {
sessions,
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::server::{
auth::extractor::{AuthenticatedEntity, AuthenticatedUser},
auth::middleware::{AuthenticatedEntity, AuthenticatedUser},
config::AppState,
shared::types::api::{ApiError, ApiResponse, ApiResult},
subnets::types::base::Subnet,
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::server::{
auth::extractor::AuthenticatedUser,
auth::middleware::AuthenticatedUser,
config::AppState,
shared::types::api::{ApiResponse, ApiResult},
topology::types::api::TopologyRequestOptions,
+1 -1
View File
@@ -59,7 +59,7 @@ pub async fn setup_test_db() -> (PgPool, String, ContainerAsync<GenericImage>) {
pub async fn test_storage() -> (StorageFactory, ContainerAsync<GenericImage>) {
let (pool, database_url, _container) = setup_test_db().await;
pool.close().await;
let factory = StorageFactory::new(&database_url).await.unwrap();
let factory = StorageFactory::new(&database_url, false).await.unwrap();
(factory, _container)
}