Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Un-sandboxed XPC Helper for Advanced Use-Cases #346

Open
clayreimann opened this issue Sep 16, 2020 · 31 comments
Open

Un-sandboxed XPC Helper for Advanced Use-Cases #346

clayreimann opened this issue Sep 16, 2020 · 31 comments
Labels
Feature Request New feature or request
Projects

Comments

@clayreimann
Copy link
Contributor

clayreimann commented Sep 16, 2020

Would it be possible to build an unsandboxed app during the GH release process?

The idea being that until and unless there is some what to allow socket connections there are a number of common-place use cases that are broken by the sandboxing process.

This is not to say that sandboxing is bad, but the decision of Sequel Ace to fully adopt sandboxing has broken a number of the 80% use cases, e.g. my company is among the growing number that require yubikey protected ssh keys, the common behavior of local mysql installations to use socket connections.

I'm not terribly familiar with the code changes required to sandbox an app so this might be an untenable proposition. However if the unsandboxing process is along the lines of removing an entitlement from the xcode project then I, among others would finally be able to use Sequel Ace.

@Jason-Morcos
Copy link
Member

#201 (comment)

I would rather not support both a sandboxed and non-sandboxed version of the app. I think it introduces a plethora of situations in the future where there is a bug in one version or the other and opens a big can of worms. You are welcome to [continue to] build your own non-sandboxed build, but I do not think we will build one or support one at this time.

I think the big issue is little differences that will emerge between the sandboxed and non-sandboxed versions of the app. As it is, we could really use more help on Sequel Ace and I'd be hesitant to add anything that would add further overhead to maintenance.

@clayreimann
Copy link
Contributor Author

