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
1 change: 1 addition & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ x25519-dalek = { version = "2", features = [
"serde",
"static_secrets",
] }
os_info = "3.12"

[target.'cfg(target_os = "macos")'.dependencies]
swift-rs = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/proto
Submodule proto updated 1 files
+12 −0 core/proxy.proto
3 changes: 2 additions & 1 deletion src-tauri/src/bin/defguard-client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ fn main() {
stop_global_logwatcher,
command_get_app_config,
command_set_app_config,
get_provisioning_config
get_provisioning_config,
get_platform_header
])
.on_window_event(|window, event| {
if let WindowEvent::CloseRequested { api, .. } = event {
Expand Down
32 changes: 28 additions & 4 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ use crate::{
},
tray::{configure_tray_icon, reload_tray_menu},
utils::{
disconnect_interface, execute_command, get_location_interface_details,
get_tunnel_interface_details, get_tunnel_or_location_name, handle_connection_for_location,
handle_connection_for_tunnel,
construct_platform_header, disconnect_interface, execute_command,
get_location_interface_details, get_tunnel_interface_details, get_tunnel_or_location_name,
handle_connection_for_location, handle_connection_for_tunnel,
},
wg_config::parse_wireguard_config,
CommonConnection, CommonConnectionInfo, CommonLocationStats, ConnectionType,
Expand Down Expand Up @@ -660,7 +660,25 @@ pub(crate) async fn do_update_instance(

if service_locations.is_empty() {
debug!(
"No service locations to process for instance {}({})",
"No service locations for instance {}({}), removing all existing service locations connections if there are any.",
instance.name, instance.id
);
let delete_request = DeleteServiceLocationsRequest {
instance_id: instance.uuid.clone(),
};
DAEMON_CLIENT
.clone()
.delete_service_locations(delete_request)
.await
.map_err(|err| {
error!(
"Error while deleting service locations from the daemon for instance {}({}): {err}",
instance.name, instance.id,
);
Error::InternalError(err.to_string())
})?;
debug!(
"Successfully removed all service locations from daemon for instance {}({})",
instance.name, instance.id
);
} else {
Expand Down Expand Up @@ -1274,3 +1292,9 @@ pub fn get_provisioning_config(
trace!("Returning config: {res:?}");
Ok(res)
}

#[tauri::command]
#[must_use]
pub fn get_platform_header() -> String {
construct_platform_header()
}
6 changes: 5 additions & 1 deletion src-tauri/src/enterprise/periodic/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ use crate::{
error::Error,
events::EventKey,
proto::{DeviceConfigResponse, InstanceInfoRequest, InstanceInfoResponse},
MIN_CORE_VERSION, MIN_PROXY_VERSION,
utils::construct_platform_header,
CLIENT_PLATFORM_HEADER, CLIENT_VERSION_HEADER, MIN_CORE_VERSION, MIN_PROXY_VERSION,
PKG_VERSION,
};

const INTERVAL_SECONDS: Duration = Duration::from_secs(30);
Expand Down Expand Up @@ -137,6 +139,8 @@ pub async fn poll_instance(
let response = Client::new()
.post(url)
.json(&request)
.header(CLIENT_VERSION_HEADER, PKG_VERSION)
.header(CLIENT_PLATFORM_HEADER, construct_platform_header())
.timeout(HTTP_REQ_TIMEOUT)
.send()
.await;
Expand Down
9 changes: 6 additions & 3 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@ pub mod utils;
pub mod wg_config;

pub const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), "-", env!("VERGEN_GIT_SHA"));
pub const MIN_CORE_VERSION: Version = Version::new(1, 5, 0);
pub const MIN_PROXY_VERSION: Version = Version::new(1, 5, 0);
pub const MIN_CORE_VERSION: Version = Version::new(1, 6, 0);
pub const MIN_PROXY_VERSION: Version = Version::new(1, 6, 0);
pub const CLIENT_VERSION_HEADER: &str = "defguard-client-version";
pub const CLIENT_PLATFORM_HEADER: &str = "defguard-client-platform";
pub const PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
// This must match tauri.bundle.identifier from tauri.conf.json.
const BUNDLE_IDENTIFIER: &str = "net.defguard";
// Returns the path to the users data directory.
// Returns the path to the user's data directory.
#[must_use]
pub fn app_data_dir() -> Option<PathBuf> {
dirs_next::data_dir().map(|dir| dir.join(BUNDLE_IDENTIFIER))
Expand Down
1 change: 0 additions & 1 deletion src-tauri/src/service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ use super::VERSION;
use crate::enterprise::service_locations::ServiceLocationManager;
#[cfg(windows)]
use crate::service::named_pipe::{get_named_pipe_server_stream, PIPE_NAME};

use crate::{
enterprise::service_locations::ServiceLocationError,
service::proto::{DeleteServiceLocationsRequest, SaveServiceLocationsRequest},
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/src/service/named_pipe.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{os::windows::io::RawHandle, pin::Pin};

use async_stream::stream;
use futures_core::stream::Stream;
use std::{os::windows::io::RawHandle, pin::Pin};
use tokio::{
io::{self, AsyncRead, AsyncWrite},
net::windows::named_pipe::NamedPipeServer,
Expand Down
24 changes: 24 additions & 0 deletions src-tauri/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
use std::time::Duration;
use std::{env, path::Path, process::Command, str::FromStr};

use base64::{prelude::BASE64_STANDARD, Engine};
use common::{find_free_tcp_port, get_interface_name};
use defguard_wireguard_rs::{host::Peer, key::Key, net::IpAddrMask, InterfaceConfiguration};
use prost::Message;
use sqlx::query;
#[cfg(target_os = "macos")]
use swift_rs::SRString;
Expand Down Expand Up @@ -40,6 +42,7 @@ use crate::{
error::Error,
events::EventKey,
log_watcher::service_log_watcher::spawn_log_watcher_task,
proto::ClientPlatformInfo,
service::{
proto::{CreateInterfaceRequest, ReadInterfaceDataRequest, RemoveInterfaceRequest},
utils::DAEMON_CLIENT,
Expand Down Expand Up @@ -958,3 +961,24 @@ pub async fn sync_connections(app_handle: &AppHandle) -> Result<(), Error> {

Ok(())
}

#[must_use]
pub(crate) fn construct_platform_header() -> String {
let os = os_info::get();

let platform_info = ClientPlatformInfo {
os_family: std::env::consts::OS.to_string(),
os_type: os.os_type().to_string(),
version: os.version().to_string(),
edition: os.edition().map(str::to_string),
codename: os.codename().map(str::to_string),
bitness: Some(os.bitness().to_string()),
architecture: os.architecture().map(str::to_string),
};

debug!("Constructed platform info header: {platform_info:?}");

let buffer = platform_info.encode_to_vec();

BASE64_STANDARD.encode(buffer)
}
31 changes: 25 additions & 6 deletions src/components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import '../../shared/scss/index.scss';

import { QueryClient } from '@tanstack/query-core';
import { QueryClientProvider } from '@tanstack/react-query';
import { getVersion } from '@tauri-apps/api/app';
import { debug, info } from '@tauri-apps/plugin-log';
import { openUrl } from '@tauri-apps/plugin-opener';
import { exit } from '@tauri-apps/plugin-process';
import dayjs from 'dayjs';
import customParseData from 'dayjs/plugin/customParseFormat';
import duration from 'dayjs/plugin/duration';
Expand All @@ -15,13 +17,15 @@ import timezone from 'dayjs/plugin/timezone';
import updateLocale from 'dayjs/plugin/updateLocale';
import utc from 'dayjs/plugin/utc';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { createBrowserRouter, Navigate, RouterProvider } from 'react-router-dom';
import { localStorageDetector } from 'typesafe-i18n/detectors';
import TypesafeI18n from '../../i18n/i18n-react';
import { detectLocale } from '../../i18n/i18n-util';
import { loadLocaleAsync } from '../../i18n/i18n-util.async';
import { ClientPage } from '../../pages/client/ClientPage';
import { clientApi } from '../../pages/client/clientAPI/clientApi';
import type { PlatformInfo } from '../../pages/client/clientAPI/types';
import { useClientStore } from '../../pages/client/hooks/useClientStore';
import { CarouselPage } from '../../pages/client/pages/CarouselPage/CarouselPage';
import { ClientAddedPage } from '../../pages/client/pages/ClientAddedPage/ClientAddedPage';
Expand All @@ -38,8 +42,6 @@ import { useTheme } from '../../shared/defguard-ui/hooks/theme/useTheme';
import { ThemeProvider } from '../../shared/providers/ThemeProvider/ThemeProvider';
import { routes } from '../../shared/routes';
import { ApplicationUpdateManager } from '../ApplicationUpdateManager/ApplicationUpdateManager';
import { exit } from '@tauri-apps/plugin-process';
import { useHotkeys } from 'react-hotkeys-hook';

dayjs.extend(duration);
dayjs.extend(utc);
Expand Down Expand Up @@ -127,12 +129,13 @@ export const App = () => {
const localeLoadRef = useRef(false);
const [localeLoaded, setWasLoaded] = useState(false);
const [settingsLoaded, setSettingsLoaded] = useState(false);
const [platformInfoLoaded, setPlatformInfoLoaded] = useState(false);
const setClientState = useClientStore((state) => state.setState);
const { changeTheme } = useTheme();

const appLoaded = useMemo(
() => localeLoaded && settingsLoaded,
[localeLoaded, settingsLoaded],
() => localeLoaded && settingsLoaded && platformInfoLoaded,
[localeLoaded, settingsLoaded, platformInfoLoaded],
);

// load locales
Expand Down Expand Up @@ -190,10 +193,26 @@ export const App = () => {

// register ctrl+q keyboard shortcut
useHotkeys('ctrl+q', () => {
info("Ctrl-Q pressed, exiting.");
exit(0);
info('Ctrl-Q pressed, exiting.');
exit(0);
});

useEffect(() => {
const loadPlatformInfo = async () => {
debug('Loading platform info from Tauri');
const version = await getVersion().catch(() => 'unknown');
const platformHeader = await clientApi.getPlatformHeader();
const platformInfo: PlatformInfo = {
client_version: `${version}`,
platform_info: platformHeader,
};
setClientState({ platformInfo });
debug('Platform info loaded from Tauri');
setPlatformInfoLoaded(true);
};
void loadPlatformInfo();
}, [setClientState]);

if (!appLoaded) return null;

return (
Expand Down
4 changes: 4 additions & 0 deletions src/pages/client/clientAPI/clientApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ const getAppConfig = async (): Promise<AppConfig> =>
const getProvisioningConfig = async (): Promise<ProvisioningConfig | null> =>
invokeWrapper('get_provisioning_config');

const getPlatformHeader = async (): Promise<string> =>
invokeWrapper('get_platform_header');

const setAppConfig = async (
appConfig: Partial<AppConfig>,
emitEvent: boolean,
Expand Down Expand Up @@ -169,4 +172,5 @@ export const clientApi = {
startGlobalLogWatcher,
stopGlobalLogWatcher,
getProvisioningConfig,
getPlatformHeader,
};
8 changes: 7 additions & 1 deletion src/pages/client/clientAPI/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ export type AppConfig = {
peer_alive_period: number;
};

export type PlatformInfo = {
client_version: string;
platform_info: string;
};

export type ProvisioningConfig = {
enrollment_token: string;
enrollment_url: string;
Expand Down Expand Up @@ -148,4 +153,5 @@ export type TauriCommandKey =
| 'stop_global_logwatcher'
| 'command_get_app_config'
| 'command_set_app_config'
| 'get_provisioning_config';
| 'get_provisioning_config'
| 'get_platform_header';
7 changes: 6 additions & 1 deletion src/pages/client/hooks/useClientStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createJSONStorage, persist } from 'zustand/middleware';
import { createWithEqualityFn } from 'zustand/traditional';

import { clientApi } from '../clientAPI/clientApi';
import type { AppConfig, ClientView } from '../clientAPI/types';
import type { AppConfig, ClientView, PlatformInfo } from '../clientAPI/types';
import {
ClientConnectionType,
type CommonWireguardFields,
Expand Down Expand Up @@ -36,6 +36,10 @@ const defaultValues: StoreValues = {
check_for_updates: true,
peer_alive_period: 300,
},
platformInfo: {
client_version: '',
platform_info: '',
},
};

export const useClientStore = createWithEqualityFn<Store>()(
Expand Down Expand Up @@ -110,6 +114,7 @@ type StoreValues = {
listChecked: boolean;
selectedView: ClientView;
appConfig: AppConfig;
platformInfo: PlatformInfo;
};

type StoreMethods = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const AddInstanceDeviceForm = () => {
const localLL = LL.pages.client.pages.addInstancePage.forms.device;
const toaster = useToaster();
const setClientStore = useClientStore((state) => state.setState);
const platformInfo = useClientStore((state) => state.platformInfo);
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(false);
const response = useAddInstanceStore((s) => s.response as AddInstanceInitResponse);
Expand Down Expand Up @@ -91,9 +92,12 @@ export const AddInstanceDeviceForm = () => {
name: values.name,
pubkey: publicKey,
};

const headers = {
'Content-Type': 'application/json',
Cookie: cookie,
CLIENT_VERSION_HEADER: platformInfo.client_version,
CLIENT_PLATFORM_HEADER: platformInfo.platform_info,
};
try {
await fetch(`${proxyUrl}/enrollment/create_device`, {
Expand Down
Loading