airsdk / Adobe-Runtime-Support

Report, track and discuss issues in Adobe AIR. Monitored by Adobe - and HARMAN - and maintained by the AIR community.
199 stars 11 forks source link

CodeSign, Notarize, Staple #1778

Open chazhenry opened 2 years ago

chazhenry commented 2 years ago

I know there are fragments of this in many posts, but it needs to be pulled together. Ideally, a shell script that prompts or has a header that collects the variables and then accomplishes the entire signing for Mac distribution. I've spent days beating my head on this. Stuck again, but close enough to know it's possible. I'll share my script when I break through.

For now, I'm stuck at getting the .app notarized and I believe its because the .app is not properly signed. I also get The signature of the binary is invalid.

What elements of the framework do I need sign? Currently, I sign the two internal pieces below and then the .app itself. The commented line was from a previous post, but my bundle does not have that (seems obsolete).

Is this all of the code in the bundle? My codesign all works, but it won't notarize.

 # paths and strings
appPath="/pathToMy.app"
framework="Contents/Frameworks/Adobe AIR.framework"
v1Res="Versions/1.0/Resources"

# Code-signing the pieces
#codesign --timestamp --deep -f -v -s "$certApp" "$appPath/$framework/$v1Res/Flash Player.plugin/Contents/MacOS/FlashPlayer-10.6"
codesign --timestamp --deep -f -v -s "$certApp" --options runtime  "$appPath/$framework/$v1Res/A2712Enabler"
codesign --timestamp --deep -f -v -s "$certApp" "$appPath/$framework"

From Apple, this is the most comprehensive instruction sheet It also says sign the pieces from the inside out. What order should we sign the framework pieces?

So many discrepancies.

There's been great progress on the SDK, but the final mile is full of potholes. I'm broke-down again after hitting this one. Thanks for your help.

ajwfrost commented 2 years ago

We've been trying to make this a little easier by providing the ability to sign the application bundle, which includes going through and signing all relevant components/frameworks within this. So e.g.

adt -sign  -storetype KeyChainStore -alias "Developer ID Application" -target bundle main.app signed.app

This copies the original application bundle (main.app) and then signs it in the new location (signed.app) so then you should be able to package this and notarize it. From memory, we may have 'deep' on there but I was under the impression it didn't actually do anything now. We also thought that including a provisioning profile was optional, we don't have that on any of the apps we distribute (afaik, I may have to check that now!)

We also only notarize a package e.g. when we create installers via pkgbuild, or the AIR runtime dmg file, as the Apple tools break these open to scan the contents anyway. When we were first putting together our scripts, the process was basically:

Plus of course, although in practice you'd only notarize the distributable, there's no reason you can't zip up and submit the .app folder for notarization to eliminate any packaging issues from this loop.

Hope that helps... I would actually hope that if you sign an app that was generated by the AIR SDK using that adt -sign utility, then the notarization would succeed: that's our aim, anyway, so if you find things that aren't working we should adjust it so that it does!

thanks

chazhenry commented 2 years ago

@ajwfrost I don't use or know adt. I've been working with all of the xcode command line utilities. I start with the .app produced by captive runtime bundle. Then, I'm using codesign, productsign, packagesbuild, productsign, xcrun, spctl.

According to this Apple post, you need to codesign each executable in the bundle and you need to know whether it is Bundled, or Standalone, a main executable or a library. These answers inform how you sign the code. He gives a great example. Do we know these answers (where all the code is) forthe bundle created?

Have you (or anyone else) successfully codesigned all the way through a standalone package that allows installation without relaxing security?

ajwfrost commented 2 years ago

If the bundle was put together as an AIR application then it should have used adt, so you should have this (in the AIR SDK) - it's a command-line tool under the "bin" folder of the SDK.

Within adt, it does the following if you use the -sign command:

