Mobile Device Management (MDM)

Introduction

Starting with iOS 7, Apple added support for managed application configuration. An MDM server can push a configuration to the iOS App. The app can access this configuration (read-only) using the NSUserDefaults class by reading a configuration dictionary under the key com.apple.configuration.managed. An app can also observe a system notification (NSUserDefaultsDidChangeNotification) to get notified about configuration changes. In addition feedback can be queried back by MDM server. To enable that, app has to write a dictionary with feedback information into user defaults under com.apple.feedback.managed key. The configuration is basically a key-value dictionary provided as a .plist file.

Configurable Settings

ownCloud App implements a mechanism internally called Class Settings which can be derived from different sources:

  • Environment variables which e.g. can be set in Xcode for testing. In this case setting keys have to be prepended with oc: prefix.

  • User preferences accessed by the very same API but stored under org.owncloud.user-settings key.

  • Settings dictionary pushed by an MDM Server and accessible using NSUserDefaults API under the key com.apple.configuration.managed.

  • Default settings defined directly in the app sourcecode.

  • Branding.plist which is the part of the Xcode project under ownCloud/Resources/Theming. It allows to override class settings by specifying them in the Configuration section

This is also an order in which these settings take precedence (environment variables have highest priority). So, when settings are accessed, they are merged and higher priority value for the same key overwrites lower priority ones.

Some settings are accessed only once at runtime and the read value is cached, so that new setting to take effect may a require an app to be terminated and restarted.

App Basic Configurations

There are few settings allowing to mark an app installation as BETA and e.g. to supress UIKit animation and review prompt.

Key Type Default Description Status

app.app-store-link

string

https://itunes.apple.com/app/id1359583808?mt=8

URL for the app in the App Store.

advanced candidate

app.enable-review-prompt

bool

true

Enable/disable review prompt.

advanced candidate

app.recommend-to-friend-enabled

bool

true

Enables/disables the recommend to a friend entry in the settings.

advanced candidate

app.enable-ui-animations

bool

true

Enable/disable UI animations.

debugOnly

app.is-beta-build

bool

false

Controls if the app is built for beta or release purposes.

debugOnly

app.show-beta-warning

bool

false

Controls whether a warning should be shown on the first run of a beta version.

debugOnly

Extensions / Actions

ownCloud app uses internally a plug-in like mechanism called extensions. Extensions are used to implement menu actions mostly found under "+" menu allowing to add new items (Upload media, take photo etc.) or in more menu (Copy, Move, Open in etc.). Using below settings actions / extensions can be disabled. Extensions are enabled by default, however this might depend on licensing requirements of a particular extension.

Key Type Default Description Status

action.allowed

stringArray

[]

List of all allowed actions. If provided, actions not listed here are not allowed.

Value

Description

com.owncloud.action.collaborate

Sharing

com.owncloud.action.copy

Copy

com.owncloud.action.createFolder

Create folder

com.owncloud.action.cutpasteboard

Cut

com.owncloud.action.delete

Delete

com.owncloud.action.duplicate

Duplicate

com.owncloud.action.favorite

Favorite item

com.owncloud.action.importpasteboard

Paste

com.owncloud.action.links

Links

com.owncloud.action.makeAvailableOffline

Make available offline

com.owncloud.action.makeUnavailableOffline

Available Offline

com.owncloud.action.markup

Markup

com.owncloud.action.move

Move

com.owncloud.action.openin

Open in

com.owncloud.action.pdfpage

Go to page

com.owncloud.action.presentationmode

Presentation Mode

com.owncloud.action.rename

Rename

com.owncloud.action.scan

Scan document

com.owncloud.action.show-exif

Image metadata

com.owncloud.action.unfavorite

Unfavorite item

com.owncloud.action.unshare

Unshare

com.owncloud.action.upload.camera_media

Take photo or video

com.owncloud.action.uploadfile

Upload file

com.owncloud.action.uploadphotos

Upload from your photo library

advanced candidate

action.disallowed

stringArray

[]

List of all disallowed actions. If provided, actions not listed here are allowed.

Value

Description

com.owncloud.action.collaborate

Sharing

com.owncloud.action.copy

Copy

com.owncloud.action.createFolder

Create folder

