Feat/macos notarize#24
Closed
gok03 wants to merge 2 commits into
Closed
Conversation
…er ID
Apple Gatekeeper currently blocks first-launch of the macOS binaries with
"Apple could not verify 'refuse' is free of malware…" because the
artifacts are unsigned. Fix by signing with the Developer ID Application
certificate and submitting to Apple's notary service.
Implementation:
- `.goreleaser.yaml` gains a `notarize.macos:` block, gated on
`{{ isEnvSet "MACOS_SIGN_P12" }}` so forks without the secrets get a
clean no-op rather than an error. Goreleaser's notarize step shells
out to rcodesign (bundled), so the work runs on a Linux runner — no
macOS runner needed.
- `.github/workflows/release.yaml` exports the 5 secrets goreleaser
reads at template time:
MACOS_SIGN_P12 — base64 of the .p12 cert
MACOS_SIGN_PASSWORD — password the .p12 was exported with
MACOS_NOTARY_KEY — base64 of the App Store Connect .p8 key
MACOS_NOTARY_KEY_ID — 10-char Key ID from App Store Connect
MACOS_NOTARY_ISSUER_ID — UUID Issuer ID from App Store Connect
After this lands, the next tag push produces darwin binaries that are
signed by your Developer ID and stapled with an Apple notarization
ticket. `brew install refusehq/tap/refuse` (and direct .tar.gz
downloads) launch without the Gatekeeper dialog.
goreleaser's built-in `notarize.macos` block fails on Apple Developer ID
certificates with:
failed to verify certificate chain: x509: unhandled critical extension
because Go's stdlib x509 verifier doesn't recognise Apple's critical
extension OIDs (e.g. 1.2.840.113635.100.6.1.13 for Developer ID
Application). Replace it with `rcodesign` (Rust) which handles them
correctly.
Pipeline shape:
1. release.yaml downloads + installs the rcodesign binary on the
ubuntu-latest runner before goreleaser runs.
2. .goreleaser.yaml drops the broken `notarize:` block. Instead,
`builds.hooks.post` invokes scripts/sign-macos.sh once per built
binary, which signs darwin binaries with rcodesign +
--code-signature-flags runtime. Non-darwin builds and missing
secret = silent no-op.
3. After goreleaser finishes (archives + checksums + cosign + sbom),
release.yaml runs scripts/notarize-macos.sh against dist/, which
re-zips each darwin binary, submits to Apple's notary API via the
App Store Connect key, and waits for approval.
We don't staple — stapling only works on bundles/.pkg/.dmg, and a plain
Mach-O CLI binary can't carry a ticket. Apple records notarization
server-side and Gatekeeper online-queries at first launch, which is
sufficient for a CLI.
Both scripts are env-gated: forks and snapshot builds without the
secrets pass through unchanged.
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Why
Closes #
How
Test plan
go test ./...passesgo vet ./...cleangolangci-lint runclean (if applicable)Checklist