Skip to content

remove openvpn management protocol; add key auth types #108

remove openvpn management protocol; add key auth types

remove openvpn management protocol; add key auth types #108

Workflow file for this run

name: Build and Sign
on:
push:
branches:
- master
tags:
- 'v*'
permissions:
contents: write
jobs:
build-app:
runs-on: macos-14
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
fetch-tags: true
- name: Select Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: "16.1"
- name: Cache DerivedData
uses: actions/cache@v4
with:
path: |
~/Library/Developer/Xcode/DerivedData
~/.swiftpm
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
- name: Cache BoringSSL build
uses: actions/cache@v4
with:
path: pkcs11/vendor/boringssl/build
key: ${{ runner.os }}-boringssl-${{ hashFiles('pkcs11/vendor/boringssl/CMakeLists.txt', 'pkcs11/vendor/boringssl/crypto/**') }}
- name: Install certificate and provisioning profile
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
PROVISIONING_PROFILE_BASE64: ${{ secrets.PROVISIONING_PROFILE_BASE64 }}
INSTALLER_CERTIFICATE: ${{ secrets.INSTALLER_CERTIFICATE }}
INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.INSTALLER_CERTIFICATE_PASSWORD }}
run: |
echo "$MACOS_CERTIFICATE" | base64 --decode > signing.p12
security create-keychain -p "" build.keychain
security import signing.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign
rm signing.p12
if [ -n "$INSTALLER_CERTIFICATE" ]; then
echo "$INSTALLER_CERTIFICATE" | base64 --decode > installer.p12
security import installer.p12 -k build.keychain -P "$INSTALLER_CERTIFICATE_PASSWORD" -T /usr/bin/productsign
rm installer.p12
fi
security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "" build.keychain
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
echo "$PROVISIONING_PROFILE_BASE64" | base64 --decode > ~/Library/MobileDevice/Provisioning\ Profiles/nailed.provisionprofile
echo "$PROVISIONING_PROFILE_BASE64" | base64 --decode > build_profile.provisionprofile
- name: Build PKCS#11 dylib
run: |
cd pkcs11
make clean || true
make -j$(sysctl -n hw.ncpu)
echo "Built dylib:"
ls -la libnailed_pkcs11.dylib
file libnailed_pkcs11.dylib
- name: Sign PKCS#11 dylib
env:
CODE_SIGN_IDENTITY: ${{ vars.CODE_SIGN_IDENTITY }}
run: |
DYLIB="pkcs11/libnailed_pkcs11.dylib"
codesign --force --options runtime --timestamp \
--sign "$CODE_SIGN_IDENTITY" \
"$DYLIB"
codesign --verify --verbose=2 "$DYLIB"
echo "Dylib signature info:"
codesign -dvv "$DYLIB"
- name: Build app (Release, unsigned)
run: |
set -e
xcodebuild \
-project nailed.xcodeproj \
-scheme nailed \
-configuration Release \
-archivePath $PWD/build/nailed.xcarchive \
CODE_SIGN_IDENTITY="-" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGNING_ALLOWED=NO \
clean archive | xcpretty && exit ${PIPESTATUS[0]}
- name: Export and sign .app
env:
CODE_SIGN_IDENTITY: ${{ vars.CODE_SIGN_IDENTITY }}
DEVELOPMENT_TEAM: ${{ vars.DEVELOPMENT_TEAM }}
run: |
mkdir -p build/export
ditto build/nailed.xcarchive/Products/Applications/nailed.app build/export/nailed.app
APP="build/export/nailed.app"
cp build_profile.provisionprofile "$APP/Contents/embedded.provisionprofile"
sed "s/\$(AppIdentifierPrefix)/${DEVELOPMENT_TEAM}./g" \
nailed/nailed.entitlements > build/entitlements.plist
echo "Resolved entitlements:"
cat build/entitlements.plist
find "$APP/Contents/Resources" -name "*.bundle" -type d | while read bundle; do
echo "Signing bundle: $bundle"
codesign --force --options runtime --timestamp \
--sign "$CODE_SIGN_IDENTITY" \
"$bundle"
done
if [ -d "$APP/Contents/Frameworks" ]; then
find "$APP/Contents/Frameworks" -name "*.framework" -type d | while read framework; do
echo "Signing framework: $framework"
codesign --force --options runtime --timestamp \
--sign "$CODE_SIGN_IDENTITY" \
"$framework"
done
fi
codesign --force --options runtime --timestamp \
--entitlements build/entitlements.plist \
--sign "$CODE_SIGN_IDENTITY" \
"$APP"
codesign --verify --verbose=2 "$APP"
echo "Signature info:"
codesign -dvv "$APP"
echo "Embedded entitlements:"
codesign -d --entitlements - "$APP" 2>/dev/null || true
echo "Signature verification passed"
- name: Create installer package
env:
INSTALLER_SIGN_IDENTITY: ${{ vars.INSTALLER_SIGN_IDENTITY }}
run: |
chmod +x scripts/build-pkg.sh
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
VERSION="${GITHUB_REF#refs/tags/v}"
else
VERSION="0.0.0-dev"
fi
scripts/build-pkg.sh \
"build/export/nailed.app" \
"pkcs11/libnailed_pkcs11.dylib" \
"build/nailed.pkg" \
"$INSTALLER_SIGN_IDENTITY" \
"$VERSION"
echo "Package created:"
ls -la build/nailed.pkg
if [ -n "$INSTALLER_SIGN_IDENTITY" ]; then
pkgutil --check-signature build/nailed.pkg
fi
- name: Upload app PKG artifact
uses: actions/upload-artifact@v4
with:
name: nailed-pkg
path: build/nailed.pkg
- name: Submit for notarization
if: startsWith(github.ref, 'refs/tags/v')
env:
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_KEY_ISSUER: ${{ secrets.APPLE_API_KEY_ISSUER }}
APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }}
run: |
mkdir -p ~/private_keys
echo "$APPLE_API_KEY_BASE64" | base64 --decode > ~/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8
xcrun notarytool submit build/nailed.pkg \
--key ~/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8 \
--key-id "$APPLE_API_KEY_ID" \
--issuer "$APPLE_API_KEY_ISSUER" \
--output-format json | tee notarization-result.json
SUBMISSION_ID=$(cat notarization-result.json | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
echo "Submission ID: $SUBMISSION_ID"
echo "$SUBMISSION_ID" > build/submission-id.txt
- name: Wait for notarization and staple
if: startsWith(github.ref, 'refs/tags/v')
env:
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_KEY_ISSUER: ${{ secrets.APPLE_API_KEY_ISSUER }}
run: |
SUBMISSION_ID=$(cat build/submission-id.txt)
echo "Waiting for notarization (up to 2 minutes)..."
if xcrun notarytool wait "$SUBMISSION_ID" \
--key ~/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8 \
--key-id "$APPLE_API_KEY_ID" \
--issuer "$APPLE_API_KEY_ISSUER" \
--timeout 2m; then
echo "Notarization completed, stapling..."
xcrun stapler staple build/nailed.pkg
xcrun stapler validate build/nailed.pkg
else
echo "error: Notarization not completed within timeout"
exit 1
fi
rm -rf ~/private_keys
- name: Upload stapled PKG
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/upload-artifact@v4
with:
name: nailed-pkg-stapled
path: build/nailed.pkg
- name: Upload submission ID
if: failure()
uses: actions/upload-artifact@v4
with:
name: notarization-submission
path: build/submission-id.txt
build-openvpn:
runs-on: macos-14
env:
OPENSSL_VERSION: "3.5.5"
LZO_VERSION: "2.10"
LZ4_VERSION: "1.10.0"
PKCS11_HELPER_VERSION: "1.30.0"
OPENVPN_VERSION: "2.7.0"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install certificate
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
INSTALLER_CERTIFICATE: ${{ secrets.INSTALLER_CERTIFICATE }}
INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.INSTALLER_CERTIFICATE_PASSWORD }}
run: |
echo "$MACOS_CERTIFICATE" | base64 --decode > signing.p12
security create-keychain -p "" build.keychain
security import signing.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign
rm signing.p12
if [ -n "$INSTALLER_CERTIFICATE" ]; then
echo "$INSTALLER_CERTIFICATE" | base64 --decode > installer.p12
security import installer.p12 -k build.keychain -P "$INSTALLER_CERTIFICATE_PASSWORD" -T /usr/bin/productsign
rm installer.p12
fi
security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "" build.keychain
- name: Cache source tarballs
uses: actions/cache@v4
with:
path: openvpn-build/_work/sources
key: openvpn-sources-${{ env.OPENSSL_VERSION }}-${{ env.LZO_VERSION }}-${{ env.LZ4_VERSION }}-${{ env.PKCS11_HELPER_VERSION }}-${{ env.OPENVPN_VERSION }}
- name: Cache static libraries
uses: actions/cache@v4
with:
path: openvpn-build/_work/staging
key: openvpn-staging-${{ runner.os }}-${{ runner.arch }}-${{ env.OPENSSL_VERSION }}-${{ env.LZO_VERSION }}-${{ env.LZ4_VERSION }}-${{ env.PKCS11_HELPER_VERSION }}
- name: Build OpenVPN
env:
CODESIGN_IDENTITY: ${{ vars.CODE_SIGN_IDENTITY }}
INSTALLER_IDENTITY: ${{ vars.INSTALLER_SIGN_IDENTITY }}
run: |
cd openvpn-build
chmod +x build-openvpn.sh
./build-openvpn.sh
- name: Verify build
run: |
openvpn-build/output/openvpn --version
otool -L openvpn-build/output/openvpn
codesign -dvv openvpn-build/output/openvpn 2>&1
pkgutil --check-signature openvpn-build/output/*.pkg
- name: Upload OpenVPN package
uses: actions/upload-artifact@v4
with:
name: openvpn-pkg
path: openvpn-build/output/*.pkg
- name: Submit for notarization
if: startsWith(github.ref, 'refs/tags/v')
env:
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_KEY_ISSUER: ${{ secrets.APPLE_API_KEY_ISSUER }}
APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }}
run: |
mkdir -p ~/private_keys
echo "$APPLE_API_KEY_BASE64" | base64 --decode > ~/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8
xcrun notarytool submit openvpn-build/output/*.pkg \
--key ~/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8 \
--key-id "$APPLE_API_KEY_ID" \
--issuer "$APPLE_API_KEY_ISSUER" \
--output-format json | tee notarization-result.json
SUBMISSION_ID=$(python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" < notarization-result.json)
echo "Submission ID: $SUBMISSION_ID"
echo "$SUBMISSION_ID" > openvpn-submission-id.txt
- name: Wait for notarization and staple
if: startsWith(github.ref, 'refs/tags/v')
env:
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_KEY_ISSUER: ${{ secrets.APPLE_API_KEY_ISSUER }}
run: |
SUBMISSION_ID=$(cat openvpn-submission-id.txt)
echo "Waiting for notarization..."
xcrun notarytool wait "$SUBMISSION_ID" \
--key ~/private_keys/AuthKey_${APPLE_API_KEY_ID}.p8 \
--key-id "$APPLE_API_KEY_ID" \
--issuer "$APPLE_API_KEY_ISSUER" \
--timeout 10m
echo "Notarization completed, stapling..."
xcrun stapler staple openvpn-build/output/*.pkg
xcrun stapler validate openvpn-build/output/*.pkg
rm -rf ~/private_keys
- name: Upload stapled OpenVPN package
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/upload-artifact@v4
with:
name: openvpn-pkg-stapled
path: openvpn-build/output/*.pkg
- name: Upload submission ID
if: failure()
uses: actions/upload-artifact@v4
with:
name: openvpn-notarization-submission
path: openvpn-submission-id.txt
release:
if: startsWith(github.ref, 'refs/tags/v')
needs: [build-app, build-openvpn]
runs-on: ubuntu-latest
steps:
- name: Download nailed package
uses: actions/download-artifact@v4
with:
name: nailed-pkg-stapled
path: release-assets
- name: Download OpenVPN package
uses: actions/download-artifact@v4
with:
name: openvpn-pkg-stapled
path: release-assets
- name: List release assets
run: ls -lh release-assets/
- name: Create release
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
VERSION="${GITHUB_REF#refs/tags/}"
mv release-assets/nailed.pkg "release-assets/nailed-${VERSION}.pkg"
PRERELEASE_FLAG=""
if [[ "$VERSION" == *-rc* ]]; then
PRERELEASE_FLAG="--prerelease"
fi
gh release create "$VERSION" \
--title "$VERSION" \
--generate-notes \
$PRERELEASE_FLAG \
release-assets/*