Onboarding Profile Signing deprecated
Signing of Apple Configuration Profiles
The client onboarding wizard offers Apple configuration profiles (.mobileconfig) for iOS and macOS, which set up accounts on the device. The middleware can sign these profiles with a certificate and key from a PKCS#12 key store. A profile signed with a certificate the device trusts is shown as Verified; an unsigned one is shown as Unsigned, but installs just the same.
The key store is loaded from one of two sources:
- a Kubernetes secret, resolved through the middleware's key store service. This is the preferred way in Kubernetes, as it keeps the key out of the container file system, and a changed secret is picked up at runtime.
- a file in the container file system.
Configuration
| Property | Description |
|---|---|
com.openexchange.client.onboarding.plist.signature.enabled | Enables signing for the whole server. |
com.openexchange.client.onboarding.plist.pkcs12store.keystoreId | The value of the OX_KEYSTORE label of the secret holding the key store. |
com.openexchange.client.onboarding.plist.pkcs12store.filename | The path of the key store file. Only used if no keystoreId is set. |
com.openexchange.client.onboarding.plist.pkcs12store.password | The password of the key store. It MUST also unlock the private key. |
com.openexchange.client.onboarding.plist.signkey.alias | The alias of the signing key in the key store. Config-cascade aware. |
All properties are reloadable. See the property documentation for details.
Profiles are delivered unsigned without an error if signing is enabled but the password, the alias, or both key store sources are missing. If a keystoreId is set but no matching secret is found, the download fails instead of falling back to the file. The file is only used instead if the key store service itself is not running.
Deployment with a Kubernetes Secret
Create the key store from the signing certificate, its chain and the private key:
openssl pkcs12 -export -in cert.pem -certfile chain.pem -inkey key.pem -name onboarding -out onboarding.p12
Deploy it as a secret in the namespace of the middleware and label it for the key store service:
kubectl create secret generic onboarding-signing --from-file=onboarding.p12
kubectl label secret onboarding-signing OX_KEYSTORE=onboarding-signing
The secret MUST hold exactly one data entry: the key store service uses the first entry it finds. The label value MUST be unique in the namespace.
Then configure the middleware, e.g. through the properties of the core-mw chart:
properties:
com.openexchange.client.onboarding.plist.signature.enabled: true
com.openexchange.client.onboarding.plist.pkcs12store.keystoreId: onboarding-signing
com.openexchange.client.onboarding.plist.signkey.alias: onboarding
secretProperties:
com.openexchange.client.onboarding.plist.pkcs12store.password: <password>
The middleware's service account needs get, list and watch on secrets. The core-mw chart grants these as long as serviceAccount.create and rbac.create are enabled, which is the default.
Certificate Rotation
To rotate the certificate, replace the data of the secret, keeping its name, its label and the file name of the key store, which becomes the data key. With a different file name, kubectl apply MAY keep the old entry next to the new one:
kubectl create secret generic onboarding-signing --from-file=onboarding.p12 --dry-run=client -o yaml | kubectl apply -f -
No restart is needed. The key store is resolved on every profile download, and the key store service refreshes its cache when the secret changes: by polling every 30 seconds by default, or through a Kubernetes watch, see the key store properties. Cached entries also expire after 10 minutes, in case a change is missed.
The password and the alias are not part of the secret. If the new key store uses a different password or alias, change the properties as well; they are reloadable, so no restart is needed for them either.
With the com.openexchange.client.onboarding.plist logger at DEBUG, every signing logs the SHA-256 fingerprint of the signing certificate, and a rotation is logged as Plist signing certificate rotated with the old and new fingerprint.
Troubleshooting
- Profiles are shown as Unsigned: check that signing is enabled, and that the password, the alias, and either
keystoreIdorfilenameare set. - The download fails with
ONBRD-0024 Could not open keystore <keystoreId>: no secret carries the configuredOX_KEYSTORElabel value, the secret holds no data, or the middleware cannot list secrets. The last case is logged as an error bycom.openexchange.keystore.k8s, e.g. for a missing RBAC permission. For a key store file, the same error means the file cannot be read or the password does not open it. - The download fails with
Unable to convert stream to keystore: the password does not open the key store from the secret, or the secret does not hold a PKCS#12 key store. - The download fails with a signing error: the alias does not name a private key entry with a certificate in the key store. Check with
keytool -list -v -storetype PKCS12 -keystore onboarding.p12.