find "MyApp.app" -name "*.framework" -exec codesign --entitlements app.entitlements -s 'Developer ID Application' -f -o runtime --strict --timestamp --deep -v {} \;
find "MyApp.app" -name "*.dylib" -exec codesign --entitlements app.entitlements -s 'Developer ID Application' -f -o runtime --strict --timestamp --deep -v {} \;
find "MyApp.app" -name "*.plugin" -exec codesign --entitlements app.entitlements -s 'Developer ID Application' -f -o runtime --strict --timestamp --deep -v {} \;
find "MyApp.app" -name "*.dylib" -exec codesign --entitlements app.entitlements -s 'Developer ID Application' -f -o runtime --strict --timestamp --deep -v {} \;
find "MyApp.app" -name "A2712Enabler" -exec codesign --entitlements app.entitlements -s 'Developer ID Application' -f -o runtime --strict --timestamp --deep -v {} \;
codesign --entitlements app.entitlements -s 'Developer ID Application' -f -o runtime --strict --timestamp --deep -v MyApp.app

where the entitlements are a combination of some standard ones (below) plus whatever you added in the app descriptor file.

allow-jit -> true
allow-dyld-environment-variables -> true
allow-unsigned-executable-memory -> true
disable-library-validation -> true

And yes we've used that to sign a bundle and then check the notarization works.. thanks

marchbold commented 2 years ago

Would be a good idea to get the current process together for the docs site.

chazhenry commented 2 years ago

I know that IntelliJ compiles with adt. I just mean that I don't know where it gets that scripting so I start my process with the .app that it builds. The signing list above helps. It also answers the A2712Enabler question because the other post said to remove it.

Not to be contrary, just noticing discrepancies between the above and what I've unearthed, as any nuance can shift the bytes to where Apple doesn't like them.

Good news: my app is passing notarization and staple. Bad news after installation (with mild warning) the installed app says:

You do not have permission to open the application.

I've verified that its coming from the codesign and before the notarization and staple. The codesigned app exhibits the 'no permission' behavior before it's notarized. Very close.

ajwfrost commented 2 years ago

To cover those:

Good for it to get notarized! but "you do not have permissions" is an interesting one... Are you running on a device with Apple Silicon / M1? If so, you could try setting it to use Rosetta in case that makes a difference. Alternatively, we did have an issue with file permission flags a while ago, can you try looking at each of the binary files with ls -la to check that they all have the x (executable bit) set? You can do find MyApp.app -type f -exec ls -la {} \; to list every file with its permissions... then chmod a+x filename to add the executable permission to the relevant ones...

thanks

chazhenry commented 2 years ago

@ajwfrost Running on a Mini Mac i7. I don't think its a linux file issue. I've run the signing script line by line and 'no permission' happens immediately after I code sign the app. The permission bits are unchanged before and after the codesign.

Here are my codesign commands.

echo "$yellow\nCodesign the pieces...$end"
codesign --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --timestamp -v "$appPath/$framework"
codesign --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --timestamp -v "$appPath/$framework/$v1Res/A2712Enabler"
codesign --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --timestamp -v "$appPath/$framework/$v1Res/WebKit.dylib"
codesign --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --timestamp -v "$appPath/$framework/$vCur/Adobe Air"

echo "$yellow\nCodesign the app...$end"
codesign --force --deep --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --strict --timestamp -v "$appPath/"

I've selectively run each and tried running the app after each. If I sign only the piece-parts inside I immediately get 'app requires a verson of Adobe Air which cannot be found'. Once I sign the app, it turns to 'no permission'. Did the find as suggested and the executables inside are all rwxr-xr-x.

ajwfrost commented 2 years ago

Okay thanks... sounds like it may be the entitlements then? Do you have these two set up?

And also if you do a "codesign -v -vvv" and/or "codesign -dvvv" on the framework folder, does it look okay?

If you're getting "requires a version of Air which cannot be found" it implies it can't open the AIR library/framework; which probably has the same root cause as the application failing to even start opening once you've signed it.

I'm also wondering whether it's objecting to you code-signing just the "Adobe Air" binary file rather than the framework as a whole, I think it might be better re-ordered perhaps so that the below is the final one of those four parts:

codesign --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --timestamp -v "$appPath/$framework"

(assuming that "$framework" is the folder Contents/Frameworks/Adobe AIR.framework)

thanks

Oldes commented 2 years ago

When talking about entitlements... I'm just not trying to figure out, where I should put com.apple.developer.ubiquity-container-identifiers and com.apple.developer.ubiquity-kvstore-identifier which I need for iCloud key-value storage extension?

chazhenry commented 2 years ago

Yes, I have those entitlements and I've learned to do them in the Xcode editor. Yes, $framework is the folder you named. I've tried to only codesign the framework folder (hoping its recursive) and I've tried to sign each piece with the main first or last in the list. Each of those leads to 'apps requires Air...'. If I take the additional step of signing the app, the issue switches to 'no permission'. I've literally tried to add/remove each of the codesign switches. When at 'no permission' state, chmod has no effect. I've also turned off Gatekeeper, but that's not where the block is coming from either.

ajwfrost commented 2 years ago

@Oldes you can add things into macOS.Entitlements in your app descriptor - see https://airsdk.dev/docs/building/application-descriptor-files/elements/macOS. These would be picked up if you sign the app using the adt -sign options (or provide native signing options on the command line, I don't think the IDEs do that yet though).

@chazhenry sounds frustrating! it seems like you're doing everything right.. I am not sure whether there's any tool that can provide any more details on why macOS is failing to load the framework. Did you try the codesign -v -vvvv thing on MyApp.app/Contents/Frameworks/Adobe\ AIR.framework in case that is showing anything suspicious?

Oldes commented 2 years ago

@ajwfrost when using:

adt -sign -storetype KeyChainStore -alias "3rd Party Mac Developer..." -target bundle my.app signed.app

I get:

Native signing on mac needs to use KeychainStore type

What does it means?

ajwfrost commented 2 years ago

@Oldes sorry, it looks like it's case sensitive -> KeychainStore would work but your storetype is KeyChainStore ... not sure that it's actually meant to be case sensitive looking at how the code actually works, it's just the check on the type which is doing a string comparison....

Oldes commented 2 years ago

@ajwfrost Ah... interesting.. it is not complaining when used with -package.

Oldes commented 2 years ago

