TheInfiniteKind / appbundler

74 stars 24 forks source link

Hardened runtime with bundled JRE #57

Closed vbanchenko closed 4 years ago

vbanchenko commented 5 years ago

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:

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
sreilly commented 5 years ago

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.

vbanchenko commented 5 years ago

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
vbanchenko commented 5 years ago

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 5 years ago

@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?

sreilly commented 4 years ago

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

sreilly commented 4 years ago

@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.