On Aug 5, 2014, at 11:44 AM, Seth Willits <email@hidden> wrote:
... The first “solution” (if that’s it at all) is to keep header files in the internal frameworks, which I really don’t like. The second one is to remove above mentioned lines from the configuration file and add “run script” build phase for EVERY sub-project (there are about 65 of them) and sign EVERY particular executable, resource, script etc. But that would completely defeat the purpose of using Xcode to sign bundles, and I don’t even know whether if would create valid v2 signatures.
I'm far from an expert in code signing matters, but your issue sounds quite similar to one I had experienced in the past. Rather than using the resource rules file (I don't recall the details now, but I do remember finding it complicated to understand), I just added a single new Run Script phase to my top-level application's target that signed every framework within the bundle. In my case, I just did them explicitly, eg:
LOCATION="${BUILT_PRODUCTS_DIR}"/"${FRAMEWORKS_FOLDER_PATH}" IDENTITY="Developer ID Application" codesign --verbose --force --sign "$IDENTITY" "$LOCATION/FMDB.framework/Versions/A" codesign --verbose --force --sign "$IDENTITY" "$LOCATION/Growl.framework/Versions/A" codesign --verbose --force --sign "$IDENTITY" "$LOCATION/HexFiend.framework/Versions/A" ...
... but if you write the script to recursively scan for .frameworks and .plugins and whatever else you have in your situation, I don't see why it would be more than a couple dozen lines or so to get that working, and not having to explicitly list all 65 built products from subprojects.
Is there some reason that wouldn't work?
Our approach is to sign things explicitly and then confirm that all executables are signed and valid at the very end. The confirmation happens in our main build script, outside of xcodebuild. I found it easier to do it this way since code-signing has to happen from the inside-out. Controlling the order of the signing is paramount.
Each project has a shell script that we run in a script build phase. It mostly lists its signable resources like this
resources=( "$TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH/Resources/onsgmls/libs/libosp.4.dylib",isao.sonobe.OgreKit "$TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH/Resources/onsgmls/libs/onsgmls",isao.sonobe.OgreKit "$TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH/Resources/onsgmls/onsgmls.sh",isao.sonobe.OgreKit "$TARGET_BUILD_DIR/$FRAMEWORKS_FOLDER_PATH/TCMPortMapper.framework/Versions/A",de.codingmonkeys.TCMPortMapper … )
later it sources a global script that among other things signs the items in the resources list
SAVEIFS=$IFS IFS=$'\n'
for r in ${resources[@]}; do # escape the space in the file name SNAME=$(echo $r | sed 's/ /\\ /g') target=${SNAME/,*/ } identifier=${r/*,/ }
CS="xcrun codesign -f -v -s \"${CODE_SIGN_IDENTITY}\" --identifier $identifier $OTHER_CODE_SIGN_FLAGS $target" eval $CS done
In other words the strategy we use is that sub-projects don’t do any code signing. All of the signing happens in a script phase of the app and then we verify the results with
xcrun codesign --verify --verbose=4 -deep <app path>
This is helpful for telling you if you’ve signed some things out of order.
Next we display some diagnostic info with xcrun codesign -d --verbose=4 --deep <app path>
Finally, we do a gatekeeper check (warning: ruby)
executables = `find '#{$product_path}' -type f -perm -a+x` executables.each_line do |e| e.strip! cmd = "spctl --assess --verbose=4 --type execute '#{e}'" `#{cmd}` if $?.exitstatus != 0 errors += "Gatekeeper verification failed for #{e}\n" end
end failed errors unless errors == ""
I found that it’s not enough to validate the gatekeeper status of your main app bundle if you use helper tools - they’ll just die in the background if gatekeeper doesn’t like them. If you fail to sign a helper tool then your code signature check will still pass but the gatekeeper check will fail.
James Panic Inc.
|