Skip to content

Commit 2d98cfc

Browse files
committed
improved code signing & implemented notarization for macOS
fixes #50
1 parent 8a1f683 commit 2d98cfc

File tree

7 files changed

+459
-44
lines changed

7 files changed

+459
-44
lines changed

release/.env.example

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Environment variables for build scripts.
4+
# Copy this file to ".env" and enter your environment variables.
5+
#
6+
7+
# In order to sign the application for yourself, you need to obtain a Developer ID from Apple and set the
8+
# name of your signature key in the APPLE_CODESIGN_KEY variable.
9+
APPLE_CODESIGN_KEY=""
10+
11+
# In order to notarize the application, you need to obtain a Developer ID from Apple and set its email address in the
12+
# APPLE_DEVELOPER_MAIL variable.
13+
APPLE_DEVELOPER_MAIL=""
14+
15+
# In order to notarize the application, you need to obtain a Developer ID from Apple and set its password in the
16+
# APPLE_DEVELOPER_PASSWORD variable. If no password is provided, you need to enter it manually during the notification
17+
# process.
18+
#
19+
# Notice: You can't use the global password. Instead you need to login at https://appleid.apple.com/ with your account
20+
# and create an application specific password.
21+
APPLE_DEVELOPER_PASSWORD=""

release/.gitignore

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
signed
2-
target
3-
website
1+
/.env
2+
/signed
3+
/notarized
4+
/target
5+
/website

release/codesign-macos.sh

Lines changed: 81 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,59 +19,99 @@
1919
# ----------------------------------------------------------------------------
2020
# NOTICE: This script has to be executed on a macOS system with the
2121
# required certificate available. In order to sign the application for
22-
# yourself, you need to obtain a Developer ID from Apple and set the
23-
# KEY variable accordingly.
22+
# yourself, you need to obtain a Developer ID from Apple and set some
23+
# environment variables in the ".env" file. If it is not available, create a
24+
# copy from ".env.example".
2425
# ----------------------------------------------------------------------------
2526

26-
KEY="Developer ID Application: Andreas Rudolph (H48THMS543)"
27-
DIR=$( cd $( dirname ${BASH_SOURCE[0]} ) && pwd )
28-
TARGET_DIR="$DIR/target"
29-
SIGNED_DIR="$DIR/signed"
30-
TEMP_DIR="$TARGET_DIR/codesign"
27+
DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
28+
TARGET_DIR="${DIR}/target"
29+
SIGNED_DIR="${DIR}/signed"
3130
FOUND="0"
3231
set -e
3332

34-
mkdir -p "$SIGNED_DIR"
35-
export LANG="en_US.UTF-8"
33+
APPLE_CODESIGN_KEY=""
34+
if [[ -f "${DIR}/.env" ]]; then
35+
source "${DIR}/.env"
36+
fi
3637

