Skip to content

Commit

Permalink
Jared/sign in embed script (apple#37)
Browse files Browse the repository at this point in the history
To more easily integrate into developer CI systems, deferring code signing until the generated Xcode project is being built is ideal. To support this, I've updated the shell script that embeds libraries to also code sign binaries when embedding. Importantly, this final code sign step will use the same code signing identity that developers configure the generated Xcode project to use. This ensures that the code signing identity used for the rest of the app is also used to sign the native libraries copied into the generated Xcode project by Apple.Core.

So now developers can:

1. Build and sign libraries when they build with build.py, if they choose. This allows down stream consumers of the plug-ins to validate binary origin.
2. Consume plug-in libraries in their projects without having to pay attention to code signing identity; all libraries will automatically be re-signed with the code signing identity used by Xcode when building the generated Xcode project.
  • Loading branch information
jared-marsau authored and GitHub Enterprise committed Apr 22, 2024
1 parent f0911d8 commit a882aa5
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 23 deletions.
21 changes: 9 additions & 12 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
from datetime import datetime
from pathlib import Path

from scripts.python.upi_cli_argument_options import PluginID, PlatformID, ConfigID, BuildActionID, CleanActionID
from scripts.python.upi_cli_argument_options import PluginID, PlatformID, ConfigID, BuildActionID, CleanActionID, CodeSignActionID
from scripts.python.upi_build_context import BuildContext
from scripts.python.upi_utility import PromptColor, Printer

# Set a script version to track evolution
build_script_version = "2.2.0"
build_script_version = "2.2.1"

# -----------------
# Prompt Formatting
Expand Down Expand Up @@ -74,8 +74,7 @@
argument_parser.add_argument("-m", "--platforms", dest="platform_list", nargs='*', default=[PlatformID.ALL], help=f"Selects the desired platforms to target when building native libraries. Possible values are: {PlatformID.IOS}, {PlatformID.IOS_SIMULATOR}, {PlatformID.MACOS}, {PlatformID.TVOS}, {PlatformID.TVOS_SIMULATOR}, {PlatformID.VISIONOS}, {PlatformID.VISIONOS_SIMULATOR}, {PlatformID.SIMULATORS}, {PlatformID.DEVICES} or {PlatformID.ALL}. Default is: {PlatformID.ALL}")
argument_parser.add_argument("-b", "--build-action", dest="build_actions", nargs='*', default=[BuildActionID.BUILD, BuildActionID.PACK], help=f"Sets the build actions for the selected plug-ins. Possible values are: {BuildActionID.BUILD}, {BuildActionID.PACK}, {BuildActionID.NONE} or {BuildActionID.ALL}. Defaults are: {BuildActionID.BUILD}, {BuildActionID.PACK}")
argument_parser.add_argument("-bc","--build-config", dest="build_config", default=ConfigID.ALL, help=f"Sets the build configuration to compile. Possible values are: {ConfigID.RELEASE}, {ConfigID.DEBUG}, or {ConfigID.ALL} which builds all other configs. Default is: {ConfigID.ALL}")
argument_parser.add_argument("-c", "--codesign-identity", dest="codesign_identity", default=str(), help=f"String which uniquely identifies your codesign identity, typically represented by a hash. Only applied if build actions include {BuildActionID.BUILD}")
argument_parser.add_argument("-sc", "--skip-codesign", dest="skip_codesign", action="store_true", help=f"Skips codesign and all user prompts.")
argument_parser.add_argument("-c", "--codesign-identity", dest="codesign_identity", default=str(), help=f"Signs compiled native libraries with provided code signing identity hash or prompts the user to select from a list of identities on the system when {CodeSignActionID.PROMPT} is passed.")
argument_parser.add_argument("-u", "--unity-installation-root", dest="unity_installation_root", default="", help="Root path to search for Unity installations when building tests. Note: performs a full recursive search of the given directory.")
argument_parser.add_argument("-o", "--output-path", dest="output_path", default=CTX.build_output_path, help=f"Build result path for final packages. Default: {CTX.build_output_path}")
argument_parser.add_argument("-k", "--clean-action", dest="clean_actions", nargs='*', default=[CleanActionID.NONE], help=f"Sets the clean actions for the selected plug-ins. Possible values are: {CleanActionID.NATIVE}, {CleanActionID.PACKAGES}, {CleanActionID.TESTS}, {CleanActionID.NONE}, or {CleanActionID.ALL}. Defaults to no clean action.")
Expand Down Expand Up @@ -117,14 +116,11 @@ def Main():
f"\n Clean Actions({Printer.Bold('-k')}): {CTX.printer.Context(' '.join(build_args.clean_actions))}"
f"\n Force Clean({Printer.Bold('-f')}): {CTX.printer.Context('Yes (-f set)' if build_args.force_clean else 'No (-f not set)')}"
f"\n Build Tests({Printer.Bold('-t')}): {CTX.printer.Context('Yes (-t set)' if build_args.build_tests else 'No (-t not set)')}"
f"\n Skip Codesign({Printer.Bold('-sc')}): {CTX.printer.Context('Yes (-sc set)' if build_args.skip_codesign else 'No (-sc not set)')}")
f"\n Codesigning Identity({Printer.Bold('-c')}): {CTX.printer.Context(build_args.codesign_identity if len(build_args.codesign_identity) > 0 else 'None supplied.')}")