com.owncloud.action.cutpasteboard

Cut

com.owncloud.action.delete

Delete

com.owncloud.action.duplicate

Duplicate

com.owncloud.action.favorite

Favorite item

com.owncloud.action.importpasteboard

Paste

com.owncloud.action.links

Links

com.owncloud.action.makeAvailableOffline

Make available offline

com.owncloud.action.makeUnavailableOffline

Available Offline

com.owncloud.action.markup

Markup

com.owncloud.action.move

Move

com.owncloud.action.openin

Open in

com.owncloud.action.pdfpage

Go to page

com.owncloud.action.presentationmode

Presentation Mode

com.owncloud.action.rename

Rename

com.owncloud.action.scan

Scan document

com.owncloud.action.show-exif

Image metadata

com.owncloud.action.unfavorite

Unfavorite item

com.owncloud.action.unshare

Unshare

com.owncloud.action.upload.camera_media

Take photo or video

com.owncloud.action.uploadfile

Upload file

com.owncloud.action.uploadphotos

Upload from your photo library

advanced candidate

(*) These extensions might require additional license (in-app purchase, enterprise version).

Display Settings

To customize file list UI behevior, following settings are available:

Passcode Enforcement

If your organization policies require users to use a passcode as an additional security barrier for managed apps, the below setting will allow to enforce this requirement.

Key Type Default Description Status

passcode.enforced

bool

false

Controls wether the user MUST establish a passcode upon app installation

advanced candidate

passcode.maximumPasscodeDigits

int

6

Controls how many passcode digits are maximal possible for passcode lock.

advanced candidate

passcode.requiredPasscodeDigits

int

4

Controls how many passcode digits are at least required for passcode lock.

advanced candidate

Bookmark

Below settings allow to configure the app to use a certain server URL and even bind it to this URL only by setting the default non-editable.

Key Type Default Description Status

bookmark.default-url

string

The default URL for the creation of new bookmarks.

supported candidate

bookmark.url-editable

bool

true

Controls whether the server URL in the text field during the creation of new bookmarks can be changed.

supported candidate

Item Policies

Key Type Default Description Status

item-policy.local-copy-expiration

int

604800

The number of seconds that a file hasn’t been downloaded, modified or opened after which the local copy is removed.

advanced candidate

item-policy.local-copy-expiration-enabled

bool

true

Controls whether local copies should automatically be removed after they haven’t been downloaded, modified or opened for a period of time.

advanced candidate

item-policy.vacuum-sync-anchor-ttl

bool

60

Number of seconds since the removal of an item after which the metadata entry may be finally removed.

debugOnly

Connection

Settings concerinng HTTP user agent, cookies, background support etc.

Key Type Default Description Status

connection.allow-cellular

bool

true

Allow the use of cellular connections.

recommended candidate

core.cookie-support-enabled

bool

true

Enable or disable per-process, in-memory cookie storage.

supported candidate

http.user-agent

string

ownCloudApp/{{app.version}} ({{app.part}}/{{app.build}}; {{os.name}}/{{os.version}}; {{device.model}})

A custom User-Agent to send with every HTTP request.

The following placeholders can be used to make it dynamic: - {{app.build}}: the build number of the app (f.ex. 123) - {{app.version}}: the version of the app (f.ex. 1.2) - {{app.part}}: the part of the app (more exactly: the name of the main bundle) from which the request was sent (f.ex. App, ownCloud File Provider) - {{device.model}}: the model of the device running the app (f.ex. iPhone, iPad) - {{device.model-id}}: the model identifier of the device running the app (f.ex. iPhone8,1) - {{os.name}} : the name of the operating system running on the device (f.ex. iOS, iPadOS) - {{os.version}}: the version of operating system running on the device (f.ex. 13.2.2)

supported candidate

connection.always-request-private-link

bool

false

Controls whether private links are requested with regular PROPFINDs.

advanced candidate

connection.plain-http-policy

string

warn

Policy regarding the use of plain (unencryped) HTTP URLs for creating bookmarks. A value of warn will create an issue (typically then presented to the user as a warning), but ultimately allow the creation of the bookmark. A value of forbidden will block the use of http-URLs for the creation of new bookmarks.

advanced candidate