37-
for f in ${TARGET_DIR}/*.macos-*.tar.gz; do
38+
if [[ -z "${APPLE_CODESIGN_KEY}" ]]; then
39+
echo "ERROR: No signature key was specified!"
40+
exit 1
41+
fi
42+
43+
mkdir -p "${SIGNED_DIR}"
44+
export LANG="en_US.UTF-8"
3845

39-
if [[ "$FOUND" == "0" ]]; then
40-
echo ""
41-
printf "\e[1m\e[92m=======================================================================\e[0m\n"
42-
printf "\e[1m\e[92m Unlocking keychain...\e[0m\n"
43-
printf "\e[1m\e[92m=======================================================================\e[0m\n"
44-
echo ""
45-
security unlock-keychain
46-
fi
46+
for f in "${TARGET_DIR}"/*.macos-*.tar.gz; do
4747

48-
FOUND="1"
48+
if [[ "${FOUND}" == "0" ]]; then
4949
echo ""
5050
printf "\e[1m\e[92m=======================================================================\e[0m\n"
51-
printf "\e[1m\e[92m Processing $(basename "$f")...\e[0m\n"
51+
printf "\e[1m\e[92m Unlocking keychain...\e[0m\n"
5252
printf "\e[1m\e[92m=======================================================================\e[0m\n"
5353
echo ""
54-
rm -Rf "$TEMP_DIR"
55-
mkdir -p "$TEMP_DIR"
56-
tar xfz "$f" -C "$TEMP_DIR"
57-
pkg="$(ls -1 "$TEMP_DIR")"
58-
codesign --deep -s "$KEY" "$TEMP_DIR/$pkg"
59-
echo "Verifying signature:"
60-
codesign -d --verbose=4 "$TEMP_DIR/$pkg"
61-
echo ""
62-
echo "Verifying access for Gatekeeper:"
63-
spctl --assess --verbose=4 --type execute "$TEMP_DIR/$pkg"
64-
echo ""
65-
echo "Storing signed application bundle at:"
66-
echo "$SIGNED_DIR/$(basename "$f")"
67-
rm -f "$SIGNED_DIR/$(basename "$f")"
68-
cd "$TEMP_DIR"
69-
tar cfz "$SIGNED_DIR/$(basename "$f")" "$pkg"
54+
security unlock-keychain
55+
fi
56+
57+
FOUND="1"
58+
archive="$(basename "${f}")"
59+
archive_name="$(basename "${archive}" ".tar.gz")"
60+
signed_dir="${SIGNED_DIR}/${archive_name}"
61+
rm -Rf "${signed_dir}"
62+
mkdir -p "${signed_dir}"
63+
64+
echo ""
65+
printf "\e[1m\e[92m=======================================================================\e[0m\n"
66+
printf "\e[1m\e[92m Processing %s...\e[0m\n" "${archive}"
67+
printf "\e[1m\e[92m=======================================================================\e[0m\n"
68+
69+
echo ""
70+
echo "Extracting application bundle."
71+
tar xfz "${f}" -C "${signed_dir}"
72+
pkg="$(ls -1 "${signed_dir}")"
73+
signed_bundle="${signed_dir}/${pkg}"
74+
75+
echo ""
76+
echo "Signing application bundle at:"
77+
echo ""
78+
echo "${signed_bundle}"
79+
codesign --deep --force --verify --sign "${APPLE_CODESIGN_KEY}" --options runtime "${signed_bundle}"
80+
81+
echo ""
82+
echo "Verifying signature:"
83+
codesign --verify --verbose=4 "${signed_bundle}"
84+
#codesign --display --verbose=4 "${signed_bundle}"
85+
86+
echo ""
87+
echo "Verifying access for Gatekeeper:"
88+
spctl --assess --verbose=4 --type execute "${signed_dir}/${pkg}"
89+
90+
echo ""
91+
echo "Compressing application bundle to:"
92+
signed_tar="${signed_dir}/${archive_name}.tar.gz"
93+
echo "${signed_tar}"
94+
cd "${signed_dir}"
95+
rm -f "${signed_tar}"
96+
tar cfz "${signed_tar}" "$(basename "${signed_bundle}")"
97+
98+
echo ""
99+
echo "Compressing application bundle to:"
100+
signed_zip="${signed_dir}/${archive_name}.zip"
101+
echo "${signed_zip}"
102+
cd "${signed_dir}"
103+
rm -f "${signed_zip}"
104+
# According to Apples documentation "Customizing the Notarization Workflow" at
105+
# https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow
106+
# we can't use the ZIP command, as it leads to problems in the notarization process.
107+
# Therefore we're using ditto instead.
108+
#zip -r -q "${signed_zip}" "$(basename "${signed_bundle}")"
109+
ditto -c -k --keepParent "$(basename "${signed_bundle}")" "${signed_zip}"
110+
70111
done
71112

72-
if [[ "$FOUND" == "0" ]]; then
73-
echo "ERROR: No macOS packages were found at:"
74-
echo "$TARGET_DIR"
113+
if [[ "${FOUND}" == "0" ]]; then
114+
echo "ERROR: No macOS packages were found at:"
115+
echo "${TARGET_DIR}"
116+
exit 1
75117
fi
76-
77-
rm -Rf "$TEMP_DIR"

release/notarize-macos-finish.sh

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Creates a notarized application bundle after upload and approval.
4+
# Copyright 2015-2021 OpenIndex.de
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
# ----------------------------------------------------------------------------
20+
# NOTICE: This script has to be executed on a macOS system with the
21+
# required certificate available. In order to sign the application for
22+
# yourself, you need to obtain a Developer ID from Apple and set some
23+
# environment variables in the ".env" file. If it is not available, create a
24+
# copy from ".env.example".
25+
# ----------------------------------------------------------------------------
26+
27+
# ----------------------------------------------------------------------------
28+
# Further information about notarization:
29+
# https://successfulsoftware.net/2018/11/16/how-to-notarize-your-software-on-macos/
30+
# https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow
31+
# ----------------------------------------------------------------------------
32+
33+
DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
34+
SIGNED_DIR="${DIR}/signed"
35+
NOTARIZED_DIR="${DIR}/notarized"
36+
FOUND="0"
37+
set -e
38+
39+
if [[ -n "${1}" ]]; then
40+
# Using application bundle, provided as first command line argument.
41+
PKG_DIR="${SIGNED_DIR}/$(basename "$1")"
42+
else
43+
# Otherwise, showing available application bundles and let the user select.
44+
for f in "${SIGNED_DIR}"/*; do
45+
if [[ -d "${f}" ]]; then
46+
n=$(basename "${f}")
47+
if [[ -f "${f}/${n}.zip" ]]; then
48+
if [[ "${FOUND}" == "0" ]]; then
49+
echo ""
50+
printf "\e[1m\e[92m=======================================================================\e[0m\n"
51+
printf "\e[1m\e[92m Available signed macOS application bundles:\e[0m\n"
52+
printf "\e[1m\e[92m=======================================================================\e[0m\n"
53+
echo ""
54+
fi
55+
FOUND="1"
56+
echo "${n}"
57+
fi
58+
fi
59+
done
60+
61+
if [[ "${FOUND}" == "0" ]]; then
62+
echo "ERROR: No signed macOS packages were found at:"
63+
echo "${SIGNED_DIR}"
64+
exit 1
65+
fi
66+
67+
echo ""
68+
echo "Which of these bundles were successfully notarized and are ready for release?"
69+
read -r -p "Enter one of the packages names listed above: " pkg
70+
71+
PKG_DIR="${SIGNED_DIR}/${pkg}"
72+
fi
73+
74+
if [[ ! -d "${PKG_DIR}" ]]; then
75+
echo ""
76+
echo "ERROR: The application bundle does not exist in \"${SIGNED_DIR}\"!"
77+
exit 1
78+
fi
79+
80+
PKG_NAME="$(basename "${PKG_DIR}")"
81+
82+
PKG_BUNDLE=$(find "${PKG_DIR}" -maxdepth 1 -type d -name "*.app" | head -1)
83+
if [[ ! -d "${PKG_BUNDLE}" ]]; then
84+
echo ""
85+
echo "ERROR: Na application bundle found within \"${SIGNED_DIR}\"!"
86+
exit 1
87+
fi
88+
89+
echo ""
90+
printf "\e[1m\e[92m=======================================================================\e[0m\n"
91+
printf "\e[1m\e[92m Finishing notarization for %s...\e[0m\n" "${PKG_NAME}"
92+
printf "\e[1m\e[92m=======================================================================\e[0m\n"
93+
echo ""
94+
95+
xcrun stapler staple -v "${PKG_BUNDLE}"
96+
97+
mkdir -p "${NOTARIZED_DIR}"
98+
NOTARIZED_ARCHIVE="${NOTARIZED_DIR}/${PKG_NAME}.tar.gz"
99+
100+
echo ""
101+
printf "\e[1m\e[92m=======================================================================\e[0m\n"
102+
printf "\e[1m\e[92m Archiving notarized application bundle...\e[0m\n"
103+
printf "\e[1m\e[92m=======================================================================\e[0m\n"
104+
echo ""
105+
echo "Archiving notarized application bundle to:"
106+
echo "${NOTARIZED_ARCHIVE}"
107+
cd "${PKG_DIR}"
108+
tar cfz "${NOTARIZED_ARCHIVE}" "$(basename "${PKG_BUNDLE}")"
109+
110+
echo ""
111+
echo "It seems, that the notarization process finished successfully!"
112+
echo "Please check the output above for the message:"
113+
echo " \"The staple and validate action worked!\""
114+
echo ""

0 commit comments

Comments
 (0)