diff --git a/.github/workflows/current.yml b/.github/workflows/current.yml index c32d9e1fbc..490f5e6aaa 100644 --- a/.github/workflows/current.yml +++ b/.github/workflows/current.yml @@ -1,10 +1,12 @@ name: Build current image +permissions: + contents: read on: push: branches: - main - dev - - 'release/**' + - "release/**" paths-ignore: - "*.md" - "LICENSE" @@ -25,3 +27,15 @@ jobs: needs: build-current uses: ./.github/workflows/e2e.yml secrets: inherit + + trigger-dev-deploy: + needs: build-current + if: ${{ github.event_name != 'pull_request' && github.ref_name == 'dev' }} + uses: ./.github/workflows/dev-deployment.yml + secrets: inherit + + trigger-staging-deploy: + needs: build-current + if: ${{ github.event_name != 'pull_request' && startsWith(github.ref_name, 'release/') }} + uses: ./.github/workflows/staging-deployment.yml + secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3540aa572c..a79149cb92 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -84,6 +84,10 @@ jobs: with: submodules: recursive + - name: Setup `packer` + uses: hashicorp/setup-packer@main + id: setup + - name: Install Rust stable uses: actions-rs/toolchain@v1 with: @@ -153,6 +157,26 @@ jobs: fpm_args: "defguard-${{ github.ref_name }}-${{ matrix.target }}=/usr/bin/defguard defguard.service=/usr/lib/systemd/system/defguard.service .env-template=/etc/defguard/core.conf" fpm_opts: "--architecture ${{ matrix.arch }} --debug --output-type deb --version ${{ env.VERSION }} --package defguard-${{ env.VERSION }}-${{ matrix.target }}.deb" + - name: Run `packer init` + if: matrix.build == 'linux' && matrix.arch == 'amd64' + id: init + run: "packer init ./images/ami/core.pkr.hcl" + + - name: Build AMI images for multiple regions + if: matrix.build == 'linux' && matrix.arch == 'amd64' + run: | + regions=(us-east-1 eu-west-1 ap-northeast-1) + for region in "${regions[@]}"; do + echo "Building AMI for region: $region" + echo "Running packer validate for $region..." + packer validate --var "package_version=${{ env.VERSION }}" --var "region=$region" ./images/ami/core.pkr.hcl + echo "Building AMI image for $region..." + packer build -color=false -on-error=abort --var "package_version=${{ env.VERSION }}" --var "region=$region" ./images/ami/core.pkr.hcl + done + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + - name: Upload DEB if: matrix.build == 'linux' uses: actions/upload-release-asset@v1.0.2 diff --git a/Cargo.lock b/Cargo.lock index 9fbb591863..61aabb2118 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2110,9 +2110,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ "base64 0.22.1", "bytes", @@ -2126,7 +2126,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", "system-configuration", "tokio", "tower-service", @@ -2329,9 +2329,9 @@ dependencies = [ [[package]] name = "io-uring" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ "bitflags 2.9.1", "cfg-if", @@ -2539,7 +2539,7 @@ dependencies = [ "nom 8.0.0", "percent-encoding", "quoted_printable", - "socket2", + "socket2 0.5.10", "tokio", "tokio-native-tls", "url", @@ -3495,9 +3495,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.35" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", "syn", @@ -3639,7 +3639,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2", + "socket2 0.5.10", "thiserror 2.0.12", "tokio", "tracing", @@ -3676,7 +3676,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.5.10", "tracing", "windows-sys 0.59.0", ] @@ -4522,6 +4522,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "spin" version = "0.9.8" @@ -5081,7 +5091,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "slab", - "socket2", + "socket2 0.5.10", "tokio-macros", "windows-sys 0.52.0", ] @@ -5183,7 +5193,7 @@ dependencies = [ "prost", "rustls-native-certs", "rustls-pemfile", - "socket2", + "socket2 0.5.10", "tokio", "tokio-rustls", "tokio-stream", diff --git a/Cargo.toml b/Cargo.toml index c48ad4cde3..3a5f0a6d97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ resolver = "2" [workspace.dependencies] # internal crates -defguard_core = { path = "./crates/defguard_core", version = "1.3.1" } +defguard_core = { path = "./crates/defguard_core", version = "1.5.0" } defguard_event_logger = { path = "./crates/defguard_event_logger", version = "0.0.0" } defguard_event_router = { path = "./crates/defguard_event_router", version = "0.0.0" } defguard_web_ui = { path = "./crates/defguard_web_ui", version = "0.0.0" } diff --git a/crates/defguard_core/src/add_network_device b/crates/defguard_core/src/add_network_device deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/crates/defguard_core/src/db/models/wireguard.rs b/crates/defguard_core/src/db/models/wireguard.rs index 5fa1fd84dc..d58d36f1bc 100644 --- a/crates/defguard_core/src/db/models/wireguard.rs +++ b/crates/defguard_core/src/db/models/wireguard.rs @@ -43,7 +43,7 @@ use crate::{ }; pub const DEFAULT_KEEPALIVE_INTERVAL: i32 = 25; -pub const DEFAULT_DISCONNECT_THRESHOLD: i32 = 180; +pub const DEFAULT_DISCONNECT_THRESHOLD: i32 = 300; // Used in process of importing network from wireguard config #[derive(Clone, Debug, Deserialize, Serialize)] 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 9897fbd72f..ec7187f037 100644 --- a/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs +++ b/crates/defguard_core/src/enterprise/grpc/desktop_client_mfa.rs @@ -65,8 +65,13 @@ impl ClientMfaServer { return Err(Status::invalid_argument("invalid MFA method")); } - let (ip, user_agent) = parse_client_info(&info).map_err(Status::internal)?; - let context = BidiRequestContext::new(user.id, user.username.clone(), ip, user_agent); + let (ip, _user_agent) = parse_client_info(&info).map_err(Status::internal)?; + let context = BidiRequestContext::new( + user.id, + user.username.clone(), + ip, + format!("{} (ID {})", device.name, device.id), + ); let code = AuthorizationCode::new(request.code.clone()); let url = match Url::parse(&request.callback_url).map_err(|err| { diff --git a/crates/defguard_core/src/events.rs b/crates/defguard_core/src/events.rs index 9f37e055b3..9b5b1d571b 100644 --- a/crates/defguard_core/src/events.rs +++ b/crates/defguard_core/src/events.rs @@ -331,18 +331,18 @@ pub struct BidiRequestContext { pub user_id: Id, pub username: String, pub ip: IpAddr, - pub user_agent: String, + pub device_name: String, } impl BidiRequestContext { - pub fn new(user_id: Id, username: String, ip: IpAddr, user_agent: String) -> Self { + pub fn new(user_id: Id, username: String, ip: IpAddr, device_name: String) -> Self { let timestamp = Utc::now().naive_utc(); Self { timestamp, user_id, username, ip, - user_agent, + device_name, } } } diff --git a/crates/defguard_core/src/grpc/desktop_client_mfa.rs b/crates/defguard_core/src/grpc/desktop_client_mfa.rs index ba8891f433..ddcf0c3c7f 100644 --- a/crates/defguard_core/src/grpc/desktop_client_mfa.rs +++ b/crates/defguard_core/src/grpc/desktop_client_mfa.rs @@ -315,8 +315,13 @@ impl ClientMfaServer { } = session; // Prepare event context - let (ip, user_agent) = parse_client_info(&info).map_err(Status::internal)?; - let context = BidiRequestContext::new(user.id, user.username.clone(), ip, user_agent); + let (ip, _user_agent) = parse_client_info(&info).map_err(Status::internal)?; + let context = BidiRequestContext::new( + user.id, + user.username.clone(), + ip, + format!("{} (ID {})", device.name, device.id), + ); // validate code match method { diff --git a/crates/defguard_core/tests/integration/common/mod.rs b/crates/defguard_core/tests/integration/common/mod.rs index 15cf2cd27a..e167b3146d 100644 --- a/crates/defguard_core/tests/integration/common/mod.rs +++ b/crates/defguard_core/tests/integration/common/mod.rs @@ -201,7 +201,7 @@ pub(crate) async fn exceed_enterprise_limits(client: &TestClient) { "dns": "1.1.1.1", "allowed_groups": [], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -221,7 +221,7 @@ pub(crate) async fn exceed_enterprise_limits(client: &TestClient) { "dns": "1.1.1.1", "allowed_groups": [], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -241,7 +241,7 @@ pub(crate) fn make_network() -> Value { "dns": "1.1.1.1", "allowed_groups": [], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" diff --git a/crates/defguard_core/tests/integration/wireguard.rs b/crates/defguard_core/tests/integration/wireguard.rs index 1001769b62..2f71537a20 100644 --- a/crates/defguard_core/tests/integration/wireguard.rs +++ b/crates/defguard_core/tests/integration/wireguard.rs @@ -299,7 +299,7 @@ async fn test_network_address_reassignment(_: PgPoolOptions, options: PgConnectO "dns": "1.1.1.1", "allowed_groups": [], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -367,7 +367,7 @@ async fn test_network_address_reassignment(_: PgPoolOptions, options: PgConnectO "dns": "1.1.1.1", "allowed_groups": [], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" diff --git a/crates/defguard_core/tests/integration/wireguard_network_allowed_groups.rs b/crates/defguard_core/tests/integration/wireguard_network_allowed_groups.rs index 24c8e528ef..16288fa64f 100644 --- a/crates/defguard_core/tests/integration/wireguard_network_allowed_groups.rs +++ b/crates/defguard_core/tests/integration/wireguard_network_allowed_groups.rs @@ -148,7 +148,7 @@ async fn test_create_new_network(_: PgPoolOptions, options: PgConnectOptions) { "dns": "1.1.1.1", "allowed_groups": ["allowed group"], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -194,7 +194,7 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "dns": "1.1.1.1", "allowed_groups": [], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -227,7 +227,7 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "dns": "1.1.1.1", "allowed_groups": ["allowed group"], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -254,7 +254,7 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "dns": "1.1.1.1", "allowed_groups": ["allowed group", "not allowed group"], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -282,7 +282,7 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "dns": "1.1.1.1", "allowed_groups": ["not allowed group"], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -309,7 +309,7 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "dns": "1.1.1.1", "allowed_groups": [], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -558,7 +558,7 @@ async fn test_modify_user(_: PgPoolOptions, options: PgConnectOptions) { "dns": "1.1.1.1", "allowed_groups": ["allowed group"], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -657,7 +657,7 @@ async fn test_delete_only_allowed_group(_: PgPoolOptions, options: PgConnectOpti "dns": "1.1.1.1", "allowed_groups": ["allowed group"], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" diff --git a/crates/defguard_core/tests/integration/wireguard_network_devices.rs b/crates/defguard_core/tests/integration/wireguard_network_devices.rs index 7fcd849585..1867226b06 100644 --- a/crates/defguard_core/tests/integration/wireguard_network_devices.rs +++ b/crates/defguard_core/tests/integration/wireguard_network_devices.rs @@ -23,7 +23,7 @@ fn make_network() -> Value { "dns": "1.1.1.1", "allowed_groups": [], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" @@ -40,7 +40,7 @@ fn make_second_network() -> Value { "dns": "1.1.1.1", "allowed_groups": [], "keepalive_interval": 25, - "peer_disconnect_threshold": 180, + "peer_disconnect_threshold": 300, "acl_enabled": false, "acl_default_allow": false, "location_mfa_mode": "disabled" diff --git a/crates/defguard_event_logger/src/message.rs b/crates/defguard_event_logger/src/message.rs index a5475ee2df..9100416fbf 100644 --- a/crates/defguard_event_logger/src/message.rs +++ b/crates/defguard_event_logger/src/message.rs @@ -74,7 +74,7 @@ impl EventContext { username: val.username, location, ip: val.ip, - device: val.user_agent, + device: val.device_name, } } diff --git a/e2e/package.json b/e2e/package.json index 9d01651436..209237b493 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -5,7 +5,7 @@ "type": "commonjs", "scripts": { "lint": "pnpm prettier --check './tests/**.ts' './utils/**/*.ts' && pnpm eslint './tests/**.ts' './utils/**/*.ts'", - "fix": "pnpm prettier -w './tests/**.ts' './utils/**/*.ts' && pnpm eslint --fix ./tests/**/*.ts ./utils/**/*.ts", + "fix": "pnpm prettier -w ./tests/**/*.ts ./utils/**/*.ts && pnpm eslint --fix ./tests/**/*.ts ./utils/**/*.ts", "test": "pnpm playwright test" }, "keywords": [], @@ -42,4 +42,4 @@ "volta": { "node": "19.9.0" } -} \ No newline at end of file +} diff --git a/e2e/tests/externalopenid.spec.ts b/e2e/tests/externalopenid.spec.ts index 29cbf60aac..1f09ea0761 100644 --- a/e2e/tests/externalopenid.spec.ts +++ b/e2e/tests/externalopenid.spec.ts @@ -20,8 +20,8 @@ test.describe('External OIDC.', () => { const client: OpenIdClient = { name: 'test 01', redirectURL: [ - 'http://localhost:8000/auth/callback', - 'http://localhost:8080/openid/callback', + `${testsConfig.BASE_URL}/auth/callback`, + `${testsConfig.ENROLLMENT_URL}/openid/callback`, ], scopes: ['openid', 'profile', 'email'], }; @@ -84,16 +84,17 @@ test.describe('External OIDC.', () => { await page.getByTestId('login-form-password').fill(testUser.password); await page.getByTestId('login-form-submit').click(); await page.getByTestId('openid-allow').click(); - const instanceUrlBox = page - .locator('div') - .filter({ hasText: /^Instance URL$/ }) - .getByRole('textbox'); + const instanceUrlBoxText = await page + .locator('div.copy-field div.list-cell-text ') + .first() + .textContent(); + expect(instanceUrlBoxText).toBe(testsConfig.ENROLLMENT_URL + '/'); - expect(await instanceUrlBox.inputValue()).toBe('http://localhost:8080/'); - const instanceTokenBox = page - .locator('div') - .filter({ hasText: /^Token$/ }) - .getByRole('textbox'); - expect((await instanceTokenBox.inputValue()).length).toBeGreaterThan(1); + const instanceTokenBoxText = await page + .locator('div.copy-field div.list-cell-text ') + .nth(1) + .textContent(); + expect(instanceTokenBoxText).toBeDefined(); + expect(instanceTokenBoxText?.length).toBeGreaterThan(1); }); }); diff --git a/e2e/tests/externalopenidmfa.spec.ts b/e2e/tests/externalopenidmfa.spec.ts index 785e7cc1a1..b1c82ed31d 100644 --- a/e2e/tests/externalopenidmfa.spec.ts +++ b/e2e/tests/externalopenidmfa.spec.ts @@ -19,7 +19,7 @@ test.describe('External OIDC.', () => { const client: OpenIdClient = { name: 'test 01', - redirectURL: ['http://localhost:8080/openid/mfa/callback'], + redirectURL: [`${testsConfig.ENROLLMENT_URL}/openid/mfa/callback`], scopes: ['openid', 'profile', 'email'], }; diff --git a/e2e/tests/vpn/networkdevice.spec.ts b/e2e/tests/vpn/networkdevice.spec.ts index f6636f53c1..1037004ace 100644 --- a/e2e/tests/vpn/networkdevice.spec.ts +++ b/e2e/tests/vpn/networkdevice.spec.ts @@ -60,7 +60,7 @@ test.describe('Network devices', () => { // Check if the device is really there await page.goto(routes.base + routes.admin.devices); - const deviceList = await page.locator('#devices-page-devices-list').first(); + const deviceList = page.locator('#devices-page-devices-list').first(); const deviceRows = deviceList.locator('.device-row'); await expect(deviceRows).toHaveCount(1); const deviceRow = await getDeviceRow({ page, deviceName }); diff --git a/e2e/utils/controllers/vpn/createNetworkDevice.ts b/e2e/utils/controllers/vpn/createNetworkDevice.ts index 31d444b67f..638dfad4f7 100644 --- a/e2e/utils/controllers/vpn/createNetworkDevice.ts +++ b/e2e/utils/controllers/vpn/createNetworkDevice.ts @@ -47,11 +47,14 @@ export const createNetworkDevice = async ( const context = await browser.newContext(); const page = await context.newPage(); await loginBasic(page, user); - await page.goto(routes.base + routes.admin.devices); + await page.goto(routes.base + routes.admin.devices, { + waitUntil: 'networkidle', + }); await page.getByRole('button', { name: 'Add new' }).click(); const configCard = page.locator('#add-standalone-device-modal'); + await configCard.waitFor({ state: 'visible' }); // select native-wg method - await configCard.getByTestId('standalone-device-choice-card-manual').click(); + await page.getByTestId('standalone-device-choice-card-manual').click(); await configCard.getByRole('button', { name: 'Next' }).click(); const deviceNameInput = configCard.getByTestId('field-name'); await deviceNameInput.fill(device.name); diff --git a/images/ami/core.pkr.hcl b/images/ami/core.pkr.hcl new file mode 100644 index 0000000000..8bb7d90fdd --- /dev/null +++ b/images/ami/core.pkr.hcl @@ -0,0 +1,62 @@ +packer { + required_plugins { + amazon = { + version = ">= 1.2.8" + source = "github.com/hashicorp/amazon" + } + } +} + +variable "package_version" { + type = string +} + +variable "region" { + type = string + default = "eu-north-1" +} + +variable "instance_type" { + type = string + default = "t3.micro" +} + +source "amazon-ebs" "defguard-core" { + ami_name = "defguard-core-${var.package_version}-amd64" + instance_type = var.instance_type + region = var.region + source_ami_filter { + filters = { + name = "ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*" + root-device-type = "ebs" + virtualization-type = "hvm" + } + most_recent = true + owners = ["099720109477"] + } + ssh_username = "ubuntu" +} + +build { + name = "defguard-core" + sources = [ + "source.amazon-ebs.defguard-core" + ] + + provisioner "file" { + source = "defguard-${var.package_version}-x86_64-unknown-linux-gnu.deb" + destination = "/tmp/defguard-core.deb" + } + + provisioner "shell" { + script = "./images/ami/core.sh" + } + + provisioner "shell" { + inline = ["rm /home/ubuntu/.ssh/authorized_keys"] + } + + provisioner "shell" { + inline = ["sudo rm /root/.ssh/authorized_keys"] + } +} diff --git a/images/ami/core.sh b/images/ami/core.sh new file mode 100644 index 0000000000..1203c711ae --- /dev/null +++ b/images/ami/core.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e + +echo "Updating apt repositories..." +sudo apt update + +echo "Installing Defguard package..." +sudo dpkg -i /tmp/defguard-core.deb + +echo "Cleaning up..." +sudo rm -f /tmp/defguard-core.deb + +echo "Defguard installation completed successfully." diff --git a/migrations/20250730141806_higher_peer_disconnect_threshold.down.sql b/migrations/20250730141806_higher_peer_disconnect_threshold.down.sql new file mode 100644 index 0000000000..be83412e91 --- /dev/null +++ b/migrations/20250730141806_higher_peer_disconnect_threshold.down.sql @@ -0,0 +1 @@ +ALTER TABLE wireguard_network ALTER COLUMN peer_disconnect_threshold SET DEFAULT 180; diff --git a/migrations/20250730141806_higher_peer_disconnect_threshold.up.sql b/migrations/20250730141806_higher_peer_disconnect_threshold.up.sql new file mode 100644 index 0000000000..af35bb2337 --- /dev/null +++ b/migrations/20250730141806_higher_peer_disconnect_threshold.up.sql @@ -0,0 +1 @@ +ALTER TABLE wireguard_network ALTER COLUMN peer_disconnect_threshold SET DEFAULT 300; diff --git a/web/.env b/web/.env deleted file mode 100644 index 3b3c938afe..0000000000 --- a/web/.env +++ /dev/null @@ -1 +0,0 @@ -#PROXY_TARGET="https://defguard-dev.teonite.net" diff --git a/web/.gitignore b/web/.gitignore index 07c27a65ee..88e111584e 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1 +1,2 @@ *.local* +./*.env diff --git a/web/src/components/App/App.scss b/web/src/components/App/App.scss deleted file mode 100644 index 2b4db9f378..0000000000 --- a/web/src/components/App/App.scss +++ /dev/null @@ -1,5 +0,0 @@ -#app { - height: inherit; - max-height: inherit; - position: relative; -} diff --git a/web/src/components/App/App.tsx b/web/src/components/App/App.tsx index b54b58f7a8..d29c694d56 100644 --- a/web/src/components/App/App.tsx +++ b/web/src/components/App/App.tsx @@ -1,5 +1,4 @@ import 'react-loading-skeleton/dist/skeleton.css'; -import './App.scss'; import { Navigate, Route, BrowserRouter as Router, Routes } from 'react-router-dom'; diff --git a/web/src/i18n/en/index.ts b/web/src/i18n/en/index.ts index bdc0fb18fe..32d53a4102 100644 --- a/web/src/i18n/en/index.ts +++ b/web/src/i18n/en/index.ts @@ -522,6 +522,9 @@ Licensing information: [https://docs.defguard.net/enterprise/license](https://do }, form: { submit: 'Add user', + error: { + emailReserved: 'Email already taken', + }, fields: { username: { placeholder: 'login', @@ -1991,19 +1994,22 @@ Licensing information: [https://docs.defguard.net/enterprise/license](https://do 'By default, all users will be allowed to connect to this location. If you want to restrict access to this location to a specific group, please select it below.', aclFeatureDisabled: "ACL functionality is an enterprise feature and you've exceeded the user, device or network limits to use it. In order to use this feature, purchase an enterprise license or upgrade your existing one.", - peerDisconnectThreshold: 'Clients authorized with MFA will be disconnected from the location once there has been no network activity detected between them and the VPN gateway for a length of time configured below.', + peerDisconnectThreshold: + 'Clients authorized with MFA will be disconnected from the location once there has been no network activity detected between them and the VPN gateway for a length of time configured below.', locationMfaMode: { - description: 'Choose how MFA is enforced when connecting to this location:', - internal: "Internal MFA - MFA is enforced using Defguard's built-in MFA (e.g. TOTP, WebAuthn) with internal identity", - external: 'External MFA - If configured (see [OpenID settings](settings)) this option uses external identity provider for MFA', + description: 'Choose how MFA is enforced when connecting to this location:', + internal: + "Internal MFA - MFA is enforced using Defguard's built-in MFA (e.g. TOTP, WebAuthn) with internal identity", + external: + 'External MFA - If configured (see [OpenID settings](settings)) this option uses external identity provider for MFA', }, }, sections: { accessControl: { - header: 'Access Control & Firewall' + header: 'Access Control & Firewall', }, mfa: { - header: 'Multi-Factor Authentication' + header: 'Multi-Factor Authentication', }, }, messages: { @@ -2047,7 +2053,7 @@ Licensing information: [https://docs.defguard.net/enterprise/license](https://do }, location_mfa_mode: { label: 'MFA requirement', - } + }, }, controls: { submit: 'Save changes', diff --git a/web/src/i18n/i18n-types.ts b/web/src/i18n/i18n-types.ts index 3931b0862c..af7be4fe0c 100644 --- a/web/src/i18n/i18n-types.ts +++ b/web/src/i18n/i18n-types.ts @@ -1229,6 +1229,12 @@ type RootTranslation = { * Add user */ submit: string + error: { + /** + * Email already taken + */ + emailReserved: string + } fields: { username: { /** @@ -7852,6 +7858,12 @@ export type TranslationFunctions = { * Add user */ submit: () => LocalizedString + error: { + /** + * Email already taken + */ + emailReserved: () => LocalizedString + } fields: { username: { /** diff --git a/web/src/pages/addDevice/steps/AddDeviceClientConfigurationStep/AddDeviceClientConfigurationStep.tsx b/web/src/pages/addDevice/steps/AddDeviceClientConfigurationStep/AddDeviceClientConfigurationStep.tsx index 0343302c6b..80a1acdf4a 100644 --- a/web/src/pages/addDevice/steps/AddDeviceClientConfigurationStep/AddDeviceClientConfigurationStep.tsx +++ b/web/src/pages/addDevice/steps/AddDeviceClientConfigurationStep/AddDeviceClientConfigurationStep.tsx @@ -13,9 +13,9 @@ import { import { Card } from '../../../../shared/defguard-ui/components/Layout/Card/Card'; import { CopyField } from '../../../../shared/defguard-ui/components/Layout/CopyField/CopyField'; import { MessageBox } from '../../../../shared/defguard-ui/components/Layout/MessageBox/MessageBox'; -import { useToaster } from '../../../../shared/defguard-ui/hooks/toasts/useToaster'; import { isPresent } from '../../../../shared/defguard-ui/utils/isPresent'; import { useClipboard } from '../../../../shared/hooks/useClipboard'; +import { externalLink } from '../../../../shared/links'; import { useAddDevicePageStore } from '../../hooks/useAddDevicePageStore'; import { AddDeviceStep } from '../../types'; import { enrollmentToImportToken } from '../../utils/enrollmentToToken'; @@ -23,7 +23,6 @@ import { enrollmentToImportToken } from '../../utils/enrollmentToToken'; export const AddDeviceClientConfigurationStep = () => { const { LL } = useI18nContext(); const localLL = LL.addDevicePage.steps.client; - const toaster = useToaster(); const clientData = useAddDevicePageStore((s) => s.clientSetup); const tokenValue = useAddDevicePageStore((s) => s.clientSetup @@ -74,9 +73,9 @@ export const AddDeviceClientConfigurationStep = () => {