Skip to content

Commit

Permalink
feat(bundler): support custom sign command on Windows (#9865)
Browse files Browse the repository at this point in the history
* feat(bundler): support custom sign command on Windows

closes #7188
closes #9578

* fix double quotes

* fix build

* fix build

* clippy

* Update sign.rs

* clippy && replace `winreg` with `windows-registry`

* remove log [skip ci]

* Apply suggestions from code review

* tweak arg so path with spaces work on macOS

* create nsis toolset paths

---------

Co-authored-by: Lucas Nogueira <[email protected]>
  • Loading branch information
amrbashir and lucasfernog committed May 24, 2024
1 parent fc1543c commit d6d3efb
Show file tree
Hide file tree
Showing 15 changed files with 279 additions and 150 deletions.
5 changes: 5 additions & 0 deletions .changes/custom-sign-command.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri-bundler": "patch:feat"
---

On Windows, add option to specify a custom signing command to be used. This opens an endless possibilities, for example use `osslsigncode` on non-Windows or use hardware tokens and HSM or even using Azure Trusted Signing.
5 changes: 5 additions & 0 deletions .changes/utils-sign-command.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri-utils": "patch:feat"
---

Add `sign_command` in `WindowsConfig`
9 changes: 9 additions & 0 deletions core/tauri-config-schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"certificateThumbprint": null,
"digestAlgorithm": null,
"nsis": null,
"signCommand": null,
"timestampUrl": null,
"tsp": false,
"webviewFixedRuntimePath": null,
Expand Down Expand Up @@ -1619,6 +1620,7 @@
"certificateThumbprint": null,
"digestAlgorithm": null,
"nsis": null,
"signCommand": null,
"timestampUrl": null,
"tsp": false,
"webviewFixedRuntimePath": null,
Expand Down Expand Up @@ -1977,6 +1979,13 @@
"type": "null"
}
]
},
"signCommand": {
"description": "Specify a custom command to sign the binaries. This command needs to have a `%1` in it which is just a placeholder for the binary path, which we will detect and replace before calling the command.\n\nExample: ```text sign-cli --arg1 --arg2 %1 ```\n\nBy Default we use `signtool.exe` which can be found only on Windows so if you are on another platform and want to cross-compile and sign you will need to use another tool like `osslsigncode`.",
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
Expand Down
15 changes: 15 additions & 0 deletions core/tauri-utils/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,20 @@ pub struct WindowsConfig {
pub wix: Option<WixConfig>,
/// Configuration for the installer generated with NSIS.
pub nsis: Option<NsisConfig>,
/// Specify a custom command to sign the binaries.
/// This command needs to have a `%1` in it which is just a placeholder for the binary path,
/// which we will detect and replace before calling the command.
///
/// Example:
/// ```text
/// sign-cli --arg1 --arg2 %1
/// ```
///
/// By Default we use `signtool.exe` which can be found only on Windows so
/// if you are on another platform and want to cross-compile and sign you will
/// need to use another tool like `osslsigncode`.
#[serde(alias = "sign-command")]
pub sign_command: Option<String>,
}

impl Default for WindowsConfig {
Expand All @@ -873,6 +887,7 @@ impl Default for WindowsConfig {
allow_downgrades: true,
wix: None,
nsis: None,
sign_command: None,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tooling/bundler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ dunce = "1"
[target."cfg(target_os = \"windows\")".dependencies]
uuid = { version = "1", features = [ "v4", "v5" ] }
bitness = "0.4"
winreg = "0.52"
windows-registry = "0.1.1"
glob = "0.3"

[target."cfg(target_os = \"windows\")".dependencies.windows-sys]
Expand Down
19 changes: 13 additions & 6 deletions tooling/bundler/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ pub fn bundle_project(settings: Settings) -> crate::Result<Vec<Bundle>> {
log::warn!("Cross-platform compilation is experimental and does not support all features. Please use a matching host system for full compatibility.");
}

#[cfg(target_os = "windows")]
{
if settings.can_sign() {
// Sign windows binaries before the bundling step in case neither wix and nsis bundles are enabled
for bin in settings.binaries() {
let bin_path = settings.binary_path(bin);
Expand All @@ -75,16 +74,24 @@ pub fn bundle_project(settings: Settings) -> crate::Result<Vec<Bundle>> {
for bin in settings.external_binaries() {
let path = bin?;
let skip = std::env::var("TAURI_SKIP_SIDECAR_SIGNATURE_CHECK").map_or(false, |v| v == "true");
if skip {
continue;
}

if !skip && windows::sign::verify(&path)? {
#[cfg(windows)]
if windows::sign::verify(&path)? {
log::info!(
"sidecar at \"{}\" already signed. Skipping...",
path.display()
)
} else {
windows::sign::try_sign(&path, &settings)?;
);
continue;
}

windows::sign::try_sign(&path, &settings)?;
}
} else {
#[cfg(not(target_os = "windows"))]
log::warn!("Signing, by default, is only supported on Windows hosts, but you can specify a custom signing command in `bundler > windows > sign_command`, for now, skipping signing the installer...");
}

for package_type in &package_types {
Expand Down
15 changes: 15 additions & 0 deletions tooling/bundler/src/bundle/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,20 @@ pub struct WindowsSettings {
///
/// /// The default value of this flag is `true`.
pub allow_downgrades: bool,

/// Specify a custom command to sign the binaries.
/// This command needs to have a `%1` in it which is just a placeholder for the binary path,
/// which we will detect and replace before calling the command.
///
/// Example:
/// ```text
/// sign-cli --arg1 --arg2 %1
/// ```
///
/// By Default we use `signtool.exe` which can be found only on Windows so
/// if you are on another platform and want to cross-compile and sign you will
/// need to use another tool like `osslsigncode`.
pub sign_command: Option<String>,
}

impl Default for WindowsSettings {
Expand All @@ -462,6 +476,7 @@ impl Default for WindowsSettings {
webview_install_mode: Default::default(),
webview_fixed_runtime_path: None,
allow_downgrades: true,
sign_command: None,
}
}
}
Expand Down
1 change: 0 additions & 1 deletion tooling/bundler/src/bundle/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#[cfg(target_os = "windows")]
pub mod msi;
pub mod nsis;
#[cfg(target_os = "windows")]
pub mod sign;

mod util;
Expand Down
6 changes: 5 additions & 1 deletion tooling/bundler/src/bundle/windows/msi/wix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,11 @@ pub fn build_wix_app_installer(
&msi_output_path,
)?;
rename(&msi_output_path, &msi_path)?;
try_sign(&msi_path, settings)?;

if settings.can_sign() {
try_sign(&msi_path, settings)?;
}

output_paths.push(msi_path);
}

Expand Down
36 changes: 14 additions & 22 deletions tooling/bundler/src/bundle/windows/nsis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

#[cfg(target_os = "windows")]
use crate::bundle::windows::sign::{sign_command, try_sign};

use crate::{
bundle::{
common::CommandExt,
Expand Down Expand Up @@ -67,6 +67,7 @@ pub fn bundle_project(settings: &Settings, updater: bool) -> crate::Result<Vec<P
let nsis_toolset_path = tauri_tools_path.join("NSIS");

if !nsis_toolset_path.exists() {
create_dir_all(&nsis_toolset_path)?;
get_and_extract_nsis(&nsis_toolset_path, &tauri_tools_path)?;
} else if NSIS_REQUIRED_FILES
.iter()
Expand Down Expand Up @@ -114,12 +115,10 @@ fn get_and_extract_nsis(nsis_toolset_path: &Path, _tauri_tools_path: &Path) -> c
NSIS_TAURI_UTILS_SHA1,
HashAlgorithm::Sha1,
)?;
write(
nsis_plugins
.join("x86-unicode")
.join("nsis_tauri_utils.dll"),
data,
)?;

let target_folder = nsis_plugins.join("x86-unicode");
create_dir_all(&target_folder)?;
write(target_folder.join("nsis_tauri_utils.dll"), data)?;

Ok(())
}
Expand Down Expand Up @@ -163,9 +162,6 @@ fn build_nsis_app_installer(

log::info!("Target: {}", arch);

#[cfg(not(target_os = "windows"))]
log::info!("Code signing is currently only supported on Windows hosts, skipping...");

let output_path = settings.project_out_directory().join("nsis").join(arch);
if output_path.exists() {
remove_dir_all(&output_path)?;
Expand Down Expand Up @@ -197,16 +193,9 @@ fn build_nsis_app_installer(
);
data.insert("copyright", to_json(settings.copyright_string()));

// Code signing is currently only supported on Windows hosts
#[cfg(target_os = "windows")]
if settings.can_sign() {
data.insert(
"uninstaller_sign_cmd",
to_json(format!(
"{:?}",
sign_command("%1", &settings.sign_params())?.0
)),
);
let sign_cmd = format!("{:?}", sign_command("%1", &settings.sign_params())?);
data.insert("uninstaller_sign_cmd", to_json(sign_cmd));
}

let version = settings.version_string();
Expand Down Expand Up @@ -517,9 +506,12 @@ fn build_nsis_app_installer(

rename(nsis_output_path, &nsis_installer_path)?;

// Code signing is currently only supported on Windows hosts
#[cfg(target_os = "windows")]
try_sign(&nsis_installer_path, settings)?;
if settings.can_sign() {
try_sign(&nsis_installer_path, settings)?;
} else {
#[cfg(not(target_os = "windows"))]
log::warn!("Signing, by default, is only supported on Windows hosts, but you can specify a custom signing command in `bundler > windows > sign_command`, for now, skipping signing the installer...");
}

Ok(vec![nsis_installer_path])
}
Expand Down
Loading

0 comments on commit d6d3efb

Please sign in to comment.