На работе я столкнулся с задачей внедрения Privacy Manifest в проект. Изучение вопроса началось с прочтения документации Apple, а продолжилось просмотром WWDC-сессии на тему конфиденциальности. После внедрения оказалось, что для корректной работы над задачей нужно изучить больше информации. Поэтому я решил поделиться опытом в формате инструкции. Покажу, как внедрять Privacy Manifest на примере вымышленного проекта, и дам практические советы по внедрению манифеста конфиденциальности.
Цель внедрения
Пользователей часто интересует, какие категории данных собирают о нём приложения. Используется ли эта информация для их отслеживания? Связаны ли с ними данные? Чтобы обеспечить прозрачность в этом вопросе, компания Apple создала «Манифест конфиденциальности» (Privacy Manifest), который помогает точно определять правила конфиденциальности в зависимостях приложения и в нём самом.
Теперь станет проще предоставлять точные Nutrition Labels и интегрировать прозрачность отслеживания приложений, а также дать людям контроль над тем, как и когда их данные используются для отслеживания. И это не всё. Приложения, которые ссылаются на API и потенциально могут быть использованы для fingerprinting (практика, запрещённая в App Store), теперь должны будут выбирать разрешённую причину использования API и заявлять об этом использовании в манифесте конфиденциальности. Это делается для обеспечения дополнительной защиты пользователей. В рамках этого процесса приложения должны точно описывать использование этих API, и их работа допустима только в описанных в «Манифесте» случаях.
Privacy Manifest для сторонних SDK
Большая часть конфиденциальности приложения часто зависит от сторонних SDK. В то же время от них очень сложно получить всю необходимую информацию, от которой зависят наши приложения.
Помните, что при использовании сторонних SDK в своём приложении мы несём ответственность за весь код, который SDK включает в приложение. Нам необходимо знать методы сбора и использования данных.
Манифесты конфиденциальности — это новый способ для сторонних разработчиков SDK предоставить информацию о своей политике конфиденциальности. Также они могут сами подключить манифест в свой SDK.
Файл манифеста представляет собой список свойств, в котором указано, какие типы данных собирает SDK, как используется каждый из них, связаны ли они с пользователем и применяются ли для отслеживания, как это определено политикой прозрачности отслеживания. Когда разработчики готовятся к публикации приложения, Xcode объединяет манифесты конфиденциальности всех использованных в приложении сторонних SDK в единый, простой в использовании отчёт. Благодаря этому будет проще создавать более точные Privacy Nutrition Labels.
Для чего нужны подписи SDK
Apple пытается помочь разработчикам улучшить целостность цепочки поставок программного обеспечения. При использовании сторонних SDK разработчикам может быть сложно понять, что загруженный ими код был написан именно тем разработчиком, которого они ожидают. Чтобы решить эту проблему, они ввели подписи для SDK, чтобы при использовании разработчиком новой версии стороннего SDK в своём приложении Xcode мог проверить, что она подписана тем же разработчиком. Эта функция будет полезна как разработчикам, так и пользователям.
SDK, требующие манифеста конфиденциальности и подписи
Ниже приведены наиболее часто используемые SDK в приложениях в App Store. Начиная с весны 2024 года разработчики должны включать манифест конфиденциальности для любого SDK, перечисленного ниже. Это правило работает при отправке новых приложений в App Store Connect, содержащих эти SDK, или при отправке обновления приложения, которое добавляет один из перечисленных SDK как часть обновления. Подписи также необходимы в тех случаях, когда перечисленные SDK используются в качестве бинарных зависимостей. Любая версия указанного SDK, а также все SDK, которые переупаковывают указанные в списке, включены в требование.
Начнём работу с Privacy Manifest
Список SDK
Abseil
AFNetworking
Alamofire
AppAuth
BoringSSL / openssl_grpc
Capacitor
Charts
connectivity_plus
Cordova
device_info_plus
DKImagePickerController
DKPhotoGallery
FBAEMKit
FBLPromises
FBSDKCoreKit
FBSDKCoreKit_Basics
FBSDKLoginKit
FBSDKShareKit
file_picker
FirebaseABTesting
FirebaseAuth
FirebaseCore
FirebaseCoreDiagnostics
FirebaseCoreExtension
FirebaseCoreInternal
FirebaseCrashlytics
FirebaseDynamicLinks
FirebaseFirestore
FirebaseInstallations
FirebaseMessaging
FirebaseRemoteConfig
Flutter
flutter_inappwebview
flutter_local_notifications
fluttertoast
FMDB
geolocator_apple
GoogleDataTransport
GoogleSignIn
GoogleToolboxForMac
GoogleUtilities
grpcpp
GTMAppAuth
GTMSessionFetcher
hermes
image_picker_ios
IQKeyboardManager
IQKeyboardManagerSwift
Kingfisher
leveldb
Lottie
MBProgressHUD
nanopb
OneSignal
OneSignalCore
OneSignalExtension
OneSignalOutcomes
OpenSSL
OrderedSet
package_info
package_info_plus
path_provider
path_provider_ios
Promises
Protobuf
Reachability
RealmSwift
RxCocoa
RxRelay
RxSwift
SDWebImage
share_plus
shared_preferences_ios
SnapKit
sqflite
Starscream
SVProgressHUD
SwiftyGif
SwiftyJSON
Toast
UnityFramework
url_launcher
url_launcher_ios
video_player_avfoundation
wakelock
webview_flutter_wkwebview
Что нужно сделать
Чтобы наше приложение соответствовало требованиям манифеста конфиденциальности, нужно решить две задачи:
Создать Privacy Manifest для нашего проекта.
Обновить определённые внешние зависимости (SDK).
Чтобы создать Privacy Manifest, нужно понять, что он из себя представляет и как его добавить в проект. Для добавления в проект в Xcode выбираем Choose File > New File (⌘+N) и находим файл с названием App Privacy.
Добавляем его в корневую папку проекта с включённым таргетом нашего приложения.
Манифест в проекте называется PrivacyInfo.
Что из себя представляет файл манифеста
Файл манифеста plist с расширением .xcprivacy содержит в себе следующие разделы для заполнения данными:
Privacy Tracking Enabled
Privacy Tracking Domains
Privacy Nutrition Label Types
Privacy Accessed API Types
Privacy Tracking Enabled. Логическое значение, указывающее, использует ли приложение или сторонний SDK данные для отслеживания, как это определено в рамках фреймворка App Tracking Transparency. Если в вашем приложении есть отслеживание пользователя, то вы должны указать значение YES. Предположим, что у нас оно есть.
Privacy Tracking Domains. Массив строк, в котором перечислены интернет-домены, к которым подключается приложение или сторонний SDK, и которые участвуют в отслеживании. Если для NSPrivacyTracking (Privacy Tracking Enabled) установлено значение YES, то необходимо указать хотя бы один интернет-домен.
Предположим, что мы отслеживаем пользователя по домену tracking.domain.example и указали его в файле манифеста. В документации Apple прописано, что если пользователь не предоставил разрешение на отслеживание через структуру прозрачности отслеживания приложений, то сетевые запросы к этим доменам завершаются неудачно и приложение получает ошибку. Что это означает? Начиная с iOS 14.5 есть обязательное требование о запросе разрешения пользователя в случаях отслеживания данных. В этих сценариях при входе у нас показывается подобное уведомление:
Если у пользователя версия iOS 17.0 или выше и он выбрал Ask App Not to Track, то запросы к нашему домену tracking.domain.example не выполнятся и мы получим ошибку. Этот сценарий был воспроизведён на устройстве iOS 17.2, но ошибка не возникла, и запросы на трекинг-домен тоже проходили. Надеемся, что в будущем всё заработает так, как заявляет Apple. Но как нам понять, что кроме нас больше никто (например, SDK, включённые в наше приложение) не отслеживает пользователя и наш домен единственный? Для этого Apple предлагает анализировать сетевое поведение приложения с помощью инструмента Points of Interest.
Необходимо:
Открыть приложение в Xcode.
Подключить устройство, так как сетевое поведение нельзя тестировать на симуляторе.
-
Выбрать Product > Profile, откроется Instruments, там выбрать шаблон Network.
-
Выбрать Xcode > Open Developer Tool > Instruments и там выбрать шаблон Network.
После нужно нажать на запись и переходить на нижний инструмент под названием Points of Interest. В режиме записи можно на устройстве переходить по всему приложению. В тот момент, когда пройдёт обращение к домену, на дорожке Points of Interest появится точка с подробностями о нём.
Таким образом можно выявить скрытые запросы к доменам отслеживания и устранить их, или указать в манифесте их использование.
К сожалению, этот инструмент тоже работает не идеально. Я добавил в моё приложение второй домен отслеживания, но у меня не получилось определить ни основной домен, ни дополнительный. На форуме Apple сейчас есть открытые баги по поводу неправильной работы Points of Interest.
Privacy Manifest с заполненными данными Privacy Tracking Enabled и Privacy Tracking Domains выглядит следующим образом.
Privacy Nutrition Label Types. Массив словарей, описывающий типы данных, которые собирает приложение или сторонний SDK. Nutrition Label’ы нужны для того, чтобы пользователи перед скачиванием приложения из App Store могли узнать, какие именно данные оно собирает. В App Store указанные данные выглядят так:
Стоит отметить, что Nutrition Labels — не нововведение, и если ваше приложение есть в App Store, то вы уже заполнили в App Store Connect форму с указанием данных, которые собирает ваше приложение. Теперь нужно просто переписать информацию из App Store Connect в манифест. А если вы только собираетесь впервые выложить приложение, то нужно определиться с данными, которые оно собирает. Они разделены на следующие категории:
Контактная информация.
Здоровье и фитнес.
Финансовая информация.
Геопозиция.
Чувствительная информация.
Контакты.
Пользовательский контент.
История браузера.
История поиска.
Идентификаторы.
Покупки.
Данные об использовании.
Диагностика.
Окружающая среда.
Тело.
Другие данные.
Предположим, что наше приложение собирает следующие данные:
И теперь надо перенести всё это в манифест. Для заполнения типов Nutrition Label существуют следующие ключи для словарей:
NSPrivacyCollectedDataType
. Строка, определяющая тип данных, которые собирает приложение или сторонний SDK.NSPrivacyCollectedDataTypeLinked
. Логическое значение, указывающее, связывает ли приложение или сторонний SDK этот тип данных с личностью пользователя.NSPrivacyCollectedDataTypeTracking
. Логическое значение, указывающее, использует ли приложение или сторонний SDK этот тип данных для отслеживания.NSPrivacyCollectedDataTypePurposes
. Массив строк, в котором перечислены причины, по которым приложение или сторонний SDK собирает данные.
Значения можно выбрать или из списка типов данных, находившихся в документации, или в файле манифеста, нажав на стрелку:
После заполнения Nutrition Labels наш манифест выглядит так:
Стоит отметить, что если сторонний SDK вашего приложения тоже собирает данные, то он также должен иметь свой манифест. В этом случае нет необходимости включать в ваш манифест информацию о собираемых SDK данных.
Чтобы понять, правильно ли вы создали и заполнили файл манифеста, можно cгенерировать отчёт. Для этого надо в Xcode выбрать Product > Archive.
В архиве вызываем опции и выбираем Generate Privacy Report.
Сгенерированный отчёт по нашему приложению выглядит так:
Если сторонние SDK нашего приложения собирают данные и включают в себя файл манифеста, то в отчёте также должна отображаться информация про собранные SDK данные.
Используемые API
Privacy Accessed API Types — это массив словарей, описывающих типы API, к которым обращается приложение или сторонний SDK, которые обозначены как API, и для доступа к которым требуются основания.
Apple обеспокоена тем, что наши приложения или сторонние SDK могут использовать код для доступа к сигналам устройства с целью идентификации устройства или пользователя, то есть fingerprinting. Вне зависимости от того, разрешает ли пользователь приложению отслеживать, fingerprinting запрещён. Поэтому Apple сформировала список «потенциально опасных» для пользователя API с конкретными одобренными причинами использования.
От нас требуется анализировать наш код приложения, и если окажется, что мы используем эти API, то нужно проверить причину использования и соотнести её с указанными причинами Apple. При сравнении может быть три исхода событий:
Если используем API не по причинам, указанным в документации Apple, и использование API не даёт пользователю конкретной выгоды, то мы должны отказаться от использования такого API.
Если используем API не по причинам, указанным в документации Apple, но использование API даёт пользователю конкретную выгоду, то мы можем отправить запрос на утверждение причины использования.
Если мы используем API по причинам, указанным в документации Apple, то перечисляем используемые API в файле манифеста и указываем причины использования.
Если сторонний SDK использует такие API, то он сам должен указать причины использования в своём файле манифеста.
API делятся на следующие категории
-
File timestamp API
creationDate
modificationDate
fileModificationDate
contentModificationDateKey
creationDateKey
getattrlist(_:_:_:_:_:)
getattrlistbulk(_:_:_:_:_:)
fgetattrlist(_:_:_:_:_:)
stat
fstat(_:_:)
fstatat(_:_:_:_:)
lstat(_:_:)
getattrlistat(_:_:_:_:_:_:)
-
System boot time API
systemUptime
mach_absolute_time()
-
Disk space API
volumeAvailableCapacityKey
volumeAvailableCapacityForImportantUsageKey
volumeAvailableCapacityForOpportunisticUsageKey
volumeTotalCapacityKey
systemFreeSize
systemSize
statfs(_:_:)
statvfs(_:_:)
fstatfs(_:_:)
fstatvfs(_:_:)
getattrlist(_:_:_:_:_:)
fgetattrlist(_:_:_:_:_:)
getattrlistat(_:_:_:_:_:_:)
-
Active keyboard API
activeInputModes
-
User defaults API
UserDefaults
Скорее всего, вам необходимо будет автоматизировать обнаружение использования вышеперечисленных API в вашем коде приложения. Для этого больше всего подходит написание скриптов, но в этой статье мы не будем их писать скрипты.
Предположим, что мы используем следующие API и по таким причинам:
Атрибут
creationDate
из File timestamp API по причине использования DDA9.1.Свойство
systemUptime
из System Boot Time по причине использования 35F9.1Класс
UserDefaults
из User defaults API по причине использования CA92.1
После заполнения этих данных в нашем файле манифеста мы видим:
Теперь у нас есть окончательно заполненный вариант файла манифеста:
Мы справились с первой задачей и пора приступить ко второй: обновить определённые внешние зависимости (SDK) нашего приложения. Нужно найти в нём все SDK из списка, опубликованного компанией Apple, для которых требуется манифест или манифест и подпись. Если SDK используются в качестве бинарных зависимостей, то необходимо иметь подписанный бинарник, который также содержит файл Privacy Manifest. Xcode 15 умеет показывать информацию о подписи SDK на вкладке Inspector с названием Signature, где указана информация о способе подписи, её статусе и т. д.
Таким образом проверяем наши бинарные SDK. Если они не подписаны, то необходимо у владельцев SDK попросить подписанные бинари с содержанием файла Privacy Manifest. Владелец SDK может подписать их как участник Apple Developer Program и как Self-Signed. Глобальное отличие в том, что для идентификации Apple Developer Program компания может проверить действительность используемого сертификата, в том числе если он был отозван. Это позволяет гарантировать, что несколько разработчиков не смогут зарегистрироваться под одним и тем же именем. Если используемый сертификат является Self-Signed, то разработчики приложений могут подтвердить его действительность и подлинность непосредственно у автора зависимостей.
Некоторые авторы SDK из списка Apple уже начали добавлять файлы манифеста в свои SDK. Можно зайти на их страницы на Github и попробовать найти информацию про манифест или подпись. Если вы их не нашли, то можете сами открыть дискуссию или проблему с темой обновления версии SDK c содержанием манифеста или манифеста и подписи.
Есть риск, что могут быть такие SDK, которые не захотят обновиться вовремя. Или возникнут какие-то проблемы с обновлением, и вы решите, что лучше искать альтернативные SDK. Поэтому рекомендую как можно раньше проанализировать ваши SDK, составить список для обновления или замены на альтернативные.
Указанные в статье списки SDK, API, категории данных для Nutrition Label и т. д. действительны на момент написания. Для получения актуальных списков вам необходимо следить за следующими страницами документации Apple.
Источники:
WWDC 2023: Get started with privacy manifests, Privacy manifest files, Describing use of required reason API, App privacy details on the App Store, Describing data use in privacy manifests, WWDC 2022: Create your Privacy Nutrition Label, User Privacy and Data Use, WWDC 2022: Explore App Tracking Transparency, What’s new in privacy on the App Store, Privacy updates for App Store submissions, Upcoming third-party SDK requirements, WWDC 2023: Verify app dependencies with digital signatures, Detecting when your app contacts domains that may be profiling users, Privacy updates for App Store submissions
infund
Спасибо. На днях при обновлении приложения столкнулся с требованием включения в приложение этого манифеста. В целом, не совсем понял, почему сохранение в UserDefaults настроек приложения внезапно потребовало дополнительных манипуляций. Но требование исполнил.