diff --git a/.changes/allow-updater-key-rotation.md b/.changes/allow-updater-key-rotation.md new file mode 100644 index 000000000..5a2d10820 --- /dev/null +++ b/.changes/allow-updater-key-rotation.md @@ -0,0 +1,6 @@ +--- +"@tauri-apps/cli": patch:enhance +"tauri-cli": patch:enhance +--- + +Allow rotating the updater private key. diff --git a/.github/workflows/test-core.yml b/.github/workflows/test-core.yml index 0d9bd59da..5ce515d8e 100644 --- a/.github/workflows/test-core.yml +++ b/.github/workflows/test-core.yml @@ -88,6 +88,7 @@ jobs: cargo update -p system-deps:6.1.2 --precise 6.1.1 cargo update -p toml:0.7.8 --precise 0.7.3 cargo update -p toml_edit:0.19.15 --precise 0.19.8 + cargo update -p embed-resource --precise 2.3.0 cargo update -p toml_datetime --precise 0.6.1 cargo update -p serde_spanned --precise 0.6.1 cargo update -p winnow --precise 0.4.1 @@ -100,7 +101,7 @@ jobs: cargo update -p is-terminal --precise 0.4.7 cargo update -p colored --precise 2.0.2 cargo update -p tempfile --precise 3.6.0 - cargo update -p serde_with:3.3.0 --precise 3.0.0 + cargo update -p serde_with:3.4.0 --precise 3.0.0 cargo update -p tokio --precise 1.29.0 cargo update -p flate2 --precise 1.0.26 cargo update -p h2 --precise 0.3.20 diff --git a/core/tests/app-updater/tauri.conf.json b/core/tests/app-updater/tauri.conf.json index 1de6eb67e..273e0e7fa 100644 --- a/core/tests/app-updater/tauri.conf.json +++ b/core/tests/app-updater/tauri.conf.json @@ -34,7 +34,7 @@ "updater": { "active": true, "dialog": false, - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE5QzMxNjYwNTM5OEUwNTgKUldSWTRKaFRZQmJER1h4d1ZMYVA3dnluSjdpN2RmMldJR09hUFFlZDY0SlFqckkvRUJhZDJVZXAK", + "pubkey": "dummy", "endpoints": ["http://localhost:3007"], "windows": { "installMode": "quiet" diff --git a/core/tests/app-updater/tests/update.rs b/core/tests/app-updater/tests/update.rs index dd3024367..a21821467 100644 --- a/core/tests/app-updater/tests/update.rs +++ b/core/tests/app-updater/tests/update.rs @@ -14,15 +14,30 @@ use std::{ use serde::Serialize; const UPDATER_PRIVATE_KEY: &str = "dW50cnVzdGVkIGNvbW1lbnQ6IHJzaWduIGVuY3J5cHRlZCBzZWNyZXQga2V5ClJXUlRZMEl5YTBGV3JiTy9lRDZVd3NkL0RoQ1htZmExNDd3RmJaNmRMT1ZGVjczWTBKZ0FBQkFBQUFBQUFBQUFBQUlBQUFBQWdMekUzVkE4K0tWQ1hjeGt1Vkx2QnRUR3pzQjVuV0ZpM2czWXNkRm9hVUxrVnB6TUN3K1NheHJMREhQbUVWVFZRK3NIL1VsMDBHNW5ET1EzQno0UStSb21nRW4vZlpTaXIwZFh5ZmRlL1lSN0dKcHdyOUVPclVvdzFhVkxDVnZrbHM2T1o4Tk1NWEU9Cg=="; +// const UPDATER_PUBLIC_KEY: &str = "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE5QzMxNjYwNTM5OEUwNTgKUldSWTRKaFRZQmJER1h4d1ZMYVA3dnluSjdpN2RmMldJR09hUFFlZDY0SlFqckkvRUJhZDJVZXAK"; + +const UPDATER_PRIVATE_KEY_NEXT: &str = "dW50cnVzdGVkIGNvbW1lbnQ6IHJzaWduIGVuY3J5cHRlZCBzZWNyZXQga2V5ClJXUlRZMEl5Vm1kaFhCeEh0N2svRy85djJQbmNGTnk3TUQ1emJRWTF3Y01INW9OZjJwSUFBQkFBQUFBQUFBQUFBQUlBQUFBQS9YRStJU1RjK1JmUS9QK0F3WmdaMFE0RmUrcVY1RXhkL0VaYVZEeTVDNHREWnE2Y21yTVZCcW0rM1lKOUVLd1p1MWVPVFN5WmZBZEUxYnVtT3BnWW93TDZZRnYra1FUblFXazBVempRUFZOTnFRSjdod05LMjhvK3M0VGhoR0V4YWkzWUpOQXBIcEU9Cg=="; +const UPDATER_PUBLIC_KEY_NEXT: &str = "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE3RjlEQzI0MjEzRTcxRkQKUldUOWNUNGhKTno1RjZtKzNZSjlFS3dadTFlT1RTeVpmQWRFMWJ1bU9wZ1lvd0w2WUZ2K2tRVG4K"; #[derive(Serialize)] struct PackageConfig { version: &'static str, } +#[derive(Serialize)] +struct UpdaterConfig { + pubkey: &'static str, +} + +#[derive(Serialize)] +struct TauriConfig { + updater: UpdaterConfig, +} + #[derive(Serialize)] struct Config { package: PackageConfig, + tauri: TauriConfig, } #[derive(Serialize)] @@ -57,6 +72,7 @@ fn get_cli_bin_path(cli_dir: &Path, debug: bool) -> Option { fn build_app( cli_bin_path: &Path, cwd: &Path, + envs: Vec<(&str, &str)>, config: &Config, bundle_updater: bool, target: BundleTarget, @@ -78,7 +94,7 @@ fn build_app( command.args(["--bundles", "msi", "nsis"]); command - .env("TAURI_PRIVATE_KEY", UPDATER_PRIVATE_KEY) + .envs(envs) .env("TAURI_KEY_PASSWORD", "") .args(["--bundles", "updater"]); } else { @@ -197,12 +213,18 @@ fn update_app() { let mut config = Config { package: PackageConfig { version: "1.0.0" }, + tauri: TauriConfig { + updater: UpdaterConfig { + pubkey: UPDATER_PUBLIC_KEY_NEXT, + }, + }, }; // bundle app update build_app( &cli_bin_path, &manifest_dir, + vec![("TAURI_PRIVATE_KEY", UPDATER_PRIVATE_KEY_NEXT)], &config, true, Default::default(), @@ -285,7 +307,14 @@ fn update_app() { config.package.version = "0.1.0"; // bundle initial app version - build_app(&cli_bin_path, &manifest_dir, &config, false, bundle_target); + build_app( + &cli_bin_path, + &manifest_dir, + vec![("TAURI_PRIVATE_KEY", UPDATER_PRIVATE_KEY)], + &config, + false, + bundle_target, + ); let mut binary_cmd = if cfg!(windows) { Command::new(root_dir.join("target/debug/app-updater.exe")) diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index 0ff20a1e0..946490191 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -2680,7 +2680,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", + "winreg 0.50.0", ] [[package]] @@ -3388,7 +3388,7 @@ dependencies = [ "uuid", "walkdir", "windows-sys 0.48.0", - "winreg", + "winreg 0.51.0", "zip", ] @@ -4329,6 +4329,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "xattr" version = "1.0.1" diff --git a/tooling/cli/src/build.rs b/tooling/cli/src/build.rs index cd51e802d..7cbfea4b8 100644 --- a/tooling/cli/src/build.rs +++ b/tooling/cli/src/build.rs @@ -320,9 +320,9 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> { // sign our path from environment variables let (signature_path, signature) = sign_file(&secret_key, path)?; if signature.keynum() != public_key.keynum() { - return Err(anyhow::anyhow!( - "The updater secret key from `TAURI_PRIVATE_KEY` does not match the public key defined in `tauri.conf.json > tauri > updater > pubkey`." - )); + log::warn!( + "The updater secret key from `TAURI_PRIVATE_KEY` does not match the public key defined in `tauri.conf.json > tauri > updater > pubkey`. If you are not rotating keys, this means your configuration is wrong and won't be accepted at runtime." + ); } signed_paths.push(signature_path); }