connection.validator-flags

stringArray

Allows fine-tuning the behavior of the connection validator by enabling/disabling aspects of it.

Value

Description

502-triggers

Connection validation is triggered when receiving a responses with 502 status.

clear-cookies

Clear all cookies for the connection when entering connection validation.

advanced candidate

core.action-concurrency-budgets

dictionary

map[actions:10 all:0 download:3 download-wifi-and-cellular:3 download-wifi-only:2 transfer:6 upload:3 upload-cellular-and-wifi:3 upload-wifi-only:2]

Concurrency budgets available for sync actions by action category.

advanced candidate

core.scan-for-changes-interval

int

10

Minimum number of seconds until the next scan for changes, measured from the completion of the previous scan.

advanced candidate

connection.allow-background-url-sessions

bool

true

Allow the use of background URL sessions. Note: depending on iOS version, the app may still choose not to use them. This settings is overriden by force-background-url-sessions.

debugOnly

connection.force-background-url-sessions

bool

false

Forces the use of background URL sessions. Overrides allow-background-url-sessions.

debugOnly

connection.minimum-server-version

string

10.0

The minimum server version required.

debugOnly

core.override-availability-signal

bool

Override the availability signal, so the host is considered to always be in maintenance mode (true) or never in maintenance mode (false).

debugOnly

core.override-reachability-signal

bool

Override the reachability signal, so the host is always considered reachable (true) or unreachable (false).

debugOnly

core.thumbnail-available-for-mime-type-prefixes

stringArray

[*]

Provide hints that thumbnails are available for items whose MIME-Type starts with any of the strings provided in this array. Providing an empty array turns off thumbnail loading. Providing ["*"] turns on thumbnail loading for all items.

debugOnly

host-simulator.active-simulations

stringArray

[]

Active Host simulation extensions.

Value

Description

five-seconds-of-404

Return status code 404 for every request for the first five seconds.

only-404

Return status code 404 for every request.

recovering-apm

Redirect any request without cookies to a bogus endpoint for 30 seconds, then to a cookie-setting endpoint, where cookies are set - and then redirect back.

reject-downloads-500

Reject Downloads with status 500 responses.

simple-apm

Redirect any request without cookies to a cookie-setting endpoint, where cookies are set - and then redirect back.

debugOnly

Server Endpoints

Individually configurable endpoints of the ownCloud server instance.

Key Type Default Description Status

connection.endpoint-capabilities

string

ocs/v2.php/cloud/capabilities

Endpoint to use for retrieving server capabilities.

advanced candidate

connection.endpoint-recipients

string

ocs/v2.php/apps/files_sharing/api/v1/sharees

Path of the sharing recipient API endpoint.

advanced candidate

connection.endpoint-remote-shares

string

ocs/v2.php/apps/files_sharing/api/v1/remote_shares

Path of the remote shares API endpoint.

advanced candidate

connection.endpoint-shares

string

ocs/v2.php/apps/files_sharing/api/v1/shares

Path of the shares API endpoint.

advanced candidate

connection.endpoint-status

string

status.php

Endpoint to retrieve basic status information and detect an ownCloud installation.

advanced candidate

connection.endpoint-thumbnail

string

index.php/apps/files/api/v1/thumbnail

Path of the thumbnail endpoint.

advanced candidate

connection.endpoint-user

string

ocs/v2.php/cloud/user

Endpoint to use for retrieving information on logged in user.

advanced candidate

connection.endpoint-webdav

string

remote.php/dav/files

Endpoint to use for WebDAV.

advanced candidate

connection.endpoint-webdav-meta

string

remote.php/dav/meta

Endpoint to use for WebDAV metadata.

advanced candidate

connection.well-known

string

.well-known

Path of the .well-known endpoint.

advanced candidate

Connection Authentication / Security

Settings concerning certificate validation policies.

Key Type Default Description Status

connection.allowed-authentication-methods

stringArray

Array of allowed authentication methods. Nil/Missing for no restrictions.

Value

Description

com.owncloud.basicauth

Basic Auth

com.owncloud.oauth2

OAuth2

com.owncloud.openid-connect

OpenID Connect

recommended candidate

connection.preferred-authentication-methods

stringArray

