beeware / briefcase

Tools to support converting a Python project into a standalone native application.
https://briefcase.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
2.47k stars 350 forks source link

Add a --skip-signing option when building macos / ios apps #1844

Open michelcrypt4d4mus opened 1 month ago

michelcrypt4d4mus commented 1 month ago

What is the problem or limitation you are having?

I'm looking to embed the .app produced by briefcase build in another .app bundle. As such I would like the flexibility to postpone the signing of the build products to later, when I actually do the embedding.

Describe the solution you'd like

briefcase build --skip-signing would do everything but sign the code.

Describe alternatives you've considered

I can remove the signing information with codesign --remove-signature and then re-sign later when assembling the final .app bundle.

Additional context

I've already implemented this for my local use with a pyproject.toml setting:

skip_signing = true

but i think it's probably better as a CLI option.

freakboy3742 commented 1 month ago

This is definitely a niche use case (and one that is, AFAICT, specific to macOS), but I guess there's no reason we shouldn't support it; although "sign then remove signature" would be a viable workflow, that means doing some redundant work.

Ironically, Briefcase had a --no-sign option, but it was removed about 12 months ago because some form of signing is mandatory on all apps (see #865/#1214). If we're going to re-introduce this feature, that would be the preferred spelling of the option.

If we are going to re-introduce this option, we need to careful about the design of interactions between --adhoc-sign and --no-sign, and the interpretation of --adhoc-sign and --no-sign on non macOS platforms.

My immediate suggestion is that --no-sign would be added to the mutually exclusive signing option group (as a store_false action). "No sign" would not come up as an option when selecting a signing identity; you'd need to explicitly opt into no signing as a command line option. Also, if --no-sign is specified on macOS, the user should get a warning that the app won't be executable at all without additional signing, in the same way that the --adhoc-sign option outputs a warning that the resulting app won't be executable elsewhere. On Windows (which is the only other platform that currently supports signing), --adhoc-sign and --no-sign would be equivalent as "don't sign, and don't display a warning" options.

Looking at related tickets:

michelcrypt4d4mus commented 1 month ago

There will be an interaction with the macOS signing changes that will be introduced in by https://github.com/beeware/briefcase/pull/1781.

I actually made my local changes against this branch and it was pretty easy to do.

The use case for this feature (embedded sub-apps) semi-implies another feature request here: supporting embedded sub-apps in Briefcase.

If it's of interest I had success building the bundle with briefcase build macos Xcode and then taking the resulting .app bundle and placing it in the Contents/Library/LoginItems of the main app bundle.

freakboy3742 commented 1 month ago

The use case for this feature (embedded sub-apps) semi-implies another feature request here: supporting embedded sub-apps in Briefcase.

If it's of interest I had success building the bundle with briefcase build macos Xcode and then taking the resulting .app bundle and placing it in the Contents/Library/LoginItems of the main app bundle.

Oh sure - I'm just highlighting that this approach requires an copy from an obscure path deep in the build folder; but with 2 relatively small modifications, this complexity copy path can be eliminated and turned into a first-class feature of Briefcase.

michelcrypt4d4mus commented 3 weeks ago

FWIW I ended up writing a script to:

  1. Embed the app bundle generated by briefcase in the Contents/Library/LoginItems of my "real app"
  2. Strip all the codesigning (and thus entitlements) done by briefcase with codesign --remove-signature
  3. Re-sign the now embedded briefcase app bundle files with:
    1. A bundle ID that is an extension of the app i'm embedding into. For example if the outer app is com.illmatic.app, the embedded briefcase app is signed with something like com.illmatic.app.killerverse. I'm not sure structuring bundle IDs like this is required but Apple's official documentation makes kind of a big deal about making sure bundle identifiers work like this for embedded apps.
    2. Likewise Apple's documentation asserts that embedded apps should not have their own entitlements and should instead have the entitlement com.apple.security.inherit though IIRC outside of a sandboxed build this doesn't seem to matter. Don't quote me on that but IIRC issues around inherited entitlements only came up when I went to sandbox my application bundle.
  4. Sign the rest of the contents of the larger app bundle (i.e. everything other than the contents of Contents/Library/LoginItems/IllmaticApp) with the actual entitlements I need and the bundle ID com.illmatic.app
  5. Sign the final .app/ bundle as com.illmatic.app.

Which ended up working significantly more easily and with less complaining from Apple's code signing tooling than I expected. It's possibile that step 2 could be skipped (which would save me some build time) because I end up codesign --forceing all of the files anyways with the new bundle ID / entitlements / etc but better safe than rejected by Apple for the time being.

If anyone else is looking to do something like this with their briefcase app (embed into larger app and resign appropriately) I'm happy to share the bash script that handles this.