if len(build_args.unity_installation_root) > 0:
print(f" Unity Installation Root({Printer.Bold('-u')}): {CTX.printer.Context(build_args.unity_installation_root)}")

if not build_args.skip_codesign:
print(f" Codesigning Identity({Printer.Bold('-c')}): {CTX.printer.Context(build_args.codesign_identity if len(build_args.codesign_identity) > 0 else 'None supplied.')}")

if build_args.build_tests:
print(f" Test Output Path({Printer.Bold('-to')}): {CTX.printer.Context(build_args.test_output_path)}")

Expand Down Expand Up @@ -358,10 +354,11 @@ def Main():
CTX.printer.MessageWithContext("Native library build using: ", f"Xcode {xcode_version} ({xcode_build_number})", "\n")
CTX.printer.InfoMessage(f"If this is incorrect, please update your environment with {Printer.Bold('xcode-select')}. (Call \'{Printer.Bold('xcode-select -h')}\' from the command line for more info.)")

if build_args.skip_codesign:
CTX.codesign_hash = ""
else:
CTX.codesign_hash = build_args.codesign_identity if len(build_args.codesign_identity) > 0 else toolchain.PromptForCodesignIdentity(CTX.printer)
if len(build_args.codesign_identity) > 0:
if build_args.codesign_identity == CodeSignActionID.PROMPT:
CTX.codesign_hash = toolchain.PromptForCodesignIdentity(CTX.printer)
else:
CTX.codesign_hash = build_args.codesign_identity

CTX.printer.SectionHeading("Gather Unity Installation Info")

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# CHANGELOG
All notable changes to this project will be documented in this file.

## [3.1.2] - 2024-04-11
### Added
- *Embed Apple Plug-In Libraries* script injected into the Unity-generated Xcode project will now sign native libraries using the same codesign identity configured for that Xcode project.
- This simplifies the codesign workflow substantially, now libraries won't need to be signed when running the build script.