That's a reasonable position, I guess I'll just build it locally with sandboxing disabled. Is this something that could be revisited if no solution for sockets is forthcoming from Apple, (it's been several months–any updates btw?)? I'm open to helping, but with sandboxing and without sockets Sequel Ace is DOA for me (and my coworkers which is why we're all still stuck using Sequel Pro)

@Jason-Morcos
Copy link
Member

Is this something that could be revisited if no solution for sockets is forthcoming from Apple

Certainly! What I'm really hoping we can figure out a way to do, although I haven't figured out a way to do it, would be to not un-sandbox Sequel Ace, but to provide a helper that users can download and install that allows Sequel Ace additional access. So the main app just stays sandboxed/App Store/normal updates, but we have a separate helper that users who use sockets/yubikeys/other download and then, if present, Ace would use to connect to these resources.
What's tough, is it appears NSTasks share the sandbox they are launched from, which is how we launch the tunnel assistant. So I'm not really sure how to do it. If someone has an idea/can figure out how to make that work, I'm 100% for that.

@clayreimann
Copy link
Contributor Author

Maybe an answer would be to create an XPC service? Apple Docs

Note: In rare cases, your app might have a small piece of functionality that cannot be sandboxed. Rather than abandon App Sandbox altogether, you might relegate the ineligible code to an XPC service that is not sandboxed. It is easier to secure a smaller piece of code than a larger one, and in this way, the bulk of your app enjoys the benefits of App Sandbox.

Do you know if this approach has been tried before? I'll do some more reading this weekend to see if we could use this.

@Jason-Morcos
Copy link
Member

Maybe an answer would be to create an XPC service? Apple Docs

Note: In rare cases, your app might have a small piece of functionality that cannot be sandboxed. Rather than abandon App Sandbox altogether, you might relegate the ineligible code to an XPC service that is not sandboxed. It is easier to secure a smaller piece of code than a larger one, and in this way, the bulk of your app enjoys the benefits of App Sandbox.

Do you know if this approach has been tried before? I'll do some more reading this weekend to see if we could use this.

I was looking into it, I haven't heard that anyone has tried it for Sequel Ace. The part I'm unclear about is if you can have XPC services accessible from your app outside of your app?

@clayreimann
Copy link
Contributor Author

I'll play around a bit this weekend. The docs make it seem like you can distribute an XPC as a way to break out of the sandbox if you need to.

@clayreimann
Copy link
Contributor Author

I put together a small demo (attached), that shows how XPC services can be used for reading files outside of the sandbox. I'm not entirely sure where to go from here, mostly because I don't have a great understanding of the SSH proxy architecture in SequelAce. I read the code but the lifecycle of all the bits is hard to follow. A couple questions occur:

  • Is it sufficient for the SSH command to have been run by an arbitrary process on the machine, or does it have to be run by the SequelAce process itself?
  • If the SSH command has to be executed by the process that talks to the DB, is it practicable or desirable to move all of the DB communications into an XPC that can be run outside the sandbox to still have access to sockets?
    (this would require an inter-process API but can also be a first step to making SequelAce DB agnostic–if that is a potential goal, e.g. a separate XPCs could host the MySql and SQLite code)

It's unclear from the archive documentation, but it may be the case that any XPC embedded in a MAS release needs to request a sandbox entitlement. If that is the case then the XPC approach can still work (there's a sandbox exception for talking to arbitrary XPC processes com.apple.security.temporary-exception.mach-lookup.global-name), but the helper XPC will have to be distributed as an ancillary download not in the MAS.

SandboxXPCTest.zip

@Jason-Morcos
Copy link
Member

WOW! Awesome, @clayreimann!

Currently the basic way it works (as I understand it, I inherited the setup) is an NSTask dispatches an ssh call and attaches the tunnel assistant as the SSH_ASKPASS target.
Once the tunnel is opened, the app pipes all traffic through the ns task and currently doesn't use the tunnel helper for actual communication.

It would be interesting if we could allow the app to continue to work as it does, but, if the XPC helper is present, utilize it. That way the app still works via App Store download (key to be approved) but can be enhanced by installing the XPC helper. As to how the XPC helper actually gains access to files, that's going to be the complex part.

A good first thing to try to figure out would be if an XPC helper could gain access to a socket and somehow communicate that back to the main app to allow socket connections. I'm not familiar enough with XPCs capabilities to know how to go about that.

@stale
Copy link

stale bot commented Oct 17, 2020

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale label Oct 17, 2020
@stale
Copy link

stale bot commented Oct 24, 2020

This issue has been auto-closed because there hasn't been any activity for at least 35 days. However, we really appreciate your contribution, so thank you for that! 🙏 Also, feel free to open a new issue if you still experience this problem 👍.

@stale stale bot closed this as completed Oct 24, 2020
@Jason-Morcos
Copy link
Member

@Sequel-Ace/all There was some good stuff here so flagging this so you all see it.
Notably, clearly some people have had success with the helper approach (https://community.codinn.com/t/core-helper/1103).

@jamesstout
Copy link
Contributor

A good first thing to try to figure out would be if an XPC helper could gain access to a socket and somehow communicate that back to the main app to allow socket connections.

Tried @clayreimann project with

@Published var path = "/private/tmp/mysql.sock" {

But got

guard let bytes = FileManager.default.contents(atPath: path) else {
            return reply("Failed to get contents of '\(path)'")
        }

Might be I'm not using the project correctly...`

@clayreimann
Copy link
Contributor Author

There you need to enable sandboxing for the main app and disable sandboxing for the XPC product. That simulates having 2 binaries, the MAS release and a manually installed XPC that lives outside the sandbox.

I'm currently figuring out how to talk over unix sockets using swift (because swift is more fun to write than Obj-C and I don't remember much Obj-C any more 😝). After that I need to figure out how to proxy the SSH_AUTH_SOCK traffic over the XPC transport and then back into the real (and external) SSH_AUTH_SOCK.

A little later this evening, I'll go ahead and publish my work so far over in https://github.com/Sequel-Ace/XPC-Playground. That'll be an easier way to collaborate on this.

@Jason-Morcos Jason-Morcos reopened this Oct 31, 2020
@stale stale bot removed the stale label Oct 31, 2020
@Jason-Morcos Jason-Morcos changed the title Unsandboxed release on GH in addition to sandboxed MAS release? Un-sandboxed XPC Helper for Advanced Use-Cases Oct 31, 2020
@clayreimann
Copy link
Contributor Author

More updates:

  • I found, forked, and cleaned up a unix socket library that I plan to use to do the proxying of SSH_AUTH_SOCK
  • I pushed my XPC playground project, and am working on integrating the aforementioned socket library to proxy the default ssh-agent's SSH_AUTH_SOCK

After that the things that still need figuring out

  • How to distribute a lone (and unsandboxed) XPC binary
  • How to surface the option to use this sandbox breaking XPC in the UI

@clayreimann clayreimann added this to To do in 2.x.x Nov 1, 2020
@clayreimann clayreimann moved this from To do to In progress in 2.x.x Nov 1, 2020
@Jason-Morcos
Copy link
Member

More updates:

  • I found, forked, and cleaned up a unix socket library that I plan to use to do the proxying of SSH_AUTH_SOCK

  • I pushed my XPC playground project, and am working on integrating the aforementioned socket library to proxy the default ssh-agent's SSH_AUTH_SOCK

After that the things that still need figuring out

  • How to distribute a lone (and unsandboxed) XPC binary

  • How to surface the option to use this sandbox breaking XPC in the UI

Awesome!!!

Maybe I can chime in on the distribution and surfacing questions.

Distribution the simplest way would be to include a download link for the helper on GitHub? Perhaps it could be it's own separate repository with versioning/releases. Ideally the helper is simple enough that it really doesn't need to be updated frequently/ever. However, it may be a good idea to implement some sort of auto-update in case we do update it in the future? More thought here is needed likely. Perhaps the main app that interacts with the helper can check if the helper is installed; if the helper is installed but is an older version, then we could probably show a prompt in the app to update it. I don't think Apple would have an issue with us telling the user that their helper is outdated?

How to surface this option is hard. Basically I think we can't say anything about it in the app or Apple will be mad. I would say surfacing it we can reference it all over the documentation and GitHub? One thing we may be able to do is have a link on the connection failed error message that takes a user to the documentation. On that page we could explain common connection issues AND explain that the helper is needed for specific use cases (including a link to download and such).

@clayreimann
Copy link
Contributor Author

Distribution the simplest way would be to include a download link for the helper on GitHub? Perhaps it could be it's own separate repository with versioning/releases.

This is what I was anticipating, what I meant is I'm not sure what sort of a thing we'll use. Is it just an installer that puts some magic .so file in a magic place. Do we build a full, unsandboxed, helper app that Sequel Ace talks to?

Basically I think we can't say anything about it in the app or Apple will be mad.

I'm not sure surfacing this directly to users will cause problems, based on the Core Sell FAQ you linked. This is what their app looks like:

image

So I think we're fine to have a similar checkbox down at the bottom of the connection page. This is, after all, a power user's app–we're not secreting a feature to get out of the sandbox to spy on users. This helper will enable legitimate use cases for (more) sophisticated users.

@Jason-Morcos
Copy link
Member

As to which to build, I would say whichever is easier and works well. Either way, really. I would prefer the helper tool/app is as small as possible, as minimal. But however it is, having an installer to put it in the right place is probably nice. TLDR if we can get away with a magic .so file, let's do that, unless it's a PITA.

Yup, honestly the best case may be to make it easy for power users and if apple rejects the app then tweak it. The one thing for sure is that the helper won't be able to be distributed through the App Store - users will have to go download it directly. Apple is very much not a fan of people breaking out of the sandbox, and most of our users probably won't ever need to install the helper. But for those who do need it, it definitely should be as easy as apple allows.

@Jason-Morcos Jason-Morcos removed this from In progress in 2.x.x Nov 11, 2020
@Jason-Morcos Jason-Morcos added this to To do in 3.x.x via automation Nov 11, 2020
@stale
Copy link

stale bot commented Nov 30, 2020

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale label Nov 30, 2020
@stale stale bot added the stale label Feb 15, 2021
@stale
Copy link

stale bot commented Feb 22, 2021

This issue has been auto-closed because there hasn't been any activity for at least 35 days. However, we really appreciate your contribution, so thank you for that! 🙏 Also, feel free to open a new issue if you still experience this problem 👍.

@stale stale bot closed this as completed Feb 22, 2021
3.x.x automation moved this from To do to Done Feb 22, 2021
@Jason-Morcos Jason-Morcos reopened this Feb 22, 2021
3.x.x automation moved this from Done to In progress Feb 22, 2021
@stale stale bot removed the stale label Feb 22, 2021
@stale
Copy link

stale bot commented Mar 22, 2021

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale label Mar 22, 2021
@stale
Copy link

stale bot commented Apr 20, 2021

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale label Apr 20, 2021
@stale
Copy link

stale bot commented Apr 27, 2021

This issue has been auto-closed because there hasn't been any activity for at least 35 days. However, we really appreciate your contribution, so thank you for that! 🙏 Also, feel free to open a new issue if you still experience this problem 👍.

@phoenix-down
Copy link

@clayreimann @Jason-Morcos any updates on this effort? Like several others ( #188, #94), I also ran into the YubiKey issue while attempting to migrate from Sequel Pro to Sequel Ace.

@Jason-Morcos
Copy link
Member

No updates on this effort from me - would love to see/help someone champion this into implementation but I don't have the bandwidth to do so personally

@jtsternberg
Copy link

I guess I'll just build it locally with sandboxing disabled

What about providing docs in the readme/wiki for people to be able to do this? I'd be open to considering it, depending on how involved it is.

@Jason-Morcos
Copy link
Member

I guess I'll just build it locally with sandboxing disabled

What about providing docs in the readme/wiki for people to be able to do this? I'd be open to considering it, depending on how involved it is.

Go for it! Docs are part of the repo (the /docs folder). Anyone is welcome to take a stab at creating a process and documenting it out and then proposing a PR to add the steps to the documentation site (sequel-ace.com) for others to follow. I don't have any concerns with that

@jtsternberg
Copy link

Whoops, I see how my comment could have been interpreted to mean I would contribute to the docs… I'm not actually opposed to that, but my question was asking if someone can provide me with docs for me to be able to build my own unsandboxed version.

@Jason-Morcos
Copy link
Member

Ahhh unfortunately I don't have the bandwidth to do that. Basically you'd need to turn off entitlements. I'm sure there's resources out there for going over how to do just that. Perhaps someone else in the community would be able to help with this. I bet you'd just have to disable Entitlements in Xcode and see what happens/breaks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request New feature or request
Projects
No open projects
3.x.x
In progress
Development

No branches or pull requests

5 participants