New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store submission fails with iCloud entitlements #798

Closed
rmaz opened this Issue Jul 1, 2016 · 6 comments

Comments

Projects
None yet
3 participants
@rmaz
Contributor

rmaz commented Jul 1, 2016

When a provisioning profile has iCloud entitlements enabled, the buck signed binary will not pass store submission. A typical iCloud provisioning profile will have entitlements similar to:

<key>Entitlements</key>
<dict>
    <key>keychain-access-groups</key>
    <array>
        <string>4ZX4Z3MVHG.*</string>
    </array>
    <key>application-identifier</key>
    <string>4ZX4Z3MVHG.com.appleseedinc.MyProject</string>
    <key>com.apple.developer.ubiquity-kvstore-identifier</key>
    <string>4ZX4Z3MVHG.*</string>
    <key>com.apple.developer.icloud-services</key>
    <string>*</string>
    <key>com.apple.developer.icloud-container-environment</key>
    <array>
        <string>Development</string>
        <string>Production</string>
    </array>
    <key>com.apple.developer.icloud-container-identifiers</key>
    <array>
        <string>iCloud.com.appleseedinc.MyProject</string>
        <string>iCloud.com.appleseedinc.container1</string>
    </array>
    <key>com.apple.developer.icloud-container-development-container-identifiers</key>
    <array>
        <string>iCloud.com.appleseedinc.MyProject</string>
        <string>iCloud.com.appleseedinc.container1</string>
    </array>
    <key>com.apple.developer.ubiquity-container-identifiers</key>
    <array>
        <string>iCloud.com.appleseedinc.MyProject</string>
        <string>iCloud.com.appleseedinc.container1</string>
    </array>
    <key>com.apple.developer.team-identifier</key>
    <string>4ZX4Z3MVHG</string>
    <key>aps-environment</key>
    <string>production</string>
</dict>

The default entitlements handling in buck will combine the specified entitlements file with the entitlements in the provisioning profile. This will result in both the com.apple.developer.icloud-container-development-container-identifiers and com.apple.developer.ubiquity-kvstore-identifier keys being added to the signing entitlements. Trying to submit a binary with either of these present will result in the following iTunes store errors:

ERROR ITMS-90045: "Invalid Code Signing Entitlements. Your application bundle's signature contains code signing entitlements that are not supported on iOS. Specifically, key com.apple.developer.icloud-container-development-container-identifiers in Payload/Blah.app is not supported."

and:

ERROR ITMS-90211: Invalid Code Signing Entitlements. The signature for your app bundle contains entitlement values that are not supported. For the com.apple.developer.ubiquity-kvstore-identifier entitlement, the value must start with the prefix provided by Apple in the provisioning profile, followed by characters that are uppercase or lowercase Roman letters [A-Z, a-z], the digits 0 through 9, dot, or hyphen, and not contain any wildcard characters. Specifically, value 4ZX4Z3MVHG.* for the key com.apple.developer.ubiquity-kvstore-identifier in Payload/Blah.app is not supported.

I'm not sure where the behaviour of merging the entitlements came from, is this mirroring what Xcode would do? It seems more correct to not merge the entitlements, would this result in a different error though, do we always need to merge certain keys from the provisioning profile?

@k21 k21 assigned ryu2 Jul 1, 2016

@rmaz

This comment has been minimized.

Contributor

rmaz commented Jul 4, 2016

I've done a bit of digging on this, it does appear that Xcode uses a similar approach with a blacklist of keys not to merge into the entitlements file. The list seems to include:

com.apple.developer.icloud-container-development-container-identifiers
com.apple.developer.icloud-container-environment
com.apple.developer.icloud-container-identifiers
com.apple.developer.icloud-services
com.apple.developer.restricted-resource-mode
com.apple.developer.ubiquity-container-identifiers
com.apple.developer.ubiquity-kvstore-identifier
inter-app-audio
com.apple.developer.homekit
com.apple.developer.healthkit
com.apple.developer.in-app-payments
com.apple.developer.associated-domains
com.apple.security.application-groups
com.apple.developer.maps
com.apple.developer.networking.vpn.api
com.apple.external-accessory.wireless-configuration

The behaviour is complex enough that it seems pretty risky trying to replicate it inside buck itself. Perhaps a wrapper around the system entitlements merging code is the best approach here?

@ryu2

This comment has been minimized.

Contributor

ryu2 commented Jul 5, 2016

@rmaz I looked into this, but the entitlements processing seems to be happens in a step called builtin-productPackagingUtility in Xcode. As the name implies, this doesn't seem to be cleanly exposed for external consumption (e.g. as a command-line tool).

@rmaz

This comment has been minimized.

Contributor

rmaz commented Jul 6, 2016

Yes, this is unfortunate. I have tracked down the class that does most of the heavy lifting, it is in an Xcode framework: https://github.com/luisobo/Xcode-RuntimeHeaders/blob/master/IDEFoundation/IDEArchivePackagerEntitlementsMerger.h

So the options we have are:

  • Wrap this framework in a command line tool that we optionally build when we have a Mac host
  • Reimplement its logic in buck

I was leaning towards the first approach and using JNI to invoke the framework, but this seems to be impossible due to the way that the rpath has been setup for the framework, it would require manually loading every single dependent framework as it seems runpath search flags are not correctly passed down to the JNI framework. Wrapping this in a C tool is still an option, and probably the safest course if a bit fiddly.

Otherwise we just work out what it is doing and replicate the logic, but it is unfortunately doing quite a lot more than you would expect, including adding in defaults, replacing wildcards, blacklisting a whole bunch of keys (which presumably change with every tooling upgrade) and doing some verification of some of the keys.

I think in the short term we should take the second approach and look to make this more solid down the line, thoughts?

@sdwilsh

This comment has been minimized.

Contributor

sdwilsh commented Jul 6, 2016

@ryu2

This comment has been minimized.

Contributor

ryu2 commented Jul 6, 2016

I agree the second approach is better as (platform considerations aside) depending on a private interface is something I'd like only as a last resort.

Either way, we're susceptible to Apple's changes. The second approach where we do our own implementation is advantageous in that any future breakage is more visible and presumably easier to fix.

As a side note In the longer term, we're moving away from hard-coding things like this in Java and moving more towards Python for the execution of the build steps themselves.

@rmaz

This comment has been minimized.

Contributor

rmaz commented Jul 7, 2016

OK, I added a blacklist to filter out invalid keys for now. There is also some validation behaviour that I left out, but from what I can tell this is to do with $(TeamIdentifier) variable substitution that doesn't work with buck anyway, so seems safe to leave out for now.

@ghost ghost closed this in ae0b3fa Jul 12, 2016

florianf added a commit to MobiVM/robovm that referenced this issue May 23, 2017

Exclude some Entitlement keys (#144)
Should fix #143 . As noted in facebook/buck#798 some keys of the entitlements are stripped during the build. Prevent the if the key is in the `excludedKeys`.

This issue was closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment