Git Product home page Git Product logo

xcnotary's Introduction

xcnotary is no longer needed!

Use xcrun notarytool --wait as described in Apple's docs: Customizing the notarization workflow

With a concise example given here: #22 (comment)


logo

the missing macOS app notarization helper, built with Rust

About

Notarizing a macOS app involves a series of manual steps, including zipping a bundle, uploading it to to Apple, and polling the notarization service.

xcnotary automates these steps for you. It:

  • Attempts to fail fast if necessary, performing several checks on your target before uploading it to Apple.
  • Zips the input if it is an .app bundle.
  • Submits the input to the notarization service, and polls until completion. This step typically takes a few minutes.
  • In case of success, attaches the notarization ticket to the target, enabling the app to pass Gatekeeper on first run even without an Internet connection.
  • In case of failure, fetches the error log from Apple and outputs it to stderr.
  • Return a zero/non-zero code for easy CI integration.

Notarization

Installation

Homebrew

# Install
brew install akeru-inc/tap/xcnotary

# Upgrade
brew update
brew upgrade akeru-inc/tap/xcnotary

Usage

To perform various code signing checks on the input without submitting:

xcnotary precheck <input path>

To perform code signing checks, submit to the notarization service, and block waiting for response:

xcnotary notarize <input path> \
  --developer-account <Apple Developer account> \
  --developer-password-keychain-item <name of keychain item, see below> \
  [--provider <provider short name>]
  [--no-precheck]

Supported inputs:

  • ✅ .app bundles
  • ✅ .dmg disk images
  • ✅ .pkg installer packages

Specifying the password keychain item

This tool does not handle your Apple Developer password. Instead, Xcode's helper altool reads an app-specific Apple Developer ID password directly from the keychain. See the documentation for xcrun altool --store-password-in-keychain-item to set up a suitable keychain item.

Specifying the developer team

The optional --provider argument should be specified if the developer account is associated with more than one team. This value can be obtained by running the following command and noting the "ProviderShortname" displayed.

xcrun altool --list-providers  -u "$DEVELOPER_ACCOUNT_USERNAME" -p "@keychain:$PASSWORD_KEYCHAIN_ITEM"

Required network access

  • Xcode's altool will connect to several Apple hosts as outlined in the documentation.

  • When notarization fails, xcnotary will connect to https://osxapps-ssl.itunes.apple.com/ on port 443 to retrieve the failure log.

Service response

Apple documentation advises: "Always check the log file, even if notarization succeeds, because it might contain warnings that you can fix prior to your next submission."

xcnotary will fetch and display the notarization service response upon completion.

Bundle pre-checks

xcnotary attempts to check the input for some common notarization issues before uploading it to Apple. While not foolproof, these checks may potentially save you minutes waiting for a response only to fail due to an incorrect code signing flag.

Bundle pre-check

When the input is an app bundle, the following checks will be performed:

  • ✅ Bundle being signed with a Developer ID certificate and not containing unsigned items.
  • ✅ Bundle being signed with a secure timestamp.
  • ✅ Bundle not having the get-task-allow entitlement.
  • ✅ Bundle having hardened runtime enabled.

When the input is a .dmg or a .pkg, only the Developer ID signing check is performed, i.e. the only check that can be performed at the moment without extracting the contents. In your workflow, you may want to run xcnotary precheck on your bundle target before packaging it.

In rare cases, it may be helpful to troubleshoot code signing issues directly using the notarization service response. To do so, specify --no-precheck when invoking xcnotary notarize.

Building for notarization

The following examples set various necessary build flags, such as code signing with a "secure timestamp."

Bundles

xcodebuild \
   -target <target> \
   -scheme <scheme> \
   -configuration Release \
   -derivedDataPath .xcodebuild \
   "CODE_SIGN_IDENTITY=Developer ID Application: <team name>" \
   "OTHER_CODE_SIGN_FLAGS=--timestamp --options=runtime" \
   CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO \
   CODE_SIGN_STYLE=Manual

CODE_SIGN_IDENTITY should match the corresponding Keychain certificate.

Note that --options=runtime will have the effect of opting in your binary to the hardened runtime environment. You most likely want to first manually enable the "Hardened Runtime" capability in Xcode's target settings > "Signing and Capabilities" and make sure your application functions as expected. There, you may also add any entitlements to relax the runtime restrictions.

Packages

pkgbuild \
   --component <path to bundle built according to above specs>
   --sign "Developer ID Installer: <team name>" \
   --timestamp \
   <output_pkg_name.pkg>

Disk images

Codesign after creating the DMG:

codesign -s "Developer ID Application: <team>" <dmg>

Additional Information

xcnotary's People

Contributors

davidvartan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xcnotary's Issues

Crash when notarizing app bundle without path prefix

With the current version notarizing .dmg images works flawlessly, however trying to notarize an app bundle fails with the following message:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/notarize/run.rs:116:22

The pre-checks all finish successfully, but it seems when the zip is created for upload the ditto step breaks.

EDIT: It seems that running xcnotary pointing to a file in the same directory without ./ as a prefix leads to this issue.

xcnotary notarize MY_APP.app fails, xcnotary notarize ./MY_APP.app works.

CFURLRequestSetHTTPCookieStorageAcceptPolicy_block_invoke

Today when I used xcnotary I got this error.

Notarize
Processing...

✔ Perform check: Developer ID signing
✔ Uploading to notarization service

Notarization status check failed:
2021-04-08 15:44:03.695 altool[89058:478472] CFURLRequestSetHTTPCookieStorageAcceptPolicy_block_invoke: no longer implemented and should not be called

I got an email from Apple saying the package was successfully notarized.
Is this something Apple should fix or is it part of xcnotary?

Add bottles for older versions of macOS

Travis CI (and other CI providers) support many different versions of macOS (see here). On non-Catalina systems, xcnotary is built from scratch. This, however, can take more than 7mins, which is a long time for CI builds. It'd be great if bottles for older versions of macOS could be provided.

Many thanks,
Fabio

"Error: Expected an application bundle ..." for valid app bundle

In a CI pipeline I observed that for a perfectly valid app bundle xcnotary always returned
Error: Expected an application bundle, disk image, or installer package at...

It worked fine If I ran xcnotary manually with the exact same app bundle on the same machine 😮

To find the root cause I looked into the xcnotary source and added the mdls call you use to check the input path to my build pipeline, e.g like this

