gogio: [macOS] support custom profile

This patch enables `-signkey` to load provisioning profiles.

Signed-off-by: inkeliz <inkeliz@inkeliz.com>
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
inkeliz
2023-08-25 17:42:49 +01:00
committed by Elias Naur
parent e1f06eb7b0
commit ed8d0aa9a6
4 changed files with 54 additions and 19 deletions
+2 -1
View File
@@ -69,7 +69,8 @@ its deletion.
The -x flag will print all the external commands executed by the gogio tool. The -x flag will print all the external commands executed by the gogio tool.
The -signkey flag specifies the path of the keystore, used for signing Android apk/aab files The -signkey flag specifies the path of the keystore, used for signing Android apk/aab files
or specifies the name of key on Keychain to sign MacOS app. or specifies the name of key on Keychain to sign MacOS apps. On iOS and macOS it can be used
to specify the path of a provisioning profile (.mobileprovision/.provisionprofile).
The -signpass flag specifies the password of the keystore, ignored if -signkey is not provided. The -signpass flag specifies the password of the keystore, ignored if -signkey is not provided.
If -signpass is not sepecified it will be read from the environment variable GOGIO_SIGNPASS. If -signpass is not sepecified it will be read from the environment variable GOGIO_SIGNPASS.
+44 -16
View File
@@ -75,7 +75,29 @@ func buildIOS(tmpDir, target string, bi *buildInfo) error {
if err := exeIOS(tmpDir, target, appDir, bi); err != nil { if err := exeIOS(tmpDir, target, appDir, bi); err != nil {
return err return err
} }
if err := signIOS(bi, tmpDir, appDir); err != nil {
embedded := filepath.Join(appDir, "embedded.mobileprovision")
var provisions []string
if bi.key == "" {
if ext := filepath.Ext(bi.key); ext != ".mobileprovision" && ext != ".provisionprofile" {
return fmt.Errorf("sign: -signkey specifies an Apple provisioning profile, but %q does not end in .mobileprovision or .provisionprofile", bi.key)
}
provisions = []string{bi.key}
} else {
home, err := os.UserHomeDir()
if err != nil {
return err
}
p, err := filepath.Glob(filepath.Join(home, "Library", "MobileDevice", "Provisioning Profiles", "*.mobileprovision"))
if err != nil {
return err
}
provisions = p
}
if err := signApple(bi.appID, tmpDir, embedded, appDir, provisions); err != nil {
return err return err
} }
return zipDir(out, tmpDir, "Payload") return zipDir(out, tmpDir, "Payload")
@@ -84,16 +106,8 @@ func buildIOS(tmpDir, target string, bi *buildInfo) error {
} }
} }
func signIOS(bi *buildInfo, tmpDir, app string) error { // signApple is shared between iOS and macOS.
home, err := os.UserHomeDir() func signApple(appID, tmpDir, embedded, app string, provisions []string) error {
if err != nil {
return err
}
provPattern := filepath.Join(home, "Library", "MobileDevice", "Provisioning Profiles", "*.mobileprovision")
provisions, err := filepath.Glob(provPattern)
if err != nil {
return err
}
provInfo := filepath.Join(tmpDir, "provision.plist") provInfo := filepath.Join(tmpDir, "provision.plist")
var avail []string var avail []string
for _, prov := range provisions { for _, prov := range provisions {
@@ -117,17 +131,23 @@ func signIOS(bi *buildInfo, tmpDir, app string) error {
if err != nil { if err != nil {
return err return err
} }
provAppID, err := runCmd(exec.Command("/usr/libexec/PlistBuddy", "-c", "Print:Entitlements:application-identifier", provInfo))
// iOS/macOS Catalyst
provAppIDSearchKey := "Print:Entitlements:application-identifier"
if filepath.Ext(prov) == ".provisionprofile" {
// macOS
provAppIDSearchKey = "Print:Entitlements:com.apple.application-identifier"
}
provAppID, err := runCmd(exec.Command("/usr/libexec/PlistBuddy", "-c", provAppIDSearchKey, provInfo))
if err != nil { if err != nil {
return err return err
} }
expAppID := fmt.Sprintf("%s.%s", appIDPrefix, bi.appID) expAppID := fmt.Sprintf("%s.%s", appIDPrefix, appID)
avail = append(avail, provAppID) avail = append(avail, provAppID)
if expAppID != provAppID { if expAppID != provAppID {
continue continue
} }
// Copy provisioning file. // Copy provisioning file.
embedded := filepath.Join(app, "embedded.mobileprovision")
if err := copyFile(embedded, prov); err != nil { if err := copyFile(embedded, prov); err != nil {
return err return err
} }
@@ -147,10 +167,18 @@ func signIOS(bi *buildInfo, tmpDir, app string) error {
} }
identity := sha1.Sum(certDER) identity := sha1.Sum(certDER)
idHex := hex.EncodeToString(identity[:]) idHex := hex.EncodeToString(identity[:])
_, err = runCmd(exec.Command("codesign", "-s", idHex, "-v", "--entitlements", entFile, app)) _, err = runCmd(exec.Command(
"codesign",
"--sign", idHex,
"--deep",
"--force",
"--options", "runtime",
"--entitlements",
entFile,
app))
return err return err
} }
return fmt.Errorf("sign: no valid provisioning profile found for bundle id %q among %v", bi.appID, avail) return fmt.Errorf("sign: no valid provisioning profile found for bundle id %q among %v", appID, avail)
} }
func exeIOS(tmpDir, target, app string, bi *buildInfo) error { func exeIOS(tmpDir, target, app string, bi *buildInfo) error {
+7 -1
View File
@@ -148,7 +148,7 @@ func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) {
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<true/> <true/>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>BNDL</string>
{{if .Schemes}} {{if .Schemes}}
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
<array> <array>
@@ -232,6 +232,12 @@ func (b *macBuilder) signProgram(buildInfo *buildInfo, binDest string, name stri
return err return err
} }
// If the key is a provisioning profile use the same signing process as iOS
if filepath.Ext(buildInfo.key) == ".provisionprofile" {
embedded := filepath.Join(binDest, "Contents", "embedded.provisionprofile")
return signApple(buildInfo.appID, b.TempDir, embedded, binDest, []string{buildInfo.key})
}
cmd := exec.Command( cmd := exec.Command(
"codesign", "codesign",
"--deep", "--deep",
+1 -1
View File
@@ -36,7 +36,7 @@ var (
extraLdflags = flag.String("ldflags", "", "extra flags to the Go linker") extraLdflags = flag.String("ldflags", "", "extra flags to the Go linker")
extraTags = flag.String("tags", "", "extra tags to the Go tool") extraTags = flag.String("tags", "", "extra tags to the Go tool")
iconPath = flag.String("icon", "", "specify an icon for iOS and Android") iconPath = flag.String("icon", "", "specify an icon for iOS and Android")
signKey = flag.String("signkey", "", "specify the path of the keystore to be used to sign Android apk files.") signKey = flag.String("signkey", "", "specify the path of the keystore (Android) or provisioning profile (macOS or iOS) for signing")
signPass = flag.String("signpass", "", "specify the password to decrypt the signkey.") signPass = flag.String("signpass", "", "specify the password to decrypt the signkey.")
notaryID = flag.String("notaryid", "", "specify the apple id to use for notarization.") notaryID = flag.String("notaryid", "", "specify the apple id to use for notarization.")
notaryPass = flag.String("notarypass", "", "specify app-specific password of the Apple ID to be used for notarization.") notaryPass = flag.String("notarypass", "", "specify app-specific password of the Apple ID to be used for notarization.")