Signing
The Eclipse Foundation allows committers to sign JAR and some executable files on its behalf. Signing is done from any of the Jenkins servers. There are three ways to sign:
CBI Maven signing plugin
Using the CBI Maven Plugins, the signing process can be directly performed at the end of a Maven Tycho build.
Maven Profiles
As signing an Eclipse project is only available from an Eclipse Jenkins server, a common practice is to place the CBI Maven signing plugins in a dedicated profile and enable that profile only in the Jenkins job. This way you can still run your Maven Tycho builds locally without signing. See Maven - Introduction to Build Profiles
<profiles>
<profile>
<id>sign</id>
<build>
<plugins>
[...]
</plugins>
</build>
</profile>
</profiles>
The profile can then be activated in the Jenkins build via the -P argument.
JAR signing
Ensure that all created JAR files are correctly signed by using the eclipse-jarsigner-plugin
<plugin>
<groupId>org.eclipse.cbi.maven.plugins</groupId>
<artifactId>eclipse-jarsigner-plugin</artifactId>
<version>${cbi-version}</version>
<executions>
<execution>
<id>sign</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
Windows signing
To sign the Windows executables, use the eclipse-winsigner-plugin
<plugin>
<groupId>org.eclipse.cbi.maven.plugins</groupId>
<artifactId>eclipse-winsigner-plugin</artifactId>
<version>${cbi-version}</version>
<executions>
<execution>
<id>sign</id>
<goals>
<goal>sign</goal>
</goals>
<phase>package</phase>
<configuration>
<signFiles>
<signFile>${project.build.directory}/products/${product-folder}/win32/win32/x86_64/eclipse.exe</signFile>
<signFile>${project.build.directory}/products/${product-folder}/win32/win32/x86_64/eclipsec.exe</signFile>
</signFiles>
</configuration>
</execution>
</executions>
</plugin>
macOS signing
To sign the macOS executables use the eclipse-macsigner-plugin
<plugin>
<groupId>org.eclipse.cbi.maven.plugins</groupId>
<artifactId>eclipse-macsigner-plugin</artifactId>
<version>${cbi-version}</version>
<executions>
<execution>
<id>sign</id>
<goals>
<goal>sign</goal>
</goals>
<phase>package</phase>
<configuration>
<signFiles>
<signFile>${project.build.directory}/products/${product-folder}/macosx/cocoa/x86_64/Eclipse.app</signFile>
</signFiles>
<timeoutMillis>300000</timeoutMillis>
<continueOnFail>${macSigner.forceContinue}</continueOnFail>
<entitlements>${project.basedir}/application.entitlement</entitlements>
</configuration>
</execution>
</executions>
</plugin>
Entitlements
The security guidelines for macOS application development requires the definition of Entitlements to grant an executable permission to use a service or technology. The entitlements used by the Eclipse Platform are defined here
macOS DMG file creation
macOS applications are typically published as .dmg files, which are containers that serve as installers with additional security information to avoid that the application gets tampered. To create a DMG file the eclipse-dmg-packager can be used.
<plugin>
<groupId>org.eclipse.cbi.maven.plugins</groupId>
<artifactId>eclipse-dmg-packager</artifactId>
<version>${cbi-version}</version>
<executions>
<execution>
<goals>
<goal>package-dmg</goal>
</goals>
<phase>integration-test</phase>
<configuration>
<source>${project.build.directory}/products/${product-id}-macosx.cocoa.x86_64.tar.gz</source>
<continueOnFail>true</continueOnFail>
<timeoutMillis>600000</timeoutMillis>
<continueOnFail>${macSigner.forceContinue}</continueOnFail>
<sign>true</sign>
</configuration>
</execution>
</executions>
</plugin>
macOS Notarization
Since macOS Catalina macOS software that is published outside the AppStore needs to be notarized, so the Gatekeeper gets information about trusting the software or not.
As of now the notarization is not available as Tycho plugin. Therefore the macos-notarization-service webservice needs to be used in the Jenkins job similar to the following snippet:
PRODUCT_ID=...
BUILD_DIR="${WORKSPACE}/${PRODUCT_ID}/target/products/"
DMG=${PRODUCT_ID}-macosx.cocoa.x86_64.dmg
pushd $BUILD_DIR
PRIMARY_BUNDLE_ID="app-bundle"
RESPONSE=$(curl -s -X POST -F file=@${DMG} -F 'options={"primaryBundleId": "'${PRIMARY_BUNDLE_ID}'", "staple": true};type=application/json' https://cbi.eclipse.org/macos/xcrun/notarize)
UUID=$(echo $RESPONSE | grep -Po '"uuid"\s*:\s*"\K[^"]+')
STATUS=$(echo $RESPONSE | grep -Po '"status"\s*:\s*"\K[^"]+')
while [[ ${STATUS} == 'IN_PROGRESS' ]]; do
sleep 1m
RESPONSE=$(curl -s [https://cbi.eclipse.org/macos/xcrun/${UUID}/status](https://cbi.eclipse.org/macos/xcrun/$%7BUUID%7D/status))
STATUS=$(echo $RESPONSE | grep -Po '"status"\s*:\s*"\K[^"]+')
done
if [[ ${STATUS} != 'COMPLETE' ]]; then
echo "Notarization failed: ${RESPONSE}"
exit 1
fi
rm "${DMG}"
curl -JO [https://cbi.eclipse.org/macos/xcrun/${UUID}/download](https://cbi.eclipse.org/macos/xcrun/$%7BUUID%7D/download)
popd
A more detailed script is the Oomph script.
CBI Maven Plugins Version
For correct signing needed for notarization (including for example hardened runtime) at least the CBI Plugins version 1.1.8-SNAPSHOT needs to be used. Ensure to configure the correct pluginRepository to be able to consume that version CBI Maven Plugins Version For correct signing needed for notarization (including for example hardened runtime) at least the CBI Plugins version 1.1.8-SNAPSHOT needs to be used. Ensure to configure the correct pluginRepository to be able to consume that version
<pluginRepositories>
<pluginRepository>
<id>cbi</id>
<url>https://repo.eclipse.org/content/repositories/cbi-releases/</url>
</pluginRepository>
<pluginRepository>
<id>cbi-snapshots</id>
<url>https://repo.eclipse.org/content/repositories/cbi-snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
Once 1.1.8 is released, the SNAPSHOTS repository is not needed anymore.
Eclipse Platform Version
The macOS notarization will only succeed if the dmg file signing is matching certain criteria (e.g. hardened runtime). The first Eclipse Platform version that includes the Eclipse Launcher and native libraries that match those criterias are included in 2019-09. For any previous versions the notarization will fail.
For further information on the CBI Maven Plugins have a look at: https://eclipse-cbi.github.io/org.eclipse.cbi/
Note that these plugins use the web services in the background.
Web service
Using a web POST method, individual JAR files can be signed from any of the internal Jenkins servers with this service:
- https://cbi.eclipse.org/jarsigner/sign
The output of that service will be the signed file. Please note that the web service does not pack or process jar files. You must condition/pack them yourself prior to signing if you wish to do so.
Resigning Jarsigner
The web service always resigns already signed jars. The maven jar signer plugin lets you specify a strategy to avoid submitting already signed jar to the webservice. If you use the webservice directly, you need to do deal with it by yourself. You can see how the re-signing strategies are defined by looking at the code of the JarResigner
# JAR FILES: Submit unsigned-jar.jar and save signed output to signedfile.jar
curl -o signedfile.jar -F file=@unsigned-jar.jar https://cbi.eclipse.org/jarsigner/sign
# WINDOWS EXE: Submit Windows unsigned.exe and save signed output to signed.exe
curl -o signed.exe -F file=@unsigned.exe https://cbi.eclipse.org/authenticode/sign
# WINDOWS MSI: Submit Windows unsigned.msi and save signed output to signed.msi
curl -o signed.msi -F file=@unsigned.msi https://cbi.eclipse.org/authenticode/sign
# MAC: Submit unsigned and save signed output to signed.zip
# Note: You must zip your entire *.app directory for example: zip -r unsigned.zip Eclipse.app
curl -o signed.zip -F file=@unsigned.zip https://cbi.eclipse.org/macos/codesign/sign
# If you need to set entitlements on your app / binary (see https://developer.apple.com/documentation/security/hardened_runtime?preferredLanguage=occ for details),
# add an `entitlements` part to the request like below
curl -o signed.zip -F file=@unsigned.zip -F entitlements=@file.entitlements https://cbi.eclipse.org/macos/codesign/sign
Using the webservice is equally easy from Ant. Note that ${filename} cannot be a path. Input and output file name can be the same.
<exec dir="${dirname}" executable="curl">
<arg value="--output"/>
<arg value="${filename}"/>
<arg value="--form"/>
<arg value="file=@${filename}"/>
<arg value="--silent"/>
<arg value="--show-error"/>
<arg value="--fail"/>
<arg value="https://cbi.eclipse.org/jarsigner/sign"/>
</exec>
Version of Jarsigner
The web service only signs with Java 11 version of jarsigner.
Using the web service to sign Mac and Windows applications is also easy from Tycho, see
- eclipse-macsigner-plugin
- eclipse-winsigner-plugin
- Sign your eclipse project (codetrails.com/archive.org)
- OS X application signing (cbi-dev mailing list)
What about GPG signing?
JAR signing of the bundles and GPG-signing of the Maven artifacts are two different steps. Once a jar has been "jar-signed", you may or may not GPG sign the corresponding Maven artifact (.jar + .pom file) so as it can be deployed on Central. As you hinted, JAR signing has to be done before the GPG signing, since doing it the other way around would break the GPG signature.
So you first have to sign your JAR file with the Eclipse Foundation certificate, either using the Maven plugin from CBI, the command line utility, or the signing web service – see above. Once you have your signed JAR, you can GPG sign it and stage it on Central like this: