From dfafe9921df302dc9bbb09d34a15656c5a8558e3 Mon Sep 17 00:00:00 2001 From: Laszlo Pusok Date: Wed, 19 Jan 2022 10:08:14 +0100 Subject: [PATCH 1/2] Intalling certificate for local codesign assets --- autocodesign/autocodesign.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/autocodesign/autocodesign.go b/autocodesign/autocodesign.go index 63d57bdc..4e84c379 100644 --- a/autocodesign/autocodesign.go +++ b/autocodesign/autocodesign.go @@ -191,6 +191,14 @@ func (m codesignAssetManager) EnsureCodesignAssets(appLayout AppLayout, opts Cod } printExistingCodesignAssets(localCodesignAssets, distrType) + if localCodesignAssets != nil { + // Did not check if selected certificate is installed yet + fmt.Println() + log.Infof("Installing certificate") + if err := m.assetWriter.InstallCertificate(localCodesignAssets.Certificate); err != nil { + return nil, fmt.Errorf("failed to install certificate: %w", err) + } + } finalAssets := localCodesignAssets if missingAppLayout != nil { @@ -213,7 +221,7 @@ func (m codesignAssetManager) EnsureCodesignAssets(appLayout AppLayout, opts Cod // Install new certificates and profiles fmt.Println() - log.Infof("Install certificates and profiles") + log.Infof("Installing certificates and profiles") if err := m.assetWriter.Write(map[DistributionType]AppCodesignAssets{distrType: *newCodesignAssets}); err != nil { return nil, fmt.Errorf("failed to install codesigning files: %w", err) } From 6930c7f4e342eb69a842a5105055b3c5faf90714 Mon Sep 17 00:00:00 2001 From: Laszlo Pusok Date: Thu, 20 Jan 2022 10:16:27 +0100 Subject: [PATCH 2/2] Added tests --- autocodesign/autocodesign.go | 2 +- autocodesign/autocodesign_test.go | 97 ++++++++++++++++++++++++++++--- 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/autocodesign/autocodesign.go b/autocodesign/autocodesign.go index 4e84c379..452b26b5 100644 --- a/autocodesign/autocodesign.go +++ b/autocodesign/autocodesign.go @@ -179,7 +179,6 @@ func (m codesignAssetManager) EnsureCodesignAssets(appLayout AppLayout, opts Cod devPortalDeviceIDs = append(devPortalDeviceIDs, devPortalDevice.ID) devPortalDeviceUDIDs = append(devPortalDeviceUDIDs, devPortalDevice.Attributes.UDID) } - } codesignAssetsByDistributionType := map[DistributionType]AppCodesignAssets{} @@ -195,6 +194,7 @@ func (m codesignAssetManager) EnsureCodesignAssets(appLayout AppLayout, opts Cod // Did not check if selected certificate is installed yet fmt.Println() log.Infof("Installing certificate") + log.Printf("certificate: %s", localCodesignAssets.Certificate.CommonName) if err := m.assetWriter.InstallCertificate(localCodesignAssets.Certificate); err != nil { return nil, fmt.Errorf("failed to install certificate: %w", err) } diff --git a/autocodesign/autocodesign_test.go b/autocodesign/autocodesign_test.go index fdd18b95..38797229 100644 --- a/autocodesign/autocodesign_test.go +++ b/autocodesign/autocodesign_test.go @@ -25,13 +25,14 @@ func newMockCertificateProvider(certs []certificateutil.CertificateInfoModel) Ce func newDefaultMockAssetWriter() AssetWriter { mockAssetWriter := new(MockAssetWriter) mockAssetWriter.On("Write", mock.Anything).Return(nil) + mockAssetWriter.On("InstallCertificate", mock.Anything).Return(nil) return mockAssetWriter } -func newMockLocalCodeSignAssetManager(assets *AppCodesignAssets, appLayout AppLayout) LocalCodeSignAssetManager { +func newMockLocalCodeSignAssetManager(assets *AppCodesignAssets, missingAppLayout *AppLayout) LocalCodeSignAssetManager { mockLocalCodeSignAssetManager := new(MockLocalCodeSignAssetManager) - mockLocalCodeSignAssetManager.On("FindCodesignAssets", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(assets, &appLayout, nil) + mockLocalCodeSignAssetManager.On("FindCodesignAssets", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(assets, missingAppLayout, nil) return mockLocalCodeSignAssetManager } @@ -211,7 +212,7 @@ func Test_codesignAssetManager_EnsureCodesignAssets(t *testing.T) { devPortalClient: checkOnlyDevportalProfile, certificateProvider: newMockCertificateProvider([]certificateutil.CertificateInfoModel{devCert}), assetWriter: newDefaultMockAssetWriter(), - localCodeSignAssetManager: newMockLocalCodeSignAssetManager(nil, appIDAndProfileFoundAppLayout), + localCodeSignAssetManager: newMockLocalCodeSignAssetManager(nil, &appIDAndProfileFoundAppLayout), }, appLayout: appIDAndProfileFoundAppLayout, opts: CodesignAssetsOpts{ @@ -234,7 +235,7 @@ func Test_codesignAssetManager_EnsureCodesignAssets(t *testing.T) { devPortalClient: checkOnlyDevportalProfile, certificateProvider: newMockCertificateProvider([]certificateutil.CertificateInfoModel{devCert}), assetWriter: newDefaultMockAssetWriter(), - localCodeSignAssetManager: newMockLocalCodeSignAssetManager(&localCodeSignAsset, appIDAndProfileFoundAppLayout), + localCodeSignAssetManager: newMockLocalCodeSignAssetManager(&localCodeSignAsset, &appIDAndProfileFoundAppLayout), }, appLayout: appIDAndProfileFoundAppLayout2, opts: CodesignAssetsOpts{ @@ -257,7 +258,7 @@ func Test_codesignAssetManager_EnsureCodesignAssets(t *testing.T) { fields: fields{ devPortalClient: devportalWithNoAppID, certificateProvider: newMockCertificateProvider([]certificateutil.CertificateInfoModel{devCert}), - localCodeSignAssetManager: newMockLocalCodeSignAssetManager(nil, icloudContainerAppLayout), + localCodeSignAssetManager: newMockLocalCodeSignAssetManager(nil, &icloudContainerAppLayout), }, appLayout: icloudContainerAppLayout, opts: CodesignAssetsOpts{ @@ -304,7 +305,7 @@ func Test_GivenNoValidAppID_WhenEnsureAppClipProfile_ThenItFails(t *testing.T) { }, } - localCodeSignAssetManager := newMockLocalCodeSignAssetManager(nil, appLayout) + localCodeSignAssetManager := newMockLocalCodeSignAssetManager(nil, &appLayout) manager := NewCodesignAssetManager(client, certProvider, assetWriter, localCodeSignAssetManager) opts := CodesignAssetsOpts{ @@ -340,7 +341,7 @@ func Test_GivenAppIDWithoutAppleSignIn_WhenEnsureAppClipProfile_ThenItFails(t *t }, } - localCodeSignAssetManager := newMockLocalCodeSignAssetManager(nil, appLayout) + localCodeSignAssetManager := newMockLocalCodeSignAssetManager(nil, &appLayout) manager := NewCodesignAssetManager(client, certProvider, assetWriter, localCodeSignAssetManager) opts := CodesignAssetsOpts{ @@ -412,7 +413,7 @@ func Test_GivenProfileExpired_WhenProfilesInconsistent_ThenItRetries(t *testing. }, } - localCodeSignAssetManager := newMockLocalCodeSignAssetManager(nil, appLayout) + localCodeSignAssetManager := newMockLocalCodeSignAssetManager(nil, &appLayout) manager := NewCodesignAssetManager(client, certProvider, assetWriter, localCodeSignAssetManager) opts := CodesignAssetsOpts{ @@ -426,6 +427,86 @@ func Test_GivenProfileExpired_WhenProfilesInconsistent_ThenItRetries(t *testing. require.NoError(t, err) } +func Test_GivenLocalProfile_WhenCertificateIsMissing_ThenInstalled(t *testing.T) { + // Given + const teamID = "MY_TEAM_ID" + expiry := time.Now().AddDate(1, 0, 0) + devCert1 := newCertificate(t, teamID, "MY_TEAM", "Apple Development: test 1", expiry) + devCert2 := newCertificate(t, teamID, "MY_TEAM", "Apple Development: test 2", expiry) + + validProfile := newMockProfile(profileArgs{ + attributes: appstoreconnect.ProfileAttributes{ + Name: profileName(appstoreconnect.IOSAppDevelopment, "io.test"), + ProfileState: appstoreconnect.Active, + ExpirationDate: appstoreconnect.Time(expiry), + }, + certificates: []string{"dev1", "dev2"}, + }) + + client := newMockDevportalClient(devportalArgs{ + certs: map[appstoreconnect.CertificateType][]Certificate{ + appstoreconnect.IOSDevelopment: { + { + CertificateInfo: devCert1, + ID: "dev1", + }, + { + CertificateInfo: devCert2, + ID: "dev2", + }, + }, + }, + profiles: map[appstoreconnect.ProfileType][]Profile{ + appstoreconnect.IOSAppDevelopment: {validProfile}, + }, + appIDs: []appstoreconnect.BundleID{{ + Attributes: appstoreconnect.BundleIDAttributes{ + Identifier: "io.test", + Name: "test-app", + }, + }}, + }) + + assetWriter := new(MockAssetWriter) + assetWriter.On("Write", mock.Anything).Return(nil) + assetWriter.On("InstallCertificate", devCert2).Return(nil).Once() + appLayout := AppLayout{ + Platform: IOS, + EntitlementsByArchivableTargetBundleID: map[string]Entitlements{ + "io.test": {}, + }, + } + + certProvider := newMockCertificateProvider([]certificateutil.CertificateInfoModel{devCert1}) + localCodeSignAssetManager := newMockLocalCodeSignAssetManager(&AppCodesignAssets{ + ArchivableTargetProfilesByBundleID: map[string]Profile{ + "io.test": validProfile, + }, + Certificate: devCert2, + }, nil) + manager := NewCodesignAssetManager(client, certProvider, assetWriter, localCodeSignAssetManager) + + opts := CodesignAssetsOpts{ + DistributionType: Development, + } + + wantAssets := map[DistributionType]AppCodesignAssets{ + Development: { + ArchivableTargetProfilesByBundleID: map[string]Profile{ + "io.test": validProfile, + }, + Certificate: devCert2, + }, + } + + // When + gotAssets, err := manager.EnsureCodesignAssets(appLayout, opts) + + // Then + require.NoError(t, err) + require.Equal(t, wantAssets, gotAssets) +} + func newClientWithoutAppIDAndProfile(cert certificateutil.CertificateInfoModel) *MockDevPortalClient { client := newMockDevportalClient(devportalArgs{ certs: map[appstoreconnect.CertificateType][]Certificate{