From 09ef08ce5fe11639d06e90964a928a2a4870a1f9 Mon Sep 17 00:00:00 2001 From: Dominic Letz Date: Mon, 8 Jan 2024 12:11:19 +0100 Subject: [PATCH] Added codesign test --- .github/workflows/test.yml | 2 ++ lib/mix/tasks/create_keychain.ex | 12 ++++--- lib/package/macos.ex | 54 +++++++++++++++----------------- test/codesign_test.exs | 9 ++++++ test/priv/main.c | 4 +++ test/test_helper.exs | 1 + 6 files changed, 49 insertions(+), 33 deletions(-) create mode 100644 test/codesign_test.exs create mode 100644 test/priv/main.c create mode 100644 test/test_helper.exs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e614dae..e5c748f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,3 +48,5 @@ jobs: mix local.rebar --force mix deps.get mix desktop.create_keychain + export MACOS_KEYCHAIN=$HOME/Library/Keychains/macos-build.keychain + mix test test/codesign_test.exs diff --git a/lib/mix/tasks/create_keychain.ex b/lib/mix/tasks/create_keychain.ex index a577ff4..3f4d931 100644 --- a/lib/mix/tasks/create_keychain.ex +++ b/lib/mix/tasks/create_keychain.ex @@ -19,11 +19,17 @@ defmodule Mix.Tasks.Desktop.CreateKeychain do security(["create-keychain", "-p", pass, name]) System.put_env("MACOS_KEYCHAIN", full_path) + security(["list-keychains", "-s", name]) + # security(["default-keychain", "-s", name]) + security(["unlock-keychain", "-p", pass, name]) + security(["set-keychain-settings", "-t", "3600", "-u", name]) + security([ "import", "#{mac_tools}/Apple Worldwide Developer Relations Certification Authority.pem", "-k", - "macos-build.keychain" + "macos-build.keychain", + "-A" ]) file = "tmp.pem" @@ -31,10 +37,6 @@ defmodule Mix.Tasks.Desktop.CreateKeychain do uids = locate_uid(file) || raise "Could not locate UID in PEM" maybe_import_pem(file, uids) - security(["list-keychains", "-s", name]) - # security(["default-keychain", "-s", "macos-build.keychain"]) - security(["unlock-keychain", "-p", pass, name]) - security(["set-keychain-settings", "-t", "3600", "-u", name]) # https://stackoverflow.com/questions/39868578/security-codesign-in-sierra-keychain-ignores-access-control-settings-and-ui-p # https://github.com/lando/code-sign-action/blob/main/action.yml diff --git a/lib/package/macos.ex b/lib/package/macos.ex index e8340fc..a3aebd5 100644 --- a/lib/package/macos.ex +++ b/lib/package/macos.ex @@ -87,7 +87,7 @@ defmodule Desktop.Deployment.Package.MacOS do developer_id = Package.MacOS.find_developer_id() if developer_id != nil do - codesign(developer_id, root) + codesign(root) end dmg = make_dmg(pkg) @@ -369,7 +369,7 @@ defmodule Desktop.Deployment.Package.MacOS do def maybe_import_pem(file, uids) do with nil <- do_find_developer_id(uids) do - cmd("security", ["import", file, "-k", keychain()]) + cmd("security", ["import", file, "-k", keychain(), "-A"]) with nil <- do_find_developer_id(uids) do raise "Failed to import PEM for uid #{inspect(uids)}" @@ -484,7 +484,7 @@ defmodule Desktop.Deployment.Package.MacOS do |> Enum.uniq() end - def codesign(developer_id, root) do + def codesign(root) do # Codesign all executable code in the package with timestamp and # hardened runtime. This is a prerequisite for notarization. to_sign = find_binaries(root) @@ -505,40 +505,38 @@ defmodule Desktop.Deployment.Package.MacOS do # Signing binaries in app directory Enum.chunk_every(to_sign, 10) |> Enum.each(fn chunk -> - IO.puts("Signing #{inspect(chunk)}") - - cmd!( - "codesign", - [ - "--keychain", - keychain(), - "-f", - "-s", - developer_id, - "--timestamp", - "--options=runtime", - "--entitlements", - entitlements | chunk - ] - ) + codesign_executable(chunk, entitlements: entitlements) end) # Signing app directory itself - cmd!( - "codesign", + codesign_executable(root, entitlements: entitlements) + end + + def codesign_executable(objects, opts \\ []) do + args = [ "--keychain", keychain(), "-f", "-s", - developer_id, + find_developer_id(), "--timestamp", - "--options=runtime", - "--entitlements", - entitlements, - root - ] - ) + "--options=runtime" + ] ++ add_codesign_args(opts) ++ List.wrap(objects) + + cmd!("codesign", args) + end + + defp add_codesign_args([{:entitlements, entitlements} | opts]) do + ["--entitlements", entitlements] ++ add_codesign_args(opts) + end + + defp add_codesign_args([]) do + [] + end + + defp add_codesign_args(other) do + raise "Unknown codesign args #{inspect(other)}" end # openssl genrsa -out mock.key 2048 diff --git a/test/codesign_test.exs b/test/codesign_test.exs new file mode 100644 index 0000000..2b3e9f9 --- /dev/null +++ b/test/codesign_test.exs @@ -0,0 +1,9 @@ +defmodule CodesignTest do + use ExUnit.Case + + test "codesign a new binary" do + {_, 0} = System.cmd("gcc", ["test/priv/main.c", "-o", "unsigned_main"]) + Desktop.Deployment.Package.MacOS.codesign_executable("unsigned_main") + File.rm("unsigned_main") + end +end diff --git a/test/priv/main.c b/test/priv/main.c new file mode 100644 index 0000000..379d14a --- /dev/null +++ b/test/priv/main.c @@ -0,0 +1,4 @@ + +int main() { + return 0; +} \ No newline at end of file diff --git a/test/test_helper.exs b/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start()