## [3.1.1] - 2024-04-08
### Added
- Adding support for tracking of Apple Unity plug-ins without native libraries.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,10 @@ public static void ProcessExportPlistOptions(AppleBuildProfile appleBuildProfile
/// <returns></returns>
private static string GenerateEmbedNativeLibraryShellScript(string projectRelativeNativeLibraryRoot)
{
string embedNativeLibraryShellScript = "# Apple Unity Plug-in Embed libraries shell script\n"
string embedNativeLibraryShellScript = "# Apple Unity Plug-in Sign & Embed libraries shell script\n"
+ "# Copyright © 2024 Apple, Inc. All rights reserved.\n"
+ "# This script is added to the generated Xcode project by the Apple.Core plug-in.\n"
+ "# Please see AppleNativeLibraryUtility.cs in the Apple.Core plug-in for more information.\n"
+ "# Please see AppleBuild.cs in the Apple.Core plug-in for more information.\n"
+ "dstFrameworkFolder=\"$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH\"\n"
+ "dstBundleFolder=\"$BUILT_PRODUCTS_DIR/$PLUGINS_FOLDER_PATH\"\n"
+ $"APPLE_PLUGIN_LIBRARY_ROOT=\"$PROJECT_DIR/{projectRelativeNativeLibraryRoot}\"\n"
Expand All @@ -393,13 +393,21 @@ private static string GenerateEmbedNativeLibraryShellScript(string projectRelati
+ " echo \" Embedding Apple plug-in framework $filename\"\n"
+ " echo \" Source: $item\"\n"
+ " echo \" Destination: $dstFrameworkFolder/$filename\"\n"
+ " if [ ! -z \"$EXPANDED_CODE_SIGN_IDENTITY\" ]; then\n"
+ " echo \" Code signing identity: $EXPANDED_CODE_SIGN_IDENTITY\"\n"
+ " codesign --force --sign $EXPANDED_CODE_SIGN_IDENTITY --timestamp\\=none --generate-entitlement-der $item\n"
+ " fi\n"
+ " ditto $item \"$dstFrameworkFolder/$filename\"\n"
+ " break\n"
+ " elif [[ $item = *'.bundle' ]]; then\n"
+ " filename=$(basename $item)\n"
+ " echo \" Embedding Apple plug-in bundle $filename\"\n"
+ " echo \" Source: $item\"\n"
+ " echo \" Destination: $dstBundleFolder/$filename\"\n"
+ " if [ ! -z \"$EXPANDED_CODE_SIGN_IDENTITY\" ]; then\n"
+ " echo \" Code signing identity: $EXPANDED_CODE_SIGN_IDENTITY\"\n"
+ " codesign --force --sign $EXPANDED_CODE_SIGN_IDENTITY --timestamp\\=none --generate-entitlement-der $item\n"
+ " fi\n"
+ " ditto $item \"$dstBundleFolder/$filename\"\n"
+ " break\n"
+ " fi\n"
Expand All @@ -413,10 +421,10 @@ private static string GenerateEmbedNativeLibraryShellScript(string projectRelati
+ " exit 1\n"
+ "fi";

string debugEmbedNativeLibraryShellScript = "# Apple Unity Plug-in Embed libraries shell script\n"
string debugEmbedNativeLibraryShellScript = "# Apple Unity Plug-in Sign & Embed libraries shell script\n"
+ "# Copyright © 2024 Apple, Inc. All rights reserved.\n"
+ "# This script is added to the generated Xcode project by the Apple.Core plug-in.\n"
+ "# Please see AppleNativeLibraryUtility.cs in the Apple.Core plug-in for more information.\n"
+ "# Please see AppleBuild.cs in the Apple.Core plug-in for more information.\n"
+ "echo \"Debug Apple Unity Plug-in Embed libraries shell script: enhanced output\"\n"
+ "echo \"***********************************************************************\"\n"
+ "dstFrameworkFolder=\"$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH\"\n"
Expand All @@ -442,13 +450,21 @@ private static string GenerateEmbedNativeLibraryShellScript(string projectRelati
+ " echo \" Embedding Apple plug-in framework $filename\"\n"
+ " echo \" Source: $item\"\n"
+ " echo \" Destination: $dstFrameworkFolder/$filename\"\n"
+ " if [ ! -z \"$EXPANDED_CODE_SIGN_IDENTITY\" ]; then\n"
+ " echo \" Code signing identity: $EXPANDED_CODE_SIGN_IDENTITY\"\n"
+ " codesign --force --sign $EXPANDED_CODE_SIGN_IDENTITY --timestamp\\=none --generate-entitlement-der $item\n"
+ " fi\n"
+ " ditto $item \"$dstFrameworkFolder/$filename\"\n"
+ " break\n"
+ " elif [[ $item = *'.bundle' ]]; then\n"
+ " filename=$(basename $item)\n"
+ " echo \" Embedding Apple plug-in bundle $filename\"\n"
+ " echo \" Source: $item\"\n"
+ " echo \" Destination: $dstBundleFolder/$filename\"\n"
+ " if [ ! -z \"$EXPANDED_CODE_SIGN_IDENTITY\" ]; then\n"
+ " echo \" Code signing identity: $EXPANDED_CODE_SIGN_IDENTITY\"\n"
+ " codesign --force --sign $EXPANDED_CODE_SIGN_IDENTITY --timestamp\\=none --generate-entitlement-der $item\n"
+ " fi\n"
+ " ditto $item \"$dstBundleFolder/$filename\"\n"
+ " break\n"
+ " fi\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "com.apple.unityplugin.core",
"displayName": "Apple.Core",
"description": "Provides project settings, post-build automation tools, and other shared functionality for Apple Unity Plug-ins.",
"version": "3.1.1",
"version": "3.1.2",
"unity": "2022.3",
"keywords": [
"apple"
Expand Down
9 changes: 9 additions & 0 deletions scripts/python/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# CHANGELOG
All notable changes to build.py and related python scripts will be noted here.

## [2.2.1] - 2024-04-11
### Updated
- Script has been updated to not sign native libraries by default now that Apple.Core has been updated to handle this step.
- Passing no codesign identity hash is no longer an issue
- Libraries can still be signed using the `-c` flag along with a passed string representing the codesign identity hash
- The string `prompt` may be passed to `-c` to instigate the script's codesign workflow which will ask the user to select from a list of codesign identities on the system
5 changes: 5 additions & 0 deletions scripts/python/upi_cli_argument_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,8 @@ class CleanActionID:

# Performs all clean actions for the selected plug-ins
ALL = "all"

# Code sign options (-c, --codesign-identity)
class CodeSignActionID:
# In general the -c flag takes a codesign identity hash as an argument, but when this argument is provided the script will enable the code signing identity selection workflow
PROMPT = "prompt"
11 changes: 5 additions & 6 deletions scripts/python/upi_toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,21 +121,20 @@ def Codesign(printer : Printer, signable_object_path : str, hash : str, logWithC

# Method prompts the user before identifying a codesign identity to use for signing newly compiled native plug-in libraries
def PromptForCodesignIdentity(printer : Printer) -> str:
printer.WarningMessage("No codesign identity provided.", "\n")
printer.InfoMessage("Recent versions of Unity require that native plug-in libraries are codesigned or they will not be loaded by the Editor or Player runtime.")
printer.Message(f"For more information about code signing, please see: {Printer.Bold('https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html')}", printer.Indent(1))

if not utility.BooleanPrompt(printer, "Would you like the script to code sign the compiled native plug-in libraries?"):
printer.Message("User opted out of code signing. Compiled libraries will not be signed and may not be loaded by Unity.")
printer.Message("User opted out of code signing.")
printer.Message(f"For more information about code signing, please see: {Printer.Bold('https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html')}", printer.Indent(1))
return ""

codesign_identities = GetCodesignIdentities()
if len(codesign_identities) == 0:
printer.WarningMessage("No codesign identities found. Compiled libraries will not be signed and may not be loaded by Unity.")
printer.WarningMessage("No codesign identities found.")
printer.Message(f"For more information about code signing, please see: {Printer.Bold('https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html')}", printer.Indent(1))
return ""

elif len(codesign_identities) == 1:
id_hash, id_name = list(codesign_identities.items())[0]
printer.InfoMessage("Only one codesign identity found.")
printer.MessageWithContext("Using codesign identity: ", f"{id_hash} {id_name}", "\n")
return id_hash

Expand Down

0 comments on commit a882aa5

Please sign in to comment.