Open anatawa12 opened 3 months ago
This PR will be converted into something generic before being merged https://github.com/tauri-apps/tauri/pull/8718
At least once MS lifts the stupid 3-years tax history requirement, this should have explicit support in tauri imo (so that it's a direct config option that doesn't require the use of the generic option)
As a workaround I created a CLI. It requires the azure cli, but downloads the required dlib for the Trusted Signing. Which gets called in the tauri.conf.json:
{
"build": {
"beforeBundleCommand": "trusted-signing-cli -e <url> -a <account name> -c <certificate profile name> path/to/exe/file1.exe",
},
cc @FabianLars: I could integrate this into Tauri, should I create a PR?
I don't think we'll add any specific solutions into tauri now with the generic solution (not sure). What i would love though is to collect different examples for the generic command (from the aforementioned #9865) in the docs.
I don't think we'll add any specific solutions into tauri now with the generic solution (not sure). What i would love though is to collect different examples for the generic command (from the aforementioned #9865) in the docs.
Thats okay, but signing with the Trusted Signing requires the Azure CLI, a specific dlib, a manifest.json, so its not that simple. Also I think this will be the recommended (or required?) way to sign apps for Windows (accroding to Microsoft) when it leave the private beta. So I think Tauri should have a built-in way to sign with Trusted Signing.
Backport is #9902
I don't think we'll add any specific solutions into tauri now with the generic solution (not sure). What i would love though is to collect different examples for the generic command (from the aforementioned https://github.com/tauri-apps/tauri/pull/9865) in the docs.
Could I nudge your view a little? As a newcomer to Tauri, it strikes me as odd to be able to supply “platform native” signing credentials for one platform but not another. I get that Azure Trusted Signing is new, and the established-three-year issue certainly sucks, but it’s clearly the direction of travel.
Also as a newcomer, I assumed without direct support I could still e.g. add the MS supplied Github action to my publish workflow as a post-build step. But with a little understanding of what’s happening, of course it needs to happen before the bundling steps in the build process. The reasons why are good, I’m writing this to say there isn’t an escape hatch here. If the custom sign-tool of #9865 allows the provider-specific cloud based flows now pretty much required by EV certificate signing, that’s great, but as @Levminer notes is not adequate for Azure Trusted Signing.
FWIW, here is the implementation I arrived for Azure Trusted Signing in Tauri on a GitHub actions workflow.
I add a prior step to the Tauri action that installs @Levminer’s CLI tool, and assembles and inserts the beforeBundleCommand
entry to invoke it into tauri.conf.json
. You’ll need to know the exact path of the file(s) you want to sign. You then supply the remaining Azure credentials alongside the Apple ones in the Tauri action.
- name: install dependencies (windows)
if: matrix.platform == 'windows-latest'
# The approach here uses the cli tool workaround from the GH issue linked below, with some tauri.conf.json manipulation to add the sign command only for windows and pre-populated with secrets
# https://github.com/tauri-apps/tauri/issues/9578
# Note Github hosted runners appear to have `az` pre-installed, which is a requirement of trusted-signing-cli
shell: bash
env:
BEFORE_BUNDLE_COMMAND: trusted-signing-cli -e "${{ secrets.AZURE_ENDPOINT }}" -a "${{ secrets.AZURE_CODE_SIGNING_NAME }}" -c "${{ secrets.AZURE_CERT_PROFILE_NAME }}" "${{ github.workspace }}/src-tauri/target/release/deps/<your app>.exe"
run: |
cd "$GITHUB_WORKSPACE"
cat './src-tauri/tauri.conf.json' | jq '.build += {
"beforeBundleCommand": env.BEFORE_BUNDLE_COMMAND
}' > './src-tauri/temp.json' && mv ‘./src-tauri/temp.json' './src-tauri/tauri.conf.json'
cargo install trusted-signing-cli
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APPLE_CERTIFICATE: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_TEAM_ID }}
AZURE_TENANT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_SECRET }}
[...]
Now, have I actually got a signed build? No, but the problem seems to be with the credentials I’ve been supplied with, as the Azure Trusted Signing action fails in the same way.
At least once MS lifts the stupid 3-years tax history requirement, this should have explicit support in tauri imo (so that it's a direct config option that doesn't require the use of the generic option)
Looks like there’s movement here, this is from a week ago (June 2024): "we are on the process of rolling out this feature for individual maintainers and or young corporations, our expectation is that it should be publicly available in the next upcoming weeks.” – https://github.com/Azure/trusted-signing-action/issues/10#issuecomment-2165678856
Looks like there’s movement here, this is from a week ago (June 2024): "we are on the process of rolling out this feature for individual maintainers and or young corporations, our expectation is that it should be publicly available in the next upcoming weeks.” – Azure/trusted-signing-action#10 (comment)
In light of this, can we re-open this ticket to collect all relevant discussions in one issue rather than across multiple new ones, please? @FabianLars @lucasfernog
Edit: for context, I'm in a similar position as OP in that I would like to have a simple way to use the (official) MS / Azure code sign pipeline with Tauri, one that doesn't need extra steps or external tooling.
FWIW, here is the implementation I arrived for Azure Trusted Signing in Tauri on a GitHub actions workflow.
I add a prior step to the Tauri action that installs @Levminer’s CLI tool, and assembles and inserts the
beforeBundleCommand
entry to invoke it intotauri.conf.json
. You’ll need to know the exact path of the file(s) you want to sign. You then supply the remaining Azure credentials alongside the Apple ones in the Tauri action.- name: install dependencies (windows) if: matrix.platform == 'windows-latest' # The approach here uses the cli tool workaround from the GH issue linked below, with some tauri.conf.json manipulation to add the sign command only for windows and pre-populated with secrets # https://github.com/tauri-apps/tauri/issues/9578 # Note Github hosted runners appear to have `az` pre-installed, which is a requirement of trusted-signing-cli shell: bash env: BEFORE_BUNDLE_COMMAND: trusted-signing-cli -e "${{ secrets.AZURE_ENDPOINT }}" -a "${{ secrets.AZURE_CODE_SIGNING_NAME }}" -c "${{ secrets.AZURE_CERT_PROFILE_NAME }}" "${{ github.workspace }}/src-tauri/target/release/deps/<your app>.exe" run: | cd "$GITHUB_WORKSPACE" cat './src-tauri/tauri.conf.json' | jq '.build += { "beforeBundleCommand": env.BEFORE_BUNDLE_COMMAND }' > './src-tauri/temp.json' && mv ‘./src-tauri/temp.json' './src-tauri/tauri.conf.json' cargo install trusted-signing-cli - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} APPLE_CERTIFICATE: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE_PASSWORD }} APPLE_SIGNING_IDENTITY: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_SIGNING_IDENTITY }} APPLE_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_ID }} APPLE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_TEAM_ID }} AZURE_TENANT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_TENANT_ID }} AZURE_CLIENT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_SECRET }} [...]
Now, have I actually got a signed build? No, but the problem seems to be with the credentials I’ve been supplied with, as the Azure Trusted Signing action fails in the same way.
Did you set up the permissions? (https://learn.microsoft.com/en-us/azure/trusted-signing/tutorial-assign-roles) If you can't sign with the official action this should be the problem.
Did you set up the permissions? (https://learn.microsoft.com/en-us/azure/trusted-signing/tutorial-assign-roles) If you can't sign with the official action this should be the problem.
For the work I’ve got I’m being supplied with them rather than doing it myself. But I’ve read every damn explainer and screenshared with the project owner while they go through it... and yeah, we’ve dotted all the i
s and crossed all the t
s as far as we can see.
@tobyspark In case you haven't seen it, this guide has been extremely helpful with getting the cert up and running: https://melatonin.dev/blog/code-signing-on-windows-with-azure-trusted-signing/ (I'm currently still in the validation step unfortunately)
With good credentials, what I posted above works. But – that’s only signing the app executable, and it is now clear to me that the installer needs to be signed. Does anybody have a working solution for that? e.g.
afterBundleCommand
equivalent to beforeBundleCommand
I could use to invoke the signing within the Tauri build action.wixproj
whatever that is. Empirically, adding the SignMSI
part as a Wix fragment in the Tauri conf doesn’t work. I’m assuming this is trivial to someone who is used to Windows and/or Tauri itself.Failing the above, I started to just brute-force it with a subsequent Github Action step, but even that is troublesome as the installer filename includes the dynamic version number.
Edit to add – I also tried the back-port of #9865 but it is not part of a v1.x release yet, and I couldn’t figure out the correct invocation of npm install
to get the v1 branch. https://gitpkg.now.sh/tauri-apps/tauri/tooling/cli/node?1.x
appears to work, correctly installs as @tauri-apps/cli
but then on use fails on a platform specific version.
Edit to add – I also tried the back-port of https://github.com/tauri-apps/tauri/pull/9865 but it is not part of a v1.x release yet, and I couldn’t figure out the correct invocation of npm install to get the v1 branchEdit to add – I also tried the back-port of https://github.com/tauri-apps/tauri/pull/9865 but it is not part of a v1.x release yet, and I couldn’t figure out the correct invocation of npm install to get the v1 branch
You can't really do that, only the cargo based cli works from git (because the npm based cli is 2 npm packages and you only get the wrapper one from git). You can however just install the cli in CI with a new step that runs cargo install tauri-cli --git https://github.com/tauri-apps/tauri --branch 1.x
and then add tauriScript: cargo tauri
to the tauri-action step. (Works locally as well of course)
Here's my action: https://github.com/Levminer/authme/blob/dev/.github/workflows/release-artifacts.yml And here is a helper script I'm using: https://github.com/Levminer/authme/blob/dev/scripts/sign.js
But basically:
Here's my action: https://github.com/Levminer/authme/blob/dev/.github/workflows/release-artifacts.yml And here is a helper script I'm using: https://github.com/Levminer/authme/blob/dev/scripts/sign.js
But basically:
- Sign the app in the beforeBundleCommand
- I get the version from the package.json
- Using that version I sign the msi or nsis
I looked into that - thanks for sharing! However, it's not using the Tauri Github Action, rather it does all the steps manually, right? I would like to use the Github Action because it does all the individual steps, including building, bundling, update sig generation and uploading in one place... :thinking:
With good credentials, what I posted above works. But – that’s only signing the app executable, and it is now clear to me that the installer needs to be signed. Does anybody have a working solution for that?
I finally did get it working! However, it requires Tauri v2, as it uses the new config parameter from #9865.
Here's the relevant Github Action block, taken from @Levminer's approach:
- name: install dependencies (windows only)
if: matrix.platform == 'windows-latest'
shell: bash
env:
# replace Azure credentials before running
WINDOWS_SIGN_COMMAND: trusted-signing-cli -e https://weu.codesigning.azure.net/ -a [AZURE_CODE_SIGNING_NAME] -c [AZURE_CERT_PROFILE_NAME] %1
run: |
cd "$GITHUB_WORKSPACE"
cat './src-tauri/tauri.conf.json' | jq '.bundle .windows += {"signCommand": env.WINDOWS_SIGN_COMMAND}' > './src-tauri/temp.json' && mv './src-tauri/temp.json' './src-tauri/tauri.conf.json'
cargo install trusted-signing-cli
I hard-coded the non-secret AZURE credentials there, but you can also use env vars if you want. The signCommand
signs the built executable before bundling and the bundled installers afterwards. Since its run directly from within the Tauri CLI, you can then use the normal Tauri Github Action to take care of the Updater signing and uploading:
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
AZURE_TENANT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_SECRET }}
with:
updaterJsonPreferNsis: true
tagName: v__VERSION__ # the action automatically replaces \_\_VERSION\_\_ with the app version.
releaseName: 'v__VERSION__ ${{ env.RELEASE_TITLE }}'
releaseBody: "${{ env.RELEASE_NOTES }}"
releaseDraft: true
prerelease: false
args: ${{ matrix.args }}
With this workflow I was able to get signed installers and also the installed app itself will run without any warning messages.
Edit: updated the config to remove the need for beforeBundleCommand
, as pointed out by @FabianLars below.
If you use the signCommand config you can remove beforeBundleCommand. Tauri will use the signCommand for everything that needs to be signed, including the inner executable.
If you use the signCommand config you can remove beforeBundleCommand. Tauri will use the signCommand for everything that needs to be signed, including the inner executable.
Oh nice, I didn't know that! I'll adjust the above code then.
One caveat with all the approaches above is that they will expose your Azure secrets to rogue code in any build.rs script you or your dependencies happen to drag via crates.io. I believe that tauri2 supports doing the bundling separately from the build, which would increase security.
Thanks all. In hindsight, why did I spent time trying to wrangle the back-port, when the upgrade to Tauri v2 proved quick and painless =]
One caveat with all the approaches above is that they will expose your Azure secrets to rogue code in any build.rs script you or your dependencies happen to drag via crates.io. I believe that tauri2 supports doing the bundling separately from the build, which would increase security.
Good point! Do you happen to know how one could get an auxiliary build tool integrated into the Tauri build chain the easiest? Just run cargo add trusted-signing-cli
in /src-tauri
and commit the updated files?
I post here, seen with FabianLars already, when building tauri via: tauri build -- --target x86_64-pc-windows-msvc (npm), signing via signCommand fails because it tries to sign the .exe located in: /target/release/.. instead of /target/x86_64-pc-windows../, so this fails. But it works well directly with "tauri build" (without the --target), for those who wish to compile for several architectures, to get around this, you must change the compilation chain via: rustup default stable-i686-pc-windows- msvc (for x86 for example) and be able to use tauri build and the signCommand which will work. I hope for a fix from Tauri. For those who have this problem.
Describe the problem
Many certificate authority sells certificates with high price. Recently Microsoft released Azure Trusted Signing for code signing and it's relatively cheap.
However, since signing tauri apps are completely integrated inside tauri cli and tauri cli doesn't have option to customize
/dlib
,/dmdf
parameters for signtool, it looks we cannot use Azure Trusted Signing.Describe the solution you'd like
Add some option to sign with Azure Trusted Signing
Alternatives considered
I think it might also be good to have some option to customize command-line options for signtool or use complately custom command for code signing.
Additional context
https://techcommunity.microsoft.com/t5/security-compliance-and-identity/trusted-signing-is-in-public-preview/ba-p/4103457 https://learn.microsoft.com/en-us/azure/trusted-signing/how-to-signing-integrations