Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sign GrandOrgue for MacOS #1835

Closed
oleg68 opened this issue Mar 9, 2024 · 23 comments · Fixed by #1864
Closed

Sign GrandOrgue for MacOS #1835

oleg68 opened this issue Mar 9, 2024 · 23 comments · Fixed by #1864

Comments

@oleg68
Copy link
Contributor

oleg68 commented Mar 9, 2024

Signing is mandatory for Apple/M1. #1831 (comment)

For signing we need

  1. To obtain a signing certificate from Apple for GrandOrgue.
  2. To adopt the build scripts for signing.
  3. To create a Github enviroment for signing.

@rousseldenis Could you help us with (1.)? Which rules are there for open source projects supported by a community? Should the certificate be a personal or one issued for organisation? Anyway could you communicate with Apple and obtain a certificate suitable for GrandOrge?

@willeke1234 Because you have built GrandOrgue locally and it works, I suppose you already have a personal developer certificate from apple. I doubt you may share it for a foreign project hosted on github, but you obviosly may test the build processus locally with your certificate and participate in (2.). Do you agree?

For (3.) there is some additional information https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development

A similar issue exists in Windows #836 but there is a workaround: to force OS to allow run GrandOrgue despite it is not signed.

@oleg68
Copy link
Contributor Author

oleg68 commented Mar 9, 2024

@willeke1234

Originally posted by @willeke1234 in #1831 (comment)

Which library is modified? Could you post here the full error message or a screenshot?

All libraries are modified. The creation and modification dates are the changed and when I verify the code signature I get:

invalid signature (code or signature have been modified)

  1. How do you verify the code signature for paticular libraries?
  2. Are only dates different, but not the library content?
  3. What policy is there for libraries: should GrandOrgue sign them or their own original signatures are still valid?

But I found the difference (paths). The following commands must be executed to code sign everything. I found Using cmake to sign target but in which script do I add what?

https://github.com/GrandOrgue/grandorgue/blob/master/cmake/BuildExecutable.cmake

You have to add

    ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD COMMAND  codesign --force -s "${CMAKE_CURRENT_BINARY_DIR}/$<TARGET_FILE_NAME:${TARGET}>")

of course, only for apple build.

Other questions:

What does the workaround in build-scripts/for-osx/prepare-osx.sh do? Is it still necessary?

Yes, it is. This script installs the all necessary build environment, tools and libraries to your mac. If we need some additional tools for code signing, installing them should be added to build-scripts/for-osx/prepare-osx.sh.

Does this affect other projects on my Mac?

Usually installing anything does not affect other projects. So it must not do this.

In build-on-osx.sh: "-DCMAKE_OSX_DEPLOYMENT_TARGET=12.1" is this still necessary? Or was it added with the workaround for macOS 10.15?

It allows GrandOrgue built on macOs 12.3 to run on 12.1.

@willeke1234
Copy link
Contributor

@oleg, @rousseldenis We don't need a signing certificate from Apple ($99/year) and I don't have one. Ad-hoc signing (free and without a certificate) will do. All it takes is running a command.

@oleg68
Copy link
Contributor Author

oleg68 commented Mar 9, 2024

If you are talking about an online signing, we need some way to identify us by apple. Otherwise any malware could be signed ad-hoc as well.

@willeke1234
Copy link
Contributor

Ad-hoc signing does not use an identity or signing certificate at all. GrandOrgue on Intel is currently unsigned but on ARM, macOS refuses to run unsigned apps. GrandOrgue will be signed at minimum to keep macOS happy. Or rather, I know it runs on my Mac, I'm not really sure it'll run on other Macs.