[com.owncloud.openid-connect com.owncloud.oauth2 com.owncloud.basicauth]

Array of authentication methods in order of preference (most preferred first).

Value

Description

com.owncloud.basicauth

Basic Auth

com.owncloud.oauth2

OAuth2

com.owncloud.openid-connect

OpenID Connect

recommended candidate

connection.certificate-extended-validation-rule

string

bookmarkCertificate == serverCertificate

Rule that defines the criteria a certificate needs to meet for OCConnection to recognize it as valid for a bookmark.

Examples of expressions: - bookmarkCertificate == serverCertificate: the whole certificate needs to be identical to the one stored in the bookmark during setup. - bookmarkCertificate.publicKeyData == serverCertificate.publicKeyData: the public key of the received certificate needs to be identical to the public key stored in the bookmark during setup. - serverCertificate.passedValidationOrIsUserAccepted == true: any certificate is accepted as long as it has passed validation by the OS or was accepted by the user. - serverCertificate.commonName == "demo.owncloud.org": the common name of the certificate must be "demo.owncloud.org". - serverCertificate.rootCertificate.commonName == "DST Root CA X3": the common name of the root certificate must be "DST Root CA X3". - serverCertificate.parentCertificate.commonName == "Let’s Encrypt Authority X3": the common name of the parent certificate must be "Let’s Encrypt Authority X3". - serverCertificate.publicKeyData.sha256Hash.asFingerPrintString == "2A 00 98 90 BD … F7": the SHA-256 fingerprint of the public key of the server certificate needs to match the provided value.

advanced candidate

connection.renewed-certificate-acceptance-rule

string

