tauri-apps / tauri

Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
https://tauri.app
Apache License 2.0
85.36k stars 2.58k forks source link

[bug] Windows EV certificate custom signing command not picking up %1 properly #11754

Open Bykow opened 1 day ago

Bykow commented 1 day ago

Describe the bug

I'm trying to EV sign a Windows build. All of this runs on a self hosted windows 11 github runner. My EV certificate provider is SSL.com and they provide a tool called CodeSignTool. It can be found here. You'll notice there is a Windows and a Linux/Mac version. I'm using the linux version, since I'm using Gitbash within Windows.

My tauri.conf.json windows section looks like this:

    "windows": {
      "nsis": {
        "template": "./bundle/windows/installer.nsi",
        "installMode": "perMachine",
        "installerIcon": "icons/nsis_icon.ico",
        "headerImage": "icons/nsis_header.bmp",
        "sidebarImage": "icons/nsis_sidebar.bmp"
      },
      "signCommand": {
        "cmd": "./CodeSignTool.sh sign",
        "args": [
          "-username ***",
          "-password ***",
          "-credential_id ***",
          "-totp_secret ***",
          "-input_file_path %1"
        ]
      }
    },

What ends up happening is:

Compiling build-info-build v0.0.39
Compiling APP_NAME v1.0.1-dev (C:\actions-runner\_work\PATHING\src-tauri)
Compiling tauri-plugin-single-instance v2.0.1
    Finished `release` profile [optimized] target(s) in 3m 58s
    Built [tauri_cli::build] application at: C:\actions-runner\_work\PATHING\src-tauri\target\release\APP_NAME.exe
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATHING\src-tauri\target\release\APP_NAME.exe
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATHING\src-tauri\target\release\APP_NAME.exe with a custom signing command
    Running [tauri_bundler::bundle::common] Command `./CodeSignTool.sh sign  -username *** -credential_id *** -totp_secret *** -input_file_path %1`
failed to bundle project: `The system cannot find the file specified. (os error 2)`
    Error [tauri_cli_node] failed to bundle project: `The system cannot find the file specified. (os error 2)`
Error: Process completed with exit code 1.

I've made sure the script is available from the path I'm working in. The issue is this %1 that does not get parsed and replaced with the path of the exe

Reproduction

No response

Expected behavior

The build should sign the binaries that require signing.

Full tauri info output

> APP_NAME@1.0.1-dev tauri
> tauri info
[✔] Environment
    - OS: Windows 10.0.22631 x86_64 (X64)
    ✔ WebView2: 130.0.2849.80
    ✔ MSVC: 
        - Visual Studio Build Tools 2022
        - Visual Studio Professional 2022
    ✔ rustc: 1.82.0 (f6e511eec 2024-10-15)
    ✔ cargo: 1.82.0 (8f40fc59f 2024-08-21)
    ✔ rustup: 1.27.1 (54dd3d00f 2024-04-24)
    ✔ Rust toolchain: stable-x86_64-pc-windows-msvc (default)
    - node: 20.12.2
    - npm: 10.5.0
[-] Packages
    - tauri 🦀: 2.1.1
    - tauri-build 🦀: 2.0.3
    - wry 🦀: 0.47.0
    - tao 🦀: 0.30.8
    - @tauri-apps/api : 2.1.1
    - @tauri-apps/cli : 2.1.0
[-] Plugins
    - tauri-plugin-single-instance 🦀: 2.0.1
    - @tauri-apps/plugin-single-instance : not installed!
    - tauri-plugin-notification 🦀: 2.0.1
    - @tauri-apps/plugin-notification : 2.0.0
    - tauri-plugin-os 🦀: 2.0.1
    - @tauri-apps/plugin-os : 2.0.0
    - tauri-plugin-shell 🦀: 2.0.2
    - @tauri-apps/plugin-shell : 2.0.1
    - tauri-plugin-dialog 🦀: 2.0.3
    - @tauri-apps/plugin-dialog : 2.0.1
    - tauri-plugin-fs 🦀: 2.0.3
    - @tauri-apps/plugin-fs : not installed!
    - tauri-plugin-window-state 🦀: 2.0.2
    - @tauri-apps/plugin-window-state : 2.0.0
    - tauri-plugin-process 🦀: 2.0.1
    - @tauri-apps/plugin-process : 2.0.0
    - tauri-plugin-updater 🦀: 2.0.2
    - @tauri-apps/plugin-updater : 2.0.0