Step 1: tweak the build scripts so GrandOrgue builds and runs on my Mac (I'm working on it)
Step 2: build on GitHub and run on my Mac
Step 3: build on GitHub and run on other Macs without developer tools

Let's worry about a signing certificate when we're sure we need it.

@willeke1234
Copy link
Contributor

GrandOrgue builds and runs on my Mac but…

  • Extra files are added:
    GrandOrgue.app/Contents/Resources/GOIcon.ico
    GrandOrgue.app/Contents/Resources/GrandOrgue.iconset
    GrandOrgue.app/Contents/Resources/GrandOrgue.manifest
    GrandOrgue.app/Contents/Resources/GrandOrgue.rc

  • The app on the disk image (.dmg) isn't signed. I tried several CPack variables but CPack doesn't sign the app. The app must be signed after adding all files to the bundle and before adding the bundle to the disk image.

  • HomeBrew installs in /usr/local on Intel and in /opt/homebrew on ARM. The workaround in prepare-osx.sh:
    for F in $(grep -l '(, weak)\?' /usr/local/Cellar/cmake/*/share/cmake/Modules/GetPrerequisites.cmake); do
    I assume the workaround doesn't work at the moment but the app appears to work.

How do I fix all this? I don't want to change things haphazardly.

I get a lot of build warnings, including warnings about errors. Do you have any tips for finding the errors and warnings I have to fix?

@willeke1234
Copy link
Contributor

The discussion moved back to #1831. This issue can be closed.

@oleg68
Copy link
Contributor Author

oleg68 commented Mar 15, 2024

The discussion moved back to #1831. This issue can be closed.

This issue is about signing. #1831 is about adding the build to github without signing.

@willeke1234
Copy link
Contributor

willeke1234 commented Mar 15, 2024

@oleg ok, I'll ask my questions where I think they belong.

@willeke1234
Copy link
Contributor

I've been digging through CPack's documentation and source code. I think the CPack DragNDrop Generator builds the app but can't sign it and the CPack Bundle Generator can sign but doesn't build the app. Questions:

  • Which script/tool/function is adding the libs to the regular app and app on the .dmg?
  • Is it possible to add a final build step, executed on both apps?
  • What is the difference between the two apps?

@oleg68
Copy link
Contributor Author

oleg68 commented Mar 20, 2024

  • Which script/tool/function is adding the libs to the regular app and app on the .dmg?

https://github.com/GrandOrgue/grandorgue/blob/master/cmake/FixupBundle.cmake

  • Is it possible to add a final build step, executed on both apps?

https://cmake.org/cmake/help/v3.5/command/install.html#custom-installation-logic

  • What is the difference between the two apps?

What two apps are you interested by?

@willeke1234
Copy link
Contributor

What two apps are you interested by?

GrandOrgueBuild/build/osx/GrandOrgue.app
/Volumes/grandorgue-3.7.5.1-0.local.osx.arm64/GrandOrgue.app (= GrandOrgueBuild/build/osx/grandorgue-3.7.5.1-0.local.osx.arm64.dmg)

Do I have to sign them separately in a build step and an install step? How do I make sure this is the last step?

@oleg68
Copy link
Contributor Author

oleg68 commented Mar 21, 2024

I see that building for MacOS differs significantly from building for other OSes. I thought that it should be at install step, but ./GrandOrgue.app is created during simple make.

So I suggest you to find where FixupBundle is called and to add a step after it.

@willeke1234
Copy link
Contributor

At the end of grandorgue/src/grandorgue/CMakeLists.txt I added:

if(APPLE)
  ADD_CUSTOM_COMMAND(TARGET "GrandOrgue" POST_BUILD
    COMMAND codesign --force --sign - "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app/Contents/Frameworks/*.*" "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app/Contents/MacOS/GrandOrguePerfTest" "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app/Contents/MacOS/GrandOrgueTool" "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app")
endif()

The app appears to be signed and macOS doesn't complain but when I verify the app, I get:

grandorgue@Virtuele-machine-van-GrandOrgue GrandOrgueBuild % codesign --verify --verbose 1 --deep  /Users/grandorgue/Documents/Projects/GrandOrgue_3.13/GrandOrgueBuild/build/osx/GrandOrgue.app 
1: dynamically valid
1: valid on disk
1: satisfies its Designated Requirement
/Users/grandorgue/Documents/Projects/GrandOrgue_3.13/GrandOrgueBuild/build/osx/GrandOrgue.app: a sealed resource is missing or invalid
file modified: /Users/grandorgue/Documents/Projects/GrandOrgue_3.13/GrandOrgueBuild/build/osx/GrandOrgue.app/Contents/Resources/GrandOrgue.iconset/icon_32x32.png
file modified: /Users/grandorgue/Documents/Projects/GrandOrgue_3.13/GrandOrgueBuild/build/osx/GrandOrgue.app/Contents/Resources/GrandOrgue.iconset/icon_1024x1024.png
file modified: /Users/grandorgue/Documents/Projects/GrandOrgue_3.13/GrandOrgueBuild/build/osx/GrandOrgue.app/Contents/Resources/GrandOrgue.iconset/icon_16x16.png

If I do PARALLEL_PRMS="-j1" then I get an error:

/Users/grandorgue/Documents/Projects/GrandOrgue_3.13/GrandOrgueBuild/build/osx/GrandOrgue.app/Contents/MacOS/GrandOrguePerfTest: No such file or directory

codesign is executed before the app is completely built. The ADD_CUSTOM_COMMAND commands in the subdirectories aren't ready yet. Signing the app in Build-on-osx.sh works, but this is not very useful when developing. On the other hand, not many people build GrandOrgue on macOS.

To sign the app on the .dmg I added in grandorgue/CMakeLists.txt after set(CPACK_GENERATOR DragNDrop):

file(WRITE "${CMAKE_BINARY_DIR}/sign_package.cmake"
  "EXECUTE_PROCESS(COMMAND codesign --force --sign - \"\${CPACK_TEMPORARY_INSTALL_DIRECTORY}/ALL_IN_ONE/${PROJECT_NAME}.app/Frameworks/*.*\")\n")
file(APPEND "${CMAKE_BINARY_DIR}/sign_package.cmake"
  "EXECUTE_PROCESS(COMMAND codesign --force --sign - \"\${CPACK_TEMPORARY_INSTALL_DIRECTORY}/ALL_IN_ONE/${PROJECT_NAME}.app/Contents/MacOS/GrandOrguePerfTest\")\n")
file(APPEND "${CMAKE_BINARY_DIR}/sign_package.cmake"
  "EXECUTE_PROCESS(COMMAND codesign --force --sign - \"\${CPACK_TEMPORARY_INSTALL_DIRECTORY}/ALL_IN_ONE/${PROJECT_NAME}.app/Contents/MacOS/GrandOrgueTool\")\n")
file(APPEND "${CMAKE_BINARY_DIR}/sign_package.cmake"
  "EXECUTE_PROCESS(COMMAND codesign --force --sign - \"\${CPACK_TEMPORARY_INSTALL_DIRECTORY}/ALL_IN_ONE/${PROJECT_NAME}.app\")\n")
set(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_BINARY_DIR}/sign_package.cmake")

The app is signed but some or all libs aren't signed, maybe a race condition or caching problem. In the log I get

-- 54/56: fixing up '//Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/Frameworks/libwx_osx_cocoau_html-3.2.0.2.2.dylib'
/Library/Developer/CommandLineTools/usr/bin/install_name_tool: warning: changes being made to the file will invalidate the code signature in: //Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/Frameworks/libwx_osx_cocoau_html-3.2.0.2.2.dylib
-- 55/56: fixing up '//Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/Frameworks/libyaml-cpp.0.8.0.dylib'
/Library/Developer/CommandLineTools/usr/bin/install_name_tool: warning: changes being made to the file will invalidate the code signature in: //Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/Frameworks/libyaml-cpp.0.8.0.dylib
-- 56/56: fixing up '//Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/Frameworks/libzstd.1.5.5.dylib'
/Library/Developer/CommandLineTools/usr/bin/install_name_tool: warning: changes being made to the file will invalidate the code signature in: //Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/Frameworks/libzstd.1.5.5.dylib
-- fixup_bundle: cleaning up...
-- fixup_bundle: verifying...
-- fixup_bundle: done
CPack: -   Install component: resources
CPack: -   Install component: demo
CPack: Executing pre-build script: /Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/sign_package.cmake
/Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/Frameworks/*.*: No such file or directory
/Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/MacOS/GrandOrguePerfTest: replacing existing signature
/Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/MacOS/GrandOrgueTool: replacing existing signature
/Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app: replacing existing signature
Checking code signature...
/Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app: invalid signature (code or signature have been modified)
In subcomponent: /Users/grandorgue/Documents/GitHub/GrandOrgueBuild/build/osx/_CPack_Packages/macOS/DragNDrop/grandorgue-3.14.0-0.local.macOS.arm64/ALL_IN_ONE/GrandOrgue.app/Contents/Frameworks/libwx_baseu-3.2.0.2.2.dylib
In architecture: arm64
CPack: Create package

install_name_tool can find the libs but codesign can't.

Any idea how to fix this?

@oleg68
Copy link
Contributor Author

oleg68 commented Mar 23, 2024

Have you tred to use the --deep switch with codesign for signing all files in all subdirectories?

@willeke1234
Copy link
Contributor

Have you tred to use the --deep switch with codesign for signing all files in all subdirectories?

--deep shouldn't be used.

from man codesign:

--deep (DEPRECATED for signing as of macOS 13.0)

Official documentation: Avoid deep code signing

If it could be used then the problem is still the same, codesign must run after the app is completely built.

@willeke1234
Copy link
Contributor

I tried the build by @MStraeten and I get

Screenshot 2024-03-23 at 14 11 07

Maybe it's because I already have an ad-hoc signed GrandOrgue.

@oleg68
Copy link
Contributor Author

oleg68 commented Mar 23, 2024

Maybe it's because I already have an ad-hoc signed GrandOrgue.

I think because ad-hoc signed applications cannot run on another computers.

@willeke1234
Copy link
Contributor

Signing the app on the .dmg now works and the GitHub build works on my Mac. It behaves like an unsigned app:

Screenshot 2024-03-23 at 19 37 28

And Open from the context menu:

Screenshot 2024-03-23 at 19 37 43

If anyone wants to try (at your own risk):
Apple Silicon: https://github.com/willeke1234/grandorgue/actions/runs/8403203222/attempts/2
Intel: https://github.com/willeke1234/grandorgue/actions/runs/8403203222
Scroll to the bottom
I didn't test the Intel one.

@MStraeten
Copy link

MStraeten commented Mar 24, 2024

Maybe it's because I already have an ad-hoc signed GrandOrgue.

It’s because it’s within a zip file and was downloaded from somewhere in the internet.
Signing the dmg gives a further level of trust. That’s the best you can get without an apple developer id

@willeke1234
Copy link
Contributor

As far as I know, the .dmg is not signed.
I tested on a new virtual Mac with the same result.

The intel version works on this virtual Mac with Rosetta.

@Benitoite
Copy link

Benitoite commented Mar 27, 2024

I was able to create a universal code-signed app using my apple cert.
For some reason the app gets bundled with a bunch of symlinks in Contents/Frameworks, so I will move those temporarily:

mkdir links
for frame in GrandOrgue.app/Contents/Frameworks/* ; do
    echo $frame
    if [ -L $frame ] ; then
        mv $frame links
    fi
done

Join the architectures together with lipo:

# Create Universal App (the other arch. app is on the Desktop)

for lib in GrandOrgue.app/Contents/Frameworks/* ; do
        lipo -create -output $(basename $lib) ~/Desktop/GrandOrgue.app/Contents/Frameworks/$(basename $lib) GrandOrgue.app/Contents/Frameworks/$(basename $lib)
        echo $lib
    done

mv *dylib GrandOrgue.app/Contents/Frameworks

for bins in GrandOrgue.app/Contents/MacOS/* ; do
        lipo -create -output $(basename $bins) ~/Desktop/GrandOrgue.app/Contents/MacOS/$(basename $bins) GrandOrgue.app/Contents/MacOS/$(basename $bins)
        echo $bins
    done

mv GrandOrgue *PerfTest *Tool GrandOrgue.app/Contents/MacOS
mv links/* GrandOrgue.app/Contents/Frameworks

Codesign recursively without --deep:

# Codesign the app

    echo "Codesigning Application."
    for frame in GrandOrgue.app/Contents/Frameworks/* ; do
        echo $frame
        codesign --preserve-metadata=identifier --force --timestamp --strict -v -s "${CODESIGNID}" -i com.our-organ.GrandOrgue $frame
    done
    for resource in GrandOrgue.app/Contents/Resources/* ; do
        echo $resource
        if [ ! -d $resource ]; then
            codesign --preserve-metadata=identifier --force --timestamp --strict -v -s "${CODESIGNID}" -i com.our-organ.GrandOrgue $resource
        else
            for subresource in GrandOrgue.app/Contents/Resources/$(basename $resource)/* ; do
                if [ ! -d $subresource ]; then
                    codesign --preserve-metadata=identifier --force --timestamp --strict -v -s "${CODESIGNID}" -i com.our-organ.GrandOrgue $subresource
                fi
            done
        fi
    done
    for macOS in GrandOrgue.app/Contents/MacOS/* ; do
        echo $macOS
        codesign --preserve-metadata=identifier --force --timestamp --strict -v -s "${CODESIGNID}" -i com.our-organ.GrandOrgue $macOS
    done
    codesign --preserve-metadata=identifier --force --timestamp --strict -v -s "${CODESIGNID}" -i com.our-organ.GrandOrgue GrandOrgue.app
    spctl -a -vvvv GrandOrgue.app

Built a dmg with create-dmg/create-dmg:

mkdir GrandOrgue
mv GrandOrgue.app GrandOrgue
create-dmg --app-drop-link 50 50 --eula ../LICENSE grandorgue3.14.0.dmg GrandOrgue

Signed it also:

sudo codesign --preserve-metadata=identifier --force --timestamp --strict -v -s $CODESIGNID -i com.our-organ.GrandOrgue grandorgue3.14.0.dmg

Universal app runs on Intel (macOS 12.7+) and Apple Silicon (macOS 13.3+)
If you would like to test this build, it is available in my shared folder: https://r42.us/go

  • FWIW, program runs fine on arm64 but I didn't have enough RAM to load the big organs, so I went to build it on intel also.

@willeke1234
Copy link
Contributor

How do we proceed:

  • Who is going to build the macOS GrandOrgue app?
  • Who is going to sign the macOS GrandOrgue app and how?
  • Who is going to distribute the macOS GrandOrgue app?
  • One universal app or an Intel app and an Apple Silicon app?
  • Which macOS's are supported?

@Benitoite
Copy link

Also you may wish for the app to support hardening for notarization. As it is now the libraries load relative to @executable_path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants