diff --git a/crates/defguard_core/src/cert_settings.rs b/crates/defguard_core/src/cert_settings.rs index 6dc308f48..0824b6718 100644 --- a/crates/defguard_core/src/cert_settings.rs +++ b/crates/defguard_core/src/cert_settings.rs @@ -94,7 +94,7 @@ pub struct ExternalUrlSettingsConfig { pub key_pem: Option, } -fn ensure_https(url: &str) -> String { +pub(crate) fn ensure_https(url: &str) -> String { if let Some(rest) = url.strip_prefix("http://") { format!("https://{rest}") } else { @@ -239,10 +239,8 @@ pub async fn apply_external_url_settings( // Modify url schema if necessary let mut settings = Settings::get_current_settings(); settings.public_proxy_url = match config.ssl_type { - ExternalSslType::None => public_proxy_url.to_string(), - ExternalSslType::LetsEncrypt | ExternalSslType::DefguardCa | ExternalSslType::OwnCert => { - ensure_https(public_proxy_url) - } + ExternalSslType::None | ExternalSslType::LetsEncrypt => public_proxy_url.to_string(), + ExternalSslType::DefguardCa | ExternalSslType::OwnCert => ensure_https(public_proxy_url), }; update_current_settings(&mut *transaction, settings).await?; diff --git a/crates/defguard_core/src/handlers/component_setup.rs b/crates/defguard_core/src/handlers/component_setup.rs index c189e60da..81da222e1 100644 --- a/crates/defguard_core/src/handlers/component_setup.rs +++ b/crates/defguard_core/src/handlers/component_setup.rs @@ -22,6 +22,7 @@ use defguard_common::{ gateway::Gateway, initial_setup_wizard::{InitialSetupState, InitialSetupStep}, proxy::Proxy, + settings::update_current_settings, wizard::Wizard, }, }, @@ -55,6 +56,7 @@ use tracing::Instrument; use crate::{ auth::{AdminOrSetupRole, SessionInfo}, + cert_settings::ensure_https, enterprise::is_enterprise_license_active, letsencrypt::{ACME_TIMEOUT, acme_step_name, call_proxy_trigger_acme, parse_cert_expiry}, setup_logs::scope_setup_logs, @@ -1288,6 +1290,13 @@ pub async fn stream_proxy_acme( } } + // Ensure external url is HTTPS + let mut settings = Settings::get_current_settings(); + settings.public_proxy_url = ensure_https(&settings.public_proxy_url); + if let Err(err) = update_current_settings(&pool, settings).await { + error!("Failed to update Settings::public_proxy_url to HTTPs after successful ACME challenge: {err}"); + } + // Post-wizard: broadcast certs to the proxy via bidi channel. if let Some(ref tx) = proxy_control_tx { let msg = ProxyControlMessage::BroadcastHttpsCerts { diff --git a/crates/defguard_core/tests/integration/api/proxy_certs.rs b/crates/defguard_core/tests/integration/api/proxy_certs.rs index 44a2dd39d..893892368 100644 --- a/crates/defguard_core/tests/integration/api/proxy_certs.rs +++ b/crates/defguard_core/tests/integration/api/proxy_certs.rs @@ -240,9 +240,9 @@ async fn test_external_url_settings_endpoint(_: PgPoolOptions, opts: PgConnectOp .send() .await; assert_eq!(response.status(), StatusCode::CREATED); - // Url schema changed to https + // Url schema didn't change yet let mut settings = Settings::get(&pool).await.unwrap().unwrap(); - assert_eq!(settings.public_proxy_url, "https://edge.example.com"); + assert_eq!(settings.public_proxy_url, "http://edge.example.com"); let body: serde_json::Value = response.json().await; assert!(body["cert_info"].is_null()); diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 63a7f1b47..20cd22b2c 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -312,28 +312,24 @@ packages: engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - libc: [musl] '@biomejs/cli-linux-arm64@2.4.12': resolution: {integrity: sha512-tOwuCuZZtKi1jVzbk/5nXmIsziOB6yqN8c9r9QM0EJYPU6DpQWf11uBOSCfFKKM4H3d9ZoarvlgMfbcuD051Pw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - libc: [glibc] '@biomejs/cli-linux-x64-musl@2.4.12': resolution: {integrity: sha512-dwTIgZrGutzhkQCuvHynCkyW6hJxUuyZqKKO0YNfaS2GUoRO+tOvxXZqZB6SkWAOdfZTzwaw8IEdUnIkHKHoew==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - libc: [musl] '@biomejs/cli-linux-x64@2.4.12': resolution: {integrity: sha512-8pFeAnLU9QdW9jCIslB/v82bI0lhBmz2ZAKc8pVMFPO0t0wAHsoEkrUQUbMkIorTRIjbqyNZHA3lEXavsPWYSw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - libc: [glibc] '@biomejs/cli-win32-arm64@2.4.12': resolution: {integrity: sha512-B0DLnx0vA9ya/3v7XyCaP+/lCpnbWbMOfUFFve+xb5OxyYvdHaS55YsSddr228Y+JAFk58agCuZTsqNiw2a6ig==} @@ -613,105 +609,89 @@ packages: resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] - libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-wasm32@0.34.5': resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} @@ -829,42 +809,36 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.6': resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.6': resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.6': resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.6': resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.6': resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [musl] '@parcel/watcher-win32-arm64@2.5.6': resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} @@ -952,42 +926,36 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==} @@ -2146,28 +2114,24 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} diff --git a/web/src/pages/settings/SettingsCertificatesPage/SettingsCertificatesPage.tsx b/web/src/pages/settings/SettingsCertificatesPage/SettingsCertificatesPage.tsx index caacaa31d..d93316894 100644 --- a/web/src/pages/settings/SettingsCertificatesPage/SettingsCertificatesPage.tsx +++ b/web/src/pages/settings/SettingsCertificatesPage/SettingsCertificatesPage.tsx @@ -46,9 +46,13 @@ const breadcrumbs = [ ]; export const SettingsCertificatesPage = () => { + const navigate = useNavigate(); + const onBack = () => { + navigate({ to: '/settings' }); + }; return ( - + } > diff --git a/web/src/pages/settings/SettingsCertificatesPage/SettingsCoreCertificateWizardPage/steps/SettingsCoreCertificateWizardInternalUrlSslConfigStep.tsx b/web/src/pages/settings/SettingsCertificatesPage/SettingsCoreCertificateWizardPage/steps/SettingsCoreCertificateWizardInternalUrlSslConfigStep.tsx index 684b3d65b..059028945 100644 --- a/web/src/pages/settings/SettingsCertificatesPage/SettingsCoreCertificateWizardPage/steps/SettingsCoreCertificateWizardInternalUrlSslConfigStep.tsx +++ b/web/src/pages/settings/SettingsCertificatesPage/SettingsCoreCertificateWizardPage/steps/SettingsCoreCertificateWizardInternalUrlSslConfigStep.tsx @@ -9,7 +9,6 @@ import { Button } from '../../../../../shared/defguard-ui/components/Button/Butt import { SizedBox } from '../../../../../shared/defguard-ui/components/SizedBox/SizedBox'; import { ThemeSpacing } from '../../../../../shared/defguard-ui/types'; import { downloadFile } from '../../../../../shared/utils/download'; -import caIcon from '../../../../SetupPage/assets/ca.png'; import '../../../../SetupPage/autoAdoption/steps/style.scss'; import { SettingsCoreCertificateWizardStep } from '../types'; import { useSettingsCoreCertificateWizardStore } from '../useSettingsCoreCertificateWizardStore'; @@ -49,7 +48,6 @@ export const SettingsCoreCertificateWizardInternalUrlSslConfigStep = () => { certInfo={certInfo} caCertPem={caData?.ca_cert_pem} onDownloadCaCert={handleDownloadCaCert} - imageSrc={caIcon} /> diff --git a/web/src/pages/settings/SettingsCertificatesPage/SettingsEdgeCertificateWizardPage/steps/SettingsEdgeCertificateWizardExternalUrlSslConfigStep.tsx b/web/src/pages/settings/SettingsCertificatesPage/SettingsEdgeCertificateWizardPage/steps/SettingsEdgeCertificateWizardExternalUrlSslConfigStep.tsx index c06b30bcd..46a904d08 100644 --- a/web/src/pages/settings/SettingsCertificatesPage/SettingsEdgeCertificateWizardPage/steps/SettingsEdgeCertificateWizardExternalUrlSslConfigStep.tsx +++ b/web/src/pages/settings/SettingsCertificatesPage/SettingsEdgeCertificateWizardPage/steps/SettingsEdgeCertificateWizardExternalUrlSslConfigStep.tsx @@ -36,6 +36,7 @@ type AcmeStepState = { currentStep: AcmeStepId | null; isComplete: boolean; isProcessing: boolean; + isFailed: boolean; errorMessage: string | null; proxyLogs: string[]; }; @@ -52,6 +53,7 @@ const defaultAcmeState: AcmeStepState = { currentStep: null, isComplete: false, isProcessing: false, + isFailed: false, errorMessage: null, proxyLogs: [], }; @@ -74,6 +76,7 @@ export const SettingsEdgeCertificateWizardExternalUrlSslConfigStep = () => { currentStep: event.step, isComplete: event.step === 'Done', isProcessing: event.step !== 'Done' && !event.error, + isFailed: Boolean(event.error), errorMessage: event.error ? (event.message ?? m.initial_setup_auto_adoption_external_url_ssl_lets_encrypt_error_default()) @@ -301,6 +304,7 @@ export const SettingsEdgeCertificateWizardExternalUrlSslConfigStep = () => { const isLetsEncryptProcessing = sslType === 'lets_encrypt' && acmeState.isProcessing; const isLetsEncryptIncomplete = sslType === 'lets_encrypt' && !acmeState.isComplete && !acmeState.errorMessage; + const isLetsEncryptFailed = acmeState.isFailed; return ( @@ -311,7 +315,9 @@ export const SettingsEdgeCertificateWizardExternalUrlSslConfigStep = () => {