[-] App
    - build-type: bundle
    - CSP: unset
    - frontendDist: ../dist
    - devUrl: http://localhost:1420/
    - framework: React
    - bundler: Vite

Stack trace

No response

Additional context

No response

FabianLars commented 1 day ago

the %1 replacement only works if the arg is exactly "%1" (maybe to not replace it in urls by accident maybe?). Does it still work if you cut that arg into 2? (pretty sure i saw exactly this usecase working before somewhere so i hope it does)

Bykow commented 1 day ago

I tried splitting the arguments, the error changed slightly. The %1 was parsed this time, but no success to sign. Could it be that gitbash has trouble finding the path with these backslashes \ ?

Compiling tauri-plugin-single-instance v2.0.1
    Finished `release` profile [optimized] target(s) in 4m 00s
    Built [tauri_cli::build] application at: C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe with a custom signing command
    Running [tauri_bundler::bundle::common] Command `./CodeSignTool.sh sign  -username *** -credential_id  -totp_secret *** -input_file_path C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe`
failed to bundle project: `The system cannot find the file specified. (os error 2)`
    Error [tauri_cli_node] failed to bundle project: `The system cannot find the file specified. (os error 2)`
Error: Process completed with exit code 1.

The \ should not be the issue since I managed this from gitbash directly:

user@whatever MINGW64 ~/tmp
$ cd C:\actions-runner

user@whatever MINGW64 /c/actions-runner
$
FabianLars commented 1 day ago

i think you have to change cmd to gitbash, not just the .sh file. The signCommand is not executed in the context of the terminal you run tauri build in.

Bykow commented 17 hours ago

So i'm tying to adapt, but I have trouble finding the CodeSignTool..

    "windows": {
      "nsis": {
        "template": "./bundle/windows/installer.nsi",
        "installMode": "perMachine",
        "installerIcon": "icons/nsis_icon.ico",
        "headerImage": "icons/nsis_header.bmp",
        "sidebarImage": "icons/nsis_sidebar.bmp"
      },
      "signCommand": {
        "cmd": "bash",
        "args": [
          "/c/actions-runner/_work/PATH/src-tauri/CodeSignTool.sh sign",
          "-username ***",
          "-password ***",
          "-credential_id ***",
          "-totp_secret ***",
          "-input_file_path",
          "%1"
        ]
      }
    },
    Compiling tauri-plugin-single-instance v2.0.1
    Finished `release` profile [optimized] target(s) in 3m 34s
    Built [tauri_cli::build] application at: C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe with a custom signing command
    Running [tauri_bundler::bundle::common] Command `bash  /c/actions-runner/_work/PATH/src-tauri/CodeSignTool.sh sign -username *** -credential_id 70580cf8-d1a6-4372-a46d-3decb0c583c6 -totp_secret *** -input_file_path C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe`
bash: /c/actions-runner/_work/PATH/src-tauri/CodeSignTool.sh sign: No such file or directory
failed to bundle project: `failed to run bash`
    Error [tauri_cli_node] failed to bundle project: `failed to run bash`
Error: Process completed with exit code 1.

This context aspect is escaping my graps for now.

