From 969c50c73820c24729b9743f8c2b7b58c0613330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 25 Mar 2026 12:45:30 +0100 Subject: [PATCH 01/15] update protos --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index 28d962c67..f93bf295a 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 28d962c6746e7b2bad365f8c9cc41fd23cf1b322 +Subproject commit f93bf295a4c8e92bbacd3a049b07072c26ede7cb From ab2cbaca062a9a31f4c1d5b7074c403ecff9bbd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 25 Mar 2026 15:24:35 +0100 Subject: [PATCH 02/15] adjust protobuf imports for new proto structure --- crates/defguard_proto/build.rs | 82 +++++++++++++++++++++++++------- crates/defguard_proto/src/lib.rs | 41 ++++++++++++++-- 2 files changed, 103 insertions(+), 20 deletions(-) diff --git a/crates/defguard_proto/build.rs b/crates/defguard_proto/build.rs index 367ccb94c..c8506ff29 100644 --- a/crates/defguard_proto/build.rs +++ b/crates/defguard_proto/build.rs @@ -1,4 +1,20 @@ -fn main() -> Result<(), Box> { +use std::{ + env, + error::Error, + path::{Path, PathBuf}, +}; + +const PROTO_LAYOUT_PATHS: [&str; 4] = [ + "v2/core/proxy.proto", + "v2/worker/worker.proto", + "v2/wireguard/gateway.proto", + "enterprise/v2/firewall/firewall.proto", +]; + +fn main() -> Result<(), Box> { + let proto_repository_root = derive_proto_repository_root()?; + let proto_files = resolve_proto_files(&proto_repository_root)?; + tonic_prost_build::configure() // These types contain sensitive data. .skip_debug([ @@ -15,20 +31,54 @@ fn main() -> Result<(), Box> { "PasswordResetRequest", ]) .protoc_arg("--experimental_allow_proto3_optional") - .compile_protos( - &[ - "../../proto/core/proxy.proto", - "../../proto/worker/worker.proto", - "../../proto/wireguard/gateway.proto", - "../../proto/enterprise/firewall/firewall.proto", - ], - &[ - "../../proto/core", - "../../proto/worker", - "../../proto/wireguard", - "../../proto/enterprise/firewall", - ], - )?; - println!("cargo:rerun-if-changed=../../proto"); + .compile_protos(&proto_files, &[proto_repository_root.clone()])?; + + println!("cargo:rerun-if-changed={}", proto_repository_root.display()); Ok(()) } + +/// Derives the shared proto checkout from Cargo metadata so code generation does +/// not depend on the shell's current working directory. +fn derive_proto_repository_root() -> Result> { + let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?); + let workspace_root = manifest_dir + .parent() + .and_then(Path::parent) + .ok_or_else(|| { + format!( + "failed to derive workspace root from CARGO_MANIFEST_DIR: {}", + manifest_dir.display() + ) + })?; + let proto_repository_root = workspace_root.join("proto"); + + if !proto_repository_root.is_dir() { + return Err(format!( + "expected proto repository root at {}, but the directory does not exist", + proto_repository_root.display() + ) + .into()); + } + + Ok(proto_repository_root) +} + +/// Resolves the expected protobuf entrypoints up front so missing definitions +/// fail the build before code generation starts. +fn resolve_proto_files(proto_repository_root: &Path) -> Result, Box> { + PROTO_LAYOUT_PATHS + .iter() + .map(|relative_path| { + let proto_file = proto_repository_root.join(relative_path); + if !proto_file.is_file() { + return Err(format!( + "expected protobuf definition at {}, but the file does not exist", + proto_file.display() + ) + .into()); + } + + Ok(proto_file) + }) + .collect() +} diff --git a/crates/defguard_proto/src/lib.rs b/crates/defguard_proto/src/lib.rs index aa70796b4..f8edca150 100644 --- a/crates/defguard_proto/src/lib.rs +++ b/crates/defguard_proto/src/lib.rs @@ -1,17 +1,50 @@ use std::fmt; +mod generated { + pub mod defguard { + pub mod proxy { + pub mod v2 { + tonic::include_proto!("defguard.proxy.v2"); + } + } + + pub mod gateway { + pub mod v2 { + tonic::include_proto!("defguard.gateway.v2"); + } + } + + pub mod worker { + pub mod v2 { + tonic::include_proto!("defguard.worker.v2"); + } + } + + pub mod enterprise { + pub mod firewall { + pub mod v2 { + tonic::include_proto!("defguard.enterprise.firewall.v2"); + } + } + } + } +} + pub mod proxy { - tonic::include_proto!("defguard.proxy"); + pub use crate::generated::defguard::proxy::v2::*; } + pub mod gateway { - tonic::include_proto!("gateway"); + pub use crate::generated::defguard::gateway::v2::*; } + pub mod worker { - tonic::include_proto!("worker"); + pub use crate::generated::defguard::worker::v2::*; } + pub mod enterprise { pub mod firewall { - tonic::include_proto!("enterprise.firewall"); + pub use crate::generated::defguard::enterprise::firewall::v2::*; } } From 7671a4961400f47537e9fad551be02b82be8ba7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 25 Mar 2026 15:27:27 +0100 Subject: [PATCH 03/15] update service name --- crates/defguard_core/tests/integration/grpc/health.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/defguard_core/tests/integration/grpc/health.rs b/crates/defguard_core/tests/integration/grpc/health.rs index c2e1e5a34..68a9c9246 100644 --- a/crates/defguard_core/tests/integration/grpc/health.rs +++ b/crates/defguard_core/tests/integration/grpc/health.rs @@ -13,7 +13,7 @@ async fn worker_service_health_is_serving(_: PgPoolOptions, options: PgConnectOp let response = client .check(HealthCheckRequest { - service: "worker.WorkerService".into(), + service: "defguard.worker.v2.WorkerService".into(), }) .await .expect("health check should succeed") From 53ce532f58faf9fbbdbb11c9f937c53b58fcfade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 25 Mar 2026 15:48:04 +0100 Subject: [PATCH 04/15] go back to a simpler approach --- crates/defguard_proto/build.rs | 76 ++++++---------------------------- 1 file changed, 12 insertions(+), 64 deletions(-) diff --git a/crates/defguard_proto/build.rs b/crates/defguard_proto/build.rs index c8506ff29..4f00e1340 100644 --- a/crates/defguard_proto/build.rs +++ b/crates/defguard_proto/build.rs @@ -1,20 +1,6 @@ -use std::{ - env, - error::Error, - path::{Path, PathBuf}, -}; - -const PROTO_LAYOUT_PATHS: [&str; 4] = [ - "v2/core/proxy.proto", - "v2/worker/worker.proto", - "v2/wireguard/gateway.proto", - "enterprise/v2/firewall/firewall.proto", -]; +use std::error::Error; fn main() -> Result<(), Box> { - let proto_repository_root = derive_proto_repository_root()?; - let proto_files = resolve_proto_files(&proto_repository_root)?; - tonic_prost_build::configure() // These types contain sensitive data. .skip_debug([ @@ -31,54 +17,16 @@ fn main() -> Result<(), Box> { "PasswordResetRequest", ]) .protoc_arg("--experimental_allow_proto3_optional") - .compile_protos(&proto_files, &[proto_repository_root.clone()])?; - - println!("cargo:rerun-if-changed={}", proto_repository_root.display()); + .compile_protos( + &[ + "../../proto/v2/core/proxy.proto", + "../../proto/v2/worker/worker.proto", + "../../proto/v2/wireguard/gateway.proto", + "../../proto/enterprise/v2/firewall/firewall.proto", + ], + &["../../proto"], + )?; + + println!("cargo:rerun-if-changed=../../proto"); Ok(()) } - -/// Derives the shared proto checkout from Cargo metadata so code generation does -/// not depend on the shell's current working directory. -fn derive_proto_repository_root() -> Result> { - let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?); - let workspace_root = manifest_dir - .parent() - .and_then(Path::parent) - .ok_or_else(|| { - format!( - "failed to derive workspace root from CARGO_MANIFEST_DIR: {}", - manifest_dir.display() - ) - })?; - let proto_repository_root = workspace_root.join("proto"); - - if !proto_repository_root.is_dir() { - return Err(format!( - "expected proto repository root at {}, but the directory does not exist", - proto_repository_root.display() - ) - .into()); - } - - Ok(proto_repository_root) -} - -/// Resolves the expected protobuf entrypoints up front so missing definitions -/// fail the build before code generation starts. -fn resolve_proto_files(proto_repository_root: &Path) -> Result, Box> { - PROTO_LAYOUT_PATHS - .iter() - .map(|relative_path| { - let proto_file = proto_repository_root.join(relative_path); - if !proto_file.is_file() { - return Err(format!( - "expected protobuf definition at {}, but the file does not exist", - proto_file.display() - ) - .into()); - } - - Ok(proto_file) - }) - .collect() -} From 6696e0b91a1b228766204a0ba49277a7b0c67510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 25 Mar 2026 15:54:46 +0100 Subject: [PATCH 05/15] update protos --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index f93bf295a..b5deeca0e 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit f93bf295a4c8e92bbacd3a049b07072c26ede7cb +Subproject commit b5deeca0e0a6b6d0a34a36ccc95a4b8ed9299fa9 From 346b02f221c2f1dc91b9620108b7f611e2eb00df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 25 Mar 2026 15:57:16 +0100 Subject: [PATCH 06/15] fall back to v1 worker module --- crates/defguard_core/tests/integration/grpc/health.rs | 2 +- crates/defguard_proto/build.rs | 2 +- crates/defguard_proto/src/lib.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/defguard_core/tests/integration/grpc/health.rs b/crates/defguard_core/tests/integration/grpc/health.rs index 68a9c9246..ac6c15f89 100644 --- a/crates/defguard_core/tests/integration/grpc/health.rs +++ b/crates/defguard_core/tests/integration/grpc/health.rs @@ -13,7 +13,7 @@ async fn worker_service_health_is_serving(_: PgPoolOptions, options: PgConnectOp let response = client .check(HealthCheckRequest { - service: "defguard.worker.v2.WorkerService".into(), + service: "defguard.worker.v1.WorkerService".into(), }) .await .expect("health check should succeed") diff --git a/crates/defguard_proto/build.rs b/crates/defguard_proto/build.rs index 4f00e1340..f91a59bfb 100644 --- a/crates/defguard_proto/build.rs +++ b/crates/defguard_proto/build.rs @@ -19,8 +19,8 @@ fn main() -> Result<(), Box> { .protoc_arg("--experimental_allow_proto3_optional") .compile_protos( &[ + "../../proto/v1/worker/worker.proto", "../../proto/v2/core/proxy.proto", - "../../proto/v2/worker/worker.proto", "../../proto/v2/wireguard/gateway.proto", "../../proto/enterprise/v2/firewall/firewall.proto", ], diff --git a/crates/defguard_proto/src/lib.rs b/crates/defguard_proto/src/lib.rs index f8edca150..40c74618c 100644 --- a/crates/defguard_proto/src/lib.rs +++ b/crates/defguard_proto/src/lib.rs @@ -15,8 +15,8 @@ mod generated { } pub mod worker { - pub mod v2 { - tonic::include_proto!("defguard.worker.v2"); + pub mod v1 { + tonic::include_proto!("defguard.worker.v1"); } } @@ -39,7 +39,7 @@ pub mod gateway { } pub mod worker { - pub use crate::generated::defguard::worker::v2::*; + pub use crate::generated::defguard::worker::v1::*; } pub mod enterprise { From 20ba31ce28502dcd8058bccff334e7b1153a0ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Tue, 7 Apr 2026 11:14:00 +0200 Subject: [PATCH 07/15] update protobuf submodule --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index 0e247a24c..60ff4a214 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 0e247a24c3ae78052501dd052af4b73ab8f1e368 +Subproject commit 60ff4a214074446c1f6b8220ca8fac57c5156301 From 383dc6d85d2eb582ca85a170223345a636feb6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Tue, 7 Apr 2026 13:57:02 +0200 Subject: [PATCH 08/15] update imports for new client_types protobuf module --- .../src/enterprise/grpc/polling.rs | 5 +- .../defguard_core/src/grpc/client_version.rs | 2 +- crates/defguard_core/src/grpc/mod.rs | 2 +- crates/defguard_core/src/grpc/utils.rs | 74 +++++++++---------- crates/defguard_proto/build.rs | 5 +- crates/defguard_proto/src/lib.rs | 38 ++++++---- .../src/servers/enrollment.rs | 18 +++-- .../tests/proxy_manager/handler/enrollment.rs | 6 +- .../tests/proxy_manager/handler/polling.rs | 5 +- .../tests/proxy_manager/handler/support.rs | 14 ++-- 10 files changed, 96 insertions(+), 73 deletions(-) diff --git a/crates/defguard_core/src/enterprise/grpc/polling.rs b/crates/defguard_core/src/enterprise/grpc/polling.rs index fef268fcb..43bd272c2 100644 --- a/crates/defguard_core/src/enterprise/grpc/polling.rs +++ b/crates/defguard_core/src/enterprise/grpc/polling.rs @@ -2,7 +2,10 @@ use defguard_common::db::{ Id, models::{Device, polling_token::PollingToken, user::User}, }; -use defguard_proto::proxy::{DeviceInfo, InstanceInfoRequest, InstanceInfoResponse}; +use defguard_proto::{ + client_types::{InstanceInfoRequest, InstanceInfoResponse}, + proxy::DeviceInfo, +}; use sqlx::PgPool; use tonic::Status; diff --git a/crates/defguard_core/src/grpc/client_version.rs b/crates/defguard_core/src/grpc/client_version.rs index af2c03cf0..cc4a038fe 100644 --- a/crates/defguard_core/src/grpc/client_version.rs +++ b/crates/defguard_core/src/grpc/client_version.rs @@ -1,5 +1,5 @@ use base64::{Engine, prelude::BASE64_STANDARD}; -use defguard_proto::proxy::{ClientPlatformInfo, DeviceInfo}; +use defguard_proto::{client_types::ClientPlatformInfo, proxy::DeviceInfo}; use prost::Message; use semver::Version; diff --git a/crates/defguard_core/src/grpc/mod.rs b/crates/defguard_core/src/grpc/mod.rs index eb68fcb26..e56186a85 100644 --- a/crates/defguard_core/src/grpc/mod.rs +++ b/crates/defguard_core/src/grpc/mod.rs @@ -194,7 +194,7 @@ impl InstanceInfo { } } -impl From for defguard_proto::proxy::InstanceInfo { +impl From for defguard_proto::client_types::InstanceInfo { fn from(instance: InstanceInfo) -> Self { Self { name: instance.name, diff --git a/crates/defguard_core/src/grpc/utils.rs b/crates/defguard_core/src/grpc/utils.rs index a9ac22b5f..801ed626b 100644 --- a/crates/defguard_core/src/grpc/utils.rs +++ b/crates/defguard_core/src/grpc/utils.rs @@ -11,9 +11,12 @@ use defguard_common::{ }, }, }; -use defguard_proto::proxy::{ - DeviceConfig as ProtoDeviceConfig, DeviceConfigResponse, DeviceInfo, - LocationMfaMode as ProtoLocationMfaMode, +use defguard_proto::{ + client_types::{ + DeviceConfig as ProtoDeviceConfig, DeviceConfigResponse, + LocationMfaMode as ProtoLocationMfaMode, + }, + proxy::DeviceInfo, }; use sqlx::PgPool; use tonic::Status; @@ -94,33 +97,31 @@ pub async fn build_device_config_response( // DEPRECATED(1.5): superseeded by location_mfa_mode let mfa_enabled = network.location_mfa_mode == LocationMfaMode::Internal; - let config = - ProtoDeviceConfig { - config: Device::create_config(&network, &wireguard_network_device), - network_id: network.id, - network_name: network.name, - assigned_ip: wireguard_network_device.wireguard_ips.as_csv(), - endpoint: format!("{}:{}", network.endpoint, network.port), - pubkey: network.pubkey, - allowed_ips: network.allowed_ips.as_csv(), - dns: network.dns, - keepalive_interval: network.keepalive_interval, - #[allow(deprecated)] - mfa_enabled, - location_mfa_mode: Some( - >::into( - network.location_mfa_mode, - ) - .into(), - ), - service_location_mode: - Some( - >::into(network.service_location_mode) - .into(), - ), - }; + let config = ProtoDeviceConfig { + config: Device::create_config(&network, &wireguard_network_device), + network_id: network.id, + network_name: network.name, + assigned_ip: wireguard_network_device.wireguard_ips.as_csv(), + endpoint: format!("{}:{}", network.endpoint, network.port), + pubkey: network.pubkey, + allowed_ips: network.allowed_ips.as_csv(), + dns: network.dns, + keepalive_interval: network.keepalive_interval, + #[allow(deprecated)] + mfa_enabled, + location_mfa_mode: Some( + >::into( + network.location_mfa_mode, + ) + .into(), + ), + service_location_mode: Some( + >::into(network.service_location_mode) + .into(), + ), + }; configs.push(config); } } else { @@ -173,13 +174,12 @@ pub async fn build_device_config_response( ) .into(), ), - service_location_mode: - Some( - >::into(network.service_location_mode) - .into(), - ), + service_location_mode: Some( + >::into(network.service_location_mode) + .into(), + ), }; configs.push(config); } diff --git a/crates/defguard_proto/build.rs b/crates/defguard_proto/build.rs index f91a59bfb..d596e6168 100644 --- a/crates/defguard_proto/build.rs +++ b/crates/defguard_proto/build.rs @@ -20,9 +20,10 @@ fn main() -> Result<(), Box> { .compile_protos( &[ "../../proto/v1/worker/worker.proto", - "../../proto/v2/core/proxy.proto", - "../../proto/v2/wireguard/gateway.proto", + "../../proto/v2/proxy.proto", + "../../proto/v2/gateway.proto", "../../proto/enterprise/v2/firewall/firewall.proto", + "../../proto/common/client_types.proto", ], &["../../proto"], )?; diff --git a/crates/defguard_proto/src/lib.rs b/crates/defguard_proto/src/lib.rs index c0e2279e8..8a0f0fea0 100644 --- a/crates/defguard_proto/src/lib.rs +++ b/crates/defguard_proto/src/lib.rs @@ -27,6 +27,10 @@ mod generated { } } } + + pub mod client_types { + tonic::include_proto!("defguard.client_types"); + } } } @@ -48,6 +52,10 @@ pub mod enterprise { } } +pub mod client_types { + pub use crate::generated::defguard::client_types::*; +} + use defguard_common::{ csv::AsCsv, db::{ @@ -119,7 +127,7 @@ impl From for CoreError { } } -impl From for proxy::DeviceConfig { +impl From for client_types::DeviceConfig { fn from(config: DeviceConfig) -> Self { // DEPRECATED(1.5): superseeded by location_mfa_mode let mfa_enabled = config.location_mfa_mode == LocationMfaMode::Internal; @@ -136,11 +144,13 @@ impl From for proxy::DeviceConfig { #[allow(deprecated)] mfa_enabled, location_mfa_mode: Some( - >::into(config.location_mfa_mode) - .into(), + >::into( + config.location_mfa_mode, + ) + .into(), ), service_location_mode: Some( - >::into( + >::into( config.service_location_mode, ) .into(), @@ -149,7 +159,7 @@ impl From for proxy::DeviceConfig { } } -impl From> for proxy::Device { +impl From> for client_types::Device { fn from(device: Device) -> Self { Self { id: device.id, @@ -161,7 +171,7 @@ impl From> for proxy::Device { } } -impl From> for proxy::AdminInfo { +impl From> for client_types::AdminInfo { fn from(admin: User) -> Self { Self { name: format!("{} {}", admin.first_name, admin.last_name), @@ -171,22 +181,22 @@ impl From> for proxy::AdminInfo { } } -impl From for proxy::LocationMfaMode { +impl From for client_types::LocationMfaMode { fn from(value: LocationMfaMode) -> Self { match value { - LocationMfaMode::Disabled => proxy::LocationMfaMode::Disabled, - LocationMfaMode::Internal => proxy::LocationMfaMode::Internal, - LocationMfaMode::External => proxy::LocationMfaMode::External, + LocationMfaMode::Disabled => client_types::LocationMfaMode::Disabled, + LocationMfaMode::Internal => client_types::LocationMfaMode::Internal, + LocationMfaMode::External => client_types::LocationMfaMode::External, } } } -impl From for proxy::ServiceLocationMode { +impl From for client_types::ServiceLocationMode { fn from(value: ServiceLocationMode) -> Self { match value { - ServiceLocationMode::Disabled => proxy::ServiceLocationMode::Disabled, - ServiceLocationMode::PreLogon => proxy::ServiceLocationMode::Prelogon, - ServiceLocationMode::AlwaysOn => proxy::ServiceLocationMode::Alwayson, + ServiceLocationMode::Disabled => client_types::ServiceLocationMode::Disabled, + ServiceLocationMode::PreLogon => client_types::ServiceLocationMode::Prelogon, + ServiceLocationMode::AlwaysOn => client_types::ServiceLocationMode::Alwayson, } } } diff --git a/crates/defguard_proxy_manager/src/servers/enrollment.rs b/crates/defguard_proxy_manager/src/servers/enrollment.rs index 41e79d10a..d75f2b524 100644 --- a/crates/defguard_proxy_manager/src/servers/enrollment.rs +++ b/crates/defguard_proxy_manager/src/servers/enrollment.rs @@ -33,11 +33,15 @@ use defguard_mail::templates::{ TemplateLocation, enrollment_admin_notification, mfa_activation_mail, mfa_configured_mail, new_device_added_mail, }; -use defguard_proto::proxy::{ - ActivateUserRequest, AdminInfo, CodeMfaSetupFinishRequest, CodeMfaSetupFinishResponse, - CodeMfaSetupStartRequest, CodeMfaSetupStartResponse, DeviceConfigResponse, - EnrollmentStartRequest, EnrollmentStartResponse, ExistingDevice, InitialUserInfo, MfaMethod, - NewDevice, RegisterMobileAuthRequest, +use defguard_proto::{ + client_types::{ + ActivateUserRequest, AdminInfo, DeviceConfigResponse, EnrollmentStartRequest, + EnrollmentStartResponse, ExistingDevice, InitialUserInfo, NewDevice, + }, + proxy::{ + CodeMfaSetupFinishRequest, CodeMfaSetupFinishResponse, CodeMfaSetupStartRequest, + CodeMfaSetupStartResponse, MfaMethod, RegisterMobileAuthRequest, + }, }; use sqlx::{PgConnection, PgPool, query_scalar}; use tokio::sync::{ @@ -258,14 +262,14 @@ impl EnrollmentServer { .fetch_one(&self.pool) .await .map_err(|_| Status::internal("Failed to read data".to_string()))?; - let enrollment_settings = defguard_proto::proxy::EnrollmentSettings { + let enrollment_settings = defguard_proto::client_types::EnrollmentSettings { vpn_setup_optional, smtp_configured, only_client_activation: enterprise_settings.only_client_activation, admin_device_management: enterprise_settings.admin_device_management, mfa_required: instance_has_internal_mfa, }; - let response = defguard_proto::proxy::EnrollmentStartResponse { + let response = defguard_proto::client_types::EnrollmentStartResponse { admin: admin_info, user: Some(user_info), deadline_timestamp: session_deadline.and_utc().timestamp(), diff --git a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/enrollment.rs b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/enrollment.rs index 1943cbe97..16754bb3e 100644 --- a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/enrollment.rs +++ b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/enrollment.rs @@ -7,9 +7,9 @@ use defguard_core::{ events::{BidiStreamEventType, EnrollmentEvent}, grpc::GatewayEvent, }; -use defguard_proto::proxy::{ - CoreRequest, ExistingDevice, MfaMethod, NewDevice, RegisterMobileAuthRequest, core_request, - core_response, +use defguard_proto::{ + client_types::{ExistingDevice, NewDevice}, + proxy::{CoreRequest, MfaMethod, RegisterMobileAuthRequest, core_request, core_response}, }; use super::support::{ diff --git a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/polling.rs b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/polling.rs index 7ca9d5d67..726f87b36 100644 --- a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/polling.rs +++ b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/polling.rs @@ -1,6 +1,9 @@ use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; -use defguard_proto::proxy::{CoreRequest, InstanceInfoRequest, core_request, core_response}; +use defguard_proto::{ + client_types::InstanceInfoRequest, + proxy::{CoreRequest, core_request, core_response}, +}; use super::support::{ assert_error_response, clear_test_license, complete_proxy_handshake, create_device_for_user, diff --git a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/support.rs b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/support.rs index 09f1082c1..272f8b342 100644 --- a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/support.rs +++ b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/support.rs @@ -24,12 +24,14 @@ use defguard_core::{ }, events::{BidiStreamEvent, BidiStreamEventType, DesktopClientMfaEvent}, }; -use defguard_proto::proxy::{ - ActivateUserRequest, ClientMfaFinishRequest, ClientMfaStartRequest, - ClientMfaTokenValidationRequest, CodeMfaSetupFinishRequest, CodeMfaSetupStartRequest, - CoreRequest, CoreResponse, DeviceConfigResponse, DeviceInfo, EnrollmentStartRequest, MfaMethod, - PasswordResetInitializeRequest, PasswordResetRequest, PasswordResetStartRequest, core_request, - core_response, +use defguard_proto::{ + client_types::{ActivateUserRequest, DeviceConfigResponse, EnrollmentStartRequest}, + proxy::{ + ClientMfaFinishRequest, ClientMfaStartRequest, ClientMfaTokenValidationRequest, + CodeMfaSetupFinishRequest, CodeMfaSetupStartRequest, CoreRequest, CoreResponse, DeviceInfo, + MfaMethod, PasswordResetInitializeRequest, PasswordResetRequest, PasswordResetStartRequest, + core_request, core_response, + }, }; use ipnetwork::IpNetwork; use sqlx::PgPool; From 0dd0fda492ee22dc66c152fb447c54f82a39d9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Tue, 7 Apr 2026 16:53:41 +0200 Subject: [PATCH 09/15] update proto submodule --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index 0e247a24c..60ff4a214 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 0e247a24c3ae78052501dd052af4b73ab8f1e368 +Subproject commit 60ff4a214074446c1f6b8220ca8fac57c5156301 From 200c4e8e8073b8e2441bbfa7ee013a5a7db12120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 8 Apr 2026 16:43:17 +0200 Subject: [PATCH 10/15] update imports for updated protos --- .../src/enterprise/grpc/desktop_client_mfa.rs | 5 ++++- crates/defguard_core/src/events.rs | 2 +- .../src/grpc/proxy/client_mfa.rs | 15 +++++++++----- .../src/handlers/component_setup.rs | 9 +++++---- .../defguard_gateway_manager/src/handler.rs | 2 +- .../src/tests/common/mod.rs | 10 ++-------- crates/defguard_proto/build.rs | 1 + crates/defguard_proto/src/lib.rs | 13 +++++++++++- crates/defguard_proxy_manager/src/handler.rs | 10 ++++++---- .../src/servers/enrollment.rs | 14 +++++-------- .../tests/proxy_manager/handler/enrollment.rs | 4 ++-- .../src/tests/proxy_manager/handler/mfa.rs | 6 +++--- .../src/tests/proxy_manager/handler/oidc.rs | 20 +++++++++---------- .../tests/proxy_manager/handler/support.rs | 11 ++++++---- crates/defguard_setup/src/auto_adoption.rs | 19 +++++++----------- proto | 2 +- 16 files changed, 77 insertions(+), 66 deletions(-) diff --git a/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs b/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs index 6b595cde4..0d794e5f9 100644 --- a/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs +++ b/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs @@ -1,5 +1,8 @@ use defguard_common::{db::models::Settings, types::AuthFlowType}; -use defguard_proto::proxy::{ClientMfaOidcAuthenticateRequest, DeviceInfo, MfaMethod}; +use defguard_proto::{ + client_types::MfaMethod, + proxy::{ClientMfaOidcAuthenticateRequest, DeviceInfo}, +}; use openidconnect::{AuthorizationCode, Nonce}; use tonic::Status; diff --git a/crates/defguard_core/src/events.rs b/crates/defguard_core/src/events.rs index 93b0697fe..0366f9a31 100644 --- a/crates/defguard_core/src/events.rs +++ b/crates/defguard_core/src/events.rs @@ -8,7 +8,7 @@ use defguard_common::db::{ gateway::Gateway, group::Group, oauth2client::OAuth2Client, proxy::Proxy, }, }; -use defguard_proto::proxy::MfaMethod; +use defguard_proto::client_types::MfaMethod; use crate::{ db::WebHook, diff --git a/crates/defguard_core/src/grpc/proxy/client_mfa.rs b/crates/defguard_core/src/grpc/proxy/client_mfa.rs index 42e1b9677..5f5c6dc8e 100644 --- a/crates/defguard_core/src/grpc/proxy/client_mfa.rs +++ b/crates/defguard_core/src/grpc/proxy/client_mfa.rs @@ -19,11 +19,16 @@ use defguard_common::{ types::user_info::UserInfo, }; use defguard_mail::templates::mfa_code_mail; -use defguard_proto::proxy::{ - self, AwaitRemoteMfaFinishRequest, AwaitRemoteMfaFinishResponse, ClientMfaFinishRequest, - ClientMfaFinishResponse, ClientMfaStartRequest, ClientMfaStartResponse, - ClientMfaTokenValidationRequest, ClientMfaTokenValidationResponse, CoreResponse, MfaMethod, - core_response::Payload, +use defguard_proto::{ + client_types::{ + ClientMfaFinishRequest, ClientMfaFinishResponse, ClientMfaStartRequest, + ClientMfaStartResponse, MfaMethod, + }, + proxy::{ + self, AwaitRemoteMfaFinishRequest, AwaitRemoteMfaFinishResponse, + ClientMfaTokenValidationRequest, ClientMfaTokenValidationResponse, CoreResponse, + core_response::Payload, + }, }; use sqlx::{PgConnection, PgPool}; use thiserror::Error; diff --git a/crates/defguard_core/src/handlers/component_setup.rs b/crates/defguard_core/src/handlers/component_setup.rs index ae557096b..64a26b494 100644 --- a/crates/defguard_core/src/handlers/component_setup.rs +++ b/crates/defguard_core/src/handlers/component_setup.rs @@ -28,10 +28,11 @@ use defguard_common::{ types::proxy::ProxyControlMessage, }; use defguard_proto::{ + common::{CertificateInfo, DerPayload}, gateway::gateway_setup_client::GatewaySetupClient, proxy::{ - AcmeChallenge, AcmeLogs, AcmeStep, CertificateInfo, DerPayload, acme_issue_event, - proxy_client::ProxyClient, proxy_setup_client::ProxySetupClient, + AcmeChallenge, AcmeLogs, AcmeStep, acme_issue_event, proxy_client::ProxyClient, + proxy_setup_client::ProxySetupClient, }, }; use defguard_version::{Version, client::ClientVersionInterceptor}; @@ -945,7 +946,7 @@ pub async fn setup_gateway_tls_stream( }; let csr_response = match client - .get_csr(defguard_proto::gateway::CertificateInfo { + .get_csr(CertificateInfo { cert_hostname: hostname.to_string(), }) .await @@ -1006,7 +1007,7 @@ pub async fn setup_gateway_tls_stream( // Step 6: Configure TLS yield Ok(flow.step(SetupStep::ConfiguringTls)); - let response = defguard_proto::gateway::DerPayload { + let response = DerPayload { der_data: cert.der().to_vec(), }; diff --git a/crates/defguard_gateway_manager/src/handler.rs b/crates/defguard_gateway_manager/src/handler.rs index 6609c3222..197ca8d03 100644 --- a/crates/defguard_gateway_manager/src/handler.rs +++ b/crates/defguard_gateway_manager/src/handler.rs @@ -429,7 +429,7 @@ impl GatewayHandler { debug!("Message from Gateway {uri}"); match received.payload { - Some(core_request::Payload::ConfigRequest(_config_request)) => { + Some(core_request::Payload::ConfigRequest(())) => { if config_sent { warn!( "Ignoring repeated configuration request from {}", diff --git a/crates/defguard_gateway_manager/src/tests/common/mod.rs b/crates/defguard_gateway_manager/src/tests/common/mod.rs index 9be0a715d..4fb988716 100644 --- a/crates/defguard_gateway_manager/src/tests/common/mod.rs +++ b/crates/defguard_gateway_manager/src/tests/common/mod.rs @@ -22,9 +22,7 @@ use defguard_common::{ messages::peer_stats_update::PeerStatsUpdate, }; use defguard_core::grpc::GatewayEvent; -use defguard_proto::gateway::{ - ConfigurationRequest, CoreRequest, CoreResponse, PeerStats, core_request, gateway_server, -}; +use defguard_proto::gateway::{CoreRequest, CoreResponse, PeerStats, core_request, gateway_server}; use sqlx::{PgPool, postgres::PgConnectOptions}; use tokio::{ net::UnixListener, @@ -259,13 +257,9 @@ impl MockGatewayHarness { } pub(crate) fn send_config_request(&self) { - let request = ConfigurationRequest { - hostname: "mock-gateway".to_string(), - ..Default::default() - }; self.send_request(CoreRequest { id: self.next_message_id.fetch_add(1, Ordering::Relaxed), - payload: Some(core_request::Payload::ConfigRequest(request)), + payload: Some(core_request::Payload::ConfigRequest(())), }); } diff --git a/crates/defguard_proto/build.rs b/crates/defguard_proto/build.rs index d596e6168..ad682baf1 100644 --- a/crates/defguard_proto/build.rs +++ b/crates/defguard_proto/build.rs @@ -20,6 +20,7 @@ fn main() -> Result<(), Box> { .compile_protos( &[ "../../proto/v1/worker/worker.proto", + "../../proto/v2/common.proto", "../../proto/v2/proxy.proto", "../../proto/v2/gateway.proto", "../../proto/enterprise/v2/firewall/firewall.proto", diff --git a/crates/defguard_proto/src/lib.rs b/crates/defguard_proto/src/lib.rs index 8a0f0fea0..8f139b2b3 100644 --- a/crates/defguard_proto/src/lib.rs +++ b/crates/defguard_proto/src/lib.rs @@ -31,6 +31,12 @@ mod generated { pub mod client_types { tonic::include_proto!("defguard.client_types"); } + + pub mod common { + pub mod v2 { + tonic::include_proto!("defguard.common.v2"); + } + } } } @@ -56,6 +62,11 @@ pub mod client_types { pub use crate::generated::defguard::client_types::*; } +pub mod common { + pub use crate::generated::defguard::common::v2::*; +} + +use client_types::MfaMethod; use defguard_common::{ csv::AsCsv, db::{ @@ -67,7 +78,7 @@ use defguard_common::{ }, }, }; -use proxy::{CoreError, MfaMethod}; +use proxy::CoreError; use serde::Serialize; use tonic::Status; diff --git a/crates/defguard_proxy_manager/src/handler.rs b/crates/defguard_proxy_manager/src/handler.rs index 7e3387690..09c81397f 100644 --- a/crates/defguard_proxy_manager/src/handler.rs +++ b/crates/defguard_proxy_manager/src/handler.rs @@ -37,10 +37,12 @@ use defguard_core::{ version::{IncompatibleComponents, IncompatibleProxyData, is_proxy_version_supported}, }; use defguard_grpc_tls::{certs as tls_certs, connector::HttpsSchemeConnector}; -use defguard_proto::proxy::{ - AuthCallbackResponse, AuthFlowType as ProtoAuthFlowType, AuthInfoResponse, CoreError, - CoreRequest, CoreResponse, HttpsCerts, InitialInfo, core_request, core_response, - proxy_client::ProxyClient, +use defguard_proto::{ + client_types::AuthFlowType as ProtoAuthFlowType, + proxy::{ + AuthCallbackResponse, AuthInfoResponse, CoreError, CoreRequest, CoreResponse, HttpsCerts, + InitialInfo, core_request, core_response, proxy_client::ProxyClient, + }, }; use defguard_version::{ ComponentInfo, DefguardComponent, client::ClientVersionInterceptor, get_tracing_variables, diff --git a/crates/defguard_proxy_manager/src/servers/enrollment.rs b/crates/defguard_proxy_manager/src/servers/enrollment.rs index d75f2b524..6f9078438 100644 --- a/crates/defguard_proxy_manager/src/servers/enrollment.rs +++ b/crates/defguard_proxy_manager/src/servers/enrollment.rs @@ -33,15 +33,11 @@ use defguard_mail::templates::{ TemplateLocation, enrollment_admin_notification, mfa_activation_mail, mfa_configured_mail, new_device_added_mail, }; -use defguard_proto::{ - client_types::{ - ActivateUserRequest, AdminInfo, DeviceConfigResponse, EnrollmentStartRequest, - EnrollmentStartResponse, ExistingDevice, InitialUserInfo, NewDevice, - }, - proxy::{ - CodeMfaSetupFinishRequest, CodeMfaSetupFinishResponse, CodeMfaSetupStartRequest, - CodeMfaSetupStartResponse, MfaMethod, RegisterMobileAuthRequest, - }, +use defguard_proto::client_types::{ + ActivateUserRequest, AdminInfo, CodeMfaSetupFinishRequest, CodeMfaSetupFinishResponse, + CodeMfaSetupStartRequest, CodeMfaSetupStartResponse, DeviceConfigResponse, + EnrollmentStartRequest, EnrollmentStartResponse, ExistingDevice, InitialUserInfo, MfaMethod, + NewDevice, RegisterMobileAuthRequest, }; use sqlx::{PgConnection, PgPool, query_scalar}; use tokio::sync::{ diff --git a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/enrollment.rs b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/enrollment.rs index d69c33b24..6672a8928 100644 --- a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/enrollment.rs +++ b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/enrollment.rs @@ -6,8 +6,8 @@ use defguard_core::{ grpc::GatewayEvent, }; use defguard_proto::{ - client_types::{ExistingDevice, NewDevice}, - proxy::{CoreRequest, MfaMethod, RegisterMobileAuthRequest, core_request, core_response}, + client_types::{ExistingDevice, MfaMethod, NewDevice, RegisterMobileAuthRequest}, + proxy::{CoreRequest, core_request, core_response}, }; use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; diff --git a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/mfa.rs b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/mfa.rs index 76b76182d..57b946312 100644 --- a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/mfa.rs +++ b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/mfa.rs @@ -2,9 +2,9 @@ use std::time::Duration; use defguard_common::db::Id; use defguard_core::grpc::GatewayEvent; -use defguard_proto::proxy::{ - AwaitRemoteMfaFinishRequest, ClientMfaFinishRequest, ClientMfaStartRequest, CoreRequest, - MfaMethod, core_request, core_response, +use defguard_proto::{ + client_types::{ClientMfaFinishRequest, ClientMfaStartRequest, MfaMethod}, + proxy::{AwaitRemoteMfaFinishRequest, CoreRequest, core_request, core_response}, }; use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; use tokio::{task, time::timeout}; diff --git a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/oidc.rs b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/oidc.rs index ee31cf7d3..cb152ba30 100644 --- a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/oidc.rs +++ b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/oidc.rs @@ -1,8 +1,11 @@ #![allow(deprecated)] use defguard_core::db::models::enrollment::Token; -use defguard_proto::proxy::{ - AuthCallbackRequest, AuthFlowType, AuthInfoRequest, ClientMfaOidcAuthenticateRequest, - CoreRequest, MfaMethod, core_request, core_response, +use defguard_proto::{ + client_types::{AuthFlowType, AuthInfoRequest, MfaMethod}, + proxy::{ + AuthCallbackRequest, ClientMfaOidcAuthenticateRequest, CoreRequest, core_request, + core_response, + }, }; use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; @@ -42,7 +45,6 @@ async fn test_auth_callback_creates_new_user_on_first_login( payload: Some(core_request::Payload::AuthCallback(AuthCallbackRequest { code: code.clone(), nonce: raw_nonce.to_string(), - callback_url: String::new(), // ignored in v2 path (handler uses settings) })), }); @@ -104,9 +106,9 @@ async fn test_auth_info_enrollment_returns_authorize_url( id: 40, device_info: None, payload: Some(core_request::Payload::AuthInfo(AuthInfoRequest { - redirect_url: String::new(), // deprecated; ignored when auth_flow_type is set state: None, auth_flow_type: AuthFlowType::Enrollment as i32, + ..Default::default() })), }); @@ -166,9 +168,9 @@ async fn test_auth_info_mfa_returns_authorize_url(_: PgPoolOptions, options: PgC id: 50, device_info: None, payload: Some(core_request::Payload::AuthInfo(AuthInfoRequest { - redirect_url: String::new(), state: None, auth_flow_type: AuthFlowType::Mfa as i32, + ..Default::default() })), }); @@ -216,9 +218,9 @@ async fn test_auth_info_requires_license(_: PgPoolOptions, options: PgConnectOpt id: 60, device_info: None, payload: Some(core_request::Payload::AuthInfo(AuthInfoRequest { - redirect_url: String::new(), state: None, auth_flow_type: AuthFlowType::Enrollment as i32, + ..Default::default() })), }); @@ -247,9 +249,9 @@ async fn test_auth_info_requires_oidc_provider(_: PgPoolOptions, options: PgConn id: 70, device_info: None, payload: Some(core_request::Payload::AuthInfo(AuthInfoRequest { - redirect_url: String::new(), state: None, auth_flow_type: AuthFlowType::Enrollment as i32, + ..Default::default() })), }); @@ -308,7 +310,6 @@ async fn test_mfa_oidc_full_flow(_: PgPoolOptions, options: PgConnectOptions) { ClientMfaOidcAuthenticateRequest { code: code.clone(), state: state.clone(), - callback_url: String::new(), // unused in handler (uses settings) nonce: raw_nonce.to_string(), }, )), @@ -369,7 +370,6 @@ async fn test_auth_callback_exchanges_code_for_enrollment_token( payload: Some(core_request::Payload::AuthCallback(AuthCallbackRequest { code: code.clone(), nonce: raw_nonce.to_string(), - callback_url: String::new(), })), }); diff --git a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/support.rs b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/support.rs index 272f8b342..71efa5dd2 100644 --- a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/support.rs +++ b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/support.rs @@ -25,11 +25,14 @@ use defguard_core::{ events::{BidiStreamEvent, BidiStreamEventType, DesktopClientMfaEvent}, }; use defguard_proto::{ - client_types::{ActivateUserRequest, DeviceConfigResponse, EnrollmentStartRequest}, + client_types::{ + ActivateUserRequest, ClientMfaFinishRequest, ClientMfaStartRequest, + CodeMfaSetupFinishRequest, CodeMfaSetupStartRequest, DeviceConfigResponse, + EnrollmentStartRequest, MfaMethod, + }, proxy::{ - ClientMfaFinishRequest, ClientMfaStartRequest, ClientMfaTokenValidationRequest, - CodeMfaSetupFinishRequest, CodeMfaSetupStartRequest, CoreRequest, CoreResponse, DeviceInfo, - MfaMethod, PasswordResetInitializeRequest, PasswordResetRequest, PasswordResetStartRequest, + ClientMfaTokenValidationRequest, CoreRequest, CoreResponse, DeviceInfo, + PasswordResetInitializeRequest, PasswordResetRequest, PasswordResetStartRequest, core_request, core_response, }, }; diff --git a/crates/defguard_setup/src/auto_adoption.rs b/crates/defguard_setup/src/auto_adoption.rs index c933c11c2..999bc535f 100644 --- a/crates/defguard_setup/src/auto_adoption.rs +++ b/crates/defguard_setup/src/auto_adoption.rs @@ -25,14 +25,9 @@ use defguard_core::{ version::{MIN_GATEWAY_VERSION, MIN_PROXY_VERSION}, }; use defguard_proto::{ - gateway::{ - CertificateInfo as GatewayCertificateInfo, DerPayload as GatewayDerPayload, - gateway_setup_client::GatewaySetupClient, - }, - proxy::{ - CertificateInfo as ProxyCertificateInfo, DerPayload as ProxyDerPayload, - proxy_setup_client::ProxySetupClient, - }, + common::{CertificateInfo as ProtoCertificateInfo, DerPayload as ProtoDerPayload}, + gateway::gateway_setup_client::GatewaySetupClient, + proxy::proxy_setup_client::ProxySetupClient, }; use defguard_version::{Version, client::ClientVersionInterceptor}; use ipnetwork::IpNetwork; @@ -420,7 +415,7 @@ async fn run_edge_adoption_attempt_scoped( debug!("Requesting CSR from proxy hostname={hostname}"); let csr_response = match client - .get_csr(ProxyCertificateInfo { + .get_csr(ProtoCertificateInfo { cert_hostname: hostname.to_string(), }) .await @@ -471,7 +466,7 @@ async fn run_edge_adoption_attempt_scoped( debug!("CSR signed for proxy hostname={hostname}; sending certificate"); if let Err(err) = client - .send_cert(ProxyDerPayload { + .send_cert(ProtoDerPayload { der_data: cert.der().to_vec(), }) .await @@ -729,7 +724,7 @@ async fn run_gateway_adoption_attempt_scoped( debug!("Requesting CSR from gateway hostname={hostname}"); let csr_response = match client - .get_csr(GatewayCertificateInfo { + .get_csr(ProtoCertificateInfo { cert_hostname: hostname.to_string(), }) .await @@ -780,7 +775,7 @@ async fn run_gateway_adoption_attempt_scoped( debug!("CSR signed for gateway hostname={hostname}; sending certificate"); if let Err(err) = client - .send_cert(GatewayDerPayload { + .send_cert(ProtoDerPayload { der_data: cert.der().to_vec(), }) .await diff --git a/proto b/proto index 60ff4a214..1abef440a 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 60ff4a214074446c1f6b8220ca8fac57c5156301 +Subproject commit 1abef440a4b69476a2e0b49a959df17ab4a9d426 From 808864a1bb48a5a40f3c7ec40844e9adfd59ed8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 8 Apr 2026 20:40:50 +0200 Subject: [PATCH 11/15] handle updated handshake type --- Cargo.lock | 2 ++ Cargo.toml | 1 + crates/defguard_gateway_manager/Cargo.toml | 1 + .../defguard_gateway_manager/src/handler.rs | 33 +++++++++++++------ .../src/tests/common/mod.rs | 3 +- crates/defguard_proto/Cargo.toml | 1 + proto | 2 +- 7 files changed, 31 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61a8e310b..523ca14c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1487,6 +1487,7 @@ dependencies = [ "defguard_version", "hyper-rustls", "hyper-util", + "prost-types", "reqwest", "semver", "serde_json", @@ -1558,6 +1559,7 @@ version = "0.0.0" dependencies = [ "defguard_common", "prost", + "prost-types", "serde", "tonic", "tonic-prost", diff --git a/Cargo.toml b/Cargo.toml index d73543e7d..73416b02b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,6 +76,7 @@ parse_link_header = "0.4" paste = "1.0" pgp = { version = "0.19", default-features = false } prost = "0.14" +prost-types = "0.14" pulldown-cmark = "0.13" # match version used by sqlx rand = "0.8" diff --git a/crates/defguard_gateway_manager/Cargo.toml b/crates/defguard_gateway_manager/Cargo.toml index 9afb53828..f7fbdb262 100644 --- a/crates/defguard_gateway_manager/Cargo.toml +++ b/crates/defguard_gateway_manager/Cargo.toml @@ -18,6 +18,7 @@ defguard_version.workspace = true anyhow.workspace = true chrono.workspace = true hyper-rustls.workspace = true +prost-types.workspace = true reqwest.workspace = true semver.workspace = true serde_json.workspace = true diff --git a/crates/defguard_gateway_manager/src/handler.rs b/crates/defguard_gateway_manager/src/handler.rs index 197ca8d03..09a564a8a 100644 --- a/crates/defguard_gateway_manager/src/handler.rs +++ b/crates/defguard_gateway_manager/src/handler.rs @@ -36,6 +36,8 @@ use defguard_proto::{ gateway_client, update, }, }; +#[cfg(test)] +use prost_types::Timestamp; use defguard_version::client::ClientVersionInterceptor; use hyper_rustls::HttpsConnectorBuilder; use reqwest::Url; @@ -987,8 +989,9 @@ fn try_protos_into_stats_message( // try to parse endpoint let endpoint = proto_stats.endpoint.parse().ok()?; - let latest_handshake = DateTime::from_timestamp(proto_stats.latest_handshake as i64, 0) - .unwrap_or_default() + let latest_handshake = proto_stats + .latest_handshake + .and_then(|ts| DateTime::from_timestamp(ts.seconds, ts.nanos as u32))? .naive_utc(); Some(PeerStatsUpdate::new( @@ -1050,7 +1053,7 @@ mod tests { upload: 123, download: 456, keepalive_interval: 25, - latest_handshake: 1_700_000_000, + latest_handshake: Some(prost_types::Timestamp { seconds: 1_700_000_000, nanos: 0 }), allowed_ips: "10.10.0.2/32".to_string(), } } @@ -1110,21 +1113,31 @@ mod tests { } #[test] - fn try_protos_into_stats_message_falls_back_to_default_timestamp() { + fn try_protos_into_stats_message_returns_none_for_missing_handshake() { let stats = try_protos_into_stats_message( PeerStats { - latest_handshake: i64::MAX as u64, + latest_handshake: None, ..build_peer_stats("203.0.113.10:51820") }, 11, 22, - ) - .expect("valid endpoint should still produce stats"); + ); - assert_eq!( - stats.latest_handshake, - DateTime::::default().naive_utc() + assert!(stats.is_none()); + } + + #[test] + fn try_protos_into_stats_message_returns_none_for_invalid_timestamp() { + let stats = try_protos_into_stats_message( + PeerStats { + latest_handshake: Some(Timestamp { seconds: i64::MAX, nanos: 0 }), + ..build_peer_stats("203.0.113.10:51820") + }, + 11, + 22, ); + + assert!(stats.is_none()); } #[test] diff --git a/crates/defguard_gateway_manager/src/tests/common/mod.rs b/crates/defguard_gateway_manager/src/tests/common/mod.rs index 4fb988716..5b56f6e63 100644 --- a/crates/defguard_gateway_manager/src/tests/common/mod.rs +++ b/crates/defguard_gateway_manager/src/tests/common/mod.rs @@ -23,6 +23,7 @@ use defguard_common::{ }; use defguard_core::grpc::GatewayEvent; use defguard_proto::gateway::{CoreRequest, CoreResponse, PeerStats, core_request, gateway_server}; +use prost_types::Timestamp; use sqlx::{PgPool, postgres::PgConnectOptions}; use tokio::{ net::UnixListener, @@ -662,7 +663,7 @@ pub(crate) fn build_peer_stats(endpoint: &str) -> PeerStats { upload: 123, download: 456, keepalive_interval: 25, - latest_handshake: 1_700_000_000, + latest_handshake: Some(Timestamp { seconds: 1_700_000_000, nanos: 0 }), allowed_ips: "10.10.0.2/32".to_string(), } } diff --git a/crates/defguard_proto/Cargo.toml b/crates/defguard_proto/Cargo.toml index 3400b5ed9..dbdd111de 100644 --- a/crates/defguard_proto/Cargo.toml +++ b/crates/defguard_proto/Cargo.toml @@ -10,6 +10,7 @@ rust-version.workspace = true [dependencies] defguard_common.workspace = true prost.workspace = true +prost-types.workspace = true serde.workspace = true tonic.workspace = true tonic-prost.workspace = true diff --git a/proto b/proto index 32acbc6ab..4e0432a95 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 32acbc6aba6f1b797785d3fee88b6736f7ffca47 +Subproject commit 4e0432a95e68dcf6fdd9d1678d6815bccc09f709 From ffb3915030a0c72cc28d0eaab07439b76bf252a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 8 Apr 2026 20:48:17 +0200 Subject: [PATCH 12/15] formatting --- crates/defguard_gateway_manager/src/handler.rs | 13 +++++++++---- .../src/tests/common/mod.rs | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/crates/defguard_gateway_manager/src/handler.rs b/crates/defguard_gateway_manager/src/handler.rs index 09a564a8a..fe140c1df 100644 --- a/crates/defguard_gateway_manager/src/handler.rs +++ b/crates/defguard_gateway_manager/src/handler.rs @@ -36,8 +36,6 @@ use defguard_proto::{ gateway_client, update, }, }; -#[cfg(test)] -use prost_types::Timestamp; use defguard_version::client::ClientVersionInterceptor; use hyper_rustls::HttpsConnectorBuilder; use reqwest::Url; @@ -1023,6 +1021,7 @@ mod tests { }; use defguard_core::grpc::GatewayEvent; use defguard_proto::gateway::{Configuration, Peer, PeerStats, core_response}; + use prost_types::Timestamp; use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; use tokio::sync::{broadcast, mpsc::unbounded_channel, watch}; @@ -1053,7 +1052,10 @@ mod tests { upload: 123, download: 456, keepalive_interval: 25, - latest_handshake: Some(prost_types::Timestamp { seconds: 1_700_000_000, nanos: 0 }), + latest_handshake: Some(prost_types::Timestamp { + seconds: 1_700_000_000, + nanos: 0, + }), allowed_ips: "10.10.0.2/32".to_string(), } } @@ -1130,7 +1132,10 @@ mod tests { fn try_protos_into_stats_message_returns_none_for_invalid_timestamp() { let stats = try_protos_into_stats_message( PeerStats { - latest_handshake: Some(Timestamp { seconds: i64::MAX, nanos: 0 }), + latest_handshake: Some(Timestamp { + seconds: i64::MAX, + nanos: 0, + }), ..build_peer_stats("203.0.113.10:51820") }, 11, diff --git a/crates/defguard_gateway_manager/src/tests/common/mod.rs b/crates/defguard_gateway_manager/src/tests/common/mod.rs index 5b56f6e63..10962eef6 100644 --- a/crates/defguard_gateway_manager/src/tests/common/mod.rs +++ b/crates/defguard_gateway_manager/src/tests/common/mod.rs @@ -663,7 +663,10 @@ pub(crate) fn build_peer_stats(endpoint: &str) -> PeerStats { upload: 123, download: 456, keepalive_interval: 25, - latest_handshake: Some(Timestamp { seconds: 1_700_000_000, nanos: 0 }), + latest_handshake: Some(Timestamp { + seconds: 1_700_000_000, + nanos: 0, + }), allowed_ips: "10.10.0.2/32".to_string(), } } From 31b7c6491d89f6e13cef53fdac575443a8fb66ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Thu, 9 Apr 2026 07:42:13 +0200 Subject: [PATCH 13/15] handle proto naming updates --- .../src/enterprise/firewall/mod.rs | 1 + crates/defguard_core/src/lib.rs | 2 +- .../defguard_gateway_manager/src/handler.rs | 30 ++++++++++++------- crates/defguard_proto/src/lib.rs | 2 +- proto | 2 +- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/crates/defguard_core/src/enterprise/firewall/mod.rs b/crates/defguard_core/src/enterprise/firewall/mod.rs index 8b960ba5f..bf4b793c8 100644 --- a/crates/defguard_core/src/enterprise/firewall/mod.rs +++ b/crates/defguard_core/src/enterprise/firewall/mod.rs @@ -559,6 +559,7 @@ fn get_source_addrs( None } } + IpVersion::Unspecified => None, }) .collect(); diff --git a/crates/defguard_core/src/lib.rs b/crates/defguard_core/src/lib.rs index addbdbdb3..4beb37108 100644 --- a/crates/defguard_core/src/lib.rs +++ b/crates/defguard_core/src/lib.rs @@ -998,7 +998,7 @@ pub async fn gateway_config( let mut config = Configuration::new(&location, peers, maybe_firewall_config); // overwrite private key just in case - config.prvkey = "REDACTED".into(); + config.private_key = "REDACTED".into(); Ok(config) } diff --git a/crates/defguard_gateway_manager/src/handler.rs b/crates/defguard_gateway_manager/src/handler.rs index fe140c1df..088f7536e 100644 --- a/crates/defguard_gateway_manager/src/handler.rs +++ b/crates/defguard_gateway_manager/src/handler.rs @@ -32,8 +32,8 @@ use defguard_grpc_tls::{certs as tls_certs, connector::HttpsSchemeConnector}; use defguard_proto::{ enterprise::firewall::FirewallConfig, gateway::{ - Configuration, CoreResponse, Peer, PeerStats, Update, core_request, core_response, - gateway_client, update, + Configuration, CoreResponse, Peer, PeerStats, Update, UpdateType, core_request, + core_response, gateway_client, update, }, }; use defguard_version::client::ClientVersionInterceptor; @@ -823,7 +823,7 @@ impl GatewayUpdatesHandler { update_type, update: Some(update::Update::Network(Configuration { name: network.name.clone(), - prvkey: network.prvkey.clone(), + private_key: network.prvkey.clone(), addresses: network.address().iter().map(ToString::to_string).collect(), port: network.port.cast_unsigned(), peers, @@ -836,7 +836,11 @@ impl GatewayUpdatesHandler { let msg = format!( "Failed to send network update, network {network}, update type: {update_type} \ ({}), error: {err}", - if update_type == 0 { "CREATE" } else { "MODIFY" }, + if update_type == UpdateType::Create as i32 { + "CREATE" + } else { + "MODIFY" + }, ); error!(msg); return Err(Status::new(Code::Internal, msg)); @@ -854,10 +858,10 @@ impl GatewayUpdatesHandler { if let Err(err) = self.tx.send(CoreResponse { id: 0, payload: Some(core_response::Payload::Update(Update { - update_type: 2, + update_type: UpdateType::Delete as i32, update: Some(update::Update::Network(Configuration { name: network_name.to_string(), - prvkey: String::new(), + private_key: String::new(), addresses: Vec::new(), port: 0, peers: Vec::new(), @@ -892,7 +896,11 @@ impl GatewayUpdatesHandler { "Failed to send peer update for network {}, update type: {update_type} ({}), \ error: {err}", self.network, - if update_type == 0 { "CREATE" } else { "MODIFY" }, + if update_type == UpdateType::Create as i32 { + "CREATE" + } else { + "MODIFY" + }, ); error!(msg); return Err(Status::new(Code::Internal, msg)); @@ -907,7 +915,7 @@ impl GatewayUpdatesHandler { if let Err(err) = self.tx.send(CoreResponse { id: 0, payload: Some(core_response::Payload::Update(Update { - update_type: 2, + update_type: UpdateType::Delete as i32, update: Some(update::Update::Peer(Peer { pubkey: peer_pubkey.into(), allowed_ips: Vec::new(), @@ -937,7 +945,7 @@ impl GatewayUpdatesHandler { if let Err(err) = self.tx.send(CoreResponse { id: 0, payload: Some(core_response::Payload::Update(Update { - update_type: 1, + update_type: UpdateType::Modify as i32, update: Some(update::Update::FirewallConfig(firewall_config)), })), }) { @@ -961,7 +969,7 @@ impl GatewayUpdatesHandler { if let Err(err) = self.tx.send(CoreResponse { id: 0, payload: Some(core_response::Payload::Update(Update { - update_type: 2, + update_type: UpdateType::Delete as i32, update: Some(update::Update::DisableFirewall(())), })), }) { @@ -1164,7 +1172,7 @@ mod tests { assert_eq!(config.name, "test-network"); assert_eq!(config.port, 51820); - assert_eq!(config.prvkey, "network-private-key"); + assert_eq!(config.private_key, "network-private-key"); assert_eq!(config.addresses, vec!["10.10.0.1/24", "fd00::1/64"]); assert_eq!(config.mtu, 1420); assert_eq!(config.fwmark, 4321); diff --git a/crates/defguard_proto/src/lib.rs b/crates/defguard_proto/src/lib.rs index 8f139b2b3..26fc0d575 100644 --- a/crates/defguard_proto/src/lib.rs +++ b/crates/defguard_proto/src/lib.rs @@ -221,7 +221,7 @@ impl Configuration { Self { name: location.name.clone(), port: location.port.cast_unsigned(), - prvkey: location.prvkey.clone(), + private_key: location.prvkey.clone(), addresses: location.address().iter().map(ToString::to_string).collect(), peers, firewall_config: maybe_firewall_config, diff --git a/proto b/proto index 4e0432a95..0a6b81bde 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 4e0432a95e68dcf6fdd9d1678d6815bccc09f709 +Subproject commit 0a6b81bdec6e4cf215ba7b7c8f02af8324a4ce8a From 973a8a7c45450dc541d9452b4418077ac99c5135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Thu, 9 Apr 2026 10:44:44 +0200 Subject: [PATCH 14/15] update protobuf submodule --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index 0a6b81bde..7adfe3bfd 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 0a6b81bdec6e4cf215ba7b7c8f02af8324a4ce8a +Subproject commit 7adfe3bfd1b7b701e58d25ddadd0c0c7a4a3e046 From f0b5a068e00f6f94bec398bc469cd472fcfa6d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Thu, 9 Apr 2026 11:20:50 +0200 Subject: [PATCH 15/15] replace raw integers with enum --- .../defguard_gateway_manager/src/handler.rs | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/crates/defguard_gateway_manager/src/handler.rs b/crates/defguard_gateway_manager/src/handler.rs index 088f7536e..1bbb95bc7 100644 --- a/crates/defguard_gateway_manager/src/handler.rs +++ b/crates/defguard_gateway_manager/src/handler.rs @@ -686,7 +686,12 @@ impl GatewayUpdatesHandler { let result = match update { GatewayEvent::NetworkCreated(network_id, network) => { if network_id == self.network_id { - self.send_network_update(&network, Vec::new(), None, 0) + self.send_network_update( + &network, + Vec::new(), + None, + UpdateType::Create as i32, + ) } else { Ok(()) } @@ -698,8 +703,12 @@ impl GatewayUpdatesHandler { maybe_firewall_config, ) => { if network_id == self.network_id { - let result = - self.send_network_update(&network, peers, maybe_firewall_config, 1); + let result = self.send_network_update( + &network, + peers, + maybe_firewall_config, + UpdateType::Modify as i32, + ); // update stored network data self.network = network; result @@ -725,7 +734,7 @@ impl GatewayUpdatesHandler { &device.device.name, device.device.wireguard_pubkey, network_info, - 0, + UpdateType::Create as i32, ), None => Ok(()), } @@ -741,7 +750,7 @@ impl GatewayUpdatesHandler { &device.device.name, device.device.wireguard_pubkey, network_info, - 1, + UpdateType::Modify as i32, ), None => Ok(()), } @@ -791,7 +800,7 @@ impl GatewayUpdatesHandler { &device.name, device.wireguard_pubkey, &network_info, - 0, + UpdateType::Create as i32, ) } else { Ok(())