Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
Polish notarization/codesigning. Add warnings when signing arguments …
Browse files Browse the repository at this point in the history
…are missing.
  • Loading branch information
caesay committed Jun 20, 2022
1 parent e148207 commit ec71f49
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 58 deletions.
34 changes: 19 additions & 15 deletions src/Squirrel.CommandLine/OSX/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,20 @@ private static void Pack(PackOptions options)

// code signing all mach-o binaries
if (SquirrelRuntimeInfo.IsOSX && !String.IsNullOrEmpty(options.signAppIdentity) && !String.IsNullOrEmpty(options.notaryProfile)) {
HelperExe.CodeSign(options.signAppIdentity, options.signEntitlements, new []{ appBundlePath });
HelperExe.AssessCodeSign(appBundlePath);

// notarize and staple the .app before creating a Squirrel release
HelperExe.CodeSign(options.signAppIdentity, options.signEntitlements, appBundlePath);
HelperExe.CreateDittoZip(appBundlePath, zipPath);
HelperExe.Notarize(zipPath, options.notaryProfile);
HelperExe.Staple(appBundlePath);

// re-create the zip from the app with the stapled notarization
File.Delete(zipPath);
HelperExe.CreateDittoZip(appBundlePath, zipPath);
} else if (SquirrelRuntimeInfo.IsOSX && !String.IsNullOrEmpty(options.signAppIdentity)) {
HelperExe.CodeSign(options.signAppIdentity, options.signEntitlements, appBundlePath);
Log.Warn("Package was signed but will not be notarized. Must supply the --notaryProfile option.");
} else {
Log.Warn("Package will not be signed or notarized. Only supported on OSX with the --signAppIdentity and --notaryProfile options.");
}

// create a portable zip package from signed/notarized bundle
if (SquirrelRuntimeInfo.IsOSX) {
HelperExe.CreateDittoZip(appBundlePath, zipPath);
} else {
EasyZip.CreateZipFromDirectory(zipPath, appBundlePath, nestDirectory: true);
}

Expand Down Expand Up @@ -168,15 +169,18 @@ private static void Pack(PackOptions options)
releases.Add(ReleaseEntry.GenerateFromFile(newPkgPath));
ReleaseEntry.WriteReleaseFile(releases, releaseFilePath);