Unfortunately when trying to run the signed result, I get You do not have permission to open the application “signed”. (I'm on M1 Mac now)

ajwfrost commented 2 years ago

Hmmm... so can you please double-check the file permissions, I thought we'd fixed them but if you do something like:

find signed.app/Contents/MacOS -type f -exec ls -la {} \;

and check it's got the x flags?

Oldes commented 2 years ago

The flags looks ok... isn't it because of missing provision profile?

Oldes commented 2 years ago

Btw... when I run on freshly made app:

codesign --verbose=4 --verify My.app

I get:

My.app: invalid Info.plist (plist or signature have been modified)
In architecture: arm64

Is this ok?

ajwfrost commented 2 years ago

If it's a freshly made app then it implies there's a left-over code signature in some component that's not valid, it would be better if it said it wasn't signed at all... but not sure that should make a difference after we re-apply the new signing process.

On the signed app, can you perhaps try something similar but checking all the components:

find "MyApp.app" -name "*.framework" -exec codesign --verbose=4 --verify {} \;
find "MyApp.app" -name "*.dylib" -exec codesign --verbose=4 --verify {} \;
find "MyApp.app" -name "*.plugin" -exec codesign --verbose=4 --verify {} \;
find "MyApp.app" -name "A2712Enabler" -exec codesign --verbose=4 --verify {} \;

thanks

Oldes commented 2 years ago

Ok.. it looks that my extension is a problem:

My.app/Contents/Resources/META-INF/AIR/extensions/xxx/META-INF/ANE/MacOS-x86-64/MyMac.framework: bundle format is ambiguous (could be app or framework)

How should I resolve it? The same message is also with the signed app after the adt -sign ... step.

chazhenry commented 2 years ago

I'm giving up on Mac support. I've spent days 'programming' something that should be automatic. This took me 30 mins on the PC. I don't consider the SDK cross platform at this point. I couldn't get Mac or Android working. I also tried to upgrade to premium with Harman and instead of getting a web page where I could pay, I got a screen telling me they'd send me an invoice. It never came. Who does that for a small bill that can be paid online? I can't see this working in the long run. Maybe I'll find a Mac person and come back. I've quit before. Either way, thanks for your help.

Oldes commented 2 years ago

@ajwfrost I'm getting the invalid Info.plist message even on basic fresh app without any extension.

find "Test.app" -name "*.framework" -exec codesign --verbose=4 --verify {} \;
Test.app/Contents/Frameworks/Adobe AIR.framework: valid on disk
Test.app/Contents/Frameworks/Adobe AIR.framework: satisfies its Designated Requirement

find "Test.app" -name "*.dylib" -exec codesign --verbose=4 --verify {} \;
Test.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/WebKit.dylib: valid on disk
Test.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/WebKit.dylib: satisfies its Designated Requirement

find "Test.app" -name "*.plugin" -exec codesign --verbose=4 --verify {} \;

find "Test.app" -name "A2712Enabler" -exec codesign --verbose=4 --verify {} \;
Test.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/A2712Enabler: valid on disk
Test.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/A2712Enabler: satisfies its Designated Requirement

No issues above, but...

codesign --verbose=4 --verify "Test.app"
Test.app: invalid Info.plist (plist or signature have been modified)
In architecture: arm64
Oldes commented 2 years ago

@ajwfrost But bigger issue is, that I can run the Test.app, but when I do:

java  \
    -jar /Users/oldes/GIT/AIRSDK_Harman_795/lib/adt.jar \
    -sign -storetype KeychainStore -alias "Mac Developer: ..." \
    -target bundle \
    ./Test.app ./Test-signed.app

I cannot run the signed version anymore (because of the permissions message), although it looks ok:

find "./Test-signed.app" -name "*.framework" -exec codesign --verbose=4 --verify {} \;
./Test-signed.app/Contents/Frameworks/Adobe AIR.framework: valid on disk
./Test-signed.app/Contents/Frameworks/Adobe AIR.framework: satisfies its Designated Requirement

find "./Test-signed.app" -name "*.dylib" -exec codesign --verbose=4 --verify {} \;
./Test-signed.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/WebKit.dylib: valid on disk
./Test-signed.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/WebKit.dylib: satisfies its Designated Requirement

find "./Test-signed.app" -name "*.plugin" -exec codesign --verbose=4 --verify {} \;

find "./Test-signed.app" -name "A2712Enabler" -exec codesign --verbose=4 --verify {} \;
./Test-signed.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/A2712Enabler: valid on disk
./Test-signed.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/A2712Enabler: satisfies its Designated Requirement

codesign --verbose=4 --verify "./Test-signed.app"
--prepared:./Test-signed.app/Contents/Frameworks/Adobe AIR.framework/Versions/Current/.
--validated:./Test-signed.app/Contents/Frameworks/Adobe AIR.framework/Versions/Current/.
./Test-signed.app: valid on disk
./Test-signed.app: satisfies its Designated Requirement
open -n ./Test-signed.app 
The application cannot be opened for an unexpected reason, error=Error Domain=NSOSStatusErrorDomain Code=-10826 "kLSNoLaunchPermissionErr: User doesn't have permission to launch the app (managed networks)" UserInfo={_LSFunction=_LSLaunchWithRunningboard, _LSLine=2561, NSUnderlyingError=0x14bf096c0 {Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0x14bf0a0d0 {Error Domain=NSPOSIXErrorDomain Code=153 "Unknown error: 153" UserInfo={NSLocalizedDescription=Launchd job spawn failed with error: 153}}}}}

@chazhenry don't blame AIR... it is Apple's ever changing complexity of all requirements fault. Internet is full of examples that we are not the only one to suffer.

Oldes commented 2 years ago

I can run the app when I re-sign the signed app using codesign --force --deep --sign - ./Test-signed.app. Can anybody explain it?

chazhenry commented 2 years ago

@ajwfrost I completely blame Apple and to clarify, I can no longer support a Mac version.

One last thought occurs to me. I'm completely subject to whatever IntelliJ is doing. Best I can tell it runs adl and not adt. Not knowing Mac, I got that to work quickly and trusted it to work (until it didn't). Wondering if by taking over the compile, it would change the internal executable? Otherwise, no idea what to try.

chazhenry commented 2 years ago

