Browse Source

feat: force endpoint URL to use https on release [TRI-015] (#41)

Lucas Nogueira 3 years ago
parent
commit
c077f44927

+ 6 - 0
.changes/updater-endpoint-url-https.md

@@ -0,0 +1,6 @@
+---
+"tauri": patch
+"tauri-utils": patch
+---
+
+Force updater endpoint URL to use `https` on release builds.

+ 46 - 3
core/tauri-utils/src/config.rs

@@ -1359,6 +1359,38 @@ impl TauriConfig {
   }
 }
 
+/// A URL to an updater server.
+///
+/// The URL must use the `https` scheme on production.
+#[skip_serializing_none]
+#[derive(Debug, PartialEq, Clone, Serialize)]
+#[cfg_attr(feature = "schema", derive(JsonSchema))]
+pub struct UpdaterEndpoint(pub Url);
+
+impl std::fmt::Display for UpdaterEndpoint {
+  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    write!(f, "{}", self.0)
+  }
+}
+
+impl<'de> Deserialize<'de> for UpdaterEndpoint {
+  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+  where
+    D: Deserializer<'de>,
+  {
+    let url = Url::deserialize(deserializer)?;
+    #[cfg(all(not(debug_assertions), not(feature = "schema")))]
+    {
+      if url.scheme() != "https" {
+        return Err(serde::de::Error::custom(
+          "The configured updater endpoint must use the `https` protocol.",
+        ));
+      }
+    }
+    Ok(Self(url))
+  }
+}
+
 /// The Updater configuration object.
 #[skip_serializing_none]
 #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
@@ -1371,8 +1403,8 @@ pub struct UpdaterConfig {
   /// Display built-in dialog or use event system if disabled.
   #[serde(default = "default_dialog")]
   pub dialog: bool,
-  /// The updater endpoints.
-  pub endpoints: Option<Vec<String>>,
+  /// The updater endpoints. TLS is enforced on production.
+  pub endpoints: Option<Vec<UpdaterEndpoint>>,
   /// Signature public key.
   pub pubkey: String,
 }
