erikberglund / SwiftPrivilegedHelper

Example application using a privileged helper tool with authentication in an unsandboxed application written in Swift
MIT License
180 stars 33 forks source link

Helper doesn't work after being notarized #33

Open mansidak opened 1 year ago

mansidak commented 1 year ago

This is what happened:

  1. I simulate the app on my mac
  2. It works as expected. The helper can help send all the commands.
  3. I notarize the product. It gets notarized
  4. The helper isn't working anymore. The command to install Helper still works but the runCommandLs isn't working it looks like.

On the other hand, when I export the app WITHOUT notarization, it works just fine. Any clue what could be going on?

mansidak commented 1 year ago

Another intel: I think it's because notarization requires hardened runtime. Does hardened runtime interfere with the helper?

chipjarred commented 1 year ago

Hardened runtime shouldn't affect the helper tool per se, but you may have to add a specific entitlement.

Sandboxing however will prevent it. Sandboxed apps (anything destined for the App Store) can't have privileged helpers except by special dispensation from Apple, which they're unlikely to grant. So distribution would have to be old school (meaning you have to arrange a hosting site, payment system, etc...).

You mentioned running in simulator, and in the previous issue, you mentioned UIKit. Is this an iOS app? macOS is the only OS in the Apple ecosystem that will run unsandboxed apps. I'm surprised if it ran in simulator.

mansidak commented 1 year ago

@chipjarred No, I never sandboxed it. Only hardened runtime since notarization requires it.

I should've mentioned it's AppKit, not UIKit. It's s Mac app of course and yes It runs in the simulator. This is what I'm noticed so far:

  1. If I notarize it, the program doesn't work as expected
  2. If I export an archive (by choosing directly distribute to customers options ) but don't notarize it, then it doesn't work either
  3. If I export a pure archive of the app, it works. But when I tested it on a friend's Mac, they had to go to System Preferences to manually allow the app to run since it wasn't notarized.

Any thoughts?

PS: At this point, I'm thinking what's the point of a privileged helper if it doesn't go through notarization? If you have a dev account, I would encourage you to try to package and get your app notarized to try to recreate the issue if you want to.

chipjarred commented 1 year ago

With that clarification, I'm thinking it's an entitlement issue. I'm not at a computer so can't explore the options myself right now, but as I recall you have to add and entitlement file, I think you add it to the helper tool, rather than the main app, but I'm going from memory right now so I'm not 100% sure. You'll have to google to find out exactly what to put in it.

When you say it runs in simulator I think you just mean that it runs in Xcode, which isn't the same thing. Xcode launches simulator for non-macOS apps to simulate the non-Mac device. For macOS apps, it just runs them natively, albeit in a way that allows attaching the debugger.

chipjarred commented 1 year ago

@mansidak Did you ever find an answer? I saw that you posted on StackOverflow as well, and unfortunately no one has answered or even commented. You say:

The command to install Helper still works but the runCommandLs isn't working

I suppose that you mean that SMJobBless returns without an error: Are you checking the outError parameter, or just the boolean returned value to know that? Have you confirmed via Finder (or command line) that the helper tool is installed in the notarized version. Remember to manually remove any currently installed helper before trying.

Assuming that you verified that the helper is installed, which based on your description I expect to be the case, the next question is whether the problem is in the main app calling out to the helper, or in the helper launching a sub-process. Debugging a helper is kind of pain, but in the helper's runCommandLs method, you can put some log(stdOut:) or log(stdErr:) before and after the call to runTask.

If after doing that you get no corresponding output in the main app, then the helper isn't being called, which would be some kind of XPC failure. In that case, it's probably an entitlement issue.

On the other hand, if you do get the log output from the helper in the main app, you'll at least know that the helper is being called, and the problem is that it's somehow failing to spawn the ls process. I don't know off the top of my head why that might happen, but at least you will have narrowed it down to something more specific to investigate.

chipjarred commented 1 year ago

FYI: I started a bounty on your SO question. I saw that you didn't have enough reputation there to do that, and I think nailing down the proper way to notarize an app with a privileged helper tool for distribution is worthy of more attention... I'm certainly interested in learning the answer. After trying the things I suggest, please update your question there with relevant info. Specifically say whether the helper is actually being installed using the notarized version, and if is, whether you can verify if the tool is being called or not. If it's not being installed include whatever error SMJobBless is returning in it's out parameter. If it is being installed, and the helper is being called, it would be helpful to include the code that calls the ls command, which would include the code for runTask. You might also mention that you are using this project as the starting point for the app, so those who might answer can look at the code. If someone finds an error in the project, we would all be interested in fixing that!

chipjarred commented 1 year ago

Also I noticed that someone edited your question to remove the swift and appkit tags - which is correct given the current state of the question, but if you end up including source code, you can legitimately add the swift tag back, and the question will probably get a wider audience - I know I usually filter on swift not on macos.

chipjarred commented 1 year ago

Also something that might make a difference, which I haven't noticed until now since I'm for now stuck on Big Sur, but I just found out that Apple has deprecated SMJobBless (in Monterey, I think), and instead provides a SMAppService class to manage helper tools, as well as daemons and log-in items. Looks like I need to acquire a new Mac so I can finally upgrade macOS, and Xcode in order to upgrade my fork for it. In any case, using SMAppService instead of SMJobBless may or may not address your problem.

madmalloc commented 7 months ago

Hi @chipjarred do you have a resolution to this issue? I'm quite interested as well, I'd also appreciate the link to the SO issue you were referring earlier