Revert "🔥 Deep code sign."

This reverts commit d0c932a90d.
This commit is contained in:
joshaber
2015-10-26 11:58:05 -04:00
parent 9bcc86be72
commit bee2be5dfb
3 changed files with 337 additions and 0 deletions
+8
View File
@@ -13,6 +13,8 @@
534FF36717D8E90A0020A51A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 534FF36517D8E90A0020A51A /* InfoPlist.strings */; };
534FF36A17D8E90A0020A51A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 534FF36917D8E90A0020A51A /* main.m */; };
534FF37317D8E9370020A51A /* com.github.Squirrel.TestApplication.TestService.xpc in Copy XPCServices */ = {isa = PBXBuildFile; fileRef = 534FF36017D8E90A0020A51A /* com.github.Squirrel.TestApplication.TestService.xpc */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
53710D7417D8F59700A992DE /* SQRLDeepCodesignSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 53710D7317D8F59700A992DE /* SQRLDeepCodesignSpec.m */; };
53710D8417D8F5CB00A992DE /* deep-codesign in Resources */ = {isa = PBXBuildFile; fileRef = 53710D7F17D8F5C300A992DE /* deep-codesign */; };
5371815F18A29DC8005ED798 /* TestAppConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 5371815E18A29DC8005ED798 /* TestAppConstants.m */; };
5371816018A29DC8005ED798 /* TestAppConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 5371815E18A29DC8005ED798 /* TestAppConstants.m */; };
5374DCC6187AD0D8006B7056 /* SQRLAuthorization.h in Headers */ = {isa = PBXBuildFile; fileRef = 5374DCC4187AD0D8006B7056 /* SQRLAuthorization.h */; };
@@ -267,8 +269,10 @@
534FF36617D8E90A0020A51A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
534FF36817D8E90A0020A51A /* TestService-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TestService-Prefix.pch"; sourceTree = "<group>"; };
534FF36917D8E90A0020A51A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
53710D7317D8F59700A992DE /* SQRLDeepCodesignSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SQRLDeepCodesignSpec.m; sourceTree = "<group>"; };
53710D7D17D8F5C300A992DE /* bootstrap */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = bootstrap; sourceTree = "<group>"; };
53710D7E17D8F5C300A992DE /* cibuild */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = cibuild; sourceTree = "<group>"; };
53710D7F17D8F5C300A992DE /* deep-codesign */ = {isa = PBXFileReference; lastKnownFileType = text; path = "deep-codesign"; sourceTree = "<group>"; };
53710D8017D8F5C300A992DE /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE.md; sourceTree = "<group>"; };
53710D8117D8F5C300A992DE /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = "<group>"; };
53710D8217D8F5C300A992DE /* targets.awk */ = {isa = PBXFileReference; lastKnownFileType = text; path = targets.awk; sourceTree = "<group>"; };
@@ -532,6 +536,7 @@
children = (
53710D7D17D8F5C300A992DE /* bootstrap */,
53710D7E17D8F5C300A992DE /* cibuild */,
53710D7F17D8F5C300A992DE /* deep-codesign */,
53710D8017D8F5C300A992DE /* LICENSE.md */,
53710D8117D8F5C300A992DE /* README.md */,
53710D8217D8F5C300A992DE /* targets.awk */,
@@ -929,6 +934,7 @@
children = (
D00F5B8D17E82DE6009A4818 /* NSProcessInfoExtensionsSpec.m */,
D0EDBEE017B0E3650058BC3C /* SQRLCodeSignatureSpec.m */,
53710D7317D8F59700A992DE /* SQRLDeepCodesignSpec.m */,
D049059A180554BA004E683E /* SQRLDirectoryManagerSpec.m */,
D09D244017B595470001FAF8 /* SQRLInstallerSpec.m */,
D049059C18055671004E683E /* SQRLShipItRequestSpec.m */,
@@ -1137,6 +1143,7 @@
D08D4E4A17B451FD0012B22D /* TestApplication.app in Resources */,
D09D244A17B59AB30001FAF8 /* TestApplication 2.1.app in Resources */,
D000219717BAD34D0050109A /* TestApplication.app.zip in Resources */,
53710D8417D8F5CB00A992DE /* deep-codesign in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1273,6 +1280,7 @@
D06B58D118035B5A00656D97 /* SQRLTerminationListenerSpec.m in Sources */,
5371815F18A29DC8005ED798 /* TestAppConstants.m in Sources */,
D0EDBEE117B0E3650058BC3C /* SQRLCodeSignatureSpec.m in Sources */,
53710D7417D8F59700A992DE /* SQRLDeepCodesignSpec.m in Sources */,
D00F5B8E17E82DE6009A4818 /* NSProcessInfoExtensionsSpec.m in Sources */,
D049059B180554BA004E683E /* SQRLDirectoryManagerSpec.m in Sources */,
5397A69D187DF8610014A477 /* SQRLInstallerOwnedBundle.m in Sources */,
+126
View File
@@ -0,0 +1,126 @@
//
// SQRLDeepCodesignSpec.m
// Squirrel
//
// Created by Keith Duncan on 2013-09-05.
// Copyright (c) 2013 GitHub. All rights reserved.
//
#import <Nimble/Nimble.h>
#import <Quick/Quick.h>
#import <ReactiveCocoa/ReactiveCocoa.h>
#import <Squirrel/Squirrel.h>
#import "QuickSpec+SQRLFixtures.h"
QuickSpecBegin(SQRLDeepCodesign)
NSMutableDictionary * (^environmentSuitableForChildProcess)(void) = ^ {
// Remove environment variables that configure the Obj-C runtime
// Specifically OBJC_DISABLE_GC so that child processes aren't forced to
// adopt the GC preference of the test suite
NSMutableDictionary *environment = [NSProcessInfo.processInfo.environment mutableCopy];
NSSet *objcEnvironmentVariables = [environment keysOfEntriesPassingTest:^(NSString *variable, id obj, BOOL *stop) {
return [variable hasPrefix:@"OBJC"];
}];
[environment removeObjectsForKeys:objcEnvironmentVariables.allObjects];
return environment;
};
NSTask * (^codesignTaskWithArguments)(NSArray *) = ^ (NSArray *arguments) {
NSTask *task = [[NSTask alloc] init];
task.launchPath = @"/usr/bin/xcrun";
task.arguments = [@[ @"codesign" ] arrayByAddingObjectsFromArray:arguments];
task.environment = environmentSuitableForChildProcess();
return task;
};
void (^resignTestApplicationPreserveEverythingButTheRequirements)(void) = ^{
NSURL *testApplicationLocation = self.testApplicationURL;
NSTask *resignCodesignTask = codesignTaskWithArguments(@[
@"--sign", @"-",
@"--force",
@"--verbose=4",
@"--preserve-metadata=identifier,entitlements,resource-rules",
testApplicationLocation.path,
]);
[resignCodesignTask launch];
[resignCodesignTask waitUntilExit];
expect(@(resignCodesignTask.terminationStatus)).to(equal(@0));
};
void (^deepCodesignTestApplication)(void) = ^{
NSURL *testApplicationLocation = self.testApplicationURL;
NSBundle *testsBundle = [NSBundle bundleForClass:self.class];
NSURL *deepCodesignLocation = [testsBundle URLForResource:@"deep-codesign" withExtension:nil];
NSNumber *executable = nil;
NSError *executableError = nil;
BOOL getExecutable = [deepCodesignLocation getResourceValue:&executable forKey:NSURLIsExecutableKey error:&executableError];
expect(@(getExecutable)).to(beTruthy());
expect(@(executable.boolValue)).to(beTruthy());
expect(executableError).to(beNil());
NSTask *deepCodesignTask = [[NSTask alloc] init];
deepCodesignTask.launchPath = deepCodesignLocation.path;
deepCodesignTask.standardError = [NSPipe pipe];
deepCodesignTask.standardOutput = [NSPipe pipe];
NSMutableDictionary *environment = environmentSuitableForChildProcess();
[environment addEntriesFromDictionary:@{
@"CODE_SIGN_IDENTITY": @"-",
@"CONFIGURATION_BUILD_DIR": testApplicationLocation.URLByDeletingLastPathComponent.path,
@"FULL_PRODUCT_NAME": testApplicationLocation.lastPathComponent,
}];
deepCodesignTask.environment = environment;
[deepCodesignTask launch];
[deepCodesignTask waitUntilExit];
expect(@(deepCodesignTask.terminationStatus)).to(equal(@0));
/*
By signing test application's contents, which are covered by test
application's ResourceRules it's signature becomes invalid. Usually,
Xcode would sign the application after deep-codesign has run so the
signature would include the _signed_ child resources which are covered
by test application's ResourceRules
test application is already signed, so we need to manually resign it
deep-codesign preserves the requirements, we can't use it to resign the
root target, the new signing identity wouldn't verify against the
original designated requirement
*/
resignTestApplicationPreserveEverythingButTheRequirements();
};
BOOL (^deepVerify)(void) = ^ BOOL {
NSTask *deepVerifyTask = codesignTaskWithArguments(@[
@"--deep-verify",
@"--verbose=4",
self.testApplicationURL.path
]);
[deepVerifyTask launch];
[deepVerifyTask waitUntilExit];
return deepVerifyTask.terminationStatus == 0;
};
it(@"should deep sign the test application", ^{
deepCodesignTestApplication();
});
xit(@"should deep verify after signing", ^{
expect(@(deepVerify())).to(beFalsy());
deepCodesignTestApplication();
expect(@(deepVerify())).to(beTruthy());
});
QuickSpecEnd
+203
View File
@@ -0,0 +1,203 @@
#!/usr/bin/env ruby
def exit_error(description)
puts "{ \"error\": \"#{description}\" }"
exit 1
end
module Targets
class Object
def self.match(path)
!File.symlink?(path)
end
attr_reader :path
def initialize(path)
@path = path
end
def search_directories
[]
end
end
class Bundle < Object
def self.match(path)
return false unless super
return false unless match = File.extname(path).match(/\.(.+)/)
return match[1] == extension
end
def contents_directories
[ "Contents" ]
end
def suffix_directories
[
"Frameworks",
"SharedFrameworks",
"XPCServices",
"PlugIns",
"Support",
"SharedSupport",
File.join("Library", "LoginItems"),
File.join("Library", "LaunchServices"),
]
end
def search_directories
contents_directories.product(suffix_directories).map do |combination|
File.join(*combination)
end
end
end
class VersionedBundle < Bundle
def contents_directories
contents_directories = []
versions_directory = File.join(@path, "Versions")
Dir.foreach(versions_directory) do |current_version|
next if current_version.start_with?('.')
full_path = File.join(versions_directory, current_version)
next if File.symlink?(full_path)
contents_directories << File.join("Versions", current_version)
end
contents_directories
end
end
class App < Bundle
def self.extension
"app"
end
end
class Framework < VersionedBundle
def self.extension
"framework"
end
end
class XPCService < Bundle
def self.extension
"xpc"
end
end
class Tool < Object
def self.match(path)
return false unless super
return false unless File.executable?(path)
# Look for an __TEXT,__info_plist section
# This contains the CFBundleIdentifier necessary for signing
`otool -l "#{path}"` =~ /__info_plist/
end
end
def self.all_targets
[ App, Framework, XPCService, Tool ]
end
end
module Codesign
class Task
def self.sign(target, identity, timestamp)
arguments = [ "--sign", identity, "--force", "--preserve-metadata=identifier,entitlements,requirements", "--verbose", target.path ]
arguments.unshift("--timestamp=none") if not timestamp
codesign_with_arguments(arguments)
end
protected
def self.codesign_with_arguments(arguments)
$stdout.flush
pid = fork
if pid.nil?
exec("/usr/bin/xcrun", *([ "codesign" ].concat(arguments)))
else
Process.wait(pid)
exit_error("codesign failed") unless $?.exitstatus == 0
end
end
end
end
codesign_identity = ENV['CODE_SIGN_IDENTITY']
unless codesign_identity
exit_error("No codesign identity provided")
end
build_dir = ENV['CONFIGURATION_BUILD_DIR']
product_name = ENV['FULL_PRODUCT_NAME']
unless build_dir && product_name
exit_error("Path to built product not provided")
end
input_path = File.realpath(File.join(build_dir, product_name))
unless File.exists?(input_path)
exit_error("Built product doesn't exist at path provided")
end
targets = [ ]
def match_path(path)
Targets.all_targets.each do |target|
return target.new(path) if target.match(path)
end
nil
end
root_target = match_path input_path
if root_target.nil?
exit_error("Built product is not a known file structure, cannot deep codesign")
end
# Recursion base case can't use build_dir because there can be >1 product
paths_to_search = root_target.search_directories.map do |current_dir|
File.join(root_target.path, current_dir)
end
while paths_to_search.size > 0
new_search_paths = []
paths_to_search.each do |search_path|
next unless File.directory?(search_path)
Dir.foreach(search_path) do |current_directory_entry|
next if current_directory_entry.start_with?(".")
File.delete(File.join(search_path, current_directory_entry)) if current_directory_entry.end_with?(".cstemp")
target = match_path(File.join(search_path, current_directory_entry))
next if target.nil?
targets << target
new_search_paths << target.search_directories.map do |current_search_directory|
File.join(target.path, current_search_directory)
end
end
end
paths_to_search = new_search_paths.flatten
end
puts "Signing these targets:"
puts "="*22
print "\n"
# Sort into nested-most first, outer targets might include inner targets
# in their ResourceRules
targets = targets.sort_by do |target|
target.path.size
end
targets.reverse!
use_timestamp = ENV["CONFIGURATION"] == "Release"
targets.each do |target|
puts "=> #{target.path}"
Codesign::Task.sign(target, codesign_identity, use_timestamp)
end