Hello Quinn,
Thanks for the quick reply. Yes, both questions are related. The reason we're downloading the dylibs from our servers and loading using dlopen() is that our vendor releases these dylibs very often for fixes. So, if that's the case, our users can get the fix almost immediately whenever new dylibs are available (without having to update the entire app).
However, I think we'll have to take the approach of embedding these dylibs in our app itself and increase the app's release frequency. The only drawback is that the end users will have to wait for a few extra days for the fix (because of the submission to app store/approval etc).
I can embed the dylibs in our project and say "embed and sign" so that it'll be signed with our certificate. The dylibs end up in /Applications/OUR_APP.app/Contents/Resources/DYNAMICLIB.dylib. Then, load them using "[NSBundle mainBundle] pathForResource:"
codesign -dvv of dylibs at /Applications/OUR_APP.app/Contents/Resources/DYNAMICLIB.dylib shows this :
Authority=Apple Mac OS Application Signing Authority=Apple Worldwide Developer Relations Certification Authority Authority=Apple Root CA
So, i believe there shouldn't be any conflict in our main app loading a different team's library.
However there's one final question. spctl shows this :
spctl -a -vv -t install /Applications/OUR_APP.app/Contents/Resources/DYNAMICLIB.dylib
DYNAMICLIB.dylib: rejected
origin=Apple Mac OS Application Signing
I believe this will still cause another warning from Gatekeeper? Do we have to notarise DYNAMICLIB.dylib even though it's embedded in the app?
Post
Replies
Boosts
Views
Activity
Hello Quinn,
Thanks for the quick reply. Yes, both questions are related. The reason we're downloading the dylibs from our servers and loading using dlopen() is that our vendor releases these dylibs very often for fixes. So, if that's the case, our users can get the fix almost immediately whenever new dylibs are available (without having to update the entire app).
However, I think we'll have to take the approach of embedding these dylibs in our app itself and increase the app's release frequency. The only drawback is that the end users will have to wait for a few extra days for the fix (because of the submission to app store/approval etc).
I can embed the dylibs in our project and say "embed and sign" so that it'll be signed with our certificate. The dylibs end up in /Applications/OUR_APP.app/Contents/Resources/DYNAMICLIB.dylib. Then, load them using "[NSBundle mainBundle] pathForResource:"
codesign -dvv of dylibs at /Applications/OUR_APP.app/Contents/Resources/DYNAMICLIB.dylib shows this :
Authority=Apple Mac OS Application Signing Authority=Apple Worldwide Developer Relations Certification Authority Authority=Apple Root CA
So, i believe there shouldn't be any conflict in our main app loading a different team's library.
However there's one final question. spctl shows this :
spctl -a -vv -t install /Applications/OUR_APP.app/Contents/Resources/DYNAMICLIB.dylib
DYNAMICLIB.dylib: rejected
origin=Apple Mac OS Application Signing
I believe this will still cause another warning from Gatekeeper? Do we have to notarise DYNAMICLIB.dylib even though it's embedded in the app?
Ok. Found a way. Adding com.apple.security.files.user-selected.executable in entitlements solves the issue.
It worked even without adding LSFileQuarantineEnabled in info.plist file.
https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW6
According to above link, Apple mentions that we can use the flag to not set the quarantine flags.
However, according to someone in https://developer.apple.com/forums/thread/115610, the app got rejected from App Store for using the flag.
Can anyone tell me if I can just go ahead and use the flag and submit to app store ?
Hello @Matt.
I finally got this working :) .
The solution was to delete all the VPN profiles from System Preferences -> Network and create new ones with the debug build app.
So, here's all the steps :
Our regular way of distribution is through macOS App Store
For building code, we have Mac Development and/or Apple Development profiles (not using Developer ID profiles here). We have added our development devices and test devices to the list of devices (max limit of 100)
On the test devices, If we download the code, build and run through Xcode, it'll run fine. But if we built on one machine, we cannot run it on another machine (even if we allow the app to run from "system preferences->Security & privacy -> Allow anyway"). The main GUI app works well. The extension starts but quits before it calls "startTunnelWithOptions".
After a bit of experimenting, we figured out that we had to delete the old VPN profiles on the test devices. So, build on one machine. Copy the app to another (test)machine-> Delete all VPN profiles on that test machine -> Open the app and create new VPN profiles and extension successfully loads and VPN runs! No developer ID certificate required. No notarisation required because this is not meant for general distribution but only to a list of 100 test devices, usually internally and those users can manually allow the app to run.
Hello Matt,
Thanks for the reply.
We do have "Mac Development" certificate. If we login to developer portal and select "Certificates, Identifiers & Profiles
", we generated "Mac Development" certificate there for development. Note : This is not "Developer ID Installer" or "Developer ID Application"
There's also "Mac App Distribution" certificates that are used for App Store distribution(not relevant here because App Store build works fine)
Then, in the same menu, we have "Devices" menu where we add the UUID of the test machines. We can add up to 100 devices. Then we create a "Profile" for the main app and one for NetworkExtension which are added to our Xcode. The UUIDs of these 100 devices go into the "embedded.provisionprofile" of the app.
If I open my app cd MyApp.app/Contents/embedded.provisionprofile, I can see all the UUIDs listed under ProvisionedDevices.
Does this not suffice to run our app on these 100 test machines?
If we have to notarise, why is there a facility to add 100 test devices?
Also, in any case, I did notarise and it still failed with "message": "The binary is not signed with a valid Developer ID certificate.",
codesign shows the following :
Signature size=4832
Authority=Apple Development: NAME (123ABCDE4F)
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Signed Time=28-Jan-2021 at 6:19:07 PM
Does this mean I have to sign it with a certificate that's exclusively of the type "Developer ID Application" ?
Is there no way to distribute with the Apple Development certificates we already have?
Note 2 : We're not trying to run the app on any machine, just one of the 100 test machines we have added to our profile.
I just realised - the option has to be given in entitlement file and won't take effect if we add it to plist file!So, I have to create an entitlement file and give that as an option in codesign command and that shoudl work. Will try this out and let you know.
Hi Quinn, thanks for the reply.1. I executed the codesign against the process and i don't see an explicit output for the entitlement com.apple.security.cs.disable-library-validation. However i can see that int company.app/Contents/Info.plist theentries count has increased and if i open the plsit file, i can see com.apple.security.cs.disable-library-validation as true.2. LC_VERSION_MIN_MACOSX of the vendor dylibs are 10.9 along with SDK version of 10.13. LC_VERSION_MIN_MACOSX of our app executable is 10.10 with SDK of 10.14 - so, all good here.3. Both the vendor dylib and our app have sha1 as well as sha256 - Hash choices=sha1,sha256I'm copy pasting the output of codesign run against the process :Executable=XYZ.app/Contents/MacOS/XYZIdentifier=XYZFormat=app bundle with Mach-O thin (x86_64)CodeDirectory v=20500 size=16841 flags=0x10000(runtime) hashes=519+3 location=embeddedVersionPlatform=1VersionMin=657920VersionSDK=658944Hash type=sha256 size=32CandidateCDHash sha1=f5f01417e803369a70d5b071fced1617486fb712CandidateCDHash sha256=f6cfb15a010687b5afed942507541c3aa0dc047cHash choices=sha1,sha256Page size=4096CDHash=f6cfb15a010687b5afed942507541c3aa0dc047cSignature size=9075Authority=Developer ID Application: XYZAuthority=Developer ID Certification AuthorityAuthority=Apple Root CATimestamp=31-May-2020 at 1:35:59 AMInfo.plist entries=26TeamIdentifier=XYZRuntime Version=10.14.0Sealed Resources version=2 rules=13 files=22Internal requirements count=1 size=192Our build process is summarised as :1. The plist file is named as company-Info.plist and the same name is given in "Build Settings". All options of "Capabilities" in Xcode's project are OFF, including Hardened Runtime2. I added <key>com.apple.security.cs.disable-library-validation</key> <true/> to the company-Info.plist file.3. Build using xcodebuild commandline.4. Sign the .app file using "sudo codesign -f --options runtime -s "CERTIFICATE" ./company.app --deep.5. productsign, notarise etc