Skip to content

Instantly share code, notes, and snippets.

@Sherlouk
Last active December 10, 2023 19:24
Show Gist options
  • Save Sherlouk/ba24f6366cd2cb1f9ad9c400ca18ad09 to your computer and use it in GitHub Desktop.
Save Sherlouk/ba24f6366cd2cb1f9ad9c400ca18ad09 to your computer and use it in GitHub Desktop.
Debug Profiles - Securely debugging in production

Blog post: https://blog.sidetrack.app/debugging-in-production

Creating the Certificates

  1. Open Keychain Access

  2. Click Keychain Access, Certificate Assistant, and Create a Certificate Authority

  3. Provide a name, and select 'Let me override defaults'

  4. Unselect 'Make this CA the default'

  5. Change the validity period as necessary, I recommend setting this to a longer length (such as 10 years)

  6. Leave the rest of the options, and click Next through the rest of the pages

  7. To verify, click 'Show CA Certificate'

  8. Click Keychain Access, Certificate Assistant, and Create Certificate

  9. Set the Identity Type to 'Leaf'

  10. Set Certificate Type to 'Custom' and choose the certificate authority we created earlier

  11. Override defaults and set the same validity period as you wish

  12. Set the Issuer to your certificate authority you made earlier

  13. Leave the rest of the options, and click Next through the rest of the pages

  14. Delete the private keys for both the certificate authority and the leaf certificate

  15. Right click on the Leaf certificate and press 'Export'

  16. Select the '.cer' file format

  17. Export this and add it to your iOS project (ensuring it's target membership includes your main app)

  18. Right click on the authority certificate and press 'Export'

  19. Select the '.cer' file format

  20. Export this to your project (it's good to keep it in source control) but do not add it to your app target

The leaf certificate is shipped with your application. The authority certificate is what is installed on the device, and is what enables the SecTrustEvaluateWithError call to succeed.

Creating and Installing the Profile

Using the Apple Configurator app, click on File and New Profile. Provide a name and other required details. Under Certificates, click Configure and select the CA certificate exported in step 19. This will generate a profile - you can name it anything.

There are numerous ways to install the profile onto a device. At Sidetrack, we store it in a secure Google drive where we can install it from their mobile app. Though while we've got it open, we'll do it in Configurator. Select your device and click Add. Select your profile and confirm.

Now this adds it to your phone's storage, but you must first install it for it to be trusted. Head to your iPhone Settings, General and then VPN & Device Management. Your custom profile should appear, in which case you can select it, tap Install, enter your passcode, tap Install again and you're done.

At this point the isDebugProfileInstalled computed variable should start passing, and you can use it to unlock functionality in your app.

//
// DebugDevice.swift
//
// Copyright 2022 • Sidetrack Tech Limited
//
import Foundation
// This must be called on the main-thread.
var isDebugProfileInstalled: Bool {
// DebugModeLeaf is generated in Step 16, you may need to change the name.
guard let path = Bundle.main.path(forResource: "DebugModeLeaf", ofType: "cer") else {
return false
}
// We load the certificate into memory and convert it to a certificate type using Apple's Security framework.
guard let data = try? NSData(contentsOfFile: path) as CFData else {
return false
}
let cert = SecCertificateCreateWithData(nil, data)
let policy = SecPolicyCreateBasicX509()
// Create a trust management object; a wrapper around the certificate
var trust: SecTrust?
_ = SecTrustCreateWithCertificates([ cert ] as CFArray, policy, &trust)
guard let unwrappedTrust = trust else {
return false
}
var error: CFError?
// Verify that we can trust the certificate, this will only succeed if the device has the authority profile installed
guard SecTrustEvaluateWithError(unwrappedTrust, &error) else {
// You may wish to do something with the error here...
return false
}
return true
}
@Sherlouk
Copy link
Author

Thanks for taking a look @jbehrens94!

I'd definitely take a look at the repository which encapsulates all of this information. It hopefully addresses each of these concerns: it has much better handling for threading (avoiding the purple warning), automates the creation of the profile/certificates (avoiding human error and poor instructions) and I've not had any "Not Trusted" errors.

On the last one, it will say "Not Signed" but shouldn't have any trust issues once you've installed it.

If you have any issues with the repo above, I'd recommend raising issues there and I can look into them for you!

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