Sign Windows .exes in a post-build hook#2160
Conversation
mislav
left a comment
There was a problem hiding this comment.
This looks great! Thank you so much for setting this up; it likely saves us a lot of time 🙇
One thing that I find sub-optimal about our whole build process now is that we sign .exe on Linux and the .msi on Windows, i.e. that the signing logic is basically spread across different build strategies. I'm not familiar with Mono; do you know if it's possible to also build the .msi installer on Linux under Mono? Currently we use the Wix toolset on Windows to build the installer, but this is the last bit of the build that we actually need to spin up a Windows job for.
.github/workflows/releases.yml
Outdated
| jobs: | ||
| goreleaser: | ||
| runs-on: ubuntu-latest | ||
| runs-on: ubuntu-20.04 |
There was a problem hiding this comment.
Would it be fine to leave this as ubuntu-latest?
There was a problem hiding this comment.
ubuntu-20.04 accomplishes an upgrade from mono 4.6 to 6.8.
It's needed here to enable use of SHA256 signing in signcode (-a sha256) (see mono/mono#7517)
A couple of alternatives:
- Use a different signing algorithm (md5 or sha1)
- Upgrade
monomanually (see https://www.mono-project.com/download/stable/ for 18.04 instructions)
There doesn't appear to be (at least i couldn't find it) a utility for this shipped with Mono. |
d5d0e31 to
f98e7e4
Compare
|
I believe I fell short of verifying that the output files were actually signed when originally working through this - getting the action itself to complete seems to be where I kind of dropped off. That was in a heavily modified working branch to boot, running as little as the actual release machinery as I could get away with - that didn't include important things like actually saving the .exes anywhere outside of the build process. Will definitely stare at the thing to see if anything jumps out at me but any testing of this in an actual branch of the actual repo by tagging releases (looks like that's what we're doing) is hopefully going to be easier to debug than whatever I'd need to be doing. |
|
We seem to be looking happy for 386 but not amd64? (files in the v2.5.0-pre5 release) 386: amd64: Edit: perhaps I shouldn’t expect chktrust to work with a 64 bit executable at all, though. Its docs don’t claim that it can do this. The docs for signcode don’t claim to be able to sign 64 bit executables either. I suspect we’ve gotten this to work for 32 bit but not so much for 64. |
|
I can probably take a run at getting this moved over to osslsigncode to make it work for 64 bit. The fine folks at Mozilla have been on a similar journey: |
|
hello @mbpreble ! thanks for jumping back into this PR after we let it lie for way too long 😓 I didn't even think to check the 32bit binary, interesting discovery. Getting it over to osslsigncode sounds awesome; let me know how I can help (including doing runs and grabbing binaries to run on my windows machine as needed). |
|
oh, for thoroughness I should also mention that @mislav is working on getting us off of the |
|
@vilmibm - Think I've got this moved over to osslsigncode, have copied the changes from my testing branch into a new commit. When I run a release in my fork it seems to successfully sign both the 386 and amd64 binaries - I ran Would recommend trying this as you've been doing in the context of a branch within the actual repo, adding a tag, and kicking the tires on the executables. |
|
hm, it looks like the 386 signing went fine in my prerelease build, but the 64bit one failed: the logs are a bit garbled, but: |
|
I'm actually wondering if the curl is failing the second time, somehow. I'm going to do some debugging around that. |
|
hm, now I'm not sure. the hooks run non-deterministically, so I can't actually confirm that one of them is working. I did get a different error the second time I did the prerelease build -- the |
|
I'm really at a loss, here. the final |
|
@mislav agrees that it seems like hooks running in parallel are the culprit, here. I'm going to de-generalize this into a single hook. |
|
I factored out code that would clobber itself when run in parallel into a single global before hook. Now, the signing appears to succeed without issue. I'm out and about on my mac book but later today I'll grab the .exe files and make sure everything looks good. I'll also clean up the git history ^_^() |
|
You're doing a hero's work on this one. You might be surprised to know I had no previous experience with GoReleaser and had no idea the hooks would run in parallel, in the same workspace. 🙃 |
9336cec to
f30b7db
Compare
samcoe
left a comment
There was a problem hiding this comment.
This all seems good to me. Left one non-blocking question.
.goreleaser.yml
Outdated
| hooks: | ||
| - go mod tidy | ||
| - make manpages GH_VERSION={{.Version}} | ||
| - ./script/prepare-windows-cert.sh "{{.Env.GITHUB_CERT_PASSWORD}}" "{{.Env.DESKTOP_CERT_TOKEN}}" |
There was a problem hiding this comment.
Is there a reason not to do this in the windows build section in a pre hook?
There was a problem hiding this comment.
there is!
the build matrix for windows (386 and amd64) means that the hook would be run twice in parallel. the curl would run twice and there are a pile of race conditions that occur as a result.
mislav
left a comment
There was a problem hiding this comment.
This looks good! However, this set of changes prevents me from running goreleaser locally to test out releases.
⨯ release failed after 3.19s error=template: tmpl:1:40: executing "tmpl" at <.Env.GITHUB_CERT_PASSWORD>: map has no entry for key "GITHUB_CERT_PASSWORD"
Could we make it so that Windows signing is skipped if the information necessary to fetch the certificates isn't present in the environment?
|
@mislav I've:
|


Fixes #2111
I've tested that the hook at least completes successfully (following tagging of a release) in my fork. This has been done using my own self-signed certificate in .pfx format, pulled down from my working branch via the Github API.
Signing is accomplished by Mono's
signcodeutility which is only shipped with sha256 support inubuntu-20.04(hence a bump here, but this could probably still run onubuntu-latestif we manually get a newer version of Mono).Mechanics of signing are intended to be more or less the same as that used for the MSI, there is some overlap here between the existing Windows-targeted scripts for signing the MSI and the new hook intended to sign the .exes on Linux.