How to handle TCC permissions on machines for UI test automation?

Hello,

we have a bunch of macs which we use for running automated UI test and we need to allow services kTCCServiceScreenCapture and kTCCServiceAccessibility to our application bundles (it's a kind of a screen sharing application).

We tried to do a direct change in:

  • User's ~/Library/Application Support/com.apple.TCC/TCC.db but it doesn't take effect as it looks like these permissions need to be granted in system TCC database
  • The system database at /Library/Application Support/com.apple.TCC/TCC.db is write-only due to rootless.

Is there any other way than completely disable SIP to grant these TCC permissions to our bundles?

Also we would be just fine to grant permissions manually when we're setting up the machine, but it seems these get reset from time to time. And that's my other question:

How the TCC validation works?

We're testing ad-hoc signed bundles as well as DeveloperID signed ones with the same Application ID and it seems that TCC gets confused over time and simply treats the permissions as not granted.

Would modifying csreq in TCC.db record to contain only requirement identifier=my.bundle.app.id prevent this behavior or there is some other heuristics TCC uses for permission validation?

Thank you, o/

How the TCC validation works?

It’s complicated, but a key factor is your app’s designated requirement. See TN3127 Inside Code Signing: Requirements.

We're testing ad-hoc signed bundles as well as DeveloperID signed ones with the same Application ID

This doesn’t make sense to me. Ad hoc signed code can’t use an App ID because an App ID must be authorised by a provisioning profile and a profile can only authorise code signed with signing identity whose certificate was issued by Apple. See TN3125 Inside Code Signing: Provisioning Profiles.

Regardless, when dealing with TCC it’s best to to sign your code with a stable siging identity, typically, Apple Developer for day-to-day work and Developer ID for final distribution [1]. Doing this will radically cut down on the amount of TCC thrash, which should help with your main issue.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Assuming your distributing the product independently.

Thank you Eskimo,

It’s complicated, but a key factor is your app’s designated requirement. See TN3127 Inside Code Signing: Requirements.

Do I then understand correctly that TCC uses application's designate requirements for setting up the initial access.csreq field? If I change the field will it just evaluate the requirements against the application or it also compares the access.csreq with actual the DR of the application (i.e. they match)?

This doesn’t make sense to me. Ad hoc signed code can’t use an App ID because an App ID must be authorised by a provisioning profile and a profile can only authorise code signed with signing identity whose certificate was issued by Apple. See TN3125 Inside Code Signing: Provisioning Profiles.

I'm probably using wrong term here - I should rather use a "bundle identifier". Our build environment produces macOS application bundles, which have the same bundle identifier but one is ad-hoc signed (codesign -s - ...) with restricted entitlements stripped, which is used on PR pipelines[1]. The other one is properly signed with DeveloperID distribution certificate. Problem is that machines which run the UI tests are fetching from both of these queues and even when we split them, the churn there (install/run/uninstall/repeat) seems to break a TCC a lot.


[1] This is weird but we have a few reasons for that where some are:

  • Our security policy is that we don't sign with production distribution certificates anything which was not reviewed and merged to master .

  • Using different bundle identifier is also not possible because many of the third-part integrations which we're also testing depend on the exact bundle id.

  • Running code unsigned on intel is also not an option - we still need to stick entitlements on executables so we don't run into problems with sandbox later.

  • Having provisioning profile and shared signing identity for the PR builds has a high maintenance cost because we would need to constantly update the provisioning profile with a new machine uuids (we're not small company, we're roughly of size of yours :))

Do I then understand correctly that TCC …

I’m not sufficiently up-to-speed on TCC’s implementation to answer that question.

Our build environment produces macOS application bundles, which have the same bundle identifier but one is ad-hoc signed [and the] other one is properly signed with DeveloperID distribution certificate.

Yeah, that’s exactly the sort of thing I recommend against (-: Rather, have your “PR pipeline” build use Apple Development signing.

we're not small company, we're roughly of size of yours :)

Cool. Then assigning someone to automate this shouldn’t be a problem, right? (-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Cool. Then assigning someone to automate this shouldn’t be a problem, right? (-:

Haha :-D

I'll share what we did in case someone trips over the same thing.

I did took and advantage of the fact that our test hosts are deployed with full disk access allowed for Terminal application (which runs the test runner) so I modify user's TCC.db to allow System Settings automation and then in the test script when I need screen recording permission I run automation[1] script which adds the application under test to screen recording allowlist. Not happy with that, I would rather run sql insert into TCC.db in the fraction of the time but it works somehow reliably and we don't need to disable SIP.


[1] The screen recording permissions are stored in system-wide /Library/Application Support/com.apple.TCC which has rootless attribute and can't be modified directly without disabling SIP

How to handle TCC permissions on machines for UI test automation?
 
 
Q