Skip to content

Commit bcc836b

Browse files
authored
Feature: Sign build artifacts (#71)
add code signing for macOS and windows
1 parent 1a907ca commit bcc836b

File tree

3 files changed

+189
-17
lines changed

3 files changed

+189
-17
lines changed

.github/workflows/build-mac.yml

+121-11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ on:
88
sem-version:
99
description: 'Version'
1010
required: false
11+
notarize:
12+
description: 'Notarize app'
13+
required: false
14+
type: boolean
1115

1216
permissions:
1317
contents: write
@@ -28,7 +32,11 @@ jobs:
2832
outputs:
2933
semVerStr: ${{ steps.determine-version.outputs.version }}
3034
semVerNum: ${{steps.determine-number.outputs.number}}
35+
revisionNum: ${{steps.determine-number.outputs.revision}}
3136
steps:
37+
- uses: actions/checkout@v4
38+
with:
39+
fetch-depth: 0
3240
- id: determine-version
3341
shell: pwsh
3442
run: |
@@ -45,6 +53,8 @@ jobs:
4553
run: |
4654
SEM_VER_NUM=$(echo "${{ steps.determine-version.outputs.version }}" | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
4755
echo "number=${SEM_VER_NUM}" >> "$GITHUB_OUTPUT"
56+
REVISION_NUM=`git rev-list --count HEAD`
57+
echo "revision=${REVISION_NUM}" >> "$GITHUB_OUTPUT"
4858
4959
build-binary:
5060
name: Build java app image
@@ -56,9 +66,11 @@ jobs:
5666
- os: macos-latest
5767
architecture: arm64
5868
artifact-name: cryptomator-cli-${{ needs.prepare.outputs.semVerStr }}-mac-arm64.zip
69+
xcode-path: /Applications/Xcode_16.app
5970
- os: macos-13
6071
architecture: x64
6172
artifact-name: cryptomator-cli-${{ needs.prepare.outputs.semVerStr }}-mac-x64.zip
73+
xcode-path: /Applications/Xcode_15.2.app
6274
runs-on: ${{ matrix.os }}
6375
steps:
6476
- uses: actions/checkout@v4
@@ -86,22 +98,121 @@ jobs:
8698
JP_APP_VERSION: ${{ needs.prepare.outputs.semVerNum }}
8799
APP_VERSION: ${{ needs.prepare.outputs.semVerStr }}
88100
NATIVE_ACCESS_PACKAGE: org.cryptomator.jfuse.mac
89-
- uses: actions/upload-artifact@v4
90-
with:
91-
name: cryptomator-cli-mac-${{ matrix.architecture }}
92-
path: ./target/cryptomator-cli.app
93-
if-no-files-found: error
94-
- name: TODO sign binaries
95-
run: echo "TODO sign it and notarize it"
96-
- name: Zip binary for release
97-
run: zip -r ./${{ matrix.artifact-name}} ./target/cryptomator-cli.app
101+
- name: Patch .app dir
102+
run: |
103+
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" cryptomator-cli.app/Contents/Info.plist
104+
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" cryptomator-cli.app/Contents/Info.plist
105+
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode -o "cryptomator-cli.app/Contents/embedded.provisionprofile"
106+
working-directory: target
107+
env:
108+
VERSION_NO: ${{ needs.prepare.outputs.semVerNum }}
109+
REVISION_NO: ${{ needs.prepare.outputs.revisionNum }}
110+
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
111+
- name: Install codesign certificate
112+
run: |
113+
# create variables
114+
CERTIFICATE_PATH=$RUNNER_TEMP/codesign.p12
115+
KEYCHAIN_PATH=$RUNNER_TEMP/codesign.keychain-db
116+
117+
# import certificate and provisioning profile from secrets
118+
echo -n "$CODESIGN_P12_BASE64" | base64 --decode -o $CERTIFICATE_PATH
119+
120+
# create temporary keychain
121+
security create-keychain -p "$CODESIGN_TMP_KEYCHAIN_PW" $KEYCHAIN_PATH
122+
security set-keychain-settings -lut 900 $KEYCHAIN_PATH
123+
security unlock-keychain -p "$CODESIGN_TMP_KEYCHAIN_PW" $KEYCHAIN_PATH
124+
125+
# import certificate to keychain
126+
security import $CERTIFICATE_PATH -P "$CODESIGN_P12_PW" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
127+
security list-keychain -d user -s $KEYCHAIN_PATH
128+
env:
129+
CODESIGN_P12_BASE64: ${{ secrets.MACOS_CODESIGN_P12_BASE64 }}
130+
CODESIGN_P12_PW: ${{ secrets.MACOS_CODESIGN_P12_PW }}
131+
CODESIGN_TMP_KEYCHAIN_PW: ${{ secrets.MACOS_CODESIGN_TMP_KEYCHAIN_PW }}
132+
- name: Codesign
133+
run: |
134+
echo "Codesigning jdk files..."
135+
find cryptomator-cli.app/Contents/runtime/Contents/Home/lib/ -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
136+
find cryptomator-cli.app/Contents/runtime/Contents/Home/lib/ \( -name 'jspawnhelper' -o -name 'pauseengine' -o -name 'simengine' \) -exec codesign --force -o runtime -s ${CODESIGN_IDENTITY} {} \;
137+
echo "Codesigning jar contents..."
138+
find cryptomator-cli.app/Contents/runtime/Contents/MacOS -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
139+
for JAR_PATH in `find cryptomator-cli.app -name "*.jar"`; do
140+
if [[ `unzip -l ${JAR_PATH} | grep '.dylib\|.jnilib'` ]]; then
141+
JAR_FILENAME=$(basename ${JAR_PATH})
142+
OUTPUT_PATH=${JAR_PATH%.*}
143+
echo "Codesigning libs in ${JAR_FILENAME}..."
144+
unzip -q ${JAR_PATH} -d ${OUTPUT_PATH}
145+
find ${OUTPUT_PATH} -name '*.dylib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
146+
find ${OUTPUT_PATH} -name '*.jnilib' -exec codesign --force -s ${CODESIGN_IDENTITY} {} \;
147+
rm ${JAR_PATH}
148+
pushd ${OUTPUT_PATH} > /dev/null
149+
zip -qr ../${JAR_FILENAME} *
150+
popd > /dev/null
151+
rm -r ${OUTPUT_PATH}
152+
fi
153+
done
154+
echo "Codesigning Cryptomator-cli.app..."
155+
sed -i '' "s|###APP_IDENTIFIER_PREFIX###|${TEAM_IDENTIFIER}.|g" ../dist/mac/cryptomator-cli.entitlements
156+
sed -i '' "s|###TEAM_IDENTIFIER###|${TEAM_IDENTIFIER}|g" ../dist/mac/cryptomator-cli.entitlements
157+
codesign --force --deep --entitlements ../dist/mac/cryptomator-cli.entitlements -o runtime -s ${CODESIGN_IDENTITY} cryptomator-cli.app
158+
env:
159+
CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
160+
TEAM_IDENTIFIER: ${{ secrets.MACOS_TEAM_IDENTIFIER }}
161+
working-directory: target
162+
# ditto must be used, see https://developer.apple.com/documentation/xcode/packaging-mac-software-for-distribution#Build-a-zip-archive
163+
- name: Zip binary for notarization
164+
if: inputs.notarize
165+
run: ditto -c -k --keepParent ./target/cryptomator-cli.app ./${{ matrix.artifact-name}}
166+
- name: Setup Xcode
167+
if: inputs.notarize
168+
run: sudo xcode-select -s ${{ matrix.xcode-path}}
169+
shell: bash
170+
#would like to uses cocoalibs/xcode-notarization-action@v1, but blocked due to https://github.com/cocoalibs/xcode-notarization-action/issues/1
171+
- name: Prepare Notarization Credentials
172+
if: inputs.notarize
173+
run: |
174+
# create temporary keychain
175+
KEYCHAIN_PATH=$RUNNER_TEMP/notarization.keychain-db
176+
KEYCHAIN_PASS=$(uuidgen)
177+
security create-keychain -p "${KEYCHAIN_PASS}" ${KEYCHAIN_PATH}
178+
security set-keychain-settings -lut 900 ${KEYCHAIN_PATH}
179+
security unlock-keychain -p "${KEYCHAIN_PASS}" ${KEYCHAIN_PATH}
180+
# import credentials from secrets
181+
xcrun notarytool store-credentials "notary" --apple-id "${{ secrets.MACOS_NOTARIZATION_APPLE_ID }}" --password "${{ secrets.MACOS_NOTARIZATION_PW }}" --team-id "${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}" --keychain "${KEYCHAIN_PATH}"
182+
shell: bash
183+
- name: Notarize
184+
if: inputs.notarize
185+
run: |
186+
KEYCHAIN_PATH=$RUNNER_TEMP/notarization.keychain-db
187+
xcrun notarytool submit ${{ matrix.artifact-name }} --keychain-profile "notary" --keychain "${KEYCHAIN_PATH}" --wait
188+
shell: bash
189+
- name: Staple
190+
if: inputs.notarize
191+
run: xcrun stapler staple ./target/cryptomator-cli.app
192+
shell: bash
193+
- name: Cleanup
194+
if: ${{ always() }}
195+
run: |
196+
rm -f ./${{ matrix.artifact-name}}
197+
security delete-keychain $RUNNER_TEMP/notarization.keychain-db
198+
shell: bash
199+
continue-on-error: true
200+
- name: Zip app for distribution
201+
run: ditto -c -k --keepParent ./target/cryptomator-cli.app ./${{ matrix.artifact-name}}
98202
- name: Create detached GPG signature with key 615D449FE6E6A235
99203
run: |
100204
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
101205
echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a ./${{ matrix.artifact-name }}
102206
env:
103207
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
104208
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
209+
- uses: actions/upload-artifact@v4
210+
with:
211+
name: cryptomator-cli-mac-${{ matrix.architecture }}
212+
path: |
213+
${{ matrix.artifact-name}}
214+
*.asc
215+
if-no-files-found: error
105216
- name: Publish artefact on GitHub Releases
106217
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
107218
uses: softprops/action-gh-release@v2
@@ -110,5 +221,4 @@ jobs:
110221
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
111222
files: |
112223
${{ matrix.artifact-name }}
113-
cryptomator-cli-*.asc
114-
224+
cryptomator-cli-*.asc

.github/workflows/build-win.yml

+50-6
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,50 @@ jobs:
7878
JP_APP_VERSION: ${{ needs.prepare.outputs.semVerNum }}
7979
APP_VERSION: ${{ needs.prepare.outputs.semVerStr }}
8080
NATIVE_ACCESS_PACKAGE: org.cryptomator.jfuse.win
81-
- uses: actions/upload-artifact@v4
81+
- name: Fix permissions
82+
run: attrib -r target/cryptomator-cli/cryptomator-cli.exe
83+
shell: pwsh
84+
- name: Extract jars with DLLs for Codesigning
85+
shell: pwsh
86+
run: |
87+
Add-Type -AssemblyName "System.io.compression.filesystem"
88+
$jarFolder = Resolve-Path ".\target\Cryptomator-cli\app\mods"
89+
$jarExtractDir = New-Item -Path ".\target\jar-extract" -ItemType Directory
90+
91+
#for all jars inspect
92+
Get-ChildItem -Path $jarFolder -Filter "*.jar" | ForEach-Object {
93+
$jar = [Io.compression.zipfile]::OpenRead($_.FullName)
94+
if (@($jar.Entries | Where-Object {$_.Name.ToString().EndsWith(".dll")} | Select-Object -First 1).Count -gt 0) {
95+
#jars containing dlls extract
96+
Set-Location $jarExtractDir
97+
Expand-Archive -Path $_.FullName
98+
}
99+
$jar.Dispose()
100+
}
101+
- name: Codesign
102+
uses: skymatic/code-sign-action@v3
82103
with:
83-
name: cryptomator-cli-win-x64
84-
path: ./target/cryptomator-cli
85-
if-no-files-found: error
86-
- name: TODO Sign binaries
87-
run: echo TODO
104+
certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
105+
password: ${{ secrets.WIN_CODESIGN_P12_PW }}
106+
certificatesha1: ${{ vars.WIN_CODESIGN_CERT_SHA1 }}
107+
description: Cryptomator
108+
timestampUrl: 'http://timestamp.digicert.com'
109+
folder: target
110+
recursive: true
111+
- name: Replace DLLs inside jars with signed ones
112+
shell: pwsh
113+
run: |
114+
$jarExtractDir = Resolve-Path ".\target\jar-extract"
115+
$jarFolder = Resolve-Path ".\target\cryptomator-cli\app\mods"
116+
Get-ChildItem -Path $jarExtractDir | ForEach-Object {
117+
$jarName = $_.Name
118+
$jarFile = "${jarFolder}\${jarName}.jar"
119+
Set-Location $_
120+
Get-ChildItem -Path $_ -Recurse -File "*.dll" | ForEach-Object {
121+
# update jar with signed dll
122+
jar --file="$jarFile" --update $(Resolve-Path -Relative -Path $_)
123+
}
124+
}
88125
- name: Zip binary for release
89126
shell: pwsh
90127
run: Compress-Archive -Path .\target\cryptomator-cli -DestinationPath .\${{ env.artifact-name}}
@@ -95,6 +132,13 @@ jobs:
95132
env:
96133
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
97134
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
135+
- uses: actions/upload-artifact@v4
136+
with:
137+
name: cryptomator-cli-win-x64
138+
path: |
139+
${{ env.artifact-name}}
140+
*.asc
141+
if-no-files-found: error
98142
- name: Publish artefact on GitHub Releases
99143
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
100144
uses: softprops/action-gh-release@v2

dist/mac/cryptomator-cli.entitlements

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>com.apple.application-identifier</key>
6+
<string>###APP_IDENTIFIER_PREFIX###org.cryptomator.cli</string>
7+
<key>com.apple.developer.team-identifier</key>
8+
<string>###TEAM_IDENTIFIER###</string>
9+
<key>com.apple.security.cs.allow-jit</key>
10+
<true/>
11+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
12+
<true/>
13+
<key>com.apple.security.cs.disable-executable-page-protection</key>
14+
<true/>
15+
<key>com.apple.security.cs.disable-library-validation</key>
16+
<true/>
17+
</dict>
18+
</plist>

0 commit comments

Comments
 (0)