Precision: CodeSignTool is downloaded and unzipped into the /src-tauri folder. And I am able to use it in a previous step to query for the credential_id. The step looks something like:

      - name: Download EV CodeSignTool from ssl.com
        working-directory: PATH/src-tauri
        shell: bash
        run: |
          curl -L0 https://www.ssl.com/download/codesigntool-for-linux-and-macos/ -o codesigntool.zip
          unzip codesigntool.zip

      - name: Get EV certificate credential id
        working-directory: PATH/src-tauri
        id: get_credential_ids
        shell: bash
        run: |
          echo "SSL_COM_CREDENTIAL_ID=$(./CodeSignTool.sh get_credential_ids -username=${{ secrets.SSL_COM_USERNAME }} -password=${{ secrets.SSL_COM_PASSWORD }} | sed -n '1!p' | sed 's/- //')" >> "$GITHUB_OUTPUT"
Bykow commented 13 hours ago

I guess I would like to ask the following, what is getting signed ? Because this is getting ridiculous and I could simply sign after the build ?

FabianLars commented 13 hours ago

The executable(s) inside the installer and then the installer itself.

btw, can you split "/c/actions-runner/_work/PATH/src-tauri/CodeSignTool.sh sign", into 2 args? bash will interpret this as a single argument as if sign would be part of the file name.

also out of my own interest, why are you using the bash script instead of the bat file?

Bykow commented 12 hours ago

I did split CodeSignTool.sh and sign, that did help ! But the status now is even weirder. It seems like it's signing, but we don't get Code signed successfully logged. I have no clue why. I checked both the installer and the application, none of them are signed indeed.

I added -override to prevent the CodeSignTool to ask for confirmation.

   Finished `release` profile [optimized] target(s) in 3m 33s
    Built [tauri_cli::build] application at: C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe with a custom signing command
    Running [tauri_bundler::bundle::common] Command `bash  -c /c/actions-runner/_work/PATH/src-tauri/CodeSignTool.sh sign -username *** -credential_id 70580cf8-d1a6-4372-a46d-3decb0c583c6 -totp_secret *** -input_file_path  C:\actions-runner\_work\PATH\src-tauri\target\release\APP_NAME.exe -override` 
    Info [tauri_bundler::bundle::windows::sign] ""
    Info [tauri_bundler::bundle::windows::nsis] Target: x64
    Debug [handlebars::render] Rendering value: Path(Relative(([Named("compression")], "compression")))
[... edited more Path stuff]
    Debug [handlebars::render] Rendering value: Path(Relative(([Named("estimated_size")], "estimated_size")))
    Debug [handlebars::render] Rendering helper: "each", params: [PathAndJson { relative_path: Some("languages"), value: Context(Array [String("English")], ["languages"]) }], hash: {}
    Debug [handlebars::render] Rendering value: Path(Relative(([], "this")))
    Debug [handlebars::render] Rendering helper: "each", params: [PathAndJson { relative_path: Some("language_files"), value: Context(Array [String("C:\\actions-runner\\_work\\PATH\\src-tauri\\target\\release\\nsis\\x64\\English.nsh")], ["language_files"]) }], hash: {}
    Debug [handlebars::render] Rendering value: Path(Relative(([], "this")))
    Debug [handlebars::render] Rendering helper: "each", params: [PathAndJson { relative_path: Some("resources_dirs"), value: Context(Array [], ["resources_dirs"]) }], hash: {}
    Debug [handlebars::render] Rendering helper: "each", params: [PathAndJson { relative_path: Some("resources"), value: Context(Object {}, ["resources"]) }], hash: {}
    Debug [handlebars::render] Rendering helper: "each", params: [PathAndJson { relative_path: Some("binaries"), value: Context(Object {}, ["binaries"]) }], hash: {}
    Debug [handlebars::render] Rendering helper: "each", params: [PathAndJson { relative_path: Some("resources"), value: Context(Object {}, ["resources"]) }], hash: {}
    Debug [handlebars::render] Rendering helper: "each", params: [PathAndJson { relative_path: Some("binaries"), value: Context(Object {}, ["binaries"]) }], hash: {}
    Debug [handlebars::render] Rendering helper: "each", params: [PathAndJson { relative_path: Some("resources_ancestors"), value: Context(Array [], ["resources_ancestors"]) }], hash: {}
    Running [tauri_bundler::bundle::windows::nsis] makensis.exe to produce C:\actions-runner\_work\PATH\src-tauri\target\release\bundle\nsis\APP_NAME_1.0.1-dev_x64-setup.exe
    Running [tauri_bundler::bundle::common] Command `C:\Users\user\AppData\Local\tauri\NSIS\makensis.exe  -INPUTCHARSET UTF8 -OUTPUTCHARSET UTF8 -V3 C:\actions-runner\_work\PATH\src-tauri\target\release\nsis\x64\installer.nsi`
MakeNSIS v3.08 - Copyright 1999-2021 Contributors
See the file COPYING for license details.
Credits can be found in the Users Manual.

Processing config: C:\Users\user\AppData\Local\tauri\NSIS\nsisconf.nsh
Processing script file: "C:\actions-runner\_work\PATH\src-tauri\target\release\nsis\x64\installer.nsi" (UTF8)

Processed 1 file, writing output (x86-unicode):

Output: "C:\actions-runner\_work\PATH\src-tauri\target\release\nsis\x64\nsis-output.exe"
Install: 6 pages (384 bytes), 3 sections (6216 bytes), 1330 instructions (37240 bytes), 356 strings (13572 bytes), 1 language table (414 bytes).
Uninstall: 2 pages (192 bytes), 1 section (2072 bytes), 383 instructions (10724 bytes), 177 strings (6648 bytes), 1 language table (274 bytes).
Datablock optimizer saved 154546 bytes (~0.2%).

Using lzma (compress whole) compression.

EXE header size:               66560 / 38912 bytes
Install code:                          (58290 bytes)
Install data:                          (64016622 bytes)
Uninstall code+data:                   (91171 bytes)
Compressed data:            19238574 / 64166083 bytes
CRC (0x5EA9EDD7):                  4 / 4 bytes

Total size:                 19305138 / 64204999 bytes (30.0%)
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATH\src-tauri\target\release\bundle\nsis\APP_NAME_1.0.1-dev_x64-setup.exe
    Signing [tauri_bundler::bundle::windows::sign] C:\actions-runner\_work\PATH\src-tauri\target\release\bundle\nsis\APP_NAME_1.0.1-dev_x64-setup.exe with a custom signing command
    Running [tauri_bundler::bundle::common] Command `bash  -c /c/actions-runner/_work/PATH/src-tauri/CodeSignTool.sh sign -username *** -credential_id 70580cf8-d1a6-4372-a46d-3decb0c583c6 -totp_secret *** -input_file_path  C:\actions-runner\_work\PATH\src-tauri\target\release\bundle/nsis/APP_NAME_1.0.1-dev_x64-setup.exe`
    Info [tauri_bundler::bundle::windows::sign] ""
    Finished [tauri_bundler::bundle] 1 bundle at:
        C:\actions-runner\_work\PATH\src-tauri\target\release\bundle\nsis\APP_NAME_1.0.1-dev_x64-setup.exe

As for the bat vs sh, I started with sh since I'm running with shell: bash I did not want to change my step. Plus both these scripts do the same thing:

user@hello MINGW64 ~/tmp
$ cat CodeSignTool.bat
@echo OFF

set code_sign_tool_path=%CODE_SIGN_TOOL_PATH%

if defined code_sign_tool_path (
%code_sign_tool_path%\jdk-11.0.2\bin\java -jar %code_sign_tool_path%\jar\code_sign_tool-1.3.2.jar %*
) else (
.\jdk-11.0.2\bin\java -jar .\jar\code_sign_tool-1.3.2.jar %*
)
user@hello MINGW64 ~/tmp
$ cat CodeSignTool.sh
if [[ -z "${CODE_SIGN_TOOL_PATH}" ]]; then
 java -jar ./jar/code_sign_tool-1.3.2.jar $@
else
 java -jar ${CODE_SIGN_TOOL_PATH}/jar/code_sign_tool-1.3.2.jar $@
fi