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

Improve Apple code signing #419

Merged
merged 3 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions common/shell/Shell.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class Shell(private val logger: Logger, private val verbose: Boolean = false, pr
return verbose && (!sensitive || printSensitiveData)
}

class Command(vararg args: Argument) {
val args = args.toList()
class Command(val args: List<Argument>) {
constructor(vararg args: Argument): this(args.toList())

override fun toString(): String {
return args.toString()
Expand Down
20 changes: 2 additions & 18 deletions platform/jvm/AppleCodeSigner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Codesign.Args.
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Codesign.Args.KEYCHAIN
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Codesign.Args.OPTIONS
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Codesign.Args.SIGN
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Codesign.Args.STRICT
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Codesign.Args.TIMESTAMP
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Codesign.Args.VERIFY
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Paths.CONTENTS
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Paths.MAC_OS
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Paths.RUNTIME
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Paths.TMP
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Security.CN
import com.typedb.bazel.distribution.platform.jvm.AppleCodeSigner.Security.CREATE_KEYCHAIN
Expand Down Expand Up @@ -140,7 +135,7 @@ class AppleCodeSigner(private val shell: Shell, private val macEntitlements: Fil

val nativeLibs = tmpDir.listFilesRecursively().filter { it.extension in listOf(JNILIB, DYLIB) }
if (nativeLibs.isNotEmpty()) {
nativeLibs.forEach { signFile(file = it, skipIfSigned = true) }
nativeLibs.forEach { signFile(file = it) }
jar.setWritable(true)
jar.delete()
shell.execute(listOf(ShellArgs.Programs.JAR, "cMf", "../${jar.path}", "."), baseDir = tmpPath)
Expand All @@ -150,18 +145,7 @@ class AppleCodeSigner(private val shell: Shell, private val macEntitlements: Fil
}
}

fun signFile(file: File, skipIfSigned: Boolean = false) {
if (skipIfSigned) {
val verifySignatureResult = VerifySignatureResult(
shell.execute(listOf(CODESIGN, VERIFY, STRICT, file.path), throwOnError = false)
)
if (verifySignatureResult.status == VerifySignatureResult.Status.SIGNED) return
else if (verifySignatureResult.status == VerifySignatureResult.Status.ERROR) {
throw IllegalStateException("Command '${CODESIGN}' failed with exit code " +
"${verifySignatureResult.exitValue} and output: ${verifySignatureResult.outputString()}")
}
}

fun signFile(file: File) {
file.setWritable(true)
val signCommand: MutableList<String> = mutableListOf(
CODESIGN, SIGN, certSubject,
Expand Down
6 changes: 4 additions & 2 deletions platform/jvm/JVMPlatformAssembler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,10 @@ object JVMPlatformAssembler {
null -> logger.debug { "Skipping notarizing step: Apple code signing is not enabled" }
else -> {
MacAppNotarizer(
dmgPath = Path.of(distDir.path, "${options.image.filename}-$version.dmg")
).notarize(codeSigningOptions)
dmgPath = Path.of(distDir.path, "${options.image.filename}-$version.dmg"),
appleCodeSigning = codeSigningOptions,
logging = options.logging,
).notarize()
appleCodeSigner!!.deleteKeychain()
}
}
Expand Down
39 changes: 25 additions & 14 deletions platform/jvm/MacAppNotarizer.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package com.typedb.bazel.distribution.platform.jvm

import com.typedb.bazel.distribution.common.Logging.LogLevel
import com.typedb.bazel.distribution.common.Logging.LogLevel.DEBUG
import com.typedb.bazel.distribution.common.Logging.LogLevel.ERROR
import com.typedb.bazel.distribution.common.Logging.Logger
import com.typedb.bazel.distribution.common.shell.Shell
import com.typedb.bazel.distribution.common.shell.Shell.Command.Companion.arg
import com.typedb.bazel.distribution.platform.jvm.JVMPlatformAssembler.shell
import com.typedb.bazel.distribution.platform.jvm.MacAppNotarizer.Args.APPLE_ID
import com.typedb.bazel.distribution.platform.jvm.MacAppNotarizer.Args.NOTARYTOOL
Expand All @@ -11,29 +16,34 @@ import com.typedb.bazel.distribution.platform.jvm.MacAppNotarizer.Args.STAPLER
import com.typedb.bazel.distribution.platform.jvm.MacAppNotarizer.Args.SUBMIT
import com.typedb.bazel.distribution.platform.jvm.MacAppNotarizer.Args.TEAM_ID
import com.typedb.bazel.distribution.platform.jvm.MacAppNotarizer.Args.TIMEOUT
import com.typedb.bazel.distribution.platform.jvm.MacAppNotarizer.Args.VERBOSE
import com.typedb.bazel.distribution.platform.jvm.MacAppNotarizer.Args.WAIT
import com.typedb.bazel.distribution.platform.jvm.ShellArgs.Programs.XCRUN
import java.nio.file.Path

class MacAppNotarizer(private val dmgPath: Path) {
fun notarize(appleCodeSigning: Options.AppleCodeSigning) {
shell.execute(notarizeCommand(appleCodeSigning)).outputString()
class MacAppNotarizer(
private val dmgPath: Path, appleCodeSigning: Options.AppleCodeSigning, private val logging: Options.Logging
) {
private val logger = Logger(logLevel = if (logging.verbose) DEBUG else ERROR)

fun notarize() {
shell.execute(notarizeCommand).outputString()
logger.debug { "\nUse `xcrun notarytool log <submission-id>` to view further information about this notarization\n" }
markPackageAsApproved()
}

private fun notarizeCommand(appleCodeSigning: Options.AppleCodeSigning): Shell.Command {
return Shell.Command(
Shell.Command.arg(XCRUN), Shell.Command.arg(NOTARYTOOL), Shell.Command.arg(SUBMIT),
Shell.Command.arg(APPLE_ID), Shell.Command.arg(appleCodeSigning.appleID),
Shell.Command.arg(PASSWORD), Shell.Command.arg(appleCodeSigning.appleIDPassword, printable = false),
Shell.Command.arg(TEAM_ID), Shell.Command.arg(appleCodeSigning.appleTeamID, printable = false),
Shell.Command.arg(WAIT), Shell.Command.arg(TIMEOUT), Shell.Command.arg(ONE_HOUR),
Shell.Command.arg(dmgPath.toString()),
)
}
private val notarizeCommand = Shell.Command(listOfNotNull(
arg(XCRUN), arg(NOTARYTOOL), arg(SUBMIT),
if (logging.verbose) arg(VERBOSE) else null,
arg(APPLE_ID), arg(appleCodeSigning.appleID),
arg(PASSWORD), arg(appleCodeSigning.appleIDPassword, printable = false),
arg(TEAM_ID), arg(appleCodeSigning.appleTeamID, printable = false),
arg(WAIT), arg(TIMEOUT), arg(ONE_HOUR),
arg(dmgPath.toString()),
))

private fun markPackageAsApproved() {
shell.execute(listOf(XCRUN, STAPLER, STAPLE, dmgPath.toString()))
shell.execute(listOfNotNull(XCRUN, STAPLER, STAPLE, if (logging.verbose) VERBOSE else null, dmgPath.toString()))
}

private object Args {
Expand All @@ -46,6 +56,7 @@ class MacAppNotarizer(private val dmgPath: Path) {
const val SUBMIT = "submit"
const val TIMEOUT = "--timeout"
const val TEAM_ID = "--team-id"
const val VERBOSE = "-v"
const val WAIT = "--wait"
}
}