(bookmarkCertificate.publicKeyData == serverCertificate.publicKeyData) OR check.parentCertificatesHaveIdenticalPublicKeys == true) AND (serverCertificate.passedValidationOrIsUserAccepted == true OR bookmarkCertificate.parentCertificate.sha256Fingerprint.asFingerPrintString == "73 0C 1B DC D8 5F 57 CE 5D C0 BB A7 33 E5 F1 BA 5A 92 5B 2A 77 1D 64 0A 26 F7 A4 54 22 4D AD 3B") AND (bookmarkCertificate.rootCertificate.sha256Fingerprint.asFingerPrintString == "06 87 26 03 31 A7 24 03 D9 09 F1 05 E6 9B CF 0D 32 E1 BD 24 93 FF C6 D9 20 6D 11 BC D6 77 07 39") AND (serverCertificate.parentCertificate.sha256Fingerprint.asFingerPrintString == "67 AD D1 16 6B 02 0A E6 1B 8F 5F C9 68 13 C0 4C 2A A5 89 96 07 96 86 55 72 A3 C7 E7 37 61 3D FD") AND (serverCertificate.rootCertificate.sha256Fingerprint.asFingerPrintString == "96 BC EC 06 26 49 76 F3 74 60 77 9A CF 28 C5 A7 CF E8 A3 C0 AA E1 1A 8F FC EE 05 C0 BD DF 08 C6") AND (serverCertificate.passedValidationOrIsUserAccepted == true

Rule that defines the criteria that need to be met for OCConnection to accept a renewed certificate and update the bookmark’s certificate automatically instead of prompting the user. Used when the extended validation rule fails. Set this to never if the user should always be prompted when a server’s certificate changed.

advanced candidate

user-settings.allow

stringArray

List of settings (as flat identifiers) users are allowed to change. If this list is specified, only these settings can be changed by the user.

advanced candidate

user-settings.disallow

stringArray

List of settings (as flat identifiers) users are not allowed to change. If this list is specified, all settings not on the list can be changed by the user.

advanced candidate

connection.transparent-temporary-redirect

bool

false

Controls whether 307 redirects are handled transparently at the HTTP pipeline level (by resending the headers and body).

debugOnly

OAuth2 Based Authentication

Settings allowing to configure OAuth2 based authentication.

Key Type Default Description Status

authentication-oauth2.oa2-authorization-endpoint

string

index.php/apps/oauth2/authorize

OAuth2 authorization endpoint.

advanced candidate

authentication-oauth2.oa2-client-id

string

mxd5OQDk6es5LzOzRvidJNfXLUZS2oN3oUFeXPP8LpPrhx3UroJFduGEYIBOxkY1

OAuth2 Client ID.

advanced candidate

authentication-oauth2.oa2-client-secret

string

KFeFWWEZO9TkisIQzR3fo7hfiMXlOpaqP8CFuTbSHzV1TUuGECglPxpiVKJfOXIx

OAuth2 Client Secret.

advanced candidate

authentication-oauth2.oa2-redirect-uri

string

oc://ios.owncloud.com

OAuth2 Redirect URI.

advanced candidate

authentication-oauth2.oa2-token-endpoint

string

index.php/apps/oauth2/api/v1/token

OAuth2 token endpoint.

advanced candidate

authentication-oauth2.oa2-expiration-override-seconds

int

OAuth2 Expiration Override - lets OAuth2 tokens expire after the provided number of seconds (useful to prompt quick refresh_token requests for testing)

debugOnly

Logging

Logging settings control the ammount and type of app internal log messages stored as text files and accessible via settings menu.

Key Type Default Description Status

log.level

int

4

Log level

Value

Description

-1

verbose

0

debug

1

info

2

warning

3

error

4

off

supported candidate

log.privacy-mask

bool

false

Controls whether certain objects in log statements should be masked for privacy.

supported candidate

log.blank-filtered-messages

bool

false

Controls whether filtered out messages should still be logged, but with the message replaced with -.

advanced candidate

log.colored

bool

false

Controls whether log levels should be replaced with colored emojis.

advanced candidate

log.enabled-components

stringArray

[writer.stderr writer.file]

List of enabled logging system components.

Value

Description

option.log-file-operations

Log internal file operations

option.log-requests-and-responses

Log HTTP requests and responses

writer.file

Log file

writer.stderr

Standard error output

advanced candidate

log.format

string

text

Determines the format that log messages are saved in

Value

Description

json

Detailed JSON (one line per message).

json-composed

A simpler JSON version where details are already merged into the message.

text

Standard logging as text.

advanced candidate

log.maximum-message-size

int

0

Maximum length of a log message before the message is truncated. A value of 0 means no limit.

advanced candidate

log.omit-matching

stringArray

If set, omits logs messages containing any of the exact terms in this array.

advanced candidate

log.omit-tags

stringArray

If set, omits all log messages tagged with tags in this array.

advanced candidate

log.only-matching

stringArray

If set, only logs messages containing at least one of the exact terms in this array.

advanced candidate

log.only-tags

stringArray

If set, omits all log messages not tagged with tags in this array.

advanced candidate

log.single-lined

bool

true

Controls whether messages spanning more than one line should be broken into their individual lines and each be logged with the complete lead-in/lead-out sequence.

advanced candidate

log.synchronous

bool

false

Controls whether log messages should be written synchronously (which can impact performance) or asynchronously (which can loose messages in case of a crash).

advanced candidate

measurements.enabled

bool

true

Turn measurements on or off

debugOnly

AppConfig XML Schema

The XML format, developed by AppConfig community, makes it easy for developers to define and deploy an app configuration. It not only supports configuration variables having default values, but also provides a configuration UI description, which can be interpreted by the tool and which generates a plist file. Moreover, specfile XML is consistently supported by major EMM vendors.

AppConfig conformant spec file tailored to administrator needs and containing one or more of the above settings can be easily created using Config Spec Creator tool hosted at AppConfig website.

Example: Deployment With MobileIron

  1. Open AppConfig Generator

  2. Upload a specfile.xml.

  3. Change the configuration options.

  4. Download the generated plist file (ManagedAppConfig).

  5. Open MobileIron Core.

  6. Navigate to Policies and Configs  Add New  Apple  iOS/tvOS  Managed App Config

  7. Upload the generated plist and specify name, bundle ID, and description

Example: Deployment With Jamf Pro

  1. Open AppConfig Generator

  2. Upload a specfile.xml.

  3. Change the configuration options.

  4. Copy Dictionary (button).

  5. Open Jamf Pro.

  6. Navigate to Devices  Mobile Device Apps  ownCloud - File Sync and Share  iOS/tvOS  App Configuration  Edit

  7. Paste the generated Dictionary into the "Preferences" field.