chef / omnibus

Easily create full-stack installers for your project across a variety of platforms.
Apache License 2.0
1.29k stars 296 forks source link

Add Code Signing to Mac Packages #431

Open danielsdeleo opened 9 years ago

danielsdeleo commented 9 years ago

In addition to the signatures for packages, we also need to sign programs in the packages. To demonstrate the issue, go to the firewall tab of "Security & Privacy" and turn on the firewall with default settings, then (using ChefDK as an example), run knife serve. For every invocation, you'll get a pop-up where you have to click allow or deny. If the embedded ruby is properly signed, you only have to allow it once.

I've only briefly looked at code signing. The codesign man page has a bit of info, there is more extensive documentation here: https://developer.apple.com/library/mac/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html

This issue was originally reported as https://github.com/chef/chef-dk/issues/258 which shows a workaround using local code signing.

danielsdeleo commented 9 years ago

Digging a bit more, the docs say:

In the case of installer packages (.pkg and .mpkg bundles), everything is implicitly signed: The CPIO archive containing the payload, the CPIO archive containing install scripts, and the bill of materials (BOM) each have a hash recorded in the XAR header, and that header in turn is signed. Therefore, if you modify an install script (for example) after the package has been signed, the signature will be invalid.

But this is either misleading or wrong. I signed the embedded ruby in ChefDK according to http://patrickbougie.com/2013/07/22/code-signing-manually-compiled-software-after-changes/

Before signing

codesign --verbose=9 -d /opt/chefdk/embedded/bin/ruby 
Executable=/opt/chefdk/embedded/bin/ruby
Identifier=ruby-5555494466547908e0ea339eaeedfb5f57e30754
Format=Mach-O thin (x86_64)
CodeDirectory v=20100 size=194 flags=0x2(adhoc) hashes=3+2 location=system
Hash type=sha1 size=20
    -2=2f29ef3496cbe0bf6da47697862921ef5415d75e
    -1=0000000000000000000000000000000000000000
     0=f4670dea0b54101515e8204526d218252e488ea6
     1=61cc8ac1a6a8dd2a6a0dd212ee7cc49a1f6ff179
     2=ba2f7020b72b09e54c5bb8442d8198ea27eee045
CDHash=9f1876437973cf7d79f453524c4c3bba6386d5be
Signature=adhoc
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements count=1 size=200
codesign --verify --verbose /opt/chefdk/embedded/bin/ruby
/opt/chefdk/embedded/bin/ruby: invalid signature (code or signature have been modified)
In architecture: x86_64

After Signing:

odesign --verbose=9 -d /opt/chefdk/embedded/bin/ruby    
Executable=/opt/chefdk/embedded/bin/ruby
Identifier=ruby
Format=Mach-O thin (x86_64)
CodeDirectory v=20100 size=153 flags=0x0(none) hashes=3+2 location=embedded
Hash type=sha1 size=20
    -2=be5b5bf63e24c52d09bc8b8ed8daa639c0ba1f9e
    -1=0000000000000000000000000000000000000000
     0=886d12f276910871058955bd7889052a9ab98ce4
     1=61cc8ac1a6a8dd2a6a0dd212ee7cc49a1f6ff179
     2=04ac0ce350d4d4889fb276b1d28ee9dc69d485d0
CDHash=5c81b44305b47e05781f92548a2b6e5ffdff2f9b
Signature size=1349
Authority=ddeleo-dev
Signed Time=Feb 13, 2015, 5:14:04 PM
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements count=2 size=268

Modify Ruby

Then I added a newline to the end of /opt/chefdk/embedded/bin/ruby:

bash-3.2# echo "" >> /opt/chefdk/embedded/bin/ruby

And now:

codesign --verbose=9 -d /opt/chefdk/embedded/bin/ruby
Executable=/opt/chefdk/embedded/bin/ruby
Identifier=ruby
Format=Mach-O thin (x86_64)
CodeDirectory v=20100 size=153 flags=0x0(none) hashes=3+2 location=embedded
Hash type=sha1 size=20
    -2=be5b5bf63e24c52d09bc8b8ed8daa639c0ba1f9e
    -1=0000000000000000000000000000000000000000
     0=886d12f276910871058955bd7889052a9ab98ce4
     1=61cc8ac1a6a8dd2a6a0dd212ee7cc49a1f6ff179
     2=04ac0ce350d4d4889fb276b1d28ee9dc69d485d0
CDHash=5c81b44305b47e05781f92548a2b6e5ffdff2f9b
Signature size=1349
Authority=ddeleo-dev
Signed Time=Feb 13, 2015, 5:14:04 PM
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements count=2 size=268

And

codesign --verbose --verify /opt/chefdk/embedded/bin/ruby
/opt/chefdk/embedded/bin/ruby: main executable failed strict validation

tl;dr

It seems like the embedded ruby is not being modified after the package is built, but it's not signed in the way OS X wants in the first place.