@@ -2029,7 +2061,18 @@ mod build {
       let active = self.active;
       let dialog = self.dialog;
       let pubkey = str_lit(&self.pubkey);
-      let endpoints = opt_vec_str_lit(self.endpoints.as_ref());
+      let endpoints = opt_lit(
+        self
+          .endpoints
+          .as_ref()
+          .map(|list| {
+            vec_lit(list, |url| {
+              let url = url.0.as_str();
+              quote! { ::tauri::utils::config::UpdaterEndpoint(#url.parse().unwrap()) }
+            })
+          })
+          .as_ref(),
+      );
 
       literal_struct!(tokens, UpdaterConfig, active, dialog, pubkey, endpoints);
     }

+ 7 - 1
core/tauri/src/updater/mod.rs

@@ -381,6 +381,10 @@ pub(crate) async fn check_update_with_dialog<R: Runtime>(
   window: Window<R>,
 ) {
   if let Some(endpoints) = updater_config.endpoints.clone() {
+    let endpoints = endpoints
+      .iter()
+      .map(|e| e.to_string())
+      .collect::<Vec<String>>();
     let env = window.state::<Env>().inner().clone();
     // check updates
     match self::core::builder(env)
@@ -440,7 +444,9 @@ pub(crate) fn listener<R: Runtime>(
       .endpoints
       .as_ref()
       .expect("Something wrong with endpoints")
-      .clone();
+      .iter()
+      .map(|e| e.to_string())
+      .collect::<Vec<String>>();
 
     let pubkey = updater_config.pubkey.clone();
 

+ 54 - 0
examples/updater/src-tauri/Cargo.lock

@@ -3028,6 +3028,7 @@ dependencies = [
 name = "tauri-macros"
 version = "1.0.0-beta.5"
 dependencies = [
+ "heck",
  "proc-macro2",
  "quote",
  "syn",
@@ -3611,6 +3612,28 @@ dependencies = [
  "windows 0.25.0",
 ]
 
+[[package]]
+name = "webview2-com"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abdc9ca7cebd96a1005d5ba1e9d70c61c0f6c276a41cddaeecb7842d436ab3bc"
+dependencies = [
+ "webview2-com-macros 0.4.0",
+ "webview2-com-sys 0.7.0",
+ "windows 0.25.0",
+]
+
+[[package]]
+name = "webview2-com-macros"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07bca4b354035275764ea4ca8d6bfa74cc5b0e8126e7cd675ee327574b59e13d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "webview2-com-macros"
 version = "0.4.0"
@@ -3635,6 +3658,19 @@ dependencies = [
  "windows 0.25.0",
 ]
 
+[[package]]
+name = "webview2-com-sys"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73472d7f0e9038b58204cb3f582ee138a8c181719dc6825ea03371ad085c6058"
+dependencies = [
+ "regex",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "windows 0.25.0",
+]
+
 [[package]]
 name = "wepoll-ffi"
 version = "0.1.2"
@@ -3773,6 +3809,18 @@ dependencies = [
  "windows_reader 0.21.1",
 ]
 
+[[package]]
+name = "windows_macros"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6103bcf1a7396d66f6f08a2d67d8a2ab34efaf4b1d7567301af2c002507c8c3b"
+dependencies = [
+ "syn",
+ "windows_gen 0.25.0",
+ "windows_quote 0.25.0",
+ "windows_reader 0.25.0",
+]
+
 [[package]]
 name = "windows_quote"
 version = "0.25.0"
@@ -3785,6 +3833,12 @@ version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7cf987b5288c15e1997226848f78f3ed3ef8b78dcfd71a201c8c8684163a7e4d"
 
+[[package]]
+name = "windows_quote"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e414df8d5dd2013f2317fdc414d3ad035effcb7aef1f16bf508ac5743154835a"
+
 [[package]]
 name = "windows_reader"
 version = "0.25.0"

+ 1 - 1
examples/updater/src-tauri/Cargo.toml

@@ -7,7 +7,7 @@ rust-version = "1.56"
 license = "Apache-2.0 OR MIT"
 
 [build-dependencies]
-tauri-build = { path = "../../../core/tauri-build", features = [ "codegen" ] }
+tauri-build = { path = "../../../core/tauri-build", features = ["codegen"] }
 
 [dependencies]
 serde_json = "1.0"

+ 1 - 1
tooling/cli.rs/Cargo.toml

@@ -30,7 +30,7 @@ notify = "4.0"
 shared_child = "1.0"
 toml_edit = "0.12"
 json-patch = "0.2"
-tauri-utils = { version = "1.0.0-beta.3", path = "../../core/tauri-utils" }
+tauri-utils = { version = "1.0.0-beta.3", path = "../../core/tauri-utils", features = ["isolation", "schema"] }
 schemars = { version = "0.8", features = ["url"] }
 toml = "0.5"
 valico = "3.6"

+ 7 - 2
tooling/cli.rs/schema.json

@@ -1551,13 +1551,13 @@
           "type": "boolean"
         },
         "endpoints": {
-          "description": "The updater endpoints.",
+          "description": "The updater endpoints. TLS is enforced on production.",
           "type": [
             "array",
             "null"
           ],
           "items": {
-            "type": "string"
+            "$ref": "#/definitions/UpdaterEndpoint"
           }
         },
         "pubkey": {
@@ -1567,6 +1567,11 @@
       },
       "additionalProperties": false
     },
+    "UpdaterEndpoint": {
+      "description": "A URL to an updater server.\n\nThe URL must use the `https` scheme on production.",
+      "type": "string",
+      "format": "uri"
+    },
     "WindowAllowlistConfig": {
       "description": "Allowlist for the window APIs.",
       "type": "object",

+ 3 - 1
tooling/cli.rs/src/interface/rust.rs

@@ -496,7 +496,9 @@ fn tauri_config_to_bundle_settings(
       // unwrap_or as we have a default value but used to prevent any failing
       dialog: updater_config.dialog,
       pubkey: updater_config.pubkey,
-      endpoints: updater_config.endpoints,
+      endpoints: updater_config
+        .endpoints
+        .map(|endpoints| endpoints.iter().map(|e| e.to_string()).collect()),
     }),
     ..Default::default()
   })