@@ -29,7 +29,10 @@ enum CodesignType {
29
29
withEntitlements (filename: 'entitlements.txt' ),
30
30
31
31
/// Binaries requiring codesigning that DO NOT use APIs requiring entitlements.
32
- withoutEntitlements (filename: 'without_entitlements.txt' );
32
+ withoutEntitlements (filename: 'without_entitlements.txt' ),
33
+
34
+ /// Binaries that do not require codesigning.
35
+ unsigned (filename: 'unsigned_binaries.txt' );
33
36
34
37
const CodesignType ({required this .filename});
35
38
@@ -87,6 +90,9 @@ class FileCodesignVisitor {
87
90
88
91
/// Files that require codesigning that DO NOT use APIs requiring entitlements.
89
92
Set <String > withoutEntitlementsFiles = < String > {};
93
+
94
+ /// Files that do not require codesigning.
95
+ Set <String > unsignedBinaryFiles = < String > {};
90
96
Set <String > fileConsumed = < String > {};
91
97
Set <String > directoriesVisited = < String > {};
92
98
Map <String , String > availablePasswords = {
@@ -124,26 +130,30 @@ class FileCodesignVisitor {
124
130
static final RegExp _notarytoolStatusCheckPattern = RegExp (r'[ ]*status: ([a-zA-z ]+)' );
125
131
static final RegExp _notarytoolRequestPattern = RegExp (r'id: ([a-z0-9-]+)' );
126
132
127
- static const String fixItInstructions = '''
133
+ static final String fixItInstructions = '''
128
134
Codesign test failed.
129
135
130
136
We compared binary files in engine artifacts with those listed in
131
- entitlement.txt and withoutEntitlements.txt, and the binary files do not match.
132
- *entitlements.txt is the configuration file encoded in engine artifact zip,
133
- built by BUILD.gn and Ninja, to detail the list of entitlement files.
134
- Either an expected file was not found in *entitlements.txt, or an unexpected
135
- file was found in entitlements.txt.
137
+ * ${CodesignType .withEntitlements .filename }
138
+ * ${CodesignType .withoutEntitlements .filename }
139
+ * ${CodesignType .unsigned .filename }
140
+ and the binary files do not match.
141
+
142
+ These are the configuration files encoded in engine artifact zip that detail
143
+ the code-signing requirements of each of the binaries in the archive.
144
+ Either an unexpected binary was listed in these files, or one of the expected
145
+ binaries listed in these files was not found in the archive.
136
146
137
147
This usually happens during an engine roll.
138
- If this is a valid change, then BUILD.gn needs to be changed.
139
- Binaries that will run on a macOS host require entitlements, and
140
- binaries that run on an iOS device must NOT have entitlements.
148
+
149
+ If this is a valid change, then the BUILD.gn or the codesigning configuration
150
+ files need to be changed. Binaries that will run on a macOS host require
151
+ entitlements, and binaries that run on an iOS device must NOT have entitlements.
141
152
For example, if this is a new binary that runs on macOS host, add it
142
- to [entitlements.txt] file inside the zip artifact produced by BUILD.gn.
143
- If this is a new binary that needs to be run on iOS device, add it
144
- to [withoutEntitlements.txt].
145
- If there are obsolete binaries in entitlements configuration files, please delete or
146
- update these file paths accordingly.
153
+ to ${CodesignType .withEntitlements .filename } file inside the zip artifact produced by BUILD.gn.
154
+ If this is a new binary that needs to be run on iOS device, add it to
155
+ ${CodesignType .withoutEntitlements .filename }. If there are obsolete binaries in entitlements
156
+ configuration files, please delete or update these file paths accordingly.
147
157
''' ;
148
158
149
159
/// Read a single line of password stored at [passwordFilePath] .
@@ -202,8 +212,10 @@ update these file paths accordingly.
202
212
// Read codesigning configuration files.
203
213
withEntitlementsFiles = await parseCodesignConfig (parentDirectory, CodesignType .withEntitlements);
204
214
withoutEntitlementsFiles = await parseCodesignConfig (parentDirectory, CodesignType .withoutEntitlements);
215
+ unsignedBinaryFiles = await parseCodesignConfig (parentDirectory, CodesignType .unsigned);
205
216
log.info ('parsed binaries with entitlements are $withEntitlementsFiles ' );
206
217
log.info ('parsed binaries without entitlements are $withoutEntitlementsFiles ' );
218
+ log.info ('parsed binaries without codesigning $unsignedBinaryFiles ' );
207
219
208
220
// recursively visit extracted files
209
221
await visitDirectory (directory: parentDirectory, parentVirtualPath: '' );
@@ -240,6 +252,7 @@ update these file paths accordingly.
240
252
241
253
await cleanupCodesignConfig (directory);
242
254
255
+ final Set <String > ignoredFiles = Set .from (CodesignType .values.map ((CodesignType type) => type.filename));
243
256
final List <FileSystemEntity > entities = await directory.list (followLinks: false ).toList ();
244
257
for (FileSystemEntity entity in entities) {
245
258
if (entity is io.Link ) {
@@ -254,7 +267,7 @@ update these file paths accordingly.
254
267
);
255
268
continue ;
256
269
}
257
- if (entity.basename == 'entitlements.txt' || entity.basename == 'without_entitlements.txt' ) {
270
+ if (ignoredFiles. contains ( entity.basename) ) {
258
271
continue ;
259
272
}
260
273
final FileType childType = getFileType (
@@ -306,40 +319,47 @@ update these file paths accordingly.
306
319
await newDir.delete (recursive: true );
307
320
}
308
321
309
- /// Visit and codesign a binary with / without entitlement .
322
+ /// Visit and handle code-signing for a binary .
310
323
///
311
- /// At this stage, the virtual [entitlementCurrentPath] accumulated through the recursive visit, is compared
312
- /// against the paths extracted from [withEntitlementsFiles] , to help determine if this file should be signed
313
- /// with entitlements.
324
+ /// At this stage, the virtual [currentFilePath] accumulated through the recursive
325
+ /// visit is compared against the paths extracted from the contents of the codesigning
326
+ /// config files, to help determine whether or not this file should be codesigned
327
+ /// and if so, whether or not it should be signed with entitlements.
314
328
Future <void > visitBinaryFile ({
315
329
required File binaryFile,
316
330
required String parentVirtualPath,
317
331
}) async {
318
332
final String currentFileName = binaryFile.basename;
319
- final String entitlementCurrentPath = joinEntitlementPaths (parentVirtualPath, currentFileName);
320
-
321
- if (! withEntitlementsFiles.contains (entitlementCurrentPath) &&
322
- ! withoutEntitlementsFiles.contains (entitlementCurrentPath)) {
323
- log.severe ('the binary file $currentFileName is causing an issue. \n '
324
- 'This file is located at $entitlementCurrentPath in the flutter engine artifact.' );
325
- log.severe ('The system has detected a binary file at $entitlementCurrentPath . '
326
- 'But it is not in the entitlements configuration files you provided. '
333
+ final String currentFilePath = joinEntitlementPaths (parentVirtualPath, currentFileName);
334
+
335
+ if (! withEntitlementsFiles.contains (currentFilePath) &&
336
+ ! withoutEntitlementsFiles.contains (currentFilePath) &&
337
+ ! unsignedBinaryFiles.contains (currentFilePath)) {
338
+ log.severe ('The binary file $currentFileName is causing an issue. \n '
339
+ 'This file is located at $currentFilePath in the flutter engine artifact.' );
340
+ log.severe ('The system has detected a binary file at $currentFilePath . '
341
+ 'But it is not in the codesigning configuration files you provided. '
327
342
'If this is a new engine artifact, please add it to one of the entitlements.txt files.' );
328
343
throw CodesignException (fixItInstructions);
329
344
}
330
- log.info ('signing file at path ${binaryFile .absolute .path }' );
331
- log.info ('the virtual entitlement path associated with file is $entitlementCurrentPath ' );
332
- log.info ('the decision to sign with entitlement is ${withEntitlementsFiles .contains (entitlementCurrentPath )}' );
333
- fileConsumed.add (entitlementCurrentPath);
345
+ if (unsignedBinaryFiles.contains (currentFilePath)) {
346
+ // No codesigning necessary.
347
+ log.info ('Not signing file at path ${binaryFile .absolute .path }' );
348
+ return ;
349
+ }
350
+ log.info ('Signing file at path ${binaryFile .absolute .path }' );
351
+ log.info ('The virtual entitlement path associated with file is $currentFilePath ' );
352
+ log.info ('The decision to sign with entitlement is ${withEntitlementsFiles .contains (currentFilePath )}' );
353
+ fileConsumed.add (currentFilePath);
334
354
if (dryrun) {
335
355
return ;
336
356
}
337
- await codesignAtPath (binaryOrBundlePath: binaryFile.absolute.path, entitlementCurrentPath : entitlementCurrentPath );
357
+ await codesignAtPath (binaryOrBundlePath: binaryFile.absolute.path, currentFilePath : currentFilePath );
338
358
}
339
359
340
360
Future <void > codesignAtPath ({
341
361
required String binaryOrBundlePath,
342
- String ? entitlementCurrentPath ,
362
+ String ? currentFilePath ,
343
363
}) async {
344
364
final List <String > args = < String > [
345
365
'/usr/bin/codesign' ,
@@ -351,7 +371,7 @@ update these file paths accordingly.
351
371
binaryOrBundlePath,
352
372
'--timestamp' , // add a secure timestamp
353
373
'--options=runtime' , // hardened runtime
354
- if (entitlementCurrentPath != '' && withEntitlementsFiles.contains (entitlementCurrentPath )) ...< String > [
374
+ if (currentFilePath != '' && withEntitlementsFiles.contains (currentFilePath )) ...< String > [
355
375
'--entitlements' ,
356
376
entitlementsFile.absolute.path,
357
377
],
0 commit comments