iOSアプリのベストプラクティス
iOSアプリの開発時に、ここで説明しているベストプラクティスを使用すると、iOSデバイスでCitrix Endpoint Managementとモバイルアプリ間の互換性が向上します。
MDXアプリSDKフレームワークおよびラッピング
アプリでMDXアプリSDKフレームワークを使用する場合、ラップを行うには、一致するMDX Toolkitバージョンを使用する必要があります。これらの2つのコンポーネント間でバージョンに不一致がある場合は、操作が失敗する可能性があります。
このような不一致を防ぐために、アプリをISVアプリとしてラップして、アプリモードPremiumまたはGeneralを指定します。これにより、事前にラップされたアプリを提供できるため、顧客がアプリをラップする必要がなくなり、不適切なMDX Toolkitが使用されることがありません。ISVによるラップ処理について詳しくは、「iOSモバイルアプリのラップ」を参照してください。
明示的なアプリIDの使用
使用するiOS Developer EnterpriseアカウントがワイルドカードアプリIDをサポートしていない場合、MDX Toolkitにラップする各アプリに明示的なアプリIDを作成します。また、アプリIDごとにプロビジョニングプロファイルを作成します。
メインスレッドのブロックの回避
メインスレッドでの実行時には、コードブロックは使用しないでください。これはAppleのガイドラインですが、Citrix Endpoint Managementではさらに重要です。一部の操作により、管理対象アプリで時間がかかったり、以降のスレッド実行がブロックされたりする場合があります。現在実行中のスレッドをブロックする可能性があるファイル操作、データベース操作、およびネットワーク操作などの操作は、メインスレッドでは避ける必要があります。
強固なコードの作成
特に、アプリの作成時に、『Apple Application Programming Guide』などのAppleのプログラミングガイドに記載されているベストプラクティスに従います。
Appleが公開しているインターフェイスのみ使用
すべてのAPI呼び出しの戻り値を確認し、API呼び出しの結果として発生する可能性のある例外を処理します。これにより、アプリの正常なエラー回復や正常な終了が保証されます。これはプログラミングの一般的なベストプラクティスですが、管理対象アプリでは特に重要です。
基盤となる機能がCitrix Endpoint Managementポリシーによってブロックされていると、正常に動作すると想定されているさまざまなAPIが正しく動作しません。例には、前述したすべての機能が含まれます。
- 使用できるネットワークがない場合、ネットワークAPIは失敗します。
- GPSやカメラなどのセンサーAPIは、nullを返すか例外をスローします。
以下のObjective-Cランタイムセレクタは、基盤となる機能がCitrix Endpoint Managementポリシーのためにブロックされている場合は常にnilを返すため、適時処理する必要があります。
オブジェクトクラス: AVCaptureDevice
- セレクタ名: devicesWithMediaType:
オブジェクトクラス: MFMailComposeViewController
- セレクタ名: init:
オブジェクトクラス: MFMessageComposeViewController
- セレクタ名: initWithNibName:bundle:
オブジェクトクラス: NSFileManager
- セレクタ名: URLForUbiquityContainerIdentifier:
オブジェクトクラス: NSUbiquitousKeyValueStore
- セレクタ名: defaultStore:
オブジェクトクラス: PHPhotoLibrary
- セレクタ名: sharedPhotoLibrary:
オブジェクトクラス: UIImagePickerController
- セレクタ名: availableCaptureModesForCameraDevice:
オブジェクトクラス: UIPasteboard
-
セレクタ名:
dataForPasteboardType:
valueForPasteboardType:
items:
dataForPasteboardType:inItemSet:
valuesForPasteboardType:inItemSet:
オブジェクトクラス: UIPopoverController
- セレクタ名: initWithContentViewController:
オブジェクトクラス: UINavigationController
-
セレクタ名:
ctxInitWithRootViewController:
ctxPopToViewController:animated:
ランタイムインターフェイスのリダイレクト
Citrix Endpoint ManagementではUI Pinプロンプト操作が提供されるため、アプリでこの操作を実行する必要がありません。
Citrix Endpoint Managementの準備が確実に整うように、Objective-Cランタイムセレクタをリダイレクトまたは置換しないことをお勧めします。なぜなら、Citrix Endpoint Managementは複数のオブジェクトクラスセレクタの基盤となるメソッドを開始し、アプリのランタイム動作を制御または変更するためです。次の表は、Citrix Endpoint ManagementによってリダイレクトされるObjective-Cクラスセレクタの一覧です:
オブジェクトクラス名: NSURLProtectionSpace
- セレクタ名: serverTrust
オブジェクトクラス名: NSURLAuthenticationChallenge
- セレクタ名: sender
オブジェクトクラス名: NSURLConnection
-
セレクタ名:
sendSynchronousRequest:returningResponse:error:
initWithRequest:delegate:startImmediately:
initWithRequest:delegate:
connectionWithRequest:delegate:
オブジェクトクラス名: NSURLConnectionDelegate
-
セレクタ名:
connection:canAuthenticateAgainstProtectionSpace:
connection:didReceiveAuthenticationChallenge:
connection:willSendRequestForAuthenticationChallenge:
オブジェクトクラス名: NSURLSessionConfiguration
-
セレクタ名:
defaultSessionConfiguration
ephemeralSessionConfiguration
オブジェクトクラス名: ALAssetsLibrary
- セレクタ名: authorizationStatus
オブジェクトクラス名: AVAudioRecorder
-
セレクタ名:
record
prepareToRecord
recordForDuration:
recordAtTime:
recordAtTime:ForDuration:
オブジェクトクラス名: AVAudioSession
- セレクタ名: recordPermission
オブジェクトクラス名: AVCaptureDevice
-
セレクタ名:
デバイス
devicesWithMediaType:
オブジェクトクラス名: AVAsset
- セレクタ名: assetWithURL:
オブジェクトクラス名: AVURLAsset
-
セレクタ名:
initWithURL:options:
URLAssetWithURL:options:
オブジェクトクラス名: AVPlayerItem
-
セレクタ名:
playerItemWithAsset:
initWithURL:
playerItemWithURL:
オブジェクトクラス名: AVPlayer
-
セレクタ名:
playerWithPlayerItem:
initWithPlayerItem:
initWithURL:
オブジェクトクラス名: CLLocationManager
- セレクタ名: startUpdatingLocation
オブジェクトクラス名: UIScrollView
- セレクタ名: setContentOffset:
オブジェクトクラス名: MFMailComposeViewController
-
セレクタ名:
canSendMail
init
オブジェクトクラス名: MFMessageComposeViewController
-
セレクタ名:
canSendText
initWithNibName:bundle:
オブジェクトクラス名: NSFileManager
- セレクタ名: URLForUbiquityContainerIdentifier:
オブジェクトクラス名: NSUbiquitousKeyValueStore
- セレクタ名: defaultStore
オブジェクトクラス名: PHPhotoLibrary
- セレクタ名: authorizationStatus
オブジェクトクラス名: QLPreviewController
-
セレクタ名:
setDataSource:
canPreviewItem:
オブジェクトクラス名: QLPreviewControllerDataSource
-
セレクタ名:
numberOfPreviewItemsInPreviewController:
previewController:previewItemAtIndex:
オブジェクトクラス名: SLComposeViewController
- セレクタ名: isAvailableForServiceType:
オブジェクトクラス名: UIActivityViewController
-
セレクタ名:
initWithActivityItems:applicationActivities:
setExcludedActivityTypes:
オブジェクトクラス名: UIApplication
-
セレクタ名:
openURL:
canOpenURL:
setApplicationIconBadgeNumber:
オブジェクトクラス名: UIDocument
-
セレクタ名:
closeWithCompletionHandler:
contentsForType:error:
オブジェクトクラス名: UIDocumentInteractionController
-
セレクタ名:
interactionControllerWithURL:
setURL:
setDelegate:
presentPreviewAnimated:
presentOpenInMenuFromBarButtonItem:animated:
presentOpenInMenuFromRect:inView:animated:
presentOptionsMenuFromBarButtonItem:animated:
presentOptionsMenuFromRect:inView:animated:
オブジェクトクラス名: UIDocumentMenuViewController
- セレクタ名: initWithDocumentTypes:inMode:
オブジェクトクラス名: UIImage
- セレクタ名: imageNamed:
オブジェクトクラス名: UIImagePickerController
-
セレクタ名: setSourceType:
takePicture
startVideoCapture
isSourceTypeAvailable:
isCameraDeviceAvailable:
isFlashAvailableForCameraDevice:
availableCaptureModesForCameraDevice:
setMediaTypes
オブジェクトクラス名: UINavigationController
-
セレクタ名:
ctxInitWithRootViewController:
ctxPushViewController:animated:
ctxPopToViewController:animated:
オブジェクトクラス名: UIPasteboard
-
セレクタ名:
generalPasteboard
pasteboardWithName:create:
pasteboardWithUniqueName
setValue:forPasteboardType:
setData:forPasteboardType:
setItems:
addItems:
dataForPasteboardType:
valueForPasteboardType:
numberOfItems
pasteboardTypes
pasteboardTypesForItemSet:
containsPasteboardTypes:
containsPasteboardTypes:inItemSet:
items
itemSetWithPasteboardTypes:
dataForPasteboardType:inItemSet:
valuesForPasteboardType:inItemSet:
string
strings
URL
URL
画像
images
color
colors
オブジェクトクラス名: UIPopoverController
- セレクタ名: initWithContentViewController
オブジェクトクラス名: UIPrintInteractionController
-
セレクタ名:
isPrintingAvailable
presentAnimated:completionHandler:
presentFromBarButtonItem:animated:completionHandler:
presentFromRect:inView:animated:completionHandler:
オブジェクトクラス名: UIViewController
- セレクタ名: presentViewController:animated:completion:
オブジェクトクラス名: UIWebView
-
セレクタ名:
loadRequest:
setDelegate:
UIWebViewDelegate
webView:shouldStartLoadWithRequest:navigationType:
webViewDidStartLoad:
webViewDidFinishLoad:
webView:didFailLoadWithError:
オブジェクトクラス名: UIWindow
- セレクタ名: makeKeyAndVisible
オブジェクトクラス名: UIApplicationDelegate
-
セレクタ名:
applicationDidFinishLaunching:
application:didFinishLaunchingWithOptions:
application:willFinishLaunchingWithOptions:
applicationWillResignActive:
applicationDidEnterBackground:
applicationWillEnterBackground:
applicationDidBecomeActive:
applicationWillTerminate:
application:openURL:sourceApplication:annotation:
application:handleOpenURL:
applicationProtectedDataWillBecomeUnavailable:
applicationProtectedDataDidBecomeAvailable:
application:performFetchWithCompletionHandler:
application:handleEventsForBackgroundURLSession:completionHandler:
application:didReceiveLocalNotification:
application:didReceiveRemoteNotification:
application:didReceiveRemoteNotification:fetchCompletionHandler:
application:didRegisterForRemoteNotificationsWithDeviceToken:
application:didFailToRegisterForRemoteNotificationsWithError:
applicationSignificantTimeChange:
application:shouldAllowExtensionPointIdentifier:
オブジェクトクラス名: QLPreviewController
- セレクタ名: allocWithZone:
データ暗号化機能の確保
MDXの主要機能の1つに、保持されているすべてのデータを透過的に暗号化する機能があります。アプリを変更せずにこの機能を利用でき、実際にこの機能を直接避けることはきません。Citrix Endpoint Management管理者は暗号化を選択的にまたは完全に無効化できますが、アプリではそのようにすることはできません。
これはMDXの重要な側面の1つであり、以下の点を理解しておく必要があります。
-
管理対象のプロセスで実行されるすべてのネイティブコードに対して、ファイル暗号化が実行されます。
ファイルデータ暗号化の実装は、すべてのネイティブコードをサポートしており、AppleフレームワークやApple Objective-Cランタイムを使用するアプリのコードだけではありません。Objective-Cランタイム内にこのランタイムのみを対象として実装されたファイルデータ暗号化を、簡単に無効化できます。
-
AVPlayerクラス、UIWebViewクラス、QLPreviewControllerなどの一部のフレームワークAPIは、ユーザーの管理対象アプリプロセスとは異なる実行コンテキストでiOSサービスプロセスによって実装されます。
これらのサービスプロセスは、MDX暗号化ファイルデータを暗号化解除できません。したがって、管理対象アプリでは、データの暗号化されていない一時的なコピーをサービスプロセスに提供する必要があります。このコピーは、5秒後に管理対象アプリによって削除されます。これらのクラスを使用するときは、制限に注意することが重要です。なぜなら、Appleの特定クラスの実装のためにこれらのクラスに対して提供されるデータへの抑制の制御が失われるからです。
-
メモリマッピングではアプリ呼び出しファイルI/Oシステムコールインターフェイスが使用されるため、Citrix Endpoint Management暗号化に問題が発生します。
ファイルがメモリマップされると、そのファイルのI/O要求は、Citrix Endpoint Managementの暗号化をバイパスし、ユーザーアプリのコンテキストの外部で管理されます。管理対象アプリによるすべてのPOSIX mmap(2)呼び出しがMAP_PRIVATEおよびMAP_ANONとしてマップされ、ファイル説明には関連付けられません。オペレーティングシステムによる後続のデータページイン以降にすべてのデータのファイル記述が[fault]に指定されている場合、mmap呼び出し中にすべてのマップデータで読み取りが試みられると、Citrix Endpoint Managementによって暗号化解除されずに暗号化データが読み取られます。アプリ内でメモリページの解放が行われず、メモリマップされるデータの量が小さいため、この手法はCitrix Endpoint Managementでテストされたすべてのアプリで成功しています。
-
暗号化によって、オーバーヘッドが大幅に増加します。パフォーマンスの低下を防ぐために、開発者はディスクI/Oを最適化する必要があります。たとえば、同じ情報の読み取りと書き込みを繰り返し行う場合は、アプリケーションレベルキャッシュを実装します。
-
Citrix Endpoint Managementは、Apple libsqlite.dylibのインスタンスのみを暗号化します。アプリケーションにlibsqlite.dylibのプライベートバージョンが直接リンクしている、または埋め込まれている場合、そのプライベートライブラリのデータベースインスタンスはCitrix Endpoint Managementによって暗号化されません。
-
Apple SQLiteデータベースは、SQLite仮想ファイルシステムレイヤーを使用してCitrix Endpoint Managementによって暗号化されます。
パフォーマンスが問題になる場合があります。標準のデータベースキャッシュサイズは2000ページまたは8メガバイトです。データベースのサイズが大きい場合、開発者はデータベースキャッシュサイズを増やすようにSQLiteプラグマを指定することが必要になる可能性があります。Objective-C Core Dataフレームワークで、Persistent StoreオブジェクトをPersistent Store Controllerオブジェクトに追加するときに、SQLiteプラグマをオプションディレクトリとして追加できます。
-
ライブラリがファイルI/Oインターフェイスに再リンクされて内部的にメモリマッピングが広範に使用されるため、SQLite WALモードはサポートされていません。
-
NSURLCache DiskCacheが、SQLiteデータベースを使用してiOSによって実装されます。このデータベースは管理対象外のiOSサービスプロセスによって参照されるため、関連付けられたディスクキャッシュがCitrix Endpoint Managementによって無効化されます。
-
以下は、ハードコードされて除外されるファイルパス名のパターン一覧です:
- .plist:プロセスのコンテキストの外側でのiOSシステムプロセスによるアクセスのため、除外されます。
- .app:アプリケーションバンドル名の古い部分文字列。明示的なアプリケーションバンドルパスが除外されるようになったため、この部分文字列は廃止されました。
- .db:ファイルがSQLiteデータベースでない場合、このサフィックスが付いたファイルは暗号化されません。
- /System/Library:アプリバンドルサンドボックスディレクトリ内に存在するファイルパスおよびアプリデータサンドボックス外のファイルパスは暗号化できません。iOSでは、インストールされたアプリは読み取り専用であり、実行時にアプリによって生成されて保存されるアプリデータファイルとは別のディレクトリに保存されます。
- Library/Preferences:ファイルはiOSから直接アクセスされます。通常、このディレクトリパスには.plistファイルのみ存在します。
- /com.apple.opengl/: iOSはファイルに直接アクセスします。
- csdk.db:古いCitrix SSLSDK SQLiteデータベース
- /Library/csdk.sql:Citrix SSLSDK SQLiteデータベース
- CtxLog_:Citrixログファイル名のプレフィックス
- CitrixMAM.config:MDX内部ファイル名
- CitrixMAM.traceLog:古いMDX内部ファイル名
- CtxMAM.log:MDX内部ファイル名
- data.999:MDX内部ファイル名
- CTXWrapperPersistentData:MDX内部ファイル名
- /Documents/CitrixLogs: MDXログディレクトリ
- /Document/CitrixLogs.zip:圧縮されたMDXログのディレクトリ名
- アプリバンドルディレクトリパスのファイル:アプリファイルの読み取り専用ディレクトリ
-
Citrix Endpoint Managementにより、実行時にApple Objective-C QLPreviewControllerオブジェクトクラスのインスタンスがプライベートのCitrix Endpoint Management SecureViewControllerクラスのインスタンスに置換されます。Citrix Endpoint Management SecureViewControllerクラスは、Apple Objective-C UIWebViewオブジェクトクラスから派生されます。QLPreviewControllerオブジェクトクラスは、UIWebViewオブジェクトクラスではネイティブにはサポートされていないオーディオタイプやPDFタイプなどの一部のファイル形式をネイティブにサポートしています。
-
最適なパフォーマンスを得るには、4096バイトの倍数であるファイルオフセットに対してファイルI/O要求が発行される必要があります。また、4096バイトの倍数である長さに対して発行される必要があります。
-
Citrix Endpoint Management暗号化では、O_NONBLOCKファイルモードフラグはサポートされていません。このファイルモードフラグは、Citrix Endpoint Managementによる処理時にモードリストから削除されます。
暗号化のユーザーエントロピー
Citrix Endpoint Managementの特定の暗号化オプションでは、暗号キーを生成するにはエンドユーザーがPINを入力する必要があります。このオプションはユーザーエントロピーと呼ばれるもので、アプリケーションで特定の問題が発生する可能性があります。
特に、ユーザーがPINを入力するまでファイルアクセスまたはデータベースアクセスは実行できません。PIN UIが表示できるようになる前に実行されるI/O操作が場所に存在する場合、このI/O操作は常に失敗します。
アプリケーションにこの問題がないことを確認するには、ユーザーエントロピーが有効になった状態でテストします。Citrix Endpoint ManagementクライアントプロパティEncrypt secrets using Passcodeによって、ユーザーエントロピーを追加します。このクライアントプロパティはデフォルトでは無効になっており、Citrix Endpoint Managementコンソールを使用して [構成]>[設定]>[詳細]>[クライアントプロパティ] で構成します。
データ抑制機能
- リモートビューコントローラーはMDX管理対象アプリとは別のプロセスコンテキストで実行されるので、リモートビューコントローラーではセキュリティ抑制(データ暗号化、ポリシーブロックのコピー、切り取り、貼り付けなど)が行われません。
- UIResponderではコピー操作のみがサポートされます。切り取りや削除などの他の操作は、サポートされていません。
- AirDropは、UIレベルでのみインターセプトされ、それよりも低いレベルではインターセプトされません。
- MFIおよびBluetoothはインターセプトされません。
アイコンファイルのサポート
MDXのラップには、ホーム画面アイコンまたはアプリアイコンとして使用できる1つ以上のアイコンが必要です。アプリ開発者は、アセットカタログにアイコンを追加するか、またはInfo.plistのCFBundleIconsキーまたはCFBundleIconFilesキーを使用できます。
MDX Toolkitでは、Info.plist内の既知のplistの場所一覧から最初のキーが取得されます:
- CFBundleIcons
- CFBundlePrimaryIcon
- CFBundleIconFiles
- UINewsstandIcon
- CFBundleDocumentTypes
これらのキーがInfo.plist内に見つからない場合、MDX Toolkitでアプリバンドルのルートフォルダー内にある以下のアイコンのいずれかが特定されます。
- Icon.png
- Icon-60
@
2x.png - Icon-72.png
- Icon-76.png
ネットワークおよびMicro VPN
MDXでは現在、アプリによって直接発行されたネットワーク呼び出しのみ管理されています。一部のDNSクエリはAppleフレームワークによって直接発行されるため、MDXでは管理されません。
ネットワーク用のさまざまなCitrix Endpoint Managementポリシーオプションが管理者に提供されています。
ネットワークアクセスポリシーは、アプリのネットワークアクティビティを禁止、許可、リダイレクトします。
重要:
MDX Toolkitバージョン18.12.0リリースには、以前のポリシーを組み合わせたり置き換えたりした新しいポリシーが含まれています。 [ネットワークアクセス]ポリシーは[ネットワークアクセス]、[優先VPNモード]、[VPNモードの切り替えを許可]を組み合わせたものです。[除外の一覧]ポリシーは、[分割トンネルの除外対象一覧]に置き換えられます。[オンラインセッションを必須とする]ポリシーは、[Micro VPNセッションを必須とする]ポリシーに置き換えられます。詳しくは、「以前のリリースの新機能」を参照してください。
[トンネル-Web SSO]は、この設定において[セキュアブラウズ]に相当する名前です。動作は同じです。
使用できるオプションは、次のとおりです。
- 以前の設定を使用:デフォルトでは、過去のポリシーで設定済みの値が使用されます。値の変更後は、[以前の設定を使用] に戻さないでください。また、新しいポリシーに対する変更は、ユーザーがアプリをバージョン18.12.0以降にアップグレードするまで反映されません。
- 禁止:アプリが使用するネットワークAPIは機能しません。前述のガイドラインに基づいて、このような失敗を正常に処理する必要があります。
- 制限なし:ネットワーク呼び出しはすべて直接転送され、トンネリングされません。
- トンネル-完全VPN:管理対象アプリケーションからのトラフィックはすべてCitrix Gatewayを介してトンネリングされます。
- トンネル-Web SSO:HTTP/HTTPS URLが書き込まれます。このオプションでは、HTTPトラフィックおよびHTTPSトラフィックのトンネリングのみが許可されます。トンネル-Web SSOの大きなメリットは、HTTPトラフィックとHTTPSトラフィックのシングルサインオン(SSO)、およびPKINIT認証です。Androidでは、このオプションはセットアップの手間が少ないため、Web閲覧操作に関する推奨オプションとなっています。
- トンネル-完全VPNおよびWeb SSO:必要に応じてVPNモードの自動切り替えを許可できます。いずれかのVPNモードで認証要求が処理できないためにネットワーク要求が失敗した場合、代替モードで再試行されます。
制限事項
- ユーザーは内部WebサイトにホストされているビデオをiOSラップされたMDXアプリで再生できません。MDXによってインターセプトされないデバイス上で、メディアプレーヤープロセスでビデオが再生されるためです。
- NSURLSessionのバックグラウンドダウンロード(NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier)はサポートされていません。
- ネットワークアクセスポリシーが [禁止] に設定されている場合、UDPトラフィックがブロックされます。ネットワークアクセスポリシーが [トンネル-完全VPN] に設定されている場合、UDPトラフィックはトンネリングされません。
- MDXラップされたアプリでは、受信接続をリスンするソケットサーバーを置換できません。ただし、MDXでラップされたアプリでは、クライアントソケットを使用してサーバーに接続できます。
サードパーティライブラリのサポート
一部のアプリケーションフレームワークは、Citrix Endpoint Managementで互換性の問題があります:
- Xamarinクロスプラットフォーム開発環境で開発されたアプリはサポートされています。使用例とテスト例が不十分なため、他のクロスプラットフォーム開発環境でのサポートは正式に表明されていません。
- SQLCipherではメモリマッピングを使用するため、暗号化が機能しません。解決策として、SQLCipherを使用しないという方法があります。また、暗号化除外ポリシーを使用してデータベースファイルを暗号化から除外するという方法もあります。Citrix Endpoint Management管理者は、Citrix Endpoint Managementコンソールでポリシーを構成する必要があります。
- OpenSSL libcrypto.aライブラリおよびlibssl.aライブラリに直接リンクしているアプリおよびサードパーティライブラリでは、シンボルの欠落が原因のリンクエラー、および複数シンボル定義が原因のリンクエラーが発生する可能性があります。
- Appleプッシュ通知サービスのサポートが必要なアプリでは、Appleで必要とされている特定の手順に従う必要があります。
- Citrix Endpoint Managementでは、SQLiteデータベース内でログ先行書き込み(WAL)ファイルおよびメモリマップファイルのサポートを無効化するために、SQLiteデータベースバージョンが1に明示的に設定されます。SQLiteバージョン2またはバージョン3でSQLiteインターフェイスに直接アクセスしようとすると、そのアクセスは失敗します。