@Oldes I found that I had to edit plist.info with Xcode. Once I touched the file it wrote with a text editor, it was corrupt. Supposed to be XML, but in typical Apple BS, a flavor only their tool can read. Hope that helps.

Oldes commented 2 years ago

ADL is a debug launcher. To make a version for distribution, you must use ADT, which is the developer tool

chazhenry commented 2 years ago

@Oldes Thanks. Then I assume that when I compile as captive runtime, its using adt. I just don't get to see that command as it does it all under the covers. For months, it has built an app that I could run. Just don't know exactly what its doing or how I could get to the IntelliJ script that is driving the compile.

chazhenry commented 2 years ago

@Oldes I've asked in multiple posts, but never got an answer. What is the best pipeline? What do you use to develop? I'm using IntelliJ because the 2019 version had a plugin that correctly builds a captive runtime bundle. It also can run the app in debug mode. I can't do the same on the Mac side since the app itself won't run until entitlements are applied. Wondering if my dev pipeline on Mac needs to be more hands on as the blackbox compile is not working.

chazhenry commented 2 years ago

@ajwfrost How would I compile my existing app to a mac captive runtime with adt?

Oldes commented 2 years ago

@chazhenry I'm using pure command line to compile... (I'm using Java as the AIR sdk's binaries are just work around it anyway, I guess) To get the SWF I use for example:

java  \
    -Dsun.io.useCanonCaches=false -Xms32m -Xmx512m \
    -Dflexlib="$AIRSDK/frameworks" \
    -jar "$AIRSDK/lib/mxmlc-cli.jar" \
    -load-config="$AIRSDK/frameworks/air-config.xml" \
    -load-config+=config.xml +configname=air \
    -optimize=true \
    -debug=false \
    -swf-version 44 \
    -output Main.swf

Where the config.xml is something like:

<?xml version="1.0" encoding="utf-8"?>
<flex-config>
  <target-player>33.1</target-player>
  <compiler>
    <define append="true">
      <name>CONFIG::debug</name>
      <value>false</value>
    </define>
    <define append="true">
      <name>CONFIG::release</name>
      <value>true</value>
    </define>
    <define append="true">
      <name>CONFIG::air</name>
      <value>true</value>
    </define>
    <define append="true">
      <name>CONFIG::mobile</name>
      <value>false</value>
    </define>
    <define append="true">
      <name>CONFIG::desktop</name>
      <value>true</value>
    </define>
    <optimize>true</optimize>
    <omit-trace-statements>true</omit-trace-statements>
    <verbose-stacktraces>false</verbose-stacktraces>
    <source-path append="true">
      <path-element>./</path-element>
    </source-path>
    <external-library-path append="true">
      <path-element>../build/some.ane</path-element>
    </external-library-path>
  </compiler>
  <file-specs>
    <path-element>./Main.as</path-element>
  </file-specs>
  <default-background-color>#FFFFFF</default-background-color>
  <default-frame-rate>30</default-frame-rate>
  <default-size>
    <width>480</width>
    <height>762</height>
  </default-size>
</flex-config>

To debug result can be done using:

$AIRSDK/bin/adl application.xml ./dir/with.the.main.swf -extdir ../dir/where.are.ane.files

Than to get the native bundle I use:

java  \
    -jar $AIRSDK/lib/adt.jar \
    -package \
    -storetype KeychainStore -alias "Mac Developer: ..." \
    -target bundle  \
    ../build/test.app \
    application.xml Main.swf \
    -extdir ../build/
chazhenry commented 2 years ago

@Oldes Is that Flex specific? I'm pure AS3.

Oldes commented 2 years ago

It's not Flex specific, I'm also using just AS3. This is what IDEs like FlashDevelop and IntelliJ do behind scenes.

Oldes commented 2 years ago

BUT, when you have the app ready to submit it to store, you must resign it and notarize it, which is why we are here ;-) I've done it before, but now I must include native extension for iCloud and the extension is not working in my tests, probably because of this entitlements and certificates mess.

I think that I will just submit it without testing and see what will happen (I already have it tested on iOS).

Unfortunately, to test macOS app using TestFlight, one must have OS12 and newer, which I don't have yet... so I love Apple.

chazhenry commented 2 years ago

