@@ -4,7 +4,7 @@ use defguard_certs::{
44 parse_pem_certificate,
55} ;
66use defguard_common:: db:: models:: {
7- Certificates , CoreCertSource , ProxyCertSource , settings:: update_current_settings,
7+ Certificates , CoreCertSource , ProxyCertSource , Settings , settings:: update_current_settings,
88} ;
99use serde:: { Deserialize , Serialize } ;
1010use sqlx:: PgPool ;
@@ -94,6 +94,14 @@ pub struct ExternalUrlSettingsConfig {
9494 pub key_pem : Option < String > ,
9595}
9696
97+ fn ensure_https ( url : & str ) -> String {
98+ if let Some ( rest) = url. strip_prefix ( "http://" ) {
99+ format ! ( "https://{rest}" )
100+ } else {
101+ url. to_owned ( )
102+ }
103+ }
104+
97105/// Core logic for applying internal URL certificate settings using the current Defguard URL.
98106/// Returns cert info if a certificate was generated/uploaded, `None` for `ssl_type = None`.
99107pub async fn apply_internal_url_settings (
@@ -106,11 +114,17 @@ pub async fn apply_internal_url_settings(
106114 defguard_url, config. ssl_type,
107115 ) ;
108116
109- let mut settings = defguard_common:: db:: models:: Settings :: get_current_settings ( ) ;
110- settings. defguard_url = defguard_url. to_string ( ) ;
111- update_current_settings ( pool, settings) . await ?;
117+ let mut settings = Settings :: get_current_settings ( ) ;
118+ let mut transaction = pool. begin ( ) . await ?;
119+
120+ // Modify url schema if necessary
121+ settings. defguard_url = match config. ssl_type {
122+ InternalSslType :: None => defguard_url. to_string ( ) ,
123+ InternalSslType :: DefguardCa | InternalSslType :: OwnCert => ensure_https ( defguard_url) ,
124+ } ;
125+ update_current_settings ( & mut * transaction, settings) . await ?;
112126
113- let mut certs = Certificates :: get_or_default ( pool )
127+ let mut certs = Certificates :: get_or_default ( & mut * transaction )
114128 . await
115129 . map_err ( WebError :: from) ?;
116130
@@ -120,7 +134,10 @@ pub async fn apply_internal_url_settings(
120134 certs. core_http_cert_pem = None ;
121135 certs. core_http_cert_key_pem = None ;
122136 certs. core_http_cert_expiry = None ;
123- certs. save ( pool) . await . map_err ( WebError :: from) ?;
137+ certs
138+ . save ( & mut * transaction)
139+ . await
140+ . map_err ( WebError :: from) ?;
124141 None
125142 }
126143 InternalSslType :: DefguardCa => {
@@ -156,7 +173,10 @@ pub async fn apply_internal_url_settings(
156173 certs. core_http_cert_pem = Some ( cert_pem) ;
157174 certs. core_http_cert_key_pem = Some ( key_pem) ;
158175 certs. core_http_cert_expiry = Some ( expiry) ;
159- certs. save ( pool) . await . map_err ( WebError :: from) ?;
176+ certs
177+ . save ( & mut * transaction)
178+ . await
179+ . map_err ( WebError :: from) ?;
160180
161181 Some ( CertInfoResponse {
162182 common_name : info. subject_common_name ,
@@ -181,7 +201,10 @@ pub async fn apply_internal_url_settings(
181201 certs. core_http_cert_pem = Some ( cert_pem_str) ;
182202 certs. core_http_cert_key_pem = Some ( key_pem_str) ;
183203 certs. core_http_cert_expiry = Some ( expiry) ;
184- certs. save ( pool) . await . map_err ( WebError :: from) ?;
204+ certs
205+ . save ( & mut * transaction)
206+ . await
207+ . map_err ( WebError :: from) ?;
185208
186209 Some ( CertInfoResponse {
187210 common_name : info. subject_common_name ,
@@ -192,6 +215,7 @@ pub async fn apply_internal_url_settings(
192215 }
193216 } ;
194217
218+ transaction. commit ( ) . await ?;
195219 Ok ( cert_info)
196220}
197221
@@ -207,28 +231,37 @@ pub async fn apply_external_url_settings(
207231 public_proxy_url, config. ssl_type,
208232 ) ;
209233
210- let mut certs = Certificates :: get_or_default ( pool)
234+ let mut transaction = pool. begin ( ) . await ?;
235+ let mut certs = Certificates :: get_or_default ( & mut * transaction)
211236 . await
212237 . map_err ( WebError :: from) ?;
213238
214- let hostname = if matches ! (
215- config. ssl_type,
216- ExternalSslType :: LetsEncrypt | ExternalSslType :: DefguardCa
217- ) {
218- let url = public_proxy_url. trim ( ) ;
219- if url. is_empty ( ) {
220- return Err ( WebError :: BadRequest (
221- "Public proxy URL is not configured" . to_string ( ) ,
222- ) ) ;
239+ // Modify url schema if necessary
240+ let mut settings = Settings :: get_current_settings ( ) ;
241+ settings. public_proxy_url = match config. ssl_type {
242+ ExternalSslType :: None => public_proxy_url. to_string ( ) ,
243+ ExternalSslType :: LetsEncrypt | ExternalSslType :: DefguardCa | ExternalSslType :: OwnCert => {
244+ ensure_https ( public_proxy_url)
245+ }
246+ } ;
247+ update_current_settings ( & mut * transaction, settings) . await ?;
248+
249+ let hostname = match config. ssl_type {
250+ ExternalSslType :: None | ExternalSslType :: OwnCert => String :: new ( ) ,
251+ ExternalSslType :: DefguardCa | ExternalSslType :: LetsEncrypt => {
252+ let url = public_proxy_url. trim ( ) ;
253+ if url. is_empty ( ) {
254+ return Err ( WebError :: BadRequest (
255+ "Public proxy URL is not configured" . to_string ( ) ,
256+ ) ) ;
257+ }
258+
259+ reqwest:: Url :: parse ( url)
260+ . ok ( )
261+ . and_then ( |u| u. host_str ( ) . map ( ToString :: to_string) )
262+ . filter ( |host| !host. is_empty ( ) )
263+ . unwrap_or_else ( || url. to_string ( ) )
223264 }
224-
225- reqwest:: Url :: parse ( url)
226- . ok ( )
227- . and_then ( |u| u. host_str ( ) . map ( ToString :: to_string) )
228- . filter ( |host| !host. is_empty ( ) )
229- . unwrap_or_else ( || url. to_string ( ) )
230- } else {
231- String :: new ( )
232265 } ;
233266
234267 let cert_info = match config. ssl_type {
@@ -239,7 +272,10 @@ pub async fn apply_external_url_settings(
239272 certs. proxy_http_cert_pem = None ;
240273 certs. proxy_http_cert_key_pem = None ;
241274 certs. proxy_http_cert_expiry = None ;
242- certs. save ( pool) . await . map_err ( WebError :: from) ?;
275+ certs
276+ . save ( & mut * transaction)
277+ . await
278+ . map_err ( WebError :: from) ?;
243279 None
244280 }
245281 ExternalSslType :: LetsEncrypt => {
@@ -278,7 +314,10 @@ pub async fn apply_external_url_settings(
278314 certs. proxy_http_cert_pem = Some ( cert_pem) ;
279315 certs. proxy_http_cert_key_pem = Some ( key_pem) ;
280316 certs. proxy_http_cert_expiry = Some ( expiry) ;
281- certs. save ( pool) . await . map_err ( WebError :: from) ?;
317+ certs
318+ . save ( & mut * transaction)
319+ . await
320+ . map_err ( WebError :: from) ?;
282321
283322 Some ( CertInfoResponse {
284323 common_name : info. subject_common_name ,
@@ -304,7 +343,10 @@ pub async fn apply_external_url_settings(
304343 certs. proxy_http_cert_pem = Some ( cert_pem_str) ;
305344 certs. proxy_http_cert_key_pem = Some ( key_pem_str) ;
306345 certs. proxy_http_cert_expiry = Some ( expiry) ;
307- certs. save ( pool) . await . map_err ( WebError :: from) ?;
346+ certs
347+ . save ( & mut * transaction)
348+ . await
349+ . map_err ( WebError :: from) ?;
308350
309351 Some ( CertInfoResponse {
310352 common_name : info. subject_common_name ,
@@ -315,5 +357,6 @@ pub async fn apply_external_url_settings(
315357 }
316358 } ;
317359
360+ transaction. commit ( ) . await ?;
318361 Ok ( cert_info)
319362}
0 commit comments