TheInfiniteKind/appbundler

Hardened runtime with bundled JRE

Closed this issue · 6 comments

I am destributing Java application for Mac OS, and using appbundler for building the application. It is necessary to notarize application for now, also necessary is to enable Hardened Runtime to pass the notarization. There are some problems about this:

  • If I codesign the application without --option runtime it works, but can't pass notarization
  • If I codesign the application with --option runtime it can pass notarization, but can't be launched.

Building app with Maven:

<build>
	<finalName>${organization.name}-${version}</finalName>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-antrun-plugin</artifactId>
			<dependencies>
				<dependency>
					<groupId>com.panayotis</groupId>
					<artifactId>appbundler</artifactId>
					<version>1.1.0</version>
				</dependency>
			</dependencies>
			<executions>
				<execution>
					<phase>package</phase>
					<goals>
						<goal>run</goal>
					</goals>
					<configuration>
						<target>
							<mkdir dir="${build.directory}/${build.finalName}"/>
							<taskdef name="bundleapp" classname="com.oracle.appbundler.AppBundlerTask"/>
							<bundleapp outputdirectory="${build.directory}/${build.finalName}"
									   name="${organization.name}"
									   displayname="${organization.name}"
									   identifier="com.company.product"
									   shortversion="${revision}"
									   icon="src/main/resources/icons/Icon.icns"
									   mainclassname="org.springframework.boot.loader.JarLauncher"
									   copyright="2019 Company">
								<runtime dir="${project.basedir}/../misc/jdk-11.0.4+11/Contents/Home"/>
								<classpath file="${build.directory}/${organization.name}-${revision}.jar"/>
								<option value="-Dspring.config.location=classpath:/application.yml,file:./application.yml"/>
								<option value="-Djava.awt.headless=false"/>
								<option value="-Xmx512m"/>
							</bundleapp>
						</target>
					</configuration>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>

Codesigning flow:

codesign --options runtime --entitlements entitlements.plist --sign "Dev. ID" App.app/Contents/PlugIns/jdk-11.0.4+11
find "App.app/Contents/Resources/additional executables" -type -f -exec "codesign --options runtime --entitlements entitlements.plist --sign "Dev. ID" {}"
codesign --options runtime --entitlements entitlements.plist --sign "Dev. ID" App.app/Contents/Java/App.jar
codesign --options runtime --entitlements entitlements.plist --sign "Dev. ID" App.app/Contents/MacOS/JavaAppLauncher

Entitlements:

<?xml version="1.0" encoding="UTF-8"?>
<!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.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.disable-executable-page-protection</key>
    <true/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
</dict>
</plist>

Error:

2019-08-08 10:28:51.443 JavaAppLauncher[4526:559342] int launch(char *, int, char **) Launchpath: /Applications/App.app/Contents/PlugIns/jdk-11.0.4+11/Contents/Home/lib/jli/libjli.dylib
2019-08-08 10:28:51.449 JavaAppLauncher[4526:559342] int launch(char *, int, char **) Error launching JVM Runtime (jdk-11.0.4+11) Relative Path: '/Applications/App.app/Contents/PlugIns/jdk-11.0.4+11' (dylib: /Applications/App.app/Contents/PlugIns/jdk-11.0.4+11/Contents/Home/lib/jli/libjli.dylib)
  error: JRELoadError

I'm codesigning, notarising, and using basically the same entitlements as you, so I think those configurations look OK. I wonder if it's related to the name of your jdk folder under the PlugIns folder. In the past there have been codesigning bugs that required the jdk/jvm folder under Plugins to be of the form . which is why I've named that folder "vm.jdk". Having the + sign in there might also pose a problem.

I'm codesigning, notarising, and using basically the same entitlements as you, so I think those configurations look OK. I wonder if it's related to the name of your jdk folder under the PlugIns folder. In the past there have been codesigning bugs that required the jdk/jvm folder under Plugins to be of the form . which is why I've named that folder "vm.jdk". Having the + sign in there might also pose a problem.

I've re-built my application with JDK named jdk-11.jdk, but the problem is still exists:

2019-08-08 10:28:51.443 JavaAppLauncher[4526:559342] int launch(char *, int, char **) Launchpath: /Applications/App.app/Contents/PlugIns/jdk-11.jdk/Contents/Home/lib/jli/libjli.dylib
2019-08-08 10:28:51.449 JavaAppLauncher[4526:559342] int launch(char *, int, char **) Error launching JVM Runtime (jdk-11.jdk) Relative Path: '/Applications/App.app/Contents/PlugIns/jdk-11.jdk' (dylib: /Applications/App.app/Contents/PlugIns/jdk-11.jdk/Contents/Home/lib/jli/libjli.dylib)
  error: JRELoadError

Also, I've tried not to include the JDK into my application, in this case the error was:

2019-08-08 13:56:43.616 JavaAppLauncher[5029:635472] NSString *findJavaDylib(NSString *, _Bool, _Bool, _Bool, _Bool) Searching for a JRE.
2019-08-08 13:56:43.751 JavaAppLauncher[5029:635472] int launch(char *, int, char **) Launchpath: /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/jli/libjli.dylib
2019-08-08 13:56:43.756 JavaAppLauncher[5029:635472] int launch(char *, int, char **) Error launching JVM Runtime ((null)) Relative Path: '/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home' (dylib: /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/jli/libjli.dylib)
  error: JRELoadError

I'm codesigning, notarising, and using basically the same entitlements as you, so I think those configurations look OK. I wonder if it's related to the name of your jdk folder under the PlugIns folder. In the past there have been codesigning bugs that required the jdk/jvm folder under Plugins to be of the form . which is why I've named that folder "vm.jdk". Having the + sign in there might also pose a problem.

Can you, please, provide a sample of your application building and codesigning?

gdams commented

@vbanchenko are you sure that this command:

find "App.app/Contents/Resources/additional executables" -type -f -exec "codesign --options runtime --entitlements entitlements.plist --sign "Dev. ID" {}"

definetely signs the dylib file referenced in /Applications/App.app/Contents/PlugIns/jdk-11.jdk' (dylib: /Applications/App.app/Contents/PlugIns/jdk-11.jdk/Contents/Home/lib/jli/libjli.dylib?

I've found that I also need to remove the ${BUNDLEDJDK}/Contents/MacOS/libjli.dylib symlink before codesigning. Does that help in your case?

@vbanchenko if this is still a problem for you please ping me via email at sreilly@infinitekind.com and I'll send you a copy of my mac build script.