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
49 changes: 49 additions & 0 deletions crates/defguard_core/src/grpc/client_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,21 @@ pub(crate) fn parse_client_version_platform(
#[derive(Debug)]
pub enum ClientFeature {
ServiceLocations,
PostureChecks,
}

impl ClientFeature {
const fn min_version(&self) -> Option<Version> {
match self {
Self::ServiceLocations => Some(Version::new(1, 6, 0)),
Self::PostureChecks => Some(Version::new(2, 1, 0)),
}
}

fn required_os_family(&self) -> Option<Vec<&'static str>> {
match self {
Self::ServiceLocations => Some(vec!["windows"]),
Self::PostureChecks => None,
}
}

Expand Down Expand Up @@ -383,4 +386,50 @@ mod tests {
"ServiceLocations should not be supported with pre-release version below minimum"
);
}

#[test]
fn test_posture_checks_feature_support() {
// PostureChecks has no OS family requirement, so it should work on any platform
// as long as the client version is at least 2.1.0.
for os_family in ["windows", "macos", "linux"] {
let info = create_device_info(
Some("2.1.0".to_owned()),
Some(ClientPlatformInfo {
os_family: os_family.to_owned(),
..Default::default()
}),
);
assert!(
ClientFeature::PostureChecks.is_supported_by_device(Some(&info)),
"PostureChecks should be supported on {os_family} at minimum version"
);
}

// Higher version is supported even without platform info.
let info = create_device_info(Some("2.5.0".to_owned()), None);
assert!(
ClientFeature::PostureChecks.is_supported_by_device(Some(&info)),
"PostureChecks should be supported with higher version"
);

// Version below minimum is not supported.
let info = create_device_info(Some("2.0.9".to_owned()), None);
assert!(
!ClientFeature::PostureChecks.is_supported_by_device(Some(&info)),
"PostureChecks should not be supported below minimum version"
);

// Missing version info means the feature is not supported.
let info = create_device_info(None, None);
assert!(
!ClientFeature::PostureChecks.is_supported_by_device(Some(&info)),
"PostureChecks should not be supported without version info"
);

// No device info at all means the feature is not supported.
assert!(
!ClientFeature::PostureChecks.is_supported_by_device(None),
"PostureChecks should not be supported without device info"
);
}
}
10 changes: 10 additions & 0 deletions crates/defguard_core/src/grpc/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,16 @@ pub async fn build_device_config_response(
Status::internal(format!("unexpected error: {err}"))
})?;

if device_config.posture_check_required
&& !ClientFeature::PostureChecks.is_supported_by_device(device_info.as_ref())
{
info!(
"Device {} does not support posture checks feature, skipping sending network {} configuration to device {}.",
device.name, network.name, device.name
);
continue;
}

let config = ProtoDeviceConfig {
config: device_config.config,
network_id: device_config.network_id,
Expand Down
6 changes: 5 additions & 1 deletion crates/defguard_proxy_manager/src/servers/enrollment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,14 +857,18 @@ impl EnrollmentServer {
device.wireguard_pubkey, user.username, user.id,
);

// Don't send them service locations if they don't support it
// Don't send them service locations or posture-checked locations if they don't support it
let configs = configs
.into_iter()
.filter(|config| {
config.service_location_mode == ServiceLocationMode::Disabled
|| ClientFeature::ServiceLocations
.is_supported_by_device(req_device_info.as_ref())
})
.filter(|config| {
!config.posture_check_required
|| ClientFeature::PostureChecks.is_supported_by_device(req_device_info.as_ref())
})
.collect::<Vec<DeviceConfig>>();

let template_locations = configs
Expand Down
Loading