Notarization and application development

We have an organization with multiple developers trying to develop apps. There are times where they want to find out if their app will pass notarization or not? We have a Developer ID Application certificate that we use to sign files right before production deployment and then for notarization approval. But this is not possible when developers are working in their sandboxes.

Providing each developer their own Developer ID Application certificate for distribution is both not feasible and perhaps not very secure.

Is there a way in which they can find out if their apps would pass the notarization tests without actually uploading to Apple?

Answered by DTS Engineer in 804561022
Are there test methodologies that we can follow to write tests for problems presented by hardened runtime, missing entitlements and code/artifacts not in the right folder for the app?

Sure. I’ll come back to that below.

We have a Developer ID certificate in our CI CD right at the time of shipping. Perhaps we can move that up as well.

Right. That’d be the easiest option. Notarising every CI build isn’t a great idea, but notarising, say, your nightly builds is fine. That’ll head off any notarisation issues quickly, but it has another benefit: Once you have a notarised build, you can do a Gatekeeper evaluation using syspolicy_check.

Remember that notarisation and Gatekeeper are different things, and it’s easy to create a build that passes notarisation but fails Gatekeeper.

I have a bunch of backstory to this in Resolving Trusted Execution Problems.


In terms of running checks on your code’s structure, all of the things you mentioned are possible. It’s really just a question of how much time you want to spend on this, and how much time that saves you when it stops a problem getting through. That’s the reasoning behind my earlier “what sort of problems?” question. If you understand what the common problems are, you can focus your tooling efforts on those.

And regarding the things you specifically called out…

write tests for problems presented by hardened runtime … ?

Testing that the hardened runtime is enabled is trivially easy. You can do that using codesign or programmatically with the SecCode API.

Testing that your code works with the hardened runtime is enabled is… well… just testing. You should absolutely have the hardened runtime enabled on all your builds — development and distribution — and thus all your day-to-day testing should be testing the hardened runtime case.

write tests for problems presented by … missing entitlements … ?

Again, there are two aspects to this. It’s feasible to do a static test to confirm that:

  • You’re only claiming entitlements on executables, not libraries.

  • All of the entitlements you claim are either unrestricted or authorised by a provisioning profile.

Again, codesign and SecCode work for this, along with using security to work out the entitlements in your profile. And you’ll probably want to read TN3125 Inside Code Signing: Provisioning Profiles.

Testing for the runtime behaviour of this is, again, just testing.

The added challenge is that provisioning profiles are different for development and distribution, so you’ll want to run this test again in your CI. Or do the syspolicy_check thing, because it should catch such issues.

write tests for problems presented by … code/artifacts not in the right folder for the app?

That is trickier. It’s relatively easy to programmatically enforce the rules in Placing Content in a Bundle, but most large apps bend those rules in one way or another. So it kinda depends on the current state of your product. If it’s already well structured, building a tool to enforce that structure should be pretty easy. If not, well it depends on how bad things are (-:

Regardless, there are some high-level things you can test:

  • Check that your built product has no extended attributes. Extended attributes, especially code-signing extended attributes [1], are a common indicator of structural problems.

  • Copy the built product to both case-sensitive and case-insensitive volumes, and then run this command:

% codesign --verify --deep --strict /path/to/your.app

If that fails, it’s likely that notarisation will fail.

Share and Enjoy

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

[1] See TN3126 Inside Code Signing: Hashes for an example of code-signing extended attributes.

Maybe set up a single CI server can checkout and compile a repository provided by the developer. So the certificate will be only on that server, and it won't be accessible by anyone.

Is there a way in which they can find out if their apps would pass the notarization tests without actually uploading to Apple?

No, but even if there were, I’m not sure it’d help you. To pass notarisation the code must be signed with a valid Developer ID signing identity. However, your developers can’t have one of those, so this theoretical notarisation checking tool would always respond with “No.”

Providing each developer their own Developer ID Application certificate for distribution is both not feasible and perhaps not very secure.

Agreed. I talk about this more in The Care and Feeding of Developer ID. And that suggests exactly what galad87 suggested: a centralised build system that ‘owns’ the Developer ID signing identities.

In practice, do you often find that your developers introduce problems that show up during notarisation? If so, what sort of problems? It’s possible that you could construct your own tests that catch the most common issues.

Share and Enjoy

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

"It’s possible that you could construct your own tests that catch the most common issues."

This is exactly what I am looking for here. Are there test methodologies that we can follow to write tests for problems presented by hardened runtime, missing entitlements and code/artifacts not in the right folder for the app? We have a Developer ID certificate in our CI CD right at the time of shipping. Perhaps we can move that up as well. But we would like something to help our developers write "in-model" code with the right set of entitlements and other things.

Accepted Answer
Are there test methodologies that we can follow to write tests for problems presented by hardened runtime, missing entitlements and code/artifacts not in the right folder for the app?

Sure. I’ll come back to that below.

We have a Developer ID certificate in our CI CD right at the time of shipping. Perhaps we can move that up as well.

Right. That’d be the easiest option. Notarising every CI build isn’t a great idea, but notarising, say, your nightly builds is fine. That’ll head off any notarisation issues quickly, but it has another benefit: Once you have a notarised build, you can do a Gatekeeper evaluation using syspolicy_check.

Remember that notarisation and Gatekeeper are different things, and it’s easy to create a build that passes notarisation but fails Gatekeeper.

I have a bunch of backstory to this in Resolving Trusted Execution Problems.


In terms of running checks on your code’s structure, all of the things you mentioned are possible. It’s really just a question of how much time you want to spend on this, and how much time that saves you when it stops a problem getting through. That’s the reasoning behind my earlier “what sort of problems?” question. If you understand what the common problems are, you can focus your tooling efforts on those.

And regarding the things you specifically called out…

write tests for problems presented by hardened runtime … ?

Testing that the hardened runtime is enabled is trivially easy. You can do that using codesign or programmatically with the SecCode API.

Testing that your code works with the hardened runtime is enabled is… well… just testing. You should absolutely have the hardened runtime enabled on all your builds — development and distribution — and thus all your day-to-day testing should be testing the hardened runtime case.

write tests for problems presented by … missing entitlements … ?

Again, there are two aspects to this. It’s feasible to do a static test to confirm that:

  • You’re only claiming entitlements on executables, not libraries.

  • All of the entitlements you claim are either unrestricted or authorised by a provisioning profile.

Again, codesign and SecCode work for this, along with using security to work out the entitlements in your profile. And you’ll probably want to read TN3125 Inside Code Signing: Provisioning Profiles.

Testing for the runtime behaviour of this is, again, just testing.

The added challenge is that provisioning profiles are different for development and distribution, so you’ll want to run this test again in your CI. Or do the syspolicy_check thing, because it should catch such issues.

write tests for problems presented by … code/artifacts not in the right folder for the app?

That is trickier. It’s relatively easy to programmatically enforce the rules in Placing Content in a Bundle, but most large apps bend those rules in one way or another. So it kinda depends on the current state of your product. If it’s already well structured, building a tool to enforce that structure should be pretty easy. If not, well it depends on how bad things are (-:

Regardless, there are some high-level things you can test:

  • Check that your built product has no extended attributes. Extended attributes, especially code-signing extended attributes [1], are a common indicator of structural problems.

  • Copy the built product to both case-sensitive and case-insensitive volumes, and then run this command:

% codesign --verify --deep --strict /path/to/your.app

If that fails, it’s likely that notarisation will fail.

Share and Enjoy

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

[1] See TN3126 Inside Code Signing: Hashes for an example of code-signing extended attributes.

Notarization and application development
 
 
Q