@Oldes Thanks! Will try tonight.

Oldes commented 2 years ago

This is useful tutorial imho https://scriptingosx.com/2021/07/notarize-a-command-line-tool-with-notarytool/

waveofthought-code commented 2 years ago

This colorful and hilarious post got me through the notarization phase.

https://www.molleindustria.org/blog/notarizing-your-flashair-applications-for-macos/

amorganiv commented 2 years ago

Hello Andrew... I'm attempting to use AIR 33.1.795 adt to sign a macOS development desktop application. I'm on an older mac version 10.12.6 (Sierra). The original macOS desktop app is complied with Animate and signed with a developer p12 certificate.

This command outputs Failure (1) in codesign request: adt -sign -storetype KeychainStore -alias "Developer ID Application" -target bundle main.app signed.app invalid argument "runtime"

Does this require a newer version of macOS codesign? Also, want to confirm the "Developer ID Application" is the ID# associated with the Mac Developer certificate listed in Keychain Access.

ajwfrost commented 2 years ago

Hi - a few things to cover here (I was out yesterday so missed most of the above...!!)

This also looks to be a good tutorial: https://lessons.livecode.com/m/4071/l/1122100-codesigning-and-notarizing-your-lc-standalone-for-distribution-outside-the-mac-appstore in case that's useful.

@amorganiv I can't find any info on it but I suspect yes you'll need a newer codesign tool that supports hardened runtime. We found that our signed/notarized apps then wouldn't run on anything before 10.12, despite all the documentation suggesting that it should be possible ... (the codesign tool is meant to inspect them for what minimum macOS version they support, and include appropriate code signature options, but it didn't seem to do that...). Probably if you don't use the hardened runtime option then it wouldn't work on the more recent macOS versions...

And terms of the "Developer ID Application" - Developer ID certificates are what you need if you want to distribute your app outside of the App Store. Your Mac Developer certificate would only work with your named machines, but Developer ID is something that would work on any machine.

@Oldes when you said "I'm getting the invalid Info.plist message even on basic fresh app without any extension" - was this with an app just generated from ADT without doing anything? This is where I think we may have a left-over piece of code signature information in the template binary, i.e. a signature of the info.plist embeddded into the binary, but when the new app is generated, it creates the new info.plist. So we may need to look at this in case it's causing any problems...

I can run the app when I re-sign the signed app using codesign --force --deep --sign - ./Test-signed.app. Can anybody explain it?

Isn't that a command to wipe the signature, similar to what xcode does for dev builds? If you do a codesign -dvv on this it probably will tell you it's not the developer ID certificate any more. So good that it runs but maybe not so useful!

@chazhenry your question "How would I compile my existing app to a mac captive runtime with adt?" has given me an interesting idea, although it may take a bit of effort to make it work. So: you're happily using IntelliJ to develop and to run the app, which means that when IntelliJ invokes the Android Debug Launcher, it has set everything up that is required for the AIR app to run, including ANE locations etc. So I'm wondering if we could capture that launch information, and then automatically generate a script (or some config info that can be passed into a tool) that would turn whatever you just ran into a signed .app bundle... (it would probably have to do a few clever things like stripping debug info etc...). But this may help for a lot of folk who use the IDEs and aren't familiar with the ADT command line (which to be fair is a bit of a monster).

The other thing I think we need, which would be a lot quicker to do, is a simpler/better tool that could open an app and tell you information about the code signature status of its component parts, and to re-sign it again properly. We can have a look at this, the caveat being that it seems (from the above thread) as if there are still some issues with launching an app after code-signing!

@chazhenry also, would you be willing to share your application with us? we can look at code signing it here to see what may be the issue. You can upload it via https://transfer.harman.com/requests/oSUcHZQC77910DzDYQY0ET

Finally - I just found one reference to an extra condition on running these code-signed apps, and am wondering if this may be a culprit in some of these cases:

After building the app, use otool -l on each framework in the app and look for LC_RPATH to somewhere outside the bundle.

So we can also look into that to check that nothing has external dependencies that macOS is blocking..

thanks!

Oldes commented 2 years ago

@ajwfrost