// create installer package and notarize
if (SquirrelRuntimeInfo.IsOSX && !String.IsNullOrEmpty(options.signInstallIdentity) && !String.IsNullOrEmpty(options.notaryProfile)) {
// create installer package, sign and notarize
if (SquirrelRuntimeInfo.IsOSX) {
var pkgPath = Path.Combine(releaseDir.FullName, options.packId + ".pkg");
if (File.Exists(pkgPath)) File.Delete(pkgPath);
HelperExe.CreateInstallerPkg(appBundlePath, pkgPath, options.signInstallIdentity);
HelperExe.Notarize(pkgPath, options.notaryProfile);
HelperExe.Staple(pkgPath);
if (!String.IsNullOrEmpty(options.signInstallIdentity) && !String.IsNullOrEmpty(options.notaryProfile)) {
HelperExe.Notarize(pkgPath, options.notaryProfile);
} else {
Log.Warn("Package installer (.pkg) will not be Notarized. " +
"This is supported with the --signInstallIdentity and --notaryProfile arguments.");
}
} else {
Log.Warn("Package installer (.pkg) will not be created. Only supported on OSX with the --signInstallIdentity and --notaryProfile options.");
Log.Warn("Package installer (.pkg) will not be created - this is only supported on OSX.");
}

Log.Info("Done.");
Expand Down
71 changes: 32 additions & 39 deletions src/Squirrel.CommandLine/OSX/HelperExe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static string UpdateMacPath
public static string SquirrelEntitlements => FindHelperFile("Squirrel.entitlements");

[SupportedOSPlatform("osx")]
public static void CodeSign(string identity, string entitlements, string[] files)
public static void CodeSign(string identity, string entitlements, string filePath)
{
if (String.IsNullOrEmpty(entitlements)) {
Log.Info("No codesign entitlements provided, using default dotnet entitlements: " +
Expand All @@ -36,14 +36,21 @@ public static void CodeSign(string identity, string entitlements, string[] files
"--deep",
"--timestamp",
"--options", "runtime",
"--entitlements", entitlements
"--entitlements", entitlements,
filePath
};

args.AddRange(files);

Log.Info($"Preparing to codesign package...");
Log.Info($"Beginning codesign for package...");

Console.WriteLine(InvokeAndThrowIfNonZero("codesign", args, null));

var args2 = new List<string> {
"--assess",
"-vvvv",
filePath
};

Console.WriteLine(InvokeAndThrowIfNonZero("spctl", args2, null));

Log.Info("codesign completed successfully");
}
Expand All @@ -52,6 +59,8 @@ public static void CodeSign(string identity, string entitlements, string[] files
public static void CreateInstallerPkg(string appBundlePath, string pkgOutputPath, string signIdentity)
{
Log.Info($"Creating installer '.pkg' for app at '{appBundlePath}'");

if (File.Exists(pkgOutputPath)) File.Delete(pkgOutputPath);

using var _1 = Utility.GetTempDirectory(out var tmp);
using var _2 = Utility.GetTempDirectory(out var tmpPayload1);
Expand All @@ -66,59 +75,49 @@ public static void CreateInstallerPkg(string appBundlePath, string pkgOutputPath
var pkgPlistPath = Path.Combine(tmp, "tmp.plist");
InvokeAndThrowIfNonZero("pkgbuild", new[] { "--analyze", "--root", tmpPayload1, pkgPlistPath }, null);
InvokeAndThrowIfNonZero("plutil", new[] { "-replace", "BundleIsRelocatable", "-bool", "NO", pkgPlistPath }, null);

var pkg1Path = Path.Combine(tmpPayload2, "1.pkg");
string[] args1 = {
"--root", tmpPayload1,
"--component-plist", pkgPlistPath,
"--install-location", "/Applications",
pkg1Path,
};

InvokeAndThrowIfNonZero("pkgbuild", args1, null);

// create product package that installs to home dir
var distributionPath = Path.Combine(tmp, "distribution.xml");
InvokeAndThrowIfNonZero("productbuild", new[] { "--synthesize", "--package", pkg1Path, distributionPath }, null);

// disable local system installation and build final package
var distXml = File.ReadAllLines(distributionPath).ToList();
distXml.Insert(2, "<domains enable_anywhere=\"false\" enable_currentUserHome=\"true\" enable_localSystem=\"false\" />");
File.WriteAllLines(distributionPath, distXml);
List<string> args2 = new () {
"--distribution", distributionPath,

List<string> args2 = new() {
"--distribution", distributionPath,
"--package-path", tmpPayload2,
pkgOutputPath
};

if (!String.IsNullOrEmpty(signIdentity)) {
args2.Add("--sign");
args2.Add(signIdentity);
} else {
Log.Warn("No Installer signing identity provided. The '.pkg' will not be signed.");
}

InvokeAndThrowIfNonZero("productbuild", args2, null);

Log.Info("Installer created successfully");
}

[SupportedOSPlatform("osx")]
public static void Staple(string filePath)
{
Log.Info($"Stapling Notarization to '{filePath}'");
var args = new List<string> {
"stapler", "staple", filePath,
};
Console.WriteLine(InvokeAndThrowIfNonZero("xcrun", args, null));
Log.Info("Installer created successfully");
}

[SupportedOSPlatform("osx")]
public static void Notarize(string filePath, string keychainProfileName)
{
Log.Info($"Preparing to Notarize '{filePath}'. This will upload to Apple and usually takes minutes, but could take hours.");

var args = new List<string> {
"notarytool",
"submit",
Expand All @@ -127,7 +126,7 @@ public static void Notarize(string filePath, string keychainProfileName)
"--wait",
filePath
};

var ntresultjson = PlatformUtil.InvokeProcess("xcrun", args, null, CancellationToken.None);
Log.Info(ntresultjson.StdOutput);

Expand All @@ -146,13 +145,17 @@ public static void Notarize(string filePath, string keychainProfileName)
var result = PlatformUtil.InvokeProcess("xcrun", logargs, null, CancellationToken.None);
Log.Warn(result.StdOutput);
}

throw new Exception("Notarization failed: " + ntresultjson.StdOutput);
}
} catch (JsonReaderException) {
throw new Exception("Notarization failed: " + ntresultjson.StdOutput);
}

Log.Info("Notarization completed successfully");

Log.Info($"Stapling Notarization to '{filePath}'");
Console.WriteLine(InvokeAndThrowIfNonZero("xcrun", new[] { "stapler", "staple", filePath }, null));
}

private class NotaryToolResult
Expand All @@ -165,6 +168,8 @@ private class NotaryToolResult
[SupportedOSPlatform("osx")]
public static void CreateDittoZip(string folder, string outputZip)
{
if (File.Exists(outputZip)) File.Delete(outputZip);

var args = new List<string> {
"-c",
"-k",
Expand All @@ -178,17 +183,5 @@ public static void CreateDittoZip(string folder, string outputZip)
Log.Info($"Creating ditto bundle '{outputZip}'");
InvokeAndThrowIfNonZero("ditto", args, null);
}

[SupportedOSPlatform("osx")]
public static void AssessCodeSign(string filePath)
{
var args = new List<string> {
"--assess",
"-vvvv",
filePath
};

Console.WriteLine(InvokeAndThrowIfNonZero("spctl", args, null));
}
}
}
11 changes: 7 additions & 4 deletions src/Squirrel.CommandLine/OSX/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ public PackOptions()
Add("e=|mainExe=", "The file {NAME} of the main executable", v => mainExe = v);
Add("i=|icon=", "{PATH} to the .icns file for this bundle", v => icon = v);
Add("noDelta", "Skip the generation of delta packages", v => noDelta = true);
Add("signAppIdentity=", "The {SUBJECT} name of the cert to use for app code signing", v => signAppIdentity = v);
Add("signInstallIdentity=", "The {SUBJECT} name of the cert to use for installation packages", v => signInstallIdentity = v);
Add("signEntitlements=", "{PATH} to entitlements file for hardened runtime", v => signEntitlements = v);
Add("notaryProfile=", "{NAME} of profile containing Apple credentials stored with notarytool", v => notaryProfile = v);

if (SquirrelRuntimeInfo.IsOSX) {
Add("signAppIdentity=", "The {SUBJECT} name of the cert to use for app code signing", v => signAppIdentity = v);
Add("signInstallIdentity=", "The {SUBJECT} name of the cert to use for installation packages", v => signInstallIdentity = v);
Add("signEntitlements=", "{PATH} to entitlements file for hardened runtime", v => signEntitlements = v);
Add("notaryProfile=", "{NAME} of profile containing Apple credentials stored with notarytool", v => notaryProfile = v);
}
}

public override void Validate()
Expand Down

0 comments on commit ec71f49

Please sign in to comment.