From 0563642cc1cb750c69a6471005adf36fabb2b7e3 Mon Sep 17 00:00:00 2001 From: Marcio Barbosa Date: Sat, 21 Dec 2019 19:11:57 -0800 Subject: [PATCH] macos: add script to notarize OpenAFS In order to integrate the notarization process into our existing build scripts, this patch introduces a script to automatically notarize the OpenAFS package. Change-Id: Ia9743cd39485e68de540b79b165b9d92020ad187 Reviewed-on: https://gerrit.openafs.org/13671 Tested-by: BuildBot Reviewed-by: Cheyenne Wills Reviewed-by: Andrew Deason Reviewed-by: Benjamin Kaduk --- src/packaging/MacOS/notarize.pl | 186 +++++++++++++++++++++++++++++++++++++ src/packaging/MacOS/pkgbuild.sh.in | 25 ++++- 2 files changed, 210 insertions(+), 1 deletion(-) create mode 100755 src/packaging/MacOS/notarize.pl diff --git a/src/packaging/MacOS/notarize.pl b/src/packaging/MacOS/notarize.pl new file mode 100755 index 0000000..0265630 --- /dev/null +++ b/src/packaging/MacOS/notarize.pl @@ -0,0 +1,186 @@ +#!/usr/bin/perl +# +# Copyright (c) 2019 Sine Nomine Associates +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS +# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Description: +# +# Script used to automatically notarize the OpenAFS package. +# +# On success, the following output can be expected: +# +# $ sudo notarize.pl foo@bar.com "@keychain:PASSWORD" OpenAFS.dmg +# +# notarize.pl: submitting package... +# notarize.pl: checking status... +# notarize.pl: checking status... +# notarize.pl: checking status... +# (...) +# notarize.pl: checking status... +# notarize.pl: package successfully notarized + +use strict; +use File::Which; + +sub usage { + print(STDERR "usage: notarize.pl \n"); + print(STDERR "\tusername: apple id\n"); + print(STDERR "\tpassword: password of your apple id account\n"); + print(STDERR "\tpackage: package to be notarized\n"); + print(STDERR "\tnote: must be root\n"); + print(STDERR "\t can be a reference to a keychain item.\n"); + print(STDERR "\t as cleartext is not recommended.\n"); + print(STDERR "e.g.: \$ sudo notarize.pl foo\@bar.com \"\@keychain:PASSWORD\" OpenAFS.dmg\n\n"); + exit(1); +} + +sub check_prerequisites { + my (@ARGS) = @_; + + if ($> != 0) { + print(STDERR "error: must be root\n\n"); + usage(); + } + if (scalar @ARGS != 3) { + print(STDERR "error: check arguments\n\n"); + usage(); + } + if (!which('xcrun')) { + print(STDERR "error: xcrun not found in \$PATH\n\n"); + usage(); + } + if (not -e $ARGS[2]) { + print(STDERR "error: package not found\n\n"); + } +} + +sub submit_package { + my ($username, $password, $package) = @_; + + print(STDOUT "notarize.pl: submitting package...\n"); + + my $output = qx(xcrun altool -t osx -f "$package" --primary-bundle-id org.openafs.OpenAFS --notarize-app --username "$username" --password "$password" 2>&1); + my $exitcode = $? >> 8; + + if ($exitcode) { + print(STDERR "error: $exitcode\n"); + print(STDERR $output); + exit(1); + } + # $output looks like the following sample: + # + # No errors uploading 'OpenAFS.dmg'. + # RequestUUID = 565a4d1b-9608-47a6-aba9-53136c991bb8 + $output =~ m{RequestUUID = ([A-Za-z0-9\-]+)}; + if (not defined $1) { + print(STDERR "error: uuid not found\n"); + exit(1); + } + return $1; +} + +sub check_status { + my ($username, $password, $uuid) = @_; + my $output; + my $status; + my $exitcode; + + while (1) { + print(STDOUT "notarize.pl: checking status...\n"); + $output = qx(xcrun altool --notarization-info "$uuid" --username "$username" --password "$password" 2>&1); + $exitcode = $? >> 8; + + if ($exitcode) { + print(STDERR "error: $exitcode\n"); + print(STDERR $output); + exit(1); + } + # $output looks like the following samples: + # + # First, second, ..., (N-1)'th attempts: + # + # No errors getting notarization info. + # + # Date: 2019-11-26 21:07:46 +0000 + # Hash: 4e10ebb01518de9eb007d4579006acda2d6ff773fe040d97786bcc686ec93gg1 + # RequestUUID: 565a4d1b-9608-47a6-aba9-53136c991bb8 + # Status: in progress + # + # N'th attempt: + # + # No errors getting notarization info. + # + # Date: 2019-11-26 21:07:46 +0000 + # Hash: 4e10ebb01518de9eb007d4579006acda2d6ff773fe040d97786bcc686ec93gg1 + # RequestUUID: 565a4d1b-9608-47a6-aba9-53136c991bb8 + # Status: in progress + # Status Code: 0 + # Status Message: Package Approved + $output =~ m{Status Code: (\d+)}; + if (defined $1) { + $status = $1; + last; + } + sleep(5); + } + if ($status) { + print(STDERR "error: $status (uuid: $uuid)\n"); + print(STDERR $output); + exit(1); + } +} + +sub notarize_package { + my ($package, $uuid) = @_; + + print(STDOUT "notarize.pl: notarizing package...\n"); + + my $output = qx(xcrun stapler staple -v "$package" 2>&1); + my $exitcode = $? >> 8; + + if ($exitcode) { + print(STDERR "error: package could not be notarized (uuid: $uuid)\n"); + print(STDERR $output); + exit(1); + } + print(STDOUT "notarize.pl: package successfully notarized\n"); +} + +sub main { + my (@ARGS) = @_; + + check_prerequisites(@ARGS); + my $username = $ARGS[0]; + my $password = $ARGS[1]; + my $package = $ARGS[2]; + + my $uuid = submit_package($username, $password, $package); + check_status($username, $password, $uuid); + notarize_package($package, $uuid); + + exit(0); +} +main(@ARGV); diff --git a/src/packaging/MacOS/pkgbuild.sh.in b/src/packaging/MacOS/pkgbuild.sh.in index 4c4d629..de566ea 100644 --- a/src/packaging/MacOS/pkgbuild.sh.in +++ b/src/packaging/MacOS/pkgbuild.sh.in @@ -6,10 +6,20 @@ usage() { exec >&2 echo 'Usage: pkgbuild.sh [-x] [--app-key ] [--inst-key ]' + echo ' [--apple-id ]' echo ' [--pass N] [--csdb ] ' echo echo '--app-key and --inst-key are for signing. -x prints all comamnds as ' - echo 'they are run.' + echo 'they are run. --apple-id is for notarizing.' + echo + echo 'Note: the password associated with can be a reference to a' + echo 'keychain item. Including your password as cleartext is not' + echo 'recommended. e.g.' + echo + echo '--apple-id foo@bar.com "@keychain:PASSWORD"' + echo + echo 'In this case, keychain must hold a keychain item named PASSWORD with' + echo 'an account matching foo@bar.com.' echo echo 'By default, all passes are run. Available passes:' echo ' --pass 1: prepare pkgroot' @@ -30,6 +40,8 @@ PASS2= APP_KEY= INST_KEY= +APPLE_ID= +APPLE_PW= DEST_DIR= CSDB= @@ -48,6 +60,12 @@ while [ x"$#" != x0 ] ; do INST_KEY="$1" shift ;; + --apple-id) + APPLE_ID="$1" + shift + APPLE_PW="$1" + shift + ;; --csdb) CSDB="$1" shift @@ -519,4 +537,9 @@ if [ x"$PASS2" = x1 ]; then echo echo "Created $CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME".dmg + + if [ x"$APPLE_ID" != x ] ; then + echo "Notarizing package..." + ./notarize.pl "$APPLE_ID" "$APPLE_PW" "$CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME.dmg" + fi fi -- 1.9.4