xcodebuild -exportArchive ...
/usr/bin/mdls -name kMDItemContentTypeTree "my-appbundle.app"`
xcnotary notarize "my-appbundle.app" ...

I get kMDItemContentTypeTree = (null) as the mdls result and xcnotary fails. If I add a sleep 30 before the xcnotary call everything works fine.

I could not reproduce this on my development machine, mdls always returned correct results there. I suspect that on the build machine the spotlight index is not updated fast enough. On another machine where spotlight is completely disabled, xcnotary always returns
Error: my-appbundle.app: could not find my-appbundle.app
which is the error message mdls produces when there is no spotlight index

Maybe better not rely on a working spotlight index? 😉

The build system uses macOS 10.15.4, my test system where Spotlight was disabled used macOS 10.15.3.

wrong version number returned?

Taking a look at

Williams-MacBook-Pro-2:2020-11-30-11-11-59 wferrell$ brew install akeru-inc/tap/xcnotary
==> Installing xcnotary from akeru-inc/tap
==> Downloading https://github.com/akeru-inc/xcnotary/releases/download/v0.4.2/xcnotary-0.4.2.catalina.bottle.tar.gz
Already downloaded: /Users/wferrell/Library/Caches/Homebrew/downloads/dfed15aee218b91d34b55a09ca6804abe2a29fa657857d393ed36f208f15afab--xcnotary-0.4.2.catalina.bottle.tar.gz
==> Pouring xcnotary-0.4.2.catalina.bottle.tar.gz
Warning: This keg was marked linked already, continuing anyway
🍺  /usr/local/Cellar/xcnotary/0.4.2: 2 files, 5.5MB
Removing: /Users/wferrell/Library/Caches/Homebrew/xcnotary--0.4.2.catalina.bottle.tar.gz... (2.1MB)
Williams-MacBook-Pro-2:2020-11-30-11-11-59 wferrell$ xcnotary --version
xcnotary 0.4.0

I think I am going about the approach correctly to install 0.4.2 -- however as you can see the version returned is 0.4.0

I think that the issue is likely:

version = "0.4.0"

Unhelpful error when app-specific password is not used

Hello!

Thank you for building such a useful tool.

In June, we were using xcnotary 0.4.1 and we were creating DMGs easily and having them notarized. Then, we stopped building DMGs for a while (big new feature) -- so it wasn't until today that I tried to build a new dmg.

This is the command we are running (I pulled out our personal information):

xcnotary notarize nameofdmg.dmg -d [email protected] -k AC_PASSWORD --provider OURPROVIDERINFO

This is the error I get:

Processing...

✔ Perform check: Developer ID signing
⠚ Uploading to notarization service
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { inner: ErrorImpl { kind: Serde("missing field `notarization-upload`"), file_position: None } }', src/util/plist/mod.rs:11:5

I am running this locally on my laptop which is running 10.15.3 (19D76)

I then decided to upgrade to xcnotary 0.4.2 via a brew upgrade akeru-inc/tap/xcnotary

Same error as above.

Can you help me think through what I am doing wrong or let me know if this is a bug?

Thank you again!

Incorrect detection of get-task-allow

The entitlements file can contain an entry for get-task-allow with a false value. Example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.get-task-allow</key><false/>
  </dict>
</plist>

xcnotary reports incorrectly this entry as a problem.

Thanks

M1 Mac: framework not found Security

Trying to install xcnotary on my M1 Macbook via brew install akeru-inc/tap/xcnotary but I'm running into this linker error:

  = note: ld: framework not found Security
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

Not really sure what to do about that.

No arm64 build

The actual binary inside the arm64 archive is still x86_64

Support .pkg input

Currently, the input is restricted to app bundles. Need to also support .pkg.

Remove dependency from CFBundleName in plist

All .app bundles that I encounter no longer have it (including our apps an Apple itself)

It's a legacy key with max 15 characters which is not even used by the tool ("CFBundleIdentifier" is used I suppose)

What is worse: when the plist doesn't have CFBundleName - the tool crashes:

RUST_BACKTRACE=full xcnotary notarize "thetool.app" -d XXX -k YYY
Processing...

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { inner: ErrorImpl { kind: Serde("missing field `CFBundleName`"), file_position: None } }', src/util/plist/mod.rs:6:28
stack backtrace:
   0:        0x104bab354 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hd4b962ed89f71a03
   1:        0x104bcf0e0 - core::fmt::write::h94ae1e793baa7a00
   2:        0x104ba439b - std::io::Write::write_fmt::h5c716758fdc3057f
   3:        0x104bad575 - std::panicking::default_hook::{{closure}}::hc6119c7d16548caf
   4:        0x104bad2b7 - std::panicking::default_hook::heae8b62897b351dc
   5:        0x104badb15 - std::panicking::rust_panic_with_hook::hc36596b4257bea99
   6:        0x104bad6ab - std::panicking::begin_panic_handler::{{closure}}::h49e5ddc3f21ca2fb
   7:        0x104bab7c8 - std::sys_common::backtrace::__rust_end_short_backtrace::h9bd32c9ad3fad18f
   8:        0x104bad66a - _rust_begin_unwind
   9:        0x104bde84f - core::panicking::panic_fmt::hcdc9362d34d55302
  10:        0x104bde755 - core::option::expect_none_failed::hef0458611b13747b
  11:        0x1048badf3 - xcnotary::main::hf99224fe654abb34
  12:        0x1048bb0ca - std::sys_common::backtrace::__rust_begin_short_backtrace::h3796f84a44bcf507
  13:        0x1048bb12c - std::rt::lang_start::{{closure}}::h43d4e0f376c8876a
  14:        0x104badeb0 - std::rt::lang_start_internal::hd0c760d47f593c0a
  15:        0x1048bb089 - _main

Signed with Developer ID but Pre-notarization check failed

Hi, I'm signing the mac app with developer id certificate but failed in pre-check.

~ » xcnotary precheck  ~/Downloads/xxx.app
Processing...


Pre-notarization check failed:
Bundle is not signed with a Developer ID certificate or it includes unsigned binaries.

Suggested fix:
   Make sure CODE_SIGN_IDENTITY was specified during the build.

See also:
   https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/resolving_common_notarization_issues

I see the xcnotary is executing /usr/sbin/spctl -v --assess -t exec INPUT_PATH, and here's my debug information:

~ » /usr/sbin/spctl -v --assess -t exec /path/to/xxx.app
/path/to/xxx.app: rejected
source=Developer ID

~ » codesign -dvvv /path/to/xxx.app
Executable=/path/to/xxx.app/Contents/MacOS/XXX
Identifier=com.xxx.xxx
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=892 flags=0x10000(runtime) hashes=17+7 location=embedded
Hash type=sha256 size=32
CandidateCDHash sha256=3998752aaecd52de4602fcd53704979685cec41a
CandidateCDHashFull sha256=3998752aaecd52de4602fcd53704979685cec41a94815a7679f1c16582cffd24
Hash choices=sha256
CMSDigest=3998752aaecd52de4602fcd53704979685cec41a94815a7679f1c16582cffd24
CMSDigestType=2
CDHash=3998752aaecd52de4602fcd53704979685cec41a
Signature size=8968
Authority=Developer ID Application: XXX. (XXXXXXXXXX)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=May 18, 2021 at 8:14:13 PM
Info.plist entries=22
TeamIdentifier=XXXXXXXXXX
Runtime Version=11.3.0
Sealed Resources version=2 rules=13 files=11
Internal requirements count=1 size=208

~» csrutil status
System Integrity Protection status: disabled.

截屏2021-05-18 下午8 26 54

PS: My SIP is disabled, I'm not sure if it will influence the spctl command.

Use "stapler" from path, not /usr/bin/

I would like to suggest that "stapler" should be looked up from $PATH, not hard-coded to /usr/bin/stapler. The reason for this is simply because altool and stapler can be extracted from XCode for the purposes of building in a VPS, for example, where space is limited and installing a full mammoth of XCode is simply not an option. In these environments, I'm not sure, where /usr/bin/stapler comes from, but running it gives:

cloudxmac$ /usr/bin/stapler 
xcode-select: error: tool 'stapler' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

Whereas, I have a working copy of stapler in path... This is not a problem for altool because xcrun actually picks up altool from path.

Binaries are broken

All binaries for the latest release are

  • all the same no matter which macos version you download
  • not functional / broken

image
image

Support .dmg input

First of all, thanks for the tool - it's quick and easy to use and the code is concise to read, so one can rest easy that it does what is advertised (quite important when handling signing certs and such).

Would it be possible to implement support for DMG files? From what I could gather an app bundle needs be zipped, then uploaded and stapled. The flow is similar for DMGs, except that the bundling into a zip is not necessary:

xcrun altool --notarize-app --primary-bundle-id BUNDLE --username AC_USERNAME --asc-provider PROVIDER --file IMAGE.dmg
xcrun altool --notarization-history 0 --username AC_USERNAME --asc-provider PROVIDER
xcrun stapler staple -v IMAGE.dmg

I'm not aware of exact pre-check requirements however, but it would be great if DMG is also supported, as xcnotary seems like a very no-frills choice for notarization in CI workflows.

Notarization status polling should guard against Apple Gateway Timeouts (status 504)

It seems that in my testing sometimes Apple's notarization gateway tends to return a 504. It appears this happens when polling to get the status of a notarization request via altool.

When this happens xcnotary exits with a non-zero exit code. While this is correct, it might be nice to introduce a retry mechanism for scenarios where the response isn't actually a pass/fail of notarization, but some other error which may be transient like a 504.

I don't think it should retry indefinitely, but a retry or 3 might be helpful to ensure that these edge cases don't result in having to re-run xcnotary when the "failure" isn't actually a failure per-se.

Pre-check and notarization fail due to misinterpreted spctl failure

While trying to get an app bundle notarized today, I noticed that xcnotary aborts the process 100% of the time as the pre-check fails in all cases.

This seems to be due to spctl always exiting with a non-zero return code when checking a non-notarized bundle due to the following error:

source=Unnotarized Developer ID

This is an expected error however, as the bundle is supposed to be unnotarized by that point. xcnotarys error message is also confusing, as it suggests the bundle includes unsigned binaries or the bundle is not signed with a developer ID cert, but a assessment run via codesign -vvv --deep --strict BUNDLE.app showed all binaries had been correctly signed.

Can't specify provider for Apple ID account while notarizing

I fail to notarize with xcnotary since my developer account is attatched to mutiple develop teams.
in "xcrun altool", there is an option "-itc_provider" which could specify the provider.

Here is the error message from xcnotary.
1 package(s) were not uploaded because they had problems:
/var/folders/16/qpjbykss3fg1ld3_3j0st8480000gn/T/4E9DC4ED-AFDC-492C-97D5-2C702B2513D7/CloudUEM.pkg.itmsp - Error Messages:
Your Apple ID account is attached to other providers. You will need to specify which provider you intend to submit content to. Please contact us if you have questions or need help. (1627)

xcnotary notarize error

With the v4.1 version notarizing .app images works flawlessly, however trying to notarize an app bundle fails with the following message:

thread 'main' panicked at 'called Result::unwrap()on anErrvalue: Error { inner: ErrorImpl { kind: Serde("missing fieldCFBundleVersion"), file_position: None } }', src/util/plist/mod.rs:6:5 note: run with RUST_BACKTRACE=1environment variable to display a backtrace

But I precheck success
xcnotary precheck ./xxx.app
Processing...

✔ Perform check: Developer ID signing
✔ Perform check: Hardened runtime
✔ Perform check: No get-task-allow entitlement
✔ Perform check: Secure timestamp

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.