From 537fea4049c4d871502888486fb60c7e7374499c Mon Sep 17 00:00:00 2001 From: Akos Birmacher Date: Fri, 25 May 2018 12:06:52 +0200 Subject: [PATCH 1/3] teamHasCertificates --- codesigndoc/codesigngroup.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/codesigndoc/codesigngroup.go b/codesigndoc/codesigngroup.go index c788e095..2b8a26c3 100644 --- a/codesigndoc/codesigngroup.go +++ b/codesigndoc/codesigngroup.go @@ -81,7 +81,9 @@ Would you like to use this team to sign your project?`, archiveCertificate.TeamI if !useArchiveTeam { teams := []string{} for team := range certificatesByTeam { - teams = append(teams, team) + if teamHasCertificates(archiveCertificate, certificatesByTeam[team]) { + teams = append(teams, team) + } } fmt.Println() @@ -366,3 +368,17 @@ func collectIpaExportSelectableCodeSignGroups(archive xcarchive.IosArchive, inst return codeSignGroups } + +func teamHasCertificates(archiveCertificate certificateutil.CertificateInfoModel, certificates []certificateutil.CertificateInfoModel) bool { + if isDistributionCertificate(archiveCertificate) { + developmentCertificates := certificateutil.FilterCertificateInfoModelsByFilterFunc(certificates, func(certInfo certificateutil.CertificateInfoModel) bool { + return !isDistributionCertificate(certInfo) + }) + return len(developmentCertificates) > 0 + } + + distributionCertificates := certificateutil.FilterCertificateInfoModelsByFilterFunc(certificates, func(certInfo certificateutil.CertificateInfoModel) bool { + return isDistributionCertificate(certInfo) + }) + return len(distributionCertificates) > 0 +} From 3d5eb5f0931431e472ae26d45e1a4838bf01b8c6 Mon Sep 17 00:00:00 2001 From: Akos Birmacher Date: Fri, 8 Jun 2018 13:06:34 +0200 Subject: [PATCH 2/3] PR clean - fix (+4 squashed commits) Squashed commits: [3fa4b0d] - [b3e302a] - [8e25678] - (+2 squashed commits) Squashed commits: [86e8e42] log fix [5439d32] PR clean - fix [b9572ef] No codesign cert find issue fix for the --certs-only flag --- codesigndoc/codesigngroup.go | 143 ++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 51 deletions(-) diff --git a/codesigndoc/codesigngroup.go b/codesigndoc/codesigngroup.go index b4e1a14a..91a06d5c 100644 --- a/codesigndoc/codesigngroup.go +++ b/codesigndoc/codesigngroup.go @@ -68,85 +68,123 @@ func printCodesignGroup(group export.IosCodeSignGroup) { func collectIpaExportCertificate(archiveCertificate certificateutil.CertificateInfoModel, installedCertificates []certificateutil.CertificateInfoModel) (certificateutil.CertificateInfoModel, error) { fmt.Println() fmt.Println() - question := fmt.Sprintf(`The archive used codesigning files of team: %s - %s -Would you like to use this team to sign your project?`, archiveCertificate.TeamID, archiveCertificate.TeamName) - useArchiveTeam, err := goinp.AskForBoolWithDefault(question, true) - if err != nil { - return certificateutil.CertificateInfoModel{}, fmt.Errorf("failed to read input: %s", err) - } - selectedTeam := "" - certificatesByTeam := mapCertificatesByTeam(installedCertificates) + selectedCertificate := certificateutil.CertificateInfoModel{} - if !useArchiveTeam { - teams := []string{} - for team := range certificatesByTeam { - if teamHasCertificates(archiveCertificate, certificatesByTeam[team]) { - teams = append(teams, team) - } - } + // Asking the user over and over until we find a valid certificate for the selected export method. + for searchingValidCertificate := true; searchingValidCertificate; { - fmt.Println() - selectedTeam, err = goinp.SelectFromStringsWithDefault("Select the Development team to sign your project", 1, teams) + // Export method + exportMethods := []string{"development", "app-store", "ad-hoc", "enterprise"} + + selectedExportMethod, err := goinp.SelectFromStringsWithDefault("Select the ipa export method", 1, exportMethods) if err != nil { return certificateutil.CertificateInfoModel{}, fmt.Errorf("failed to read input: %s", err) } - } else { - selectedTeam = fmt.Sprintf("%s - %s", archiveCertificate.TeamID, archiveCertificate.TeamName) - } + log.Debugf("selected export method: %v", selectedExportMethod) - selectedCertificate := certificateutil.CertificateInfoModel{} + // Export method needs Development or Distribution certificate? + exportDistCert := true + if selectedExportMethod == "development" { + exportDistCert = false + } - if isDistributionCertificate(archiveCertificate) { - certificates := certificatesByTeam[selectedTeam] - developmentCertificates := certificateutil.FilterCertificateInfoModelsByFilterFunc(certificates, func(certInfo certificateutil.CertificateInfoModel) bool { - return !isDistributionCertificate(certInfo) - }) + selectedTeam := "" + log.Debugf("InstalledCerts: %v\n", installedCertificates) - certificateOptions := []string{} - for _, certInfo := range developmentCertificates { - certificateOption := fmt.Sprintf("%s [%s]", certInfo.CommonName, certInfo.Serial) - certificateOptions = append(certificateOptions, certificateOption) + // Filter the installed certificates by distribution type + var certsForSelectedExport []certificateutil.CertificateInfoModel + if exportDistCert { + certsForSelectedExport = certificateutil.FilterCertificateInfoModelsByFilterFunc(installedCertificates, func(certInfo certificateutil.CertificateInfoModel) bool { + return isDistributionCertificate(certInfo) + }) + log.Debugf("Distribution certificated: %v\n", certsForSelectedExport) + } else { + certsForSelectedExport = certificateutil.FilterCertificateInfoModelsByFilterFunc(installedCertificates, func(certInfo certificateutil.CertificateInfoModel) bool { + return !isDistributionCertificate(certInfo) + }) + log.Debugf("Developer certificated: %v\n", certsForSelectedExport) } - fmt.Println() - question := fmt.Sprintf(`The Xcode archive used distribution certificate: %s [%s]. -Please select a development certificate:`, archiveCertificate.CommonName, archiveCertificate.Serial) - selectedCertificateOption, err := goinp.SelectFromStringsWithDefault(question, 1, certificateOptions) - if err != nil { - return certificateutil.CertificateInfoModel{}, fmt.Errorf("failed to read input: %s", err) + filteredCertificatesByTeam := mapCertificatesByTeam(certsForSelectedExport) + log.Debugf("Filtered certificates (by distribution type) by team: %v\n", filteredCertificatesByTeam) + + if len(filteredCertificatesByTeam) == 0 { + log.Warnf("🚨 We couldn't find any certificate for the %s export method.", selectedExportMethod) + continue } - for _, certInfo := range developmentCertificates { - certificateOption := fmt.Sprintf("%s [%s]", certInfo.CommonName, certInfo.Serial) - if certificateOption == selectedCertificateOption { - selectedCertificate = certInfo + useArchiveTeam := true + _, contains := filteredCertificatesByTeam[fmt.Sprintf("%s - %s", archiveCertificate.TeamID, archiveCertificate.TeamName)] + + // Ask the question if there is multiple valid team and the archiving team is one of them. + // Skip it if only 1 team has certificates on the machine. Or the archiving team does'n have the desired certificate type. + // Skip the question + set the useArchiveTeam = false, if multiple team has certificate for the export method but the archiving team is not one of them. + if len(filteredCertificatesByTeam) > 1 && contains { + question := fmt.Sprintf(`The archive used codesigning files of team: %s - %s +Would you like to use this team to sign your project?`, archiveCertificate.TeamID, archiveCertificate.TeamName) + useArchiveTeam, err = goinp.AskForBoolWithDefault(question, true) + if err != nil { + return certificateutil.CertificateInfoModel{}, fmt.Errorf("failed to read input: %s", err) } + // If multiple team has certificate for the export method but the archiving team is not one of them. + } else if !contains { + archiveTeam := fmt.Sprintf("%s - %s", archiveCertificate.TeamName, archiveCertificate.TeamID) + + fmt.Println() + log.Warnf("🚨 The archiving team (%s) doesn't have certificate for the %s export method", archiveTeam, selectedExportMethod) + useArchiveTeam = false + } else { + archiveTeam := fmt.Sprintf("%s - %s", archiveCertificate.TeamName, archiveCertificate.TeamID) + + fmt.Println() + log.Printf("Only the archiving team (%s) has certificate for the %s export method", archiveTeam, selectedExportMethod) } - } else { - certificates := certificatesByTeam[selectedTeam] - distributionCertificates := certificateutil.FilterCertificateInfoModelsByFilterFunc(certificates, func(certInfo certificateutil.CertificateInfoModel) bool { - return isDistributionCertificate(certInfo) - }) + // Use different team for export than archive. + if !useArchiveTeam { + teams := []string{} + for team := range filteredCertificatesByTeam { + if hasCertificateForDistType(exportDistCert, filteredCertificatesByTeam[team]) { + teams = append(teams, team) + } + } + + fmt.Println() + selectedTeam, err = goinp.SelectFromStringsWithDefault("Select the Development team to sign your project", 1, teams) + if err != nil { + return certificateutil.CertificateInfoModel{}, fmt.Errorf("failed to read input: %s", err) + } + } else { + selectedTeam = fmt.Sprintf("%s - %s", archiveCertificate.TeamID, archiveCertificate.TeamName) + } + + // Find the specific development certificate. + filteredTeamCertificates := filteredCertificatesByTeam[selectedTeam] certificateOptions := []string{} - for _, certInfo := range distributionCertificates { + + for _, certInfo := range filteredTeamCertificates { certificateOption := fmt.Sprintf("%s [%s]", certInfo.CommonName, certInfo.Serial) certificateOptions = append(certificateOptions, certificateOption) } + certType := "distribution" + if !exportDistCert { + certType = "development" + } + fmt.Println() - question := fmt.Sprintf(`The Xcode archive used development certificate: %s [%s]. -Please select a distribution certificate:`, archiveCertificate.CommonName, archiveCertificate.Serial) + question := fmt.Sprintf("Please select a %s certificate:", certType) selectedCertificateOption, err := goinp.SelectFromStringsWithDefault(question, 1, certificateOptions) if err != nil { return certificateutil.CertificateInfoModel{}, fmt.Errorf("failed to read input: %s", err) } - for _, certInfo := range distributionCertificates { + for _, certInfo := range filteredTeamCertificates { certificateOption := fmt.Sprintf("%s [%s]", certInfo.CommonName, certInfo.Serial) if certificateOption == selectedCertificateOption { selectedCertificate = certInfo + searchingValidCertificate = false } } } @@ -370,8 +408,11 @@ func collectIpaExportSelectableCodeSignGroups(archive xcarchive.IosArchive, inst return codeSignGroups } -func teamHasCertificates(archiveCertificate certificateutil.CertificateInfoModel, certificates []certificateutil.CertificateInfoModel) bool { - if isDistributionCertificate(archiveCertificate) { +// hasCertificateForDistType returns true if the provided certificate list has certificate for the selected cert type. +// If isDistCert == true it will search for Distribution Certificates. If it's == false it will search for Developmenttion Certificates. +// If the team doesn't have any certificate for the selected cert type, it will return false. +func hasCertificateForDistType(isDistCert bool, certificates []certificateutil.CertificateInfoModel) bool { + if !isDistCert { developmentCertificates := certificateutil.FilterCertificateInfoModelsByFilterFunc(certificates, func(certInfo certificateutil.CertificateInfoModel) bool { return !isDistributionCertificate(certInfo) }) From 658022c680675fa4bb370d4fbc96b95149f40ff9 Mon Sep 17 00:00:00 2001 From: Akos Birmacher Date: Mon, 11 Jun 2018 14:59:47 +0200 Subject: [PATCH 3/3] PR clean fix --- codesigndoc/codesigngroup.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codesigndoc/codesigngroup.go b/codesigndoc/codesigngroup.go index 91a06d5c..cfdba478 100644 --- a/codesigndoc/codesigngroup.go +++ b/codesigndoc/codesigngroup.go @@ -122,7 +122,7 @@ func collectIpaExportCertificate(archiveCertificate certificateutil.CertificateI // Skip the question + set the useArchiveTeam = false, if multiple team has certificate for the export method but the archiving team is not one of them. if len(filteredCertificatesByTeam) > 1 && contains { question := fmt.Sprintf(`The archive used codesigning files of team: %s - %s -Would you like to use this team to sign your project?`, archiveCertificate.TeamID, archiveCertificate.TeamName) +Would you like to use this team to export an ipa file?`, archiveCertificate.TeamID, archiveCertificate.TeamName) useArchiveTeam, err = goinp.AskForBoolWithDefault(question, true) if err != nil { return certificateutil.CertificateInfoModel{}, fmt.Errorf("failed to read input: %s", err) @@ -151,7 +151,7 @@ Would you like to use this team to sign your project?`, archiveCertificate.TeamI } fmt.Println() - selectedTeam, err = goinp.SelectFromStringsWithDefault("Select the Development team to sign your project", 1, teams) + selectedTeam, err = goinp.SelectFromStringsWithDefault("Select the Development team to export your app", 1, teams) if err != nil { return certificateutil.CertificateInfoModel{}, fmt.Errorf("failed to read input: %s", err) }