Для идентичности процессов macOS одного Team ID недостаточно
Практическая модель идентичности процессов macOS: Team ID, идентификатор подписи, designated requirements, пути и строгая обработка неподписанных сборок.

Одного Team ID недостаточно, чтобы решить, какой процесс macOS может пользоваться секретом. Он определяет команду разработчиков Apple, а не конкретный исполняемый файл этой команды. Если авторизовать только Team ID, такое же право получат все подходящим образом подписанные приложения, помощники, тестовые утилиты и будущие бинарные файлы этой команды.
Надёжная идентичность для авторизации сочетает полномочия подписанта с идентификатором подписи, сохраняет requirement, переживающее легитимные обновления, и сопоставляет эту идентичность с процессом, который действительно запрашивает доступ. Путь к исполняемому файлу всё ещё нужен в карточке одобрения и записи аудита, но не должен определять авторизацию. Для неподписанных сборок и сборок для разработки с ad hoc подписью нужен отдельный, явно более слабый путь, а не молчаливое исключение.
Это особенно важно на границе доступа к секретам. Подпись кода может сказать, кто подписал процесс и какое имя программы указал подписант. Она не говорит, заслуживает ли процесс пароль от базы данных, разумен ли его текущий запрос и следует ли давать то же разрешение другой программе того же разработчика. Идентичность - один из входных данных для авторизации, а не её замена.
Team ID определяет подписанта, а не программу
Team ID отвечает на полезный, но широкий вопрос: какая команда разработчиков Apple выпустила идентичность подписи для этого кода? Для сертификатов разработчиков, выпущенных Apple, язык requirements раскрывает Team ID через поле organizational unit в сертификате leaf. Инструменты также могут показывать значение TeamIdentifier в сведениях о подписи.
Запускайте команду для точного исполняемого файла, а не только для внешнего пакета приложения:
codesign -dvvv /Applications/Example.app/Contents/MacOS/Example 2>&1
Полезная часть вывода выглядит так:
Executable=/Applications/Example.app/Contents/MacOS/Example
Identifier=dev.example.agent
Authority=Developer ID Application: Example Developer (A1B2C3D4E5)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
TeamIdentifier=A1B2C3D4E5
Корректный Team ID задаёт область подписанта. Он исключает бинарные файлы, подписанные другими командами, и не позволяет стороннему разработчику заявить тот же идентификатор подписи и пройти проверку. Apple прямо указывает это в документации SigningIdentifier: идентификатор подписи могут заявлять несколько подписантов, поэтому для безопасной проверки стороннего кода также нужно ограничение TeamIdentifier и подходящая категория проверки.
Обратное утверждение и есть ловушка. Одна команда может подписывать множество несвязанных продуктов и множество компонентов одного продукта. Приложение, его привилегированный помощник, элемент входа, инструмент командной строки, служба XPC и внутренняя диагностическая утилита могут иметь общий Team ID. Скомпрометированная служба подписи может выпустить ещё один бинарный файл в области этого подписанта. Принадлежность к команде не различает их.
Поэтому Team ID == approved team слишком широко для работы с секретами. Это похоже на выдачу доступа всем сотрудникам компании только потому, что их пропуска выдал один и тот же орган. Кто выдал пропуск, важно, но важно и имя на нём.
В узких случаях использовать один Team ID можно намеренно. Например, инструмент разработчика может позволять любому компоненту, подписанному собственной командой пользователя, обращаться к одноразовому локальному набору данных. Это политика доверия к команде, а не идентичность процесса, и текст одобрения должен говорить об этом. Не храните её в поле с именем application, чтобы потом не забыть, какой объём полномочий она даёт.
Идентификатор подписи различает программы внутри команды
Идентификатор подписи добавляет измерение программы, которого не хватает Team ID. codesign выводит его как Identifier. У пакетного приложения это часто идентификатор пакета, но Apple прямо говорит, что совпадение не обязательно. Значение выбирает подписант, а исполняемые файлы командной строки могут иметь идентификаторы, не будучи пакетами приложений.
Пара Team ID и идентификатора подписи даёт значительно лучшую минимальную идентичность:
team_id = A1B2C3D4E5
signing_identifier = dev.example.agent
Пара означает «программа с именем dev.example.agent, подписанная командой A1B2C3D4E5». Другая команда может скопировать идентификатор, но не сможет выполнить ограничение по команде. У другой программы одобренной команды должен быть иной идентификатор, поэтому она не должна совпасть.
В последнем предложении важно слово «должен». Команда управляет своими идентификаторами и может использовать один повторно. Неосторожная конфигурация сборки способна присвоить помощнику идентификатор основного приложения. Злоумышленник или скомпрометированный подписант может скопировать одобренное значение. Пара сужает полномочия при условии, что подписант защищает свои учётные данные подписи и пространство имён идентификаторов.
Тем не менее это обычная граница для устойчивой к обновлениям идентичности стороннего ПО в macOS. Хеши кода точнее, но меняются с каждым легитимным релизом. Отпечатки сертификатов тоже неудобны как опора непрерывности, потому что сертификаты истекают и сменяются. Team ID вместе с идентификатором подписи выражает нужную большинству приложений непрерывность: принимать будущие версии этой программы от этого подписанта, не принимая весь каталог подписанта.
Проверяйте каждый исполняемый файл, который может подключаться. Не выводите идентификатор помощника из содержащего его приложения. В Apple TN3127 пример с приложением и его встроенным инструментом командной строки показывает то же самое: у них общий Team ID, но разные идентификаторы подписи кода, и Apple считает такое разделение хорошей практикой. Если запрос начинает помощник, на границе важна его идентичность.
С идентификаторами также нужно обращаться побайтно. Текущая документация Apple SigningIdentifier говорит, что при сравнении не выполняется нормализация Unicode. Храните и сравнивайте значение, возвращённое Code Signing Services, как непрозрачную строку или последовательность байтов. Приведение к нижнему регистру, нормализация или восстановление из CFBundleIdentifier создают вторую систему идентичности с другими правилами.
Designated requirement сохраняет идентичность при обновлениях
Designated requirement, обычно сокращённо DR, - нативный механизм macOS, позволяющий определить, совпадает ли код, увиденный сейчас, с кодом, увиденным раньше. Он объединяет идентификатор подписи с ограничениями на полномочия подписанта. Для авторизации он ближе к нужному объекту, чем каждое из этих полей по отдельности.
Apple TN3127 описывает DR как способ кода сообщить, как другая сторона сможет узнать его снова. Практическая проверка из технической заметки - обновление: версия 1.3 должна удовлетворять идентичности, сохранённой для версии 1.2, хотя её байты изменились. При этом другой продукт должен не пройти проверку. Именно это противоречие должно разрешить устойчивое разрешение на доступ к секрету.
Покажите DR командой:
codesign -d -r- /Applications/Example.app/Contents/MacOS/Example 2>&1
Для Developer ID результат обычно имеет такой вид, хотя сведения о сертификате зависят от пути подписи:
Executable=/Applications/Example.app/Contents/MacOS/Example
designated => anchor apple generic and identifier "dev.example.agent" and certificate leaf[subject.OU] = "A1B2C3D4E5"
Не разбирайте эту строку вывода на самодельные поля и не пытайтесь воспроизвести проверщик Apple. TN3125 предупреждает, что структуры подписей меняются, и предлагает использовать codesign или Code Signing Services для проверки. Получайте requirement через SecCodeCopyDesignatedRequirement, а код проверяйте с помощью SecCodeCheckValidity или API requirements текущего процесса. Пусть платформа компилирует и сравнивает собственную форму requirement.
Отсюда следует тонкий момент: собственное DR кода - это заявление, а не решение об авторизации. Подписант может предоставить явное DR, а Code Signing Services может создать его, если встроенного нет. Ваша система всё равно решает, какое requirement сохранить и соответствует ли его область разрешению. Если прочитать DR и объявить код «доверенным», материал об идентичности смешивается с политикой.
Для обычного ПО с Developer ID разумно по умолчанию сохранять проверенное DR в момент одобрения. Сохраняйте также показанные Team ID и идентификатор подписи как поля аудита, чтобы человек мог понять решение. При последующих запросах проверяйте работающий процесс по сохранённому requirement, а не сравнивайте свежевыведенную строку DR на текстовое равенство. Объекты requirements выражают поведение, и эквивалентные выражения не обязаны иметь одинаковое форматирование.
Изменения способа распространения требуют осознанного подхода. TN3127 отмечает, что стандартные DR для вариантов Mac App Store и Developer ID не совместимы автоматически, хотя Xcode может применять пользовательские requirements для объединения запланированных форм распространения. Не расширяйте проверку на ходу, когда релиз меняет канал. Считайте новое requirement изменением идентичности, покажите его пользователю и запросите новое одобрение, если не разработали и не протестировали явное requirement совместимости.
Пути к исполняемым файлам дают контекст, а не доказательство
Путь к исполняемому файлу сообщает оператору, где macOS нашла образ. Это отличный контекст для одобрения и слабое доказательство непрерывности. Файлы перемещаются, app translocation меняет их расположение, пользователи держат несколько версий, а менеджеры пакетов устанавливают их по путям с номерами версий. И наоборот, злоумышленник, способный заменить файл в одобренном доступном для записи пути, может унаследовать разрешение, основанное только на пути.
Обычный список разрешённых путей ошибается в обе стороны. Он отклоняет ту же подписанную программу после безобидного перемещения и принимает другие байты после враждебной подмены. Проверки владельца и режима снижают часть риска подмены, но не превращают имя пути в криптографическую идентичность.
Оставьте путь для трёх задач:
- Показывать пользователю, какая установка начала запрос.
- Сохранять достаточно контекста для расследования неожиданного вызова.
- Применять необязательное ограничение расположения после успешной проверки идентичности по подписи.
Последнее применение может быть разумным в управляемых средах. Можно требовать одобренное DR и одновременно требовать, чтобы исполняемый файл находился в каталоге развёртывания, принадлежащем root. Тогда путь ограничивает, где может запускаться уже идентифицированная программа. Он никогда не исправит отсутствующую или недействительную подпись.
Определяйте и сохраняйте исполняемый файл, реально связанный с работающим процессом. Не доверяйте строке, предоставленной клиентом, например argv[0], рабочему каталогу, пути к пакету в запросе или переменной окружения. Это заявления запрашивающей стороны. Даже канонизированный путь может привести к гонке, если вы проверили файл, а затем авторизовали процесс только по сохранённому имени.
Когда платформа предоставляет их, я храню в аудите и исходный наблюдаемый путь, и разрешённый путь, потому что символьные ссылки и обёртки запуска объясняют многие неожиданности. Ни одно из этих значений не входит в устойчивый кортеж идентичности. Если организация выбирает ограничение пути, храните его в отдельном поле location_constraint, чтобы проверяющие видели, что это политика, наложенная поверх идентичности.
Проверяйте работающего вызывающего, а не путь
Проверка авторизации должна быть привязана к процессу, устанавливающему соединение. Проверка файла при установке, сохранение его пути и доверие к тому, что позднее запускается по этому пути, оставляют окно между проверкой и использованием. Проверка текущего файла по этому пути после получения запроса тоже может исследовать подмену, а не уже работающий образ.
Code Signing Services в macOS различает статический код на диске и динамический код, связанный с работающим процессом. Apple документирует SecCodeCopyGuestWithAttributes для получения объекта кода гостевого кода, обычно по PID, и SecCodeCheckValidityWithProcessRequirement для проверки работающего процесса по requirement. Новый облегчённый API requirements позволяет явно задать ограничения TeamIdentifier и SigningIdentifier. Используйте поддерживаемый API, подходящий вашей целевой версии развертывания, а не разбирайте вывод codesign в рабочей среде.
Надёжный поток обработки подключения выглядит так:
- Получите предоставленную ядром идентичность процесса на границе IPC, например audit token, приложенный к принятому соединению. Не принимайте PID из тела запроса.
- Сопоставьте работающий процесс с объектом динамического кода и проверьте его подпись с помощью API платформы.
- Проверьте сохранённое requirement или сохранённые ограничения подписанта и идентификатора на том же объекте кода.
- Сохраните путь, PID, идентичность запуска процесса, если она доступна, факты о подписи и результат проверки в записи решения.
- Привяжите одобрение к соединению или времени жизни процесса и отмените его, когда этот срок закончится.
Сам по себе PID не подходит как постоянный дескриптор, потому что ядро повторно использует идентификаторы процессов. Если проверяющий считывает PID, ждёт и затем снова ищет его, он может проверить другой процесс. Audit token несёт больше сведений об идентичности процесса, чем целое число от клиента, а проверка в рамках соединения сокращает окно. Конкретный API зависит от того, используете ли вы XPC, сокет домена Unix или другой механизм IPC, но правило не меняется: определяйте субъект по представлению операционной системы об удалённой стороне.
Проверяйте подпись до показа идентичности. Иначе карточка одобрения может показать поля из повреждённой или недействительной подписи так, будто macOS за них поручилась. Карточка должна различать «действительная подпись Developer ID» и «текст идентификатора присутствовал». Если проверка не прошла, не переходите к совпадению по пути в рамках того же одобрения.
Для деревьев процессов нужно явное решение. Если подписанный агент запускает /bin/sh, а оболочка подключается напрямую, удалённая сторона - оболочка. Автоматический подъём к предку и передача идентичности родителя могут авторизовать подменённых потомков или несвязанные дочерние процессы. Если архитектура предполагает авторизацию запускающего процесса, привяжите capability к исходному аутентифицированному соединению и передавайте её по контролируемому каналу. Не пытайтесь восстановить намерение, поднимаясь по PID родителей.
По той же причине авторизация должна истекать, когда одобренный процесс завершает работу. Сохранённая идентичность может поддержать будущие одобрения, но разрешение сеанса не должно отрываться от процесса и навсегда прикрепляться к любому совпадающему процессу. Разделяйте «мы узнаём эту программу» и «этот запуск одобрен сейчас».
Для неподписанных и ad hoc сборок нужна отдельная политика
У неподписанного кода нет designated requirement. У кода с ad hoc подписью есть DR, привязанное к конкретной версии кода, поэтому пересборка меняет идентичность. Apple TN3127 говорит, что macOS не может надёжно отслеживать обе формы между версиями. Брокер секретов должен сохранять это ограничение, а не скрывать его исключением для каталога.
Для производственных секретов закрывайте доступ по умолчанию, если у вызывающего нет действительной, устойчивой к обновлениям подписи. Это самое понятное и простое для объяснения правило. Разработчики могут подписывать локальные сборки идентичностью Apple Development или закрытой идентичностью подписи, доверие и requirements для которой организует сама компания. Неудобство обычно меньше неоднозначности, которую создаёт постоянное исключение для неподписанного кода.
Для локальной разработки иногда нужен более слабый режим. Подключайте его явно, назовите development approval и ограничьте радиус ущерба. Разумная схема привязывает одобрение ко времени жизни текущего процесса и точному хешу кода, заметно показывает unsigned или ad hoc, исключает наборы производственных секретов и снова запрашивает подтверждение после каждой пересборки. Повторный запрос не дефект. Он отражает, что исполняемый файл больше не имеет непрерывности, которую macOS способна доказать.
Не используйте эти популярные замены:
- Путь в домашнем каталоге пользователя, потому что тот же пользователь может его заменить.
- Имя файла или идентификатор пакета из метаданных, потому что неподписанный код может заявить любое значение.
- Подпись родительского процесса, потому что полномочиями пользуется дочерний процесс как удалённая сторона.
- Общее одобрение терминала, потому что терминалы запускают произвольные программы.
- Хеш как постоянную идентичность, потому что каждая легитимная пересборка потребует ручной миграции.
Хеш может безопасно сузить временное исключение. Он говорит «эти точные байты для этого запуска», а не «это та же программа после обновления». Пусть эта смысловая разница остаётся заметной в хранилище и интерфейсе.
Считайте отсутствующий Team ID состоянием, которое нужно классифицировать, а не пустым значением, обходящим сравнение. Код платформы, подписанный Apple, независимо подписанный код, ad hoc код и неподписанный код не укладываются в один кортеж. Определите, какие категории принимает ваш продукт, затем протестируйте каждую. Проверка if team != expected с разрешающей веткой для пустого значения породила достаточно ошибок авторизации, чтобы заслужить отдельный модульный тест.
Храните запись идентичности, которая объясняет свою область
Устойчивая запись должна сохранять пригодное для машинной проверки requirement, понятные человеку факты о подписи, категорию кода и отдельно одобренное условие расположения. Она также должна содержать область разрешения. Человек, проверяющий базу данных через шесть месяцев, должен понимать, охватывало ли одобрение один запуск, будущие подписанные версии или все программы команды.
В этом примере используются заполнители и сериализованный blob requirement в base64. Blob должен поступать из Code Signing Services, а не создаваться из строки, которую предоставил клиент:
{
"schema": 1,
"code_category": "developer_id",
"team_id": "A1B2C3D4E5",
"signing_identifier": "dev.example.agent",
"designated_requirement": "BASE64_PLATFORM_REQUIREMENT",
"approval_scope": "matching_identity_per_session",
"location_constraint": null,
"observed_path": "/Applications/Example.app/Contents/MacOS/Example"
}
Алгоритм сопоставления должен быть скучным. Сначала классифицируйте вызывающего и проверьте его подпись у работающего процесса. Для подписанной идентичности проверьте сохранённое requirement на этом процессе. Убедитесь, что возвращённые Team ID и идентификатор подписи совпадают с полями аудита: расхождение означает повреждённое состояние или ошибку, а не повод расширить доступ. Затем примените ограничение расположения, если оно есть. В конце учтите область разрешения и необходимость одобрения для каждого секрета.
Псевдокод упрощает проверку поведения при отказе:
caller = peer_from_kernel(connection)
code = dynamic_code(caller)
result = validate(code)
if result.category not in accepted_categories:
deny("unsupported code category")
identity = evaluate(stored_requirement, code)
if identity != satisfied:
deny("process identity changed")
if facts(code) != stored_audit_facts:
deny("identity record inconsistent")
if location_constraint and not location_allowed(code, location_constraint):
deny("approved program ran from an unapproved location")
authorize_for(connection_lifetime, requested_secret)
Обратите внимание, чего алгоритм не делает. Он не принимает один Team ID, не сравнивает путь до проверки подписи, не ищет в родительских процессах более удобную идентичность и не превращает неподписанного вызывающего в разрешение разработки без уведомления. Каждый отказ даёт причину, понятную пользователю и аудитору.
Планируйте миграцию идентичности как операцию, а не исключение. Передача команды, изменение идентификатора подписи, канала распространения или переход с ad hoc подписи на Developer ID могут легитимно изменить requirement. Покажите старые и новые факты рядом, потребуйте одобрения перехода уполномоченным человеком и сохраните обе записи в истории аудита. Никогда не перезаписывайте старую идентичность так, чтобы прошлые вызовы выглядели сделанными новой.
Тестируйте на враждебных фикстурах. Подпишите два исполняемых файла одной командой, но с разными идентификаторами: пройти должен только один. Подпишите другой файл одобренным идентификатором от другой команды: он должен быть отклонён. Скопируйте одобренный исполняемый файл в новый путь: идентичность должна пройти, если условие расположения не говорит иного. Замените файл после запуска и подтвердите, что проверяющий оценивает работающую удалённую сторону. Пересоберите ad hoc цель и подтвердите, что её временное одобрение не сохраняется.
Идентичность не отвечает, разрешено ли действие
Корректное совпадение процесса только определяет субъект запроса. Оно не доказывает, что субъекту можно пользоваться каждым секретом, вызывать любой хост или сохранять доступ навсегда. Держите идентичность процесса, одобрение сеанса и одобрение действия отдельными решениями, даже если один интерфейс показывает их вместе.
Такое разделение предотвращает распространённое расширение полномочий. Пользователь одобряет подписанному агенту программирования чтение одного токена разработки, система сохраняет идентичность агента, а позднее реализация начинает считать эту запись одобрением для любых учётных данных. Ни Team ID, ни идентификатор подписи, ни DR не содержат исходной границы ресурса. Идентичность оставалась прежней, пока авторизация незаметно расширялась.
Явно задайте кортеж авторизации: субъект, действие, ресурс, условия и срок. Для шлюза секретов он может выглядеть так:
subject: requirement R42 satisfied by this live process
action: perform an HTTP request with injected bearer credentials
resource: issue-tracker-development
conditions: vault unlocked and session approved
lifetime: this connection, with per-call approval if the secret requires it
Поле субъекта ссылается на запись идентичности процесса. Остальные поля берутся из запрошенной операции и контролей вокруг неё. Такая структура также подходит агенту, который использует и HTTP, и SSH, не притворяясь, что распознавание процесса автоматически авторизует оба канала.
Entitlements могут помочь специализированной политике, но не должны превращаться в импровизированную оценку репутации. Entitlement - подписанное заявление, которое macOS интерпретирует для определённых системных возможностей. Его наличие не делает программу в целом безопаснее, а отсутствие не ослабляет совпадение Team ID и идентификатора. Проверяйте конкретный entitlement, только если дизайн авторизации придаёт ему точный смысл.
Notarization и Gatekeeper тоже отвечают на другие вопросы. Их положительный результат может участвовать в проверке категории кода и доверия к распространению, но ни один из них не определяет одну программу внутри команды разработчика и не даёт доступа к вашему секрету. Во время диагностики spctl -a -vv -t exec может объяснить, принимает ли Gatekeeper файл. Не подменяйте этим результатом проверку сохранённого requirement.
Отзыв требует такой же точности. Отзыв сеанса должен остановить текущее соединение, не удаляя распознанную идентичность программы. Отзыв идентичности должен заставить совпадающие будущие процессы снова пройти одобрение. Отзыв разрешения на ресурс не должен затрагивать другие разрешения. Если один булев флаг с именем trusted управляет всеми тремя случаями, модель данных не может выразить, что именно решил пользователь.
Эти границы делают разбор инцидентов гораздо менее догадочным. Аудитор может установить, что запустилась конкретная подписанная программа, человек одобрил этот запуск, а запуск получил полномочия на определённую операцию. Без всех трёх записей даже идеальное DR не отвечает на главный вопрос: что позволило распознавание процесса?
Экраны одобрения должны говорить, что доказано
Человек не сможет проверить необработанный blob requirement во время прерывающего работу запроса одобрения. Покажите краткое утверждение на основе проверенных фактов: подписант или команда, идентификатор подписи, категория подписи, путь к исполняемому файлу и срок действия одобрения, для процесса или одного вызова. Самый широкий факт ставьте первым, только если дизайн сознательно даёт широкие полномочия.
Не используйте дружелюбные имена приложений как основную идентичность. Отображаемые имена берутся из изменяемых метаданных и часто совпадают. Они полезны как метки после проверенных фактов подписи, как и путь. Карточка с текстом Example Agent wants access скрывает, кто именно просит доступ: выпущенное приложение, помощник, локальная пересборка или неподписанная копия.
При первом вызове от нового процесса агента Sallyport показывает карточку одобрения, где на первом месте стоят сведения о подписании кода процесса, а затем привязывает одобрение к этому запуску до его завершения. Блокировка хранилища и флаг одобрения каждого вызова остаются отдельными контролями, поэтому распознавание процесса никогда не превращает идентичность в неограниченный доступ к секретам.
Событие аудита должно сохранять то, что увидел проверяющий, и правило, которое он применил. Записывайте проверенную категорию, Team ID, идентификатор подписи, ссылку на requirement, путь, идентификаторы процесса и сеанса, решение, причину отказа и область разрешения. Позднему проверяющему не должен быть нужен текущий файл по старому пути, чтобы понять вызов.
Не называйте результат «доверенный процесс». Проверяющий доказал более узкое утверждение: этот работающий процесс удовлетворил конкретному requirement кода, а пользователь или политика предоставили ему определённое действие. Такая формулировка сдерживает расползание полномочий, когда появляются новые типы секретов и новые инструменты агентов.
Team ID нужен в этом утверждении, но не способен нести его один. Используйте Team ID, чтобы назвать подписанта, идентификатор подписи, чтобы назвать программу у этого подписанта, designated requirement, чтобы сохранить идентичность между легитимными релизами, и дескриптор работающего процесса, чтобы привязать доказательство к запрашивающей стороне. Когда какого-либо из этих элементов нет, сузьте разрешение или запросите подтверждение снова. Граница доступа к секретам должна показывать неопределённость, а не превращать её в постоянный доступ.
Вопросы и ответы
Могут ли два разных приложения macOS иметь один Team ID?
Да. Все приложения и помощники, подписанные одной командой разработчиков Apple, могут иметь один Team ID. Чтобы различать программы внутри команды, используйте идентификатор подписи или designated requirement.
Идентификатор пакета совпадает с идентификатором подписи?
Часто да, но macOS этого не требует. Идентификатор подписи выбирает подписывающая сторона, а инструменты командной строки могут иметь его без пакета приложения, поэтому считывайте его из проверенной подписи кода.
Сохранять designated requirement или поля Team ID и идентификатора?
Сохраняйте designated requirement, пригодное для машинной проверки, а Team ID и идентификатор подписи оставляйте как понятные данные аудита. Проверяйте requirement через Code Signing Services, а не разбирайте и не сравнивайте его напечатанный текст.
Доказывает ли designated requirement безопасность процесса?
Нет. Оно подтверждает, что код соответствует выражению идентичности. Всё равно нужно отдельно решить, какими секретами и действиями эта идентичность может пользоваться, на какой срок и с каким одобрением человека.
Может ли путь к исполняемому файлу участвовать в авторизации процесса?
Он может быть дополнительным ограничением по месту запуска после успешной проверки личности по подписи. Один путь небезопасен: файлы перемещаются, а злоумышленник может подменить файл в доступной для записи одобренной папке.
Как службе определить процесс в IPC-подключении?
Определяйте удалённую сторону по данным подключения, предоставленным ядром, например по audit token, затем проверяйте соответствующий объект работающего кода. Никогда не доверяйте PID, пути или идентификатору, переданным в запросе клиента.
Что происходит с авторизацией при обновлении подписанного приложения?
Корректно выбранное designated requirement должно позволить легитимным обновлениям соответствовать той же идентичности. Если подписант, идентификатор или канал распространения меняется вне этого requirement, запросите явную миграцию идентичности или новое одобрение.
Можно ли навсегда авторизовать неподписанную сборку для разработки?
Можно, но постоянный доступ по пути не даёт надёжной непрерывности кода. Лучше выдавать одобрение разработки на время жизни процесса, привязанное к точной сборке и ограниченное непроизводственными секретами, а после пересборки запрашивать одобрение снова.
Должен ли дочерний процесс наследовать идентичность подписанного родителя?
Не автоматически. Если подключается дочерний процесс, он и есть непосредственная удалённая сторона. Поиск вверх по дереву процессов может передать полномочия подменённым потомкам. Если наследование предусмотрено архитектурой, передавайте ограниченную capability по контролируемому каналу.
Хеш кода лучше подходит для идентичности, чем Team ID?
Хеш определяет точные байты кода, поэтому он удобен для временного исключения для неподписанной сборки. Он не переживает легитимные обновления, тогда как Team ID вместе с идентификатором подписи или designated requirement может выразить непрерывность между релизами.