To make an installer that will work on a Mac, there’s a LOT of requirements. But to make sure the project succeeds into the future we need to do all of this to make the project useful for ‘normal’ people. This means it has to be easy to install, uninstall, get working and stay working!
You will need-
1. a Mac running recent operating system
2. Xcode
5. a ‘Developer ID Application’ signing certificate in Keychain
6. a ‘Developer ID Installer’ certificate in Keychain
7. ‘Packages’ app
1. Download the binaries
2. Make, re-name and make executable
On an Intel Mac, netclient-darwin becomes netclient
For wireguard-tools you’ll need to ‘make’ this and rename to wg
You’ll also need to ‘make’ wireguard-go according to the instructions on the website
For wireguard-tools you’ll need to ‘make’ this and rename to wg
You’ll also need to ‘make’ wireguard-go according to the instructions on the website
Example-
git clone https://git.zx2c4.com/wireguard-go
cd wireguard-go make
then make each binary executable with
chmod +x appname
3. Hardening binaries
Place the executable binary in a folder with a .plist file called ‘binaryname.entitlements’
– this describes the security entitlements that the binary requires to run, and your executable will not work unless hardened
– the ones I made might be completely wrong but they work, I added these-
com.apple.developer.networking.multicast com.apple.developer.networking.manage-thread-network-credentials
4. Signing binaries
For each of the 3 binaries, do something like-
codesign -s "Developer ID Application: Servicemax (XXXXXXXXX)" --timestamp --options runtime -f --entitlements entitlements.plist --deep YourApp.app
At this point you have 3 signed binaries, they need to be added to an installer. We will use a product called ‘Packages’ to do this
4b. Make a Postinstall Script
This is optional- In this case, we are on a Mac and can name our clients in a repeatable way. This postinstall script will
a. find the computer serial number
b. find the long name of the user
c. use the join command to join the desired network
d. patch the automatically generated launchd for the correct location of the binary
a. find the computer serial number
b. find the long name of the user
c. use the join command to join the desired network
d. patch the automatically generated launchd for the correct location of the binary
#!/bin/sh export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin # Now let's join our network # this script is for installing Netmaker client on Macs # Find machime Serial number serial=$(/usr/sbin/system_profiler SPHardwareDataType | /usr/bin/awk '/Serial Number/ { print $4; }') echo $serial # Next find machine users long name fullname=$(id -P $(stat -f%Su /dev/console) | cut -d : -f 8) echo $fullname # Let's see if it worked echo joining Netmaker network for $serial $fullname cd /usr/local/ ./bin/netclient join --name "${serial} ${fullname}" -t <token> echo joined "$serial$fullname" to Netmaker network # Unload old launchds launchctl unload /Library/LaunchDaemons/com.gravitl.netclient.plist &>/dev/null # Patch launchd so it works- this is to cope with the binary location changing from /etc to /usr/local... sudo sed -i '' 's|/etc/netclient/netclient|/usr/local/bin/netclient|g' /Library/LaunchDaemons/com.gravitl.netclient.plist # Load new launchd launchctl load -w /Library/LaunchDaemons/com.gravitl.netclient.plist &>/dev/null # Need to enable it so it launches at startup? sudo launchctl enable system/com.gravitl.netclient echo restarted patched launch daemon
4c. Making a Pre-Install Script
This is optional as well, but I’ve installed and uninstalled netclient so many times that it seems prudent to uninstall properly…
#!/bin/sh # unload lanchd launchctl unload /Library/LaunchDaemons/com.gravitl.netclient.plist # remove launchd rm -f /Library/LaunchDaemons/com.gravitl.netclient.plist # remove old bits from Servicemax install rm /usr/local/bin/netclient rm /usr/local/bin/wg rm /usr/local/bin/wireguard-go # remove receipts rm /private/var/db/receipts/com.gravitl.pkg.NetclientWireguard.bom rm /private/var/db/receipts/com.gravitl.pkg.NetclientWireguard.plist # remove bits from the Netmaker standard install that doesn't work on macOS rm -rf /private/etc/netclient
5. Putting it all together
Here is a good tutorial on Packages
In the app named ‘Packages’ create a new Project (in Packages this is a ‘Raw Package’)
In ‘Settings’ Add the identifier in reverse domain notation
Add an Apple ID Installer certificate under ‘Project’
In ‘Payload’ go to ‘Hierarchy’ and select ’Show hidden Folders’
Add all 3 binaries to /usr/local/bin
– NOTE- we are putting the binaries here because /etc seems to be a protected location in modern macOS. If you think there’s a better spot, please let us know…
– NOTE- we are putting the binaries here because /etc seems to be a protected location in modern macOS. If you think there’s a better spot, please let us know…
Packages>File>Save
Packages>Build>Build
This will output a signed package to the Build folder in your project folder
6. Notarise the Installer
Use a script to upload the new .pkg and notarise it. I used one kindly provided Armin Briegel here
I’ll try to clean up the script and add here but this could take some time…
(But it’s also possible to do this manually- adding this info in case it’s useful in future, this might be better if not using an installer?)
For notarisation we need to zip the app like this (don’t zip normally, it won’t work)
/usr/bin/ditto -c -k --keepParent YourApp.app YourApp.zip
Then upload the app like this (you need to set up an app specific password to use this method)
xcrun altool --notarize-app --primary-bundle-id "<id>" -u "<appleid>" -p "<app-specific password>" --file YourApp.zip
When notified of success, you need to staple the notarisation to the app-
xcrun stapler staple "YourApp.app"
7. Check your work
Download a copy of Suspicious Package and drop your new installer package on it- see any errors? Nope?
Go ahead and distribute you legend!
Go ahead and distribute you legend!