Skip to content

Commit f1dfdc1

Browse files
author
Alexander Matveev
committedOct 24, 2023
8311877: [macos] Add CLI options to provide signing identity directly to codesign and productbuild
Reviewed-by: asemenyuk
1 parent 9c819fd commit f1dfdc1

24 files changed

+531
-105
lines changed
 

‎src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java

+20-6
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ public MacAppBundler() {
8585
},
8686
(s, p) -> s);
8787

88+
public static final BundlerParamInfo<String> APP_IMAGE_SIGN_IDENTITY =
89+
new StandardBundlerParam<>(
90+
Arguments.CLIOptions.MAC_APP_IMAGE_SIGN_IDENTITY.getId(),
91+
String.class,
92+
params -> "",
93+
null);
94+
8895
public static final BundlerParamInfo<String> BUNDLE_ID_SIGNING_PREFIX =
8996
new StandardBundlerParam<>(
9097
Arguments.CLIOptions.MAC_BUNDLE_SIGNING_PREFIX.getId(),
@@ -127,14 +134,21 @@ private static void doValidate(Map<String, ? super Object> params)
127134
// reject explicitly set sign to true and no valid signature key
128135
if (Optional.ofNullable(
129136
SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) {
130-
String signingIdentity =
131-
DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
132-
if (signingIdentity == null) {
133-
throw new ConfigException(
134-
I18N.getString("error.explicit-sign-no-cert"),
135-
I18N.getString("error.explicit-sign-no-cert.advice"));
137+
// Validate DEVELOPER_ID_APP_SIGNING_KEY only if user provided
138+
// SIGNING_KEY_USER.
139+
if (!SIGNING_KEY_USER.getIsDefaultValue(params)) { // --mac-signing-key-user-name
140+
String signingIdentity =
141+
DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
142+
if (signingIdentity == null) {
143+
throw new ConfigException(
144+
I18N.getString("error.explicit-sign-no-cert"),
145+
I18N.getString("error.explicit-sign-no-cert.advice"));
146+
}
136147
}
137148

149+
// No need to validate --mac-app-image-sign-identity, since it is
150+
// pass through option.
151+
138152
// Signing will not work without Xcode with command line developer tools
139153
try {
140154
ProcessBuilder pb = new ProcessBuilder("/usr/bin/xcrun", "--help");

‎src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java

+42-8
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525

2626
package jdk.jpackage.internal;
2727

28+
import java.io.ByteArrayOutputStream;
2829
import java.io.IOException;
2930
import java.io.InputStream;
31+
import java.io.PrintStream;
3032
import java.io.Writer;
3133
import java.nio.file.Files;
3234
import java.nio.file.Path;
@@ -53,7 +55,10 @@
5355
import jdk.internal.util.OSVersion;
5456
import static jdk.jpackage.internal.MacAppBundler.BUNDLE_ID_SIGNING_PREFIX;
5557
import static jdk.jpackage.internal.MacAppBundler.DEVELOPER_ID_APP_SIGNING_KEY;
58+
import static jdk.jpackage.internal.MacAppBundler.APP_IMAGE_SIGN_IDENTITY;
5659
import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
60+
import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER;
61+
import static jdk.jpackage.internal.MacBaseInstallerBundler.INSTALLER_SIGN_IDENTITY;
5762
import static jdk.jpackage.internal.OverridableResource.createResource;
5863
import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
5964
import static jdk.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
@@ -395,12 +400,25 @@ private void doSigning(Map<String, ? super Object> params)
395400
} catch (InterruptedException e) {
396401
Log.error(e.getMessage());
397402
}
398-
String signingIdentity =
399-
DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
403+
String signingIdentity = null;
404+
// Try --mac-app-image-sign-identity first if set
405+
if (!APP_IMAGE_SIGN_IDENTITY.getIsDefaultValue(params)) {
406+
signingIdentity = APP_IMAGE_SIGN_IDENTITY.fetchFrom(params);
407+
} else {
408+
// Check if INSTALLER_SIGN_IDENTITY is set and if it is set
409+
// then do not sign app image, otherwise use --mac-signing-key-user-name
410+
if (INSTALLER_SIGN_IDENTITY.getIsDefaultValue(params)) {
411+
// --mac-sign and/or --mac-signing-key-user-name case
412+
signingIdentity = DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
413+
}
414+
}
400415
if (signingIdentity != null) {
401416
signAppBundle(params, root, signingIdentity,
402417
BUNDLE_ID_SIGNING_PREFIX.fetchFrom(params),
403418
ENTITLEMENTS.fetchFrom(params));
419+
} else {
420+
// Case when user requested to sign installer only
421+
signAppBundle(params, root, "-", null, null);
404422
}
405423
restoreKeychainList(params);
406424
} else if (OperatingSystem.isMacOS()) {
@@ -715,6 +733,25 @@ private static List<String> getCodesignArgs(
715733
return args;
716734
}
717735

736+
private static void runCodesign(ProcessBuilder pb, boolean quiet)
737+
throws IOException {
738+
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
739+
PrintStream ps = new PrintStream(baos)) {
740+
try {
741+
IOUtils.exec(pb, false, ps, false,
742+
Executor.INFINITE_TIMEOUT, quiet);
743+
} catch (IOException ioe) {
744+
// Log output of "codesign" in case of
745+
// error. It should help user to diagnose
746+
// issue when using --mac-app-image-sign-identity
747+
Log.info(MessageFormat.format(I18N.getString(
748+
"error.tool.failed.with.output"), "codesign"));
749+
Log.info(baos.toString().strip());
750+
throw ioe;
751+
}
752+
}
753+
}
754+
718755
static void signAppBundle(
719756
Map<String, ? super Object> params, Path appLocation,
720757
String signingIdentity, String identifierPrefix, Path entitlements)
@@ -781,8 +818,7 @@ static void signAppBundle(
781818
p.toFile().setWritable(true, true);
782819
ProcessBuilder pb = new ProcessBuilder(args);
783820
// run quietly
784-
IOUtils.exec(pb, false, null, false,
785-
Executor.INFINITE_TIMEOUT, true);
821+
runCodesign(pb, true);
786822
Files.setPosixFilePermissions(p, oldPermissions);
787823
} catch (IOException ioe) {
788824
toThrow.set(ioe);
@@ -810,8 +846,7 @@ static void signAppBundle(
810846
List<String> args = getCodesignArgs(true, path, signingIdentity,
811847
identifierPrefix, entitlements, keyChain);
812848
ProcessBuilder pb = new ProcessBuilder(args);
813-
814-
IOUtils.exec(pb);
849+
runCodesign(pb, false);
815850
} catch (IOException e) {
816851
toThrow.set(e);
817852
}
@@ -842,8 +877,7 @@ static void signAppBundle(
842877
List<String> args = getCodesignArgs(true, appLocation, signingIdentity,
843878
identifierPrefix, entitlements, keyChain);
844879
ProcessBuilder pb = new ProcessBuilder(args);
845-
846-
IOUtils.exec(pb);
880+
runCodesign(pb, false);
847881
}
848882

849883
private static String extractBundleIdentifier(Map<String, Object> params) {

‎src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java

+7
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ public abstract class MacBaseInstallerBundler extends AbstractBundler {
7979
params -> "",
8080
null);
8181

82+
public static final BundlerParamInfo<String> INSTALLER_SIGN_IDENTITY =
83+
new StandardBundlerParam<>(
84+
Arguments.CLIOptions.MAC_INSTALLER_SIGN_IDENTITY.getId(),
85+
String.class,
86+
params -> "",
87+
null);
88+
8289
public static final BundlerParamInfo<String> MAC_INSTALLER_NAME =
8390
new StandardBundlerParam<> (
8491
"mac.installerName",

‎src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java

+44-10
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
import jdk.internal.util.Architecture;
2929
import jdk.internal.util.OSVersion;
3030

31+
import java.io.ByteArrayOutputStream;
3132
import java.io.IOException;
33+
import java.io.PrintStream;
3234
import java.io.PrintWriter;
3335
import java.net.URI;
3436
import java.net.URISyntaxException;
@@ -54,6 +56,8 @@
5456
import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE;
5557
import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
5658
import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER;
59+
import static jdk.jpackage.internal.MacBaseInstallerBundler.INSTALLER_SIGN_IDENTITY;
60+
import static jdk.jpackage.internal.MacAppBundler.APP_IMAGE_SIGN_IDENTITY;
5761
import static jdk.jpackage.internal.StandardBundlerParam.APP_STORE;
5862
import static jdk.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER;
5963
import static jdk.jpackage.internal.OverridableResource.createResource;
@@ -605,8 +609,19 @@ private Path createPKG(Map<String, ? super Object> params,
605609
Log.verbose(I18N.getString("message.signing.pkg"));
606610
}
607611

608-
String signingIdentity =
609-
DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
612+
String signingIdentity = null;
613+
// --mac-installer-sign-identity
614+
if (!INSTALLER_SIGN_IDENTITY.getIsDefaultValue(params)) {
615+
signingIdentity = INSTALLER_SIGN_IDENTITY.fetchFrom(params);
616+
} else {
617+
// Use --mac-signing-key-user-name if user did not request
618+
// to sign just app image using --mac-app-image-sign-identity
619+
if (APP_IMAGE_SIGN_IDENTITY.getIsDefaultValue(params)) {
620+
// --mac-signing-key-user-name
621+
signingIdentity = DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
622+
}
623+
}
624+
610625
if (signingIdentity != null) {
611626
commandLine.add("--sign");
612627
commandLine.add(signingIdentity);
@@ -638,7 +653,21 @@ private Path createPKG(Map<String, ? super Object> params,
638653
commandLine.add(finalPKG.toAbsolutePath().toString());
639654

640655
pb = new ProcessBuilder(commandLine);
641-
IOUtils.exec(pb, false, null, true, Executor.INFINITE_TIMEOUT);
656+
657+
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
658+
PrintStream ps = new PrintStream(baos)) {
659+
try {
660+
IOUtils.exec(pb, false, ps, true, Executor.INFINITE_TIMEOUT);
661+
} catch (IOException ioe) {
662+
// Log output of "productbuild" in case of
663+
// error. It should help user to diagnose
664+
// issue when using --mac-installer-sign-identity
665+
Log.info(MessageFormat.format(I18N.getString(
666+
"error.tool.failed.with.output"), "productbuild"));
667+
Log.info(baos.toString().strip());
668+
throw ioe;
669+
}
670+
}
642671

643672
return finalPKG;
644673
} catch (Exception ignored) {
@@ -702,14 +731,19 @@ public boolean validate(Map<String, ? super Object> params)
702731
// reject explicitly set sign to true and no valid signature key
703732
if (Optional.ofNullable(
704733
SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) {
705-
String signingIdentity =
706-
DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
707-
if (signingIdentity == null) {
708-
throw new ConfigException(
709-
I18N.getString("error.explicit-sign-no-cert"),
710-
I18N.getString(
711-
"error.explicit-sign-no-cert.advice"));
734+
if (!SIGNING_KEY_USER.getIsDefaultValue(params)) {
735+
String signingIdentity =
736+
DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
737+
if (signingIdentity == null) {
738+
throw new ConfigException(
739+
I18N.getString("error.explicit-sign-no-cert"),
740+
I18N.getString(
741+
"error.explicit-sign-no-cert.advice"));
742+
}
712743
}
744+
745+
// No need to validate --mac-installer-sign-identity, since it is
746+
// pass through option.
713747
}
714748

715749
// hdiutil is always available so there's no need

‎src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
33
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
#
55
# This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@ error.no.xcode.signing.advice=Install Xcode with command line developer tools.
4444
error.cert.not.found=No certificate found matching [{0}] using keychain [{1}]
4545
error.multiple.certs.found=WARNING: Multiple certificates found matching [{0}] using keychain [{1}], using first one
4646
error.app-image.mac-sign.required=Error: --mac-sign option is required with predefined application image and with type [app-image]
47+
error.tool.failed.with.output=Error: "{0}" failed with following output:
4748
resource.bundle-config-file=Bundle config file
4849
resource.app-info-plist=Application Info.plist
4950
resource.runtime-info-plist=Java Runtime Info.plist

‎src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
33
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
#
55
# This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@ error.no.xcode.signing.advice=Installieren Sie Xcode mit Befehlszeilen-Entwickle
4444
error.cert.not.found=Kein Zertifikat gefunden, das [{0}] mit Schlüsselbund [{1}] entspricht
4545
error.multiple.certs.found=WARNUNG: Mehrere Zertifikate gefunden, die [{0}] mit Schlüsselbund [{1}] entsprechen. Es wird das erste Zertifikat verwendet
4646
error.app-image.mac-sign.required=Fehler: Die Option "--mac-sign" ist mit einem vordefinierten Anwendungsimage und Typ [app-image] erforderlich
47+
error.tool.failed.with.output=Error: "{0}" failed with following output:
4748
resource.bundle-config-file=Bundle-Konfigurationsdatei
4849
resource.app-info-plist=Info.plist der Anwendung
4950
resource.runtime-info-plist=Info.plist von Java Runtime

‎src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
33
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
#
55
# This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@ error.no.xcode.signing.advice=Xcodeとコマンドライン・デベロッパ・
4444
error.cert.not.found=キーチェーン[{1}]を使用する[{0}]と一致する証明書が見つかりません
4545
error.multiple.certs.found=警告: キーチェーン[{1}]を使用する[{0}]と一致する複数の証明書が見つかりました。最初のものを使用します
4646
error.app-image.mac-sign.required=エラー: --mac-signオプションは、事前定義済アプリケーション・イメージおよびタイプ[app-image]で必要です
47+
error.tool.failed.with.output=Error: "{0}" failed with following output:
4748
resource.bundle-config-file=バンドル構成ファイル
4849
resource.app-info-plist=アプリケーションのInfo.plist
4950
resource.runtime-info-plist=JavaランタイムのInfo.plist

‎src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
33
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
#
55
# This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@ error.no.xcode.signing.advice=安装带命令行开发人员工具的 Xcode。
4444
error.cert.not.found=使用密钥链 [{1}] 找不到与 [{0}] 匹配的证书
4545
error.multiple.certs.found=警告:使用密钥链 [{1}] 找到多个与 [{0}] 匹配的证书,将使用第一个证书
4646
error.app-image.mac-sign.required=错误:预定义的应用程序映像和类型 [app image] 需要 --mac-sign 选项
47+
error.tool.failed.with.output=Error: "{0}" failed with following output:
4748
resource.bundle-config-file=包配置文件
4849
resource.app-info-plist=应用程序 Info.plist
4950
resource.runtime-info-plist=Java 运行时 Info.plist

‎src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java

+24
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,12 @@ public enum CLIOptions {
338338
MAC_SIGNING_KEY_NAME ("mac-signing-key-user-name",
339339
OptionCategories.PLATFORM_MAC),
340340

341+
MAC_APP_IMAGE_SIGN_IDENTITY ("mac-app-image-sign-identity",
342+
OptionCategories.PLATFORM_MAC),
343+
344+
MAC_INSTALLER_SIGN_IDENTITY ("mac-installer-sign-identity",
345+
OptionCategories.PLATFORM_MAC),
346+
341347
MAC_SIGNING_KEYCHAIN ("mac-signing-keychain",
342348
OptionCategories.PLATFORM_MAC),
343349

@@ -631,6 +637,24 @@ private void validateArguments() throws PackagerException {
631637
CLIOptions.JLINK_OPTIONS.getIdWithPrefix());
632638
}
633639
}
640+
if (allOptions.contains(CLIOptions.MAC_SIGNING_KEY_NAME) &&
641+
allOptions.contains(CLIOptions.MAC_APP_IMAGE_SIGN_IDENTITY)) {
642+
throw new PackagerException("ERR_MutuallyExclusiveOptions",
643+
CLIOptions.MAC_SIGNING_KEY_NAME.getIdWithPrefix(),
644+
CLIOptions.MAC_APP_IMAGE_SIGN_IDENTITY.getIdWithPrefix());
645+
}
646+
if (allOptions.contains(CLIOptions.MAC_SIGNING_KEY_NAME) &&
647+
allOptions.contains(CLIOptions.MAC_INSTALLER_SIGN_IDENTITY)) {
648+
throw new PackagerException("ERR_MutuallyExclusiveOptions",
649+
CLIOptions.MAC_SIGNING_KEY_NAME.getIdWithPrefix(),
650+
CLIOptions.MAC_INSTALLER_SIGN_IDENTITY.getIdWithPrefix());
651+
}
652+
if (isMac && (imageOnly || "dmg".equals(type)) &&
653+
allOptions.contains(CLIOptions.MAC_INSTALLER_SIGN_IDENTITY)) {
654+
throw new PackagerException("ERR_InvalidTypeOption",
655+
CLIOptions.MAC_INSTALLER_SIGN_IDENTITY.getIdWithPrefix(),
656+
type);
657+
}
634658
if (allOptions.contains(CLIOptions.DMG_CONTENT)
635659
&& !("dmg".equals(type))) {
636660
throw new PackagerException("ERR_InvalidTypeOption",

0 commit comments

Comments
 (0)
Please sign in to comment.