Allow disabling of deep signing on macos

This commit is contained in:
Caelan Sayler
2025-02-06 21:08:18 +00:00
committed by Caelan
parent 459cc0caf3
commit bc54e03f06
6 changed files with 62 additions and 20 deletions

View File

@@ -66,6 +66,8 @@ public class PackTask : MSBuildAsyncTask
public string? SignInstallIdentity { get; set; }
public string? SignEntitlements { get; set; }
public bool SignDisableDeep { get; set; }
public string? NotaryProfile { get; set; }
@@ -80,6 +82,7 @@ public class PackTask : MSBuildAsyncTask
public bool SkipVelopackAppCheck { get; set; }
public string? SignParameters { get; set; }
public string? AzureTrustedSignFile { get; set; }
public string? SignExclude { get; set; }

View File

@@ -79,6 +79,7 @@
SignAppIdentity="$(VelopackSignAppIdentity)"
SignInstallIdentity="$(VelopackSignInstallIdentity)"
SignEntitlements="$(VelopackSignEntitlements)"
SignDisableDeep="$(VelopackSignDisableDeep)"
NotaryProfile="$(VelopackNotaryProfile)"
Keychain="$(VelopackKeychain)"
BundleId="$(VelopackBundleId)"

View File

@@ -73,7 +73,6 @@ public class OsxPackCommandRunner : PackageBuilder<OsxPackOptions>
{
var helper = new OsxBuildTools(Log);
var keychainPath = Options.Keychain;
var monoBundlePath = Path.Combine(packDir, "Contents", "MonoBundle");
string entitlements = Options.SignEntitlements;
if (String.IsNullOrEmpty(entitlements)) {
@@ -82,40 +81,72 @@ public class OsxPackCommandRunner : PackageBuilder<OsxPackOptions>
entitlements = HelperFile.VelopackEntitlements;
}
void InnerSign()
void InnerSign(Action<int> signProgress)
{
if (Directory.Exists(monoBundlePath)) {
Log.Warn("Detected invalid Xamarin MonoBundle, fixing code signing...");
var files = Directory.EnumerateFiles(monoBundlePath).ToArray();
int processed = 0;
Parallel.ForEach(files, new ParallelOptions() { MaxDegreeOfParallelism = 4}, (file) => {
helper.CodeSign(Options.SignAppIdentity, entitlements, file, false, keychainPath);
Interlocked.Increment(ref processed);
progress(Math.Min((int)(processed * 100d / files.Length), 95));
});
Thread.Sleep(100);
if (Options.SignDisableDeep) {
// when --signDisableDeep is used, we expect the user to have signed everything before calling velopack
// we only need to sign what we added (UpdateMac) and then the final .app bundle
Log.Warn("Code signing with --signDisableDeep means that Velopack will only sign binaries it adds, " +
"along with the final .app bundle. Please ensure all other binaries and frameworks are signed " +
"properly before calling velopack.");
Log.Info("Code signing Velopack binaries...");
var structure = new OsxStructureBuilder(packDir);
var updateMacPath = Path.Combine(structure.MacosDirectory, "UpdateMac");
helper.CodeSign(Options.SignAppIdentity, entitlements, updateMacPath, false, keychainPath);
signProgress(50);
Log.Info("Code signing application bundle...");
helper.CodeSign(Options.SignAppIdentity, entitlements, packDir, false, keychainPath);
signProgress(100);
} else {
// dotnet macos tfm's (xamarin) incorrectly store binaries in "MonoBundle" so are not signed by --deep
var monoBundlePath = Path.Combine(packDir, "Contents", "MonoBundle");
if (Directory.Exists(monoBundlePath)) {
Log.Warn("Detected invalid Xamarin MonoBundle, fixing code signing...");
var files = Directory.EnumerateFiles(monoBundlePath).ToArray();
int processed = 0;
Parallel.ForEach(
files,
new ParallelOptions() { MaxDegreeOfParallelism = 4 },
(file) => {
helper.CodeSign(Options.SignAppIdentity, entitlements, file, false, keychainPath);
Interlocked.Increment(ref processed);
signProgress(Math.Min((int) (processed * 100d / files.Length), 90));
});
Thread.Sleep(100); // not sure why but things break without this
}
// sign the rest of the .app with --deep to recursively sign
// this does not work 100% of the time, but it does work in a surprising number of cases so it is the default
// use --signDisableDeep to disable this behavior, which requires you to sign things before calling velopack
Log.Info("Code signing application bundle recursively (with --deep)...");
signProgress(90);
helper.CodeSign(Options.SignAppIdentity, entitlements, packDir, true, keychainPath);
signProgress(100);
}
Log.Info("Code signing application bundle...");
progress(-1); // indeterminate
helper.CodeSign(Options.SignAppIdentity, entitlements, packDir, true, keychainPath);
}
// code signing all mach-o binaries
if (!string.IsNullOrEmpty(Options.SignAppIdentity) && !string.IsNullOrEmpty(Options.NotaryProfile)) {
var zipPath = Path.Combine(TempDir.FullName, "notarize.zip");
InnerSign();
InnerSign(CoreUtil.CreateProgressDelegate(progress, 0, 50));
helper.CreateDittoZip(packDir, zipPath);
progress(60);
helper.Notarize(zipPath, Options.NotaryProfile, keychainPath);
progress(90);
helper.Staple(packDir);
progress(95);
helper.SpctlAssessCode(packDir);
File.Delete(zipPath);
progress(100);
} else if (!string.IsNullOrEmpty(Options.SignAppIdentity)) {
Log.Warn("Package will be signed but not notarized. Missing the --notaryProfile option.");
InnerSign();
InnerSign(progress);
progress(100);
} else {
Log.Warn("Package will not be signed or notarized. Missing the --signAppIdentity and --notaryProfile options.");
}
progress(100);
return Task.CompletedTask;
}

View File

@@ -27,6 +27,8 @@ public class OsxPackOptions : OsxBundleOptions, IPackOptions
public string SignInstallIdentity { get; set; }
public string SignEntitlements { get; set; }
public bool SignDisableDeep { get; set; }
public string NotaryProfile { get; set; }

View File

@@ -36,7 +36,7 @@ public class OsxBuildTools
}
if (!String.IsNullOrEmpty(keychainPath)) {
Log.Info($"Using non-default keychain at '{keychainPath}'");
Log.Debug($"Using non-default keychain at '{keychainPath}'");
args.Add("--keychain");
args.Add(keychainPath);
}

View File

@@ -15,6 +15,8 @@ public class OsxPackCommand : OsxBundleCommand
public string SignInstallIdentity { get; private set; }
public string SignEntitlements { get; private set; }
public bool SignDisableDeep { get; private set; }
public string NotaryProfile { get; private set; }
@@ -57,6 +59,9 @@ public class OsxPackCommand : OsxBundleCommand
.MustExist()
.RequiresExtension(".entitlements");
AddOption<bool>((v) => SignDisableDeep = v, "--signDisableDeep")
.SetDescription("Disable deep signing, requires you to pre-sign your binaries.");
AddOption<string>((v) => NotaryProfile = v, "--notaryProfile")
.SetDescription("Name of profile containing Apple credentials stored with notarytool.")
.SetArgumentHelpName("NAME");