Skip to content

Commit 8deb196

Browse files
authored
feat(bundler): infer signing identity from certificate to import (#10652)
1 parent d39c392 commit 8deb196

File tree

5 files changed

+40
-21
lines changed

5 files changed

+40
-21
lines changed

.changes/infer-signing-identity.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"tauri-bundler": patch:enhance
3+
"tauri-cli": patch:enhance
4+
"@tauri-apps/cli": patch:enhance
5+
---
6+
7+
Infer macOS codesign identity from the `APPLE_CERTIFICATE` environment variable when provided, meaning the identity no longer needs to be provided when signing on CI using that option. If the imported certificate name does not match a provided signingIdentity configuration, an error is returned.

tooling/bundler/src/bundle/macos/app.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
105105

106106
copy_custom_files_to_bundle(&bundle_directory, settings)?;
107107

108-
if let Some(identity) = &settings.macos().signing_identity {
108+
if let Some(keychain) = super::sign::keychain(settings.macos().signing_identity.as_deref())? {
109109
// Sign frameworks and sidecar binaries first, per apple, signing must be done inside out
110110
// https://developer.apple.com/forums/thread/701514
111111
sign_paths.push(SignTarget {
@@ -118,7 +118,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
118118
remove_extra_attr(&app_bundle_path)?;
119119

120120
// sign application
121-
let keychain = sign(sign_paths, identity, settings)?;
121+
sign(&keychain, sign_paths, settings)?;
122122

123123
// notarization is required for distribution
124124
match notarize_auth() {

tooling/bundler/src/bundle/macos/dmg.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,14 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
186186
fs::rename(bundle_dir.join(dmg_name), dmg_path.clone())?;
187187

188188
// Sign DMG if needed
189-
if let Some(identity) = &settings.macos().signing_identity {
189+
190+
if let Some(keychain) = super::sign::keychain(settings.macos().signing_identity.as_deref())? {
190191
super::sign::sign(
192+
&keychain,
191193
vec![super::sign::SignTarget {
192194
path: dmg_path.clone(),
193195
is_an_executable: false,
194196
}],
195-
identity,
196197
settings,
197198
)?;
198199
}

tooling/bundler/src/bundle/macos/sign.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,36 @@ pub struct SignTarget {
1616
pub is_an_executable: bool,
1717
}
1818

19-
pub fn sign(
20-
targets: Vec<SignTarget>,
21-
identity: &str,
22-
settings: &Settings,
23-
) -> crate::Result<tauri_macos_sign::Keychain> {
24-
log::info!(action = "Signing"; "with identity \"{}\"", identity);
25-
26-
let keychain = if let (Some(certificate_encoded), Some(certificate_password)) = (
19+
pub fn keychain(identity: Option<&str>) -> crate::Result<Option<tauri_macos_sign::Keychain>> {
20+
if let (Some(certificate_encoded), Some(certificate_password)) = (
2721
var_os("APPLE_CERTIFICATE"),
2822
var_os("APPLE_CERTIFICATE_PASSWORD"),
2923
) {
30-
// setup keychain allow you to import your certificate
31-
// for CI build
32-
tauri_macos_sign::Keychain::with_certificate(&certificate_encoded, &certificate_password)?
24+
// import user certificate - useful for for CI build
25+
let keychain =
26+
tauri_macos_sign::Keychain::with_certificate(&certificate_encoded, &certificate_password)?;
27+
if let Some(identity) = identity {
28+
let certificate_identity = keychain.signing_identity();
29+
if !certificate_identity.contains(identity) {
30+
return Err(anyhow::anyhow!("certificate from APPLE_CERTIFICATE \"{certificate_identity}\" environment variable does not match provided identity \"{identity}\"").into());
31+
}
32+
}
33+
Ok(Some(keychain))
34+
} else if let Some(identity) = identity {
35+
Ok(Some(tauri_macos_sign::Keychain::with_signing_identity(
36+
identity,
37+
)))
3338
} else {
34-
tauri_macos_sign::Keychain::with_signing_identity(identity)
35-
};
39+
Ok(None)
40+
}
41+
}
3642

37-
log::info!("Signing app bundle...");
43+
pub fn sign(
44+
keychain: &tauri_macos_sign::Keychain,
45+
targets: Vec<SignTarget>,
46+
settings: &Settings,
47+
) -> crate::Result<()> {
48+
log::info!(action = "Signing"; "with identity \"{}\"", keychain.signing_identity());
3849

3950
for target in targets {
4051
keychain.sign(
@@ -44,7 +55,7 @@ pub fn sign(
4455
)?;
4556
}
4657

47-
Ok(keychain)
58+
Ok(())
4859
}
4960

5061
pub fn notarize(

tooling/cli/ENVIRONMENT_VARIABLES.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ These environment variables are inputs to the CLI which may have an equivalent C
3131
- `API_PRIVATE_KEYS_DIR` — Specify the directory where your AuthKey file is located. See `APPLE_API_KEY`.
3232
- `APPLE_API_ISSUER` — Issuer ID. Required if `APPLE_API_KEY` is specified.
3333
- `APPLE_API_KEY_PATH` - path to the API key `.p8` file. If not specified, the bundler searches the following directories in sequence for a private key file with the name of 'AuthKey\_<api_key>.p8': './private_keys', '~/private_keys', '~/.private_keys', and '~/.appstoreconnect/private_keys'.
34-
- `APPLE_SIGNING_IDENTITY` — The identity used to code sign. Overwrites `tauri.conf.json > bundle > macOS > signingIdentity`.
34+
- `APPLE_SIGNING_IDENTITY` — The identity used to code sign. Overwrites `tauri.conf.json > bundle > macOS > signingIdentity`. If neither are set, it is inferred from `APPLE_CERTIFICATE` when provided.
3535
- `APPLE_PROVIDER_SHORT_NAME` — If your Apple ID is connected to multiple teams, you have to specify the provider short name of the team you want to use to notarize your app. Overwrites `tauri.conf.json > bundle > macOS > providerShortName`.
36-
- `APPLE_DEVELOPMENT_TEAM`TODO
36+
- `APPLE_DEVELOPMENT_TEAM`The team ID used to code sign on iOS. Overwrites `tauri.conf.json > bundle > iOS > developmentTeam`. Can be found in https://developer.apple.com/account#MembershipDetailsCard.
3737
- `TAURI_WEBVIEW_AUTOMATION` — Enables webview automation (Linux Only).
3838
- `TAURI_ANDROID_PROJECT_PATH` — Path of the tauri android project, usually will be `<project>/src-tauri/gen/android`.
3939
- `TAURI_IOS_PROJECT_PATH` — Path of the tauri iOS project, usually will be `<project>/src-tauri/gen/ios`.

0 commit comments

Comments
 (0)