diff --git a/Makefile.in b/Makefile.in
index f2ae43c06c..d72e3d33bd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -878,8 +878,11 @@ distclean: clean
src/pam/Makefile \
src/platform/Makefile \
src/platform/${MKAFS_OSTYPE}/Makefile \
- src/platform/DARWIN/growlagent/Makefile \
+ src/platform/DARWIN/AFSPreference/Info.plist \
src/platform/DARWIN/PrivilegedHelper/Makefile \
+ src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist \
+ src/platform/DARWIN/PrivilegedHelper/privhelper.c \
+ src/platform/DARWIN/growlagent/Makefile \
src/procmgmt/Makefile \
src/procmgmt/test/Makefile \
src/ptserver/Makefile \
diff --git a/configure.ac b/configure.ac
index dc1a18a2d3..1be327bc78 100644
--- a/configure.ac
+++ b/configure.ac
@@ -110,8 +110,11 @@ AC_CONFIG_FILES([
src/pam/Makefile
src/platform/Makefile
src/platform/${MKAFS_OSTYPE}/Makefile
- src/platform/DARWIN/growlagent/Makefile
+ src/platform/DARWIN/AFSPreference/Info.plist
src/platform/DARWIN/PrivilegedHelper/Makefile
+ src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist
+ src/platform/DARWIN/PrivilegedHelper/privhelper.c
+ src/platform/DARWIN/growlagent/Makefile
src/procmgmt/Makefile
src/procmgmt/test/Makefile
src/ptserver/Makefile
diff --git a/src/cf/options.m4 b/src/cf/options.m4
index f128b3630b..f559d30ada 100644
--- a/src/cf/options.m4
+++ b/src/cf/options.m4
@@ -263,6 +263,21 @@ AC_ARG_WITH([dot],
[use graphviz dot to generate dependency graphs with doxygen (defaults to autodetect)]),
[], [with_dot="maybe"])
+AC_ARG_WITH([macos-app-key],
+ AS_HELP_STRING([--with-macos-app-key=key],
+ [macOS: use the given app key to sign the code (optional, defaults to no key)]),
+ [AC_SUBST([MACOS_APP_KEY], [$withval])])
+
+AC_ARG_WITH([macos-inst-key],
+ AS_HELP_STRING([--with-macos-inst-key=key],
+ [macOS: use the given inst key to sign the installer (optional, defaults to no key)]),
+ [AC_SUBST([MACOS_INST_KEY], [$withval])])
+
+AC_ARG_WITH([macos-keychain-profile],
+ AS_HELP_STRING([--with-macos-keychain-profile=profile],
+ [macOS: use the given keychain profile to notarize the package (optional, defaults to no profile)]),
+ [AC_SUBST([MACOS_KEYCHAIN_PROFILE], [$withval])])
+
enable_login="no"
])
@@ -312,6 +327,32 @@ else
VFSCK="vfsck"
fi
fi
+
+AS_IF([test "x$with_macos_app_key" != "x"], [
+ # Retrieve the Team ID (OU field) associated with a certificate. MACOS_TEAM_ID is extracted from the
+ # certificate subject using openssl and awk.
+ #
+ # Example subject string:
+ # subject=UID=SKMME9E2Y8, CN=Developer ID Application: Org (SKMME9E2Y8), OU=SKMME9E2Y8, O=org, C=US
+ macos_app_key="$with_macos_app_key"
+ AC_MSG_CHECKING([for macOS team ID])
+
+ macos_cert=$(security find-certificate -c "$macos_app_key" -p 2>/dev/null)
+ AS_IF([test x"$macos_cert" = x],
+ [AC_MSG_ERROR([Failed to retrieve the certificate for app key: $macos_app_key])])
+
+ macos_subject=$(echo "$macos_cert" | openssl x509 -noout -subject 2>/dev/null)
+ AS_IF([test x"$macos_subject" = x],
+ [AC_MSG_ERROR([Failed to process the certificate using openssl])])
+
+ MACOS_TEAM_ID=$(echo "$macos_subject" | awk 'BEGIN { FS="OU=" } {print $[]2}' | awk 'BEGIN { FS="," } {print$[]1}')
+ AS_IF([test x"$MACOS_TEAM_ID" = x],
+ [AC_MSG_ERROR([Failed to extract the macOS Team ID])])
+
+ AC_MSG_RESULT([$MACOS_TEAM_ID])
+ AC_SUBST([MACOS_TEAM_ID])
+])
+
])
AC_DEFUN([OPENAFS_MORE_OPTION_TESTS],[
diff --git a/src/packaging/MacOS/pkgbuild.sh.in b/src/packaging/MacOS/pkgbuild.sh.in
index 4a95b0ab9e..15129587c2 100644
--- a/src/packaging/MacOS/pkgbuild.sh.in
+++ b/src/packaging/MacOS/pkgbuild.sh.in
@@ -29,11 +29,11 @@ anypass=0
PASS1=
PASS2=
-APP_KEY=
-INST_KEY=
+APP_KEY="@MACOS_APP_KEY@"
+INST_KEY="@MACOS_INST_KEY@"
DEST_DIR=
CSDB=
-KEYCHAIN_PROFILE=
+KEYCHAIN_PROFILE="@MACOS_KEYCHAIN_PROFILE@"
CODESIGN_OPTS=
diff --git a/src/platform/DARWIN/AFSPreference/.gitignore b/src/platform/DARWIN/AFSPreference/.gitignore
index 43e35a4674..1e8c27a9a0 100644
--- a/src/platform/DARWIN/AFSPreference/.gitignore
+++ b/src/platform/DARWIN/AFSPreference/.gitignore
@@ -5,3 +5,4 @@ build/*
*.mode2v3
*.perspectivev3
config
+Info.plist
diff --git a/src/platform/DARWIN/AFSPreference/Info.plist b/src/platform/DARWIN/AFSPreference/Info.plist.in
similarity index 89%
rename from src/platform/DARWIN/AFSPreference/Info.plist
rename to src/platform/DARWIN/AFSPreference/Info.plist.in
index a8f5b1b741..f330871cd3 100644
--- a/src/platform/DARWIN/AFSPreference/Info.plist
+++ b/src/platform/DARWIN/AFSPreference/Info.plist.in
@@ -30,13 +30,10 @@
OpenAFS
NSPrincipalClass
AFSCommanderPref
-
-
diff --git a/src/platform/DARWIN/PrivilegedHelper/.gitignore b/src/platform/DARWIN/PrivilegedHelper/.gitignore
index 6a9f03e6cb..c2a06e907d 100644
--- a/src/platform/DARWIN/PrivilegedHelper/.gitignore
+++ b/src/platform/DARWIN/PrivilegedHelper/.gitignore
@@ -3,3 +3,5 @@
# to check that you haven't inadvertently ignored any tracked files.
/org.openafs.privhelper
+/privhelper-info.plist
+/privhelper.c
diff --git a/src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist b/src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist.in
similarity index 80%
rename from src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist
rename to src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist.in
index 48aca78b21..2552c152c5 100644
--- a/src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist
+++ b/src/platform/DARWIN/PrivilegedHelper/privhelper-info.plist.in
@@ -10,12 +10,9 @@
privhelper
CFBundleVersion
1.0
-
-
diff --git a/src/platform/DARWIN/PrivilegedHelper/privhelper.c b/src/platform/DARWIN/PrivilegedHelper/privhelper.c.in
similarity index 99%
rename from src/platform/DARWIN/PrivilegedHelper/privhelper.c
rename to src/platform/DARWIN/PrivilegedHelper/privhelper.c.in
index 1a9669e29f..6182441b79 100644
--- a/src/platform/DARWIN/PrivilegedHelper/privhelper.c
+++ b/src/platform/DARWIN/PrivilegedHelper/privhelper.c.in
@@ -69,9 +69,6 @@
*
* "certificate leaf[subject.OU] = @MACOS_TEAM_ID@" means the code was signed
* by us.
- *
- * Replace @MACOS_TEAM_ID@ by your team ID. For example:
- * "certificate leaf[subject.OU] = SKMME9E2Y8"
*/
#define CLI_SIGNATURES "((identifier \"com.apple.systempreferences.legacyLoader.x86_64\" and anchor apple) or " \
"(identifier \"com.apple.systempreferences.legacyLoader.arm64\" and anchor apple) or " \