Download Apple CA cert and import to keychain.

It does not appear that Apple's Development ID G2 Certificate
Authority is installed in the dart-internal bots. Thus, explicitly
download it and import it into the build.keychain before
importing Flutter's Developer ID cert which is signed with this
CA.

Bug: b/333426905
Change-Id: I14191604d4e5d5388679c7723fab8751817f3efe
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/57280
Reviewed-by: Reid Baker <reidbaker@google.com>
Reviewed-by: Zach Anderson <zra@google.com>
Commit-Queue: Christopher Fujino <fujino@google.com>
diff --git a/recipe_modules/signing/resources/setup_keychain.sh b/recipe_modules/signing/resources/setup_keychain.sh
index 97027fc..608e0a5 100755
--- a/recipe_modules/signing/resources/setup_keychain.sh
+++ b/recipe_modules/signing/resources/setup_keychain.sh
@@ -73,6 +73,23 @@
       keychainName,
     ]);
 
+    // TODO(fujino): cache this via CIPD
+    final io.File g2CertFile = await _downloadFile(
+      // Link from https://www.apple.com/certificateauthority
+      remoteUri: Uri.parse('https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer'),
+      localPath: './DeveloperIDG2CA.cer',
+    );
+
+    // LOAD certificate authority into the build keychain
+    await security(<String>[
+      'import',
+      g2CertFile.absolute.path,
+      '-k', keychainName,
+      // -T allows the specified program to access this identity
+      '-T', codesignPath,
+      '-T', '/usr/bin/codesign',
+    ]);
+
     // Retrieve current list of keychains on the search list of current machine.
     final keychains = security(const <String>['list-keychains', '-d', 'user'])
         .split('\n')
@@ -99,6 +116,10 @@
       '-s', ...keychains, keychainName,
     ]);
 
+    // For diagnostic purposes, list keychains AFTER adding our newly created
+    // keychain to the search list.
+    security(const <String>['list-keychains', '-d', 'user']);
+
     // Set $keychainName as default.
     security(<String>[
       'default-keychain',
@@ -152,3 +173,19 @@
   log('failed to find a Flutter identity after $totalRetryAttempts attempts.');
   return 1;
 }
+
+Future<io.File> _downloadFile({
+  required Uri remoteUri,
+  required String localPath,
+}) async {
+  final io.HttpClient client = io.HttpClient();
+
+  final io.HttpClientRequest request = await client.getUrl(remoteUri);
+  final io.HttpClientResponse response = await request.close();
+  final io.File g2CertFile = io.File(localPath);
+  final io.IOSink sink = g2CertFile.openWrite();
+  await response.pipe(sink);
+
+  client.close();
+  return g2CertFile;
+}