"I'm getting the invalid Info.plist message even on basic fresh app without any extension" - was this with an app just generated from ADT without doing anything?

Yes... pure ADT generated app.

Oldes commented 2 years ago

@ajwfrost there must be something wrong. When I make an app using adt tool and then make an installer from it using:

productbuild --component ./my.app /Applications --sign '3rd Party Mac Developer Installer: XXX' ./my.pkg

And then upload it using (using throttled upload by -k 1900 as without it on slow connections it fails) :

xcrun altool --upload-app --type osx --file ./my.pkg -k 1900 --verbose --username XXX@XXX -p "APP-PASSWORD"

It ends with:

*** Error: Error uploading 'Build/osx-arcade/Samorost3.pkg'.
*** Error: The Info.plist in the package must contain the CFBundleVersion key. Unable to validate your application. (-27001)
 {
    NSLocalizedDescription = "The Info.plist in the package must contain the CFBundleVersion key.";
    NSLocalizedFailureReason = "Unable to validate your application.";
}

When I add CFBundleVersion into the InfoAdditions in manifest file, the adt packaging fails with:

error 105: application.macOS.InfoAdditions contains an invalid value

Note that the codesign on fresh app reports invalid Info.plist as mentioned above. So I believe that it is not possible to submit app to Mac Store without manually touching its content and resigning it (which I am not able to manage now as I was a few years ago)

Btw... the altool displays used Info.plist content (as is in the app package) and there is only CFBundleGetInfoString in it. The CFBundleVersion is really missing!

Oldes commented 2 years ago

@ajwfrost btw... what is correct use of -provisioning-profile flag? I suppose it should be used with the provision profile downloaded from the Developer portal, but the adt tool seems to be refusing it.

ajwfrost commented 2 years ago

@Oldes the CFBundleVersion is meant to come from a template file which we use for the initial set-up of the Info.plist file... and it appears in the template, but yes it's missing when the app is generated. Very odd - we can check what's going on here. Part of the native app packaging process.... you can't add it yourself from the app descriptor as we've set it as reserved as we want to set the version number from the app descriptor... it works on iOS but is oddly not working on macOS.

Provisioning profile I thought was only used when packaging IPA files, that may be another new change that we have to adapt to...

Will try to focus on this more tomorrow: have got a code-signing analysis tool done and working on getting it to do re-signing of app bundles...

thanks

amorganiv commented 2 years ago

Thanks Andrew for the information... we were able to sign the app with ADT on a newer macOS. It did output a build chain error but appears to be working for our testing purposes.

ADT sign command: AIR33_1_795/bin/adt -sign -storetype KeychainStore -alias 'Mac Developer: ID' -target bundle tmp-desktop.app tmp-desktop-signed.app Failure (1) in codesign request. tmp-desktop-signed.app: replacing existing signature Warning: unable to build chain to self-signed root for signer "Mac Developer: ID" tmp-desktop-signed.app: errSecInternalComponent In subcomponent: /Users/Development/tmp-desktop-signed.app/Contents/Frameworks/Adobe AIR.framework

ajwfrost commented 2 years ago

@amorganiv the "unable to build chain" is a nightmare one that we had for a while .. there seemed to be a whole host of issues that we had to work through, lots of suggestions online (none of which helped). We ended up switching to another machine for our build/signing process...! A few things though:

That second one with the 'errSecInternalComponent' I think is what we see if we try code-signing from an SSH terminal. There's meant to be a way to enable it, but it didn't work for us...

BTW for distribution outside of the Play Store, and for notarization, you would need to have a Developer ID certificate. So e.g. I have "Apple Development: Andrew Frost ..." that I use for dev work, and I have "Developer ID Application: HARMAN ..." which is what we use for final signing prior to notarization.

thanks

ajwfrost commented 2 years ago

Findings of a "normal" macOS application:

A quick note on signing:

The way it's going, I'm thinking: a) it may just be simpler to maintain a separate tool for checking and signing app bundles ready for notarization or for upload to the Play Store... b) on Windows we'll try to keep this working as long as you don't have Java 17 or later....

thanks

amorganiv commented 2 years ago

