Skip to content

Commit

Permalink
feat(bundler): infer signing identity from certificate to import (#10652
Browse files Browse the repository at this point in the history
)
  • Loading branch information
lucasfernog authored Aug 16, 2024
1 parent d39c392 commit 8deb196
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 21 deletions.
7 changes: 7 additions & 0 deletions .changes/infer-signing-identity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"tauri-bundler": patch:enhance
"tauri-cli": patch:enhance
"@tauri-apps/cli": patch:enhance
---

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.
4 changes: 2 additions & 2 deletions tooling/bundler/src/bundle/macos/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {

copy_custom_files_to_bundle(&bundle_directory, settings)?;

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

// sign application
let keychain = sign(sign_paths, identity, settings)?;
sign(&keychain, sign_paths, settings)?;

// notarization is required for distribution
match notarize_auth() {
Expand Down
5 changes: 3 additions & 2 deletions tooling/bundler/src/bundle/macos/dmg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,14 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
fs::rename(bundle_dir.join(dmg_name), dmg_path.clone())?;

// Sign DMG if needed
if let Some(identity) = &settings.macos().signing_identity {

if let Some(keychain) = super::sign::keychain(settings.macos().signing_identity.as_deref())? {
super::sign::sign(
&keychain,
vec![super::sign::SignTarget {
path: dmg_path.clone(),
is_an_executable: false,
}],
identity,
settings,
)?;
}
Expand Down
41 changes: 26 additions & 15 deletions tooling/bundler/src/bundle/macos/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,36 @@ pub struct SignTarget {
pub is_an_executable: bool,
}

pub fn sign(
targets: Vec<SignTarget>,
identity: &str,
settings: &Settings,
) -> crate::Result<tauri_macos_sign::Keychain> {
log::info!(action = "Signing"; "with identity \"{}\"", identity);

let keychain = if let (Some(certificate_encoded), Some(certificate_password)) = (
pub fn keychain(identity: Option<&str>) -> crate::Result<Option<tauri_macos_sign::Keychain>> {
if let (Some(certificate_encoded), Some(certificate_password)) = (
var_os("APPLE_CERTIFICATE"),
var_os("APPLE_CERTIFICATE_PASSWORD"),
) {
// setup keychain allow you to import your certificate
// for CI build
tauri_macos_sign::Keychain::with_certificate(&certificate_encoded, &certificate_password)?
// import user certificate - useful for for CI build
let keychain =
tauri_macos_sign::Keychain::with_certificate(&certificate_encoded, &certificate_password)?;
if let Some(identity) = identity {
let certificate_identity = keychain.signing_identity();
if !certificate_identity.contains(identity) {
return Err(anyhow::anyhow!("certificate from APPLE_CERTIFICATE \"{certificate_identity}\" environment variable does not match provided identity \"{identity}\"").into());
}
}
Ok(Some(keychain))
} else if let Some(identity) = identity {
Ok(Some(tauri_macos_sign::Keychain::with_signing_identity(
identity,
)))
} else {
tauri_macos_sign::Keychain::with_signing_identity(identity)
};
Ok(None)
}
}

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

for target in targets {
keychain.sign(
Expand All @@ -44,7 +55,7 @@ pub fn sign(
)?;
}

Ok(keychain)
Ok(())
}

pub fn notarize(
Expand Down
4 changes: 2 additions & 2 deletions tooling/cli/ENVIRONMENT_VARIABLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ These environment variables are inputs to the CLI which may have an equivalent C
- `API_PRIVATE_KEYS_DIR` — Specify the directory where your AuthKey file is located. See `APPLE_API_KEY`.
- `APPLE_API_ISSUER` — Issuer ID. Required if `APPLE_API_KEY` is specified.
- `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'.
- `APPLE_SIGNING_IDENTITY` — The identity used to code sign. Overwrites `tauri.conf.json > bundle > macOS > signingIdentity`.
- `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.
- `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`.
- `APPLE_DEVELOPMENT_TEAM`TODO
- `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.
- `TAURI_WEBVIEW_AUTOMATION` — Enables webview automation (Linux Only).
- `TAURI_ANDROID_PROJECT_PATH` — Path of the tauri android project, usually will be `<project>/src-tauri/gen/android`.
- `TAURI_IOS_PROJECT_PATH` — Path of the tauri iOS project, usually will be `<project>/src-tauri/gen/ios`.
Expand Down

0 comments on commit 8deb196

Please sign in to comment.