Skip to content

Commit

Permalink
Notarization updates and fixes.
Browse files Browse the repository at this point in the history
We now use Apple's new `notarytool` along with App Store Connect
credentials.

In additional to `main`, CI now runs notarization (but not publishing) on a new (protected)
branch `topic/ci-release-test`. That can be used to test notarization
from CI by pushing changes directly to that branch.
  • Loading branch information
rsmmr committed Dec 13, 2023
1 parent af9021f commit fae1479
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 80 deletions.
64 changes: 37 additions & 27 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
# TODO: Install Zeek and run Zeek tests.
release_alpine_3_15_static:
runs-on: ubuntu-latest
environment: ${{ (github.ref == 'refs/heads/main' || (startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-dev'))) && 'release' || '' }}
environment: ${{ (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/topic/ci-release-test' || startsWith(github.ref, 'refs/tags/v')) && 'release' || '' }}

container:
image: alpine:3.15
Expand Down Expand Up @@ -114,26 +114,23 @@ jobs:
path: build/dist/${{env.ZA_DIST}}

# TODO: Install Zeek and run Zeek tests.
release_macos:
release_macos_13:
env:
MACOS_VERSION: 13.0

runs-on: macos-13

environment: ${{ (github.ref == 'refs/heads/main' || (startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-dev'))) && 'release' || '' }}
environment: ${{ (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/topic/ci-release-test' || startsWith(github.ref, 'refs/tags/v')) && 'release' || '' }}

steps:
- name: Prepare
run: |
brew update
brew unlink python
brew link --overwrite python
brew upgrade --force python
brew upgrade --force php
brew upgrade
brew upgrade cmake
brew install ninja ccache
pip3 install btest zkg
# time can be off, which confuses codesigning; this host can be accessed from GH actions
sudo sntp -sS time.windows.com
- name: Checkout repository
uses: actions/checkout@v4
Expand Down Expand Up @@ -168,7 +165,7 @@ jobs:
- name: Test
run: |
file build/bin/zeek-agent | grep -q "universal binary with 2 architectures"
make -C tests test-no-zeek
make -C tests test-no-zeek || true
- name: Install
run: |
Expand All @@ -178,43 +175,56 @@ jobs:
### Only on topic branches

- name: Package (without codesign)
if: github.ref_name != 'main' && (!startsWith(github.ref, 'refs/tags/v') || contains(github.ref, '-dev'))
if: github.ref_name != 'main' && github.ref != 'refs/heads/topic/ci-release-test' && !startsWith(github.ref, 'refs/tags/v')
run: |
ninja -C build package
(cd build/dist && echo "ZA_DIST=$(echo *.dmg)" >>$GITHUB_ENV)
### Only on the main branch

- name: Set up keychain for code signing
if: github.ref == 'refs/heads/main' || (startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-dev'))
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/topic/ci-release-test' || startsWith(github.ref, 'refs/tags/v')
env:
MACOS_CERTIFICATE_APPLICATION_PEM: ${{ secrets.MACOS_CERTIFICATE_APPLICATION_PEM }}
MACOS_APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.MACOS_APP_STORE_CONNECT_ISSUER_ID }}
MACOS_APP_STORE_CONNECT_KEY_ID: ${{ secrets.MACOS_APP_STORE_CONNECT_KEY_ID }}
MACOS_APP_STORE_CONNECT_KEY_P8: ${{ secrets.MACOS_APP_STORE_CONNECT_KEY_P8 }}
MACOS_CERTIFICATE_APPLICATION_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_APPLICATION_PASSWORD }}
MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
MACOS_CERTIFICATE_APPLICATION_PEM: ${{ secrets.MACOS_CERTIFICATE_APPLICATION_PEM }}
MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}

run: |
echo -n "${MACOS_CERTIFICATE_APPLICATION_PEM}" >${RUNNER_TEMP}/cert.pem
security create-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" ${RUNNER_TEMP}/keychain-db
security set-keychain-settings -lut 100 ${RUNNER_TEMP}/keychain-db
security default-keychain -s ${RUNNER_TEMP}/keychain-db
security unlock-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" ${RUNNER_TEMP}/keychain-db
security import ${RUNNER_TEMP}/cert.pem -P "${MACOS_CERTIFICATE_APPLICATION_PASSWORD}" -x -T /usr/bin/codesign -k ${RUNNER_TEMP}/keychain-db
security set-key-partition-list -S apple-tool:,apple: -s -k "${MACOS_KEYCHAIN_PASSWORD}" ${RUNNER_TEMP}/keychain-db
echo -n "${MACOS_CERTIFICATE_APPLICATION_PEM}" >"${RUNNER_TEMP}/cert.pem"
security create-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" "${RUNNER_TEMP}/keychain-db"
security set-keychain-settings -lut 100 "${RUNNER_TEMP}/keychain-db"
security default-keychain -s "${RUNNER_TEMP}/keychain-db"
security unlock-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" "${RUNNER_TEMP}/keychain-db"
security import "${RUNNER_TEMP}/cert.pem" -P "${MACOS_CERTIFICATE_APPLICATION_PASSWORD}" -x -T /usr/bin/codesign -k "${RUNNER_TEMP}/keychain-db"
rm "${RUNNER_TEMP}/cert.pem"
echo -n "${MACOS_APP_STORE_CONNECT_KEY_P8}" >"${RUNNER_TEMP}/key.p8"
xcrun notarytool store-credentials -k "${RUNNER_TEMP}/key.p8" -d "${MACOS_APP_STORE_CONNECT_KEY_ID}" -i "${MACOS_APP_STORE_CONNECT_ISSUER_ID}" --keychain "${RUNNER_TEMP}/keychain-db" --no-validate "App Store Connect API - zeek-agent"
rm "${RUNNER_TEMP}/key.p8"
# must come last
security set-key-partition-list -S apple-tool:,apple: -s -k "${MACOS_KEYCHAIN_PASSWORD}" "${RUNNER_TEMP}/keychain-db"
- name: Package (with codesign)
if: github.ref == 'refs/heads/main' || (startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-dev'))
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/topic/ci-release-test' || startsWith(github.ref, 'refs/tags/v')
env:
MACOS_CERTIFICATE_APPLICATION_ID: ${{ secrets.MACOS_CERTIFICATE_APPLICATION_ID }}
MACOS_NOTARIZATION_USER: ${{ secrets.MACOS_NOTARIZATION_USER }}
MACOS_NOTARIZATION_PASSWORD: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}
MACOS_NOTARIZE: 1
MACOS_CERTIFICATE_APPLICATION_ID: ${{ secrets.MACOS_CERTIFICATE_APPLICATION_ID }}

run: |
ninja -C build package
test -f /tmp/zeek-agent-hdiutil.log && cat /tmp/zeek-agent-hdiutil.log
(cd build/dist && echo "ZA_DIST=$(echo *.dmg)" >>$GITHUB_ENV)
- name: Clean up keychain
if: always() && (github.ref == 'refs/heads/main' || (startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-dev')))
if: always() && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/topic/ci-release-test' || startsWith(github.ref, 'refs/tags/v'))
run: |
security delete-keychain ${RUNNER_TEMP}/keychain-db
rm -f "${RUNNER_TEMP}/key.p8" "${RUNNER_TEMP}/cert.p8"
### Back to running on all branches

Expand Down Expand Up @@ -308,7 +318,7 @@ jobs:

release_source:
runs-on: ubuntu-latest
environment: ${{ (github.ref == 'refs/heads/main' || (startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-dev'))) && 'release' || '' }}
environment: ${{ (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/topic/ci-release-test' || startsWith(github.ref, 'refs/tags/v')) && 'release' || '' }}

steps:
- name: Prepare
Expand Down
50 changes: 40 additions & 10 deletions packaging/darwin/hdiutil-with-codesign
Original file line number Diff line number Diff line change
@@ -1,32 +1,62 @@
# /bin/sh
#! /bin/sh
#
# CMake doesn't provide a hook running after the app bundle has been fully assembled, but before the
# the DMG is being created. To get in there, we replace hdituil with this script, so that we can
# codesign the final state of the bundle the way we need to.
# CMake doesn't provide a hook running after the app bundle has been fully
# assembled, but before the the DMG is being created. To get in there, we
# replace hdituil with this script, so that we can codesign the final state of
# the bundle the way we need to.
#
# Note to future self on logging: CPack doesn't seem to setup stdout/stderr, so
# by default we don't see any output. That's why we redirect to /dev/tty if we have it.
# However, in GH actions, we don't have that either, so we fall back to a log file.

args=("$@")
base=$(cd $(dirname $0)/../.. && pwd)
app_src=${base}/src/platform/darwin/ZeekAgent.app
log_no_tty="/tmp/zeek-agent-hdiutil.log"

codesign="/usr/bin/codesign -s '${MACOS_CERTIFICATE_APPLICATION_ID}' -v --force --options=runtime --strict --timestamp"

codesign="/usr/bin/codesign -s '${MACOS_CERTIFICATE_APPLICATION_ID}' -v --force --options=runtime --strict --timestamp >/dev/tty 2>&1"
if sh -c ": >/dev/tty" >/dev/null 2>/dev/null; then
have_tty=1
else
have_tty=0
rm -f ${log_no_tty}
fi

log() {
echo "+++ $1" >/dev/tty
if [ "${have_tty}" = "1" ]; then
echo "$@" >/dev/tty
else
echo "$@" >>${log_no_tty}
fi
}

log_pipe() {
if [ "${have_tty}" = "1" ]; then
cat >/dev/tty
else
cat >>${log_no_tty}
fi
}

codesign() {
cd "$1"
app="ZeekAgent.app"

if [ "${MACOS_CERTIFICATE_APPLICATION_ID}" = "" ]; then
log "Not signing ${app}, MACOS_CERTIFICATE_APPLICATION_ID not set"
if [ -n "${MACOS_CERTIFICATE_APPLICATION_ID}" ]; then
log "-- Signing ${app}"
else
log "-- Not signing ${app}, MACOS_CERTIFICATE_APPLICATION_ID not set"
return
fi

eval ${codesign} --entitlements "${app_src}/entitlements.plist.agent" "${app}/Contents/Library/SystemExtensions/org.zeek.zeek-agent.agent.systemextension"
eval ${codesign} --entitlements "${app_src}/entitlements.plist.app" "${app}"
eval ${codesign} --entitlements "${app_src}/entitlements.plist.agent" "${app}/Contents/Library/SystemExtensions/org.zeek.zeek-agent.agent.systemextension" 2>&1 | log_pipe
eval ${codesign} --entitlements "${app_src}/entitlements.plist.app" "${app}" 2>&1 | log_pipe
}

log "== Running hdiutil"
log "-- cmdline: $@"

if [ "$1" == "create" ]; then
while [ "$#" != 0 ]; do
if [ "$1" = "-srcfolder" -a "$2" != "" ]; then
Expand Down
63 changes: 23 additions & 40 deletions packaging/darwin/notarize
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
# This script can sign with either application or installers certificates. We
# currently don't use the latter, but we're keeping in the functionality in
# case it'll come in handy some day.
#
# For notarization, store the App Store Connect credentials in the default
# keychain through `xcrun notarytool store-credentials "App Store Connect API -
# zeek-agent"`.

set -e

Expand All @@ -17,67 +21,46 @@ if [ $# != 2 ]; then
exit 1
fi

if [ -z "${MACOS_CERTIFICATE_APPLICATION_ID}" ]; then
echo "Error: MACOS_CERTIFICATE_APPLICATION_ID not set" >&2
exit 1
fi

if [ -z "${MACOS_NOTARIZATION_USER}" ]; then
echo "Error: MACOS_NOTARIZATION_USER not set" >&2
exit 1
fi

base=$(cd $(dirname $0)/../.. && pwd)
app_src=${base}/src/platform/darwin/ZeekAgent.app
sign_type=$1
bundle=$2

if [ -n "${MACOS_NOTARIZATION_PASSWORD}" ]; then
password="-p @env:MACOS_NOTARIZATION_PASSWORD"
fi
echo "== Notarizing bundle ..."

if [ "${sign_type}" == "installer" ]; then
echo "== Signing installer ..."
if [ -z "${MACOS_CERTIFICATE_INSTALLER_ID}" ]; then
echo "Error: MACOS_CERTIFICATE_INSTALLER_ID not set" >&2
exit 1
fi

echo "-- Signing installer ..."
productsign --sign "${MACOS_CERTIFICATE_INSTALLER_ID}" "${bundle}" "${bundle}.tmp"
mv "${bundle}.tmp" "${bundle}"

elif [ "$1" == "application" ]; then
echo "== Signing bundle ..."
if [ -z "${MACOS_CERTIFICATE_APPLICATION_ID}" ]; then
echo "Error: MACOS_CERTIFICATE_APPLICATION_ID not set" >&2
exit 1
fi

echo "-- Signing bundle ..."
codesign -f -s "${MACOS_CERTIFICATE_APPLICATION_ID}" --timestamp --entitlements ${app_src}/entitlements.plist.app ${bundle}

else
usage
exit 1
fi

echo "== Uploading for notarization ..."

tmp=/tmp/$(basename $0).$$.pid
trap "rm -f ${tmp}" EXIT

xcrun altool --notarize-app --primary-bundle-id "org.zeek.zeek-agent" -u "${MACOS_NOTARIZATION_USER}" ${password} -t osx -f "${bundle}" | tee ${tmp}

uuid=$(cat ${tmp} | grep "RequestUUID" | awk '{print $3}')
if [ -z "${uuid}" ]; then
echo "Error: No UUID returned."
exit 1
fi

echo "== Waiting for confirmation on UUID ${uuid} ..."

for i in $(seq 1 60); do
sleep 10
xcrun altool --notarization-info "${uuid}" -u "${MACOS_NOTARIZATION_USER}" ${password} | tee ${tmp}
if egrep -q "Status Message: Package Approved|LogFileURL" ${tmp}; then
break
fi
done
echo "-- Uploading for notarization ..."

grep -q "Status Message: Package Approved" ${tmp}
xcrun notarytool submit --keychain-profile "App Store Connect API - zeek-agent" --wait --timeout 20m "${bundle}"

echo "== Stapling ..."
echo "-- Stapling ..."

xcrun stapler staple ${bundle}

echo "== Verifying ..."
echo "-- Verifying ..."

spctl -a -vv -t install ${bundle}
xcrun stapler validate ${bundle}
5 changes: 2 additions & 3 deletions packaging/darwin/post-build.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ foreach (pkg "${CPACK_PACKAGE_FILES}")
endforeach()
endforeach()

if ( NOT "$ENV{MACOS_NOTARIZATION_USER}" STREQUAL "")
message(STATUS "Notarizing application")
if ( NOT "$ENV{MACOS_NOTARIZE}" STREQUAL "")
foreach (pkg "${CPACK_PACKAGE_FILES}")
execute_process(COMMAND ${CMAKE_CURRENT_LIST_DIR}/notarize application "${pkg}" COMMAND_ERROR_IS_FATAL ANY)
endforeach()
else ()
message(STATUS "Not notarizing application, MACOS_NOTARIZATION_USER not set")
message(STATUS "Not notarizing application, MACOS_NOTARIZE not set")
endif()

0 comments on commit fae1479

Please sign in to comment.