Thanks again Andrew... we needed to add these Apple certificates to the Keychain. It signed the application correctly with both the Developer ID and Mac Developer certificates.

https://www.apple.com/certificateauthority/ Application Integration Developer ID - G2 Worldwide Developer Relations - G3

Oldes commented 2 years ago

@chazhenry when you said:

Here are my codesign commands.

echo "$yellow\nCodesign the pieces...$end"
codesign --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --timestamp -v "$appPath/$framework"
codesign --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --timestamp -v "$appPath/$framework/$v1Res/A2712Enabler"
codesign --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --timestamp -v "$appPath/$framework/$v1Res/WebKit.dylib"
codesign --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --timestamp -v "$appPath/$framework/$vCur/Adobe Air"

echo "$yellow\nCodesign the app...$end"
codesign --force --deep --entitlements "$pkgPath/$appPlist" -s "$certApp" -f -o runtime --strict --timestamp -v "$appPath/"

I believe that it is in wrong order, because the last codesign call has --deep and so replaces all previous codesign calls. Also (correct me, if I'm wrong), the --entitlements part should be done only on main executable, shouldn't it?

Oldes commented 2 years ago

@ajwfrost you have the same order with the last codesign --deep call here

In this tutorial they have the same order (frameworks first, app last), but they don't use the --deep for the app.

Oldes commented 2 years ago

I just managed to upload a version to Mac App Store for a review (no result yet) using such a shell script:

# APP_SRC is an app made using `adt` tool
APP_SRC="./path/to/my.app"
# APP is a modified app for distribution
APP="./path/to/my-dist.app"

# first remove previous app and than make a copy of the source
rm -R $APP
ditto $APP_SRC $APP

# remove unused files from the app (it works without them in my case)
rm -f -R "$APP/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/Flash Player.plugin"
rm -f    "$APP/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/WebKit.dylib"
rm -f -R "$APP/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/WebKit"
rm -f    "$APP/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/Adobe AIR.vch"
rm -f    "$APP/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/ExtendedAppEntryTemplate64"
rm -f -R "$APP/Contents/Resources/Assets"

# copy my modified files
cp ./Assets/Info.plist "$APP/Contents/Info.plist"
cp ./Assets/Icon.icns "$APP/Contents/Resources/Icon.icns"
cp ./Assets/Some.provisionprofile "$APP/Contents/embedded.provisionprofile"

# remove all previous signatures and sign again using own cert
APP_KEY="3rd Party Mac Developer Application: ..."

codesign --remove-signature "$APP"
# A2712Enabler must be before Adobe AIR.framework
codesign --timestamp -f -v -s "$APP_KEY" --options runtime --entitlements "$ENTITLE" "$APP/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/A2712Enabler"
codesign --timestamp -f -v -s "$APP_KEY" "$APP/Contents/Frameworks/Adobe AIR.framework"
# I also need a native extension
ANE_ID="my.ane.id"
ANE_NAME="SomeAneName"
codesign --timestamp -f -v -s "$APP_KEY" "$APP/Contents/Resources/META-INF/AIR/extensions/$ANE_ID/META-INF/ANE/MacOS-x86-64/$ANE_NAME.framework/Versions/A/ANE_NAME"
# the app is the last one
codesign --timestamp -f -v -s "$APP_KEY" --options runtime --entitlements "$ENTITLE" "$APP"

# validate the result
echo "\nValidation..."
codesign --verbose=4 --display --entitlements - "$APP"
echo "\n"
codesign --verbose=4 --verify "$APP"

# make a pkg for distribution
PKG_KEY="3rd Party Mac Developer Installer: ..."
productbuild --component "$APP" /Applications --sign "$PKG_KEY" "./path/to/MyApp.pkg"

# upload was mentioned in previous post using `xcrun altool`

I found, that critical is the content of the $ENTITLE file. I can run locally such a signed app with content like:

<!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.app-sandbox</key>
            <true/>
        <key>com.apple.security.cs.allow-jit</key>
            <true/>
        <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
            <true/>
    </dict>
</plist>

Unfortunately I need also other entitles (namely com.apple.developer.ubiquity-kvstore-identifier). When I add it, I get the no permission message on application startup :/ But that is not AIR fault.