Jenkins на OS X: xcodebuild дает ошибку кода

Резюме:

Настройка Jenkins на OS X была значительно упрощена с помощью последнего установщика (с 1.449 по 9 марта 2012 г.), однако управление процессом подписи кода все еще очень сложно без прямого ответа.

Мотивация:

Запустите безглавой CI-сервер, который следует общим рекомендациям по запуску служб в OS X (Некоторые из них объясняются здесь на простом языке).

Фон:

процесс:

Установите Jenkins CI через OS X установочный пакет. Для шага "Тип установки" нажмите кнопку "Настроить" и выберите "Начать при загрузке как" Дженкинс ".

Обсуждение:

Наивное ожидание на этом этапе состояло в том, что проект свободного стиля с конструкцией script xcodebuild -target MyTarget -sdk iphoneos должен работать. Как указано в заголовке этого сообщения, он не выполняет и не выполняет следующие действия:

Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificate/private key pair in the default keychain

Достаточно очевидно, что должно произойти - вам нужно добавить действительный сертификат подписи кода и закрытый ключ в цепочку ключей по умолчанию. Изучая, как это сделать, я не нашел решения, которые не открывают систему до некоторой степени уязвимости.

Проблема 1: Отсутствие брелка по умолчанию для демона денкинсов

sudo -u jenkins security default-keychain ... дает "Невозможно найти брелок по умолчанию"

Как указано ниже Ivo Dancet, UserShell по умолчанию установлен на /usr/bin/false для денкинса (я думаю, что это функция, не ошибка); следуйте его ответам, чтобы изменить UserShell на bash. Затем вы можете использовать sudo su jenkins, чтобы войти в систему как пользователь jenkins и получить приглашение bash.

  • sudo su jenkins
  • cd ~/Library
  • mkdir Keychains
  • cd Keychains
  • security create-keychain <keychain-name>.keychain
  • security default-keychain -s <keychain-name>.keychain

Хорошо, отлично. Теперь у нас есть брелок по умолчанию; пусть двигаться дальше? Но, во-первых, почему мы даже потрудились создать брелок по умолчанию?

Почти все ответы, предложения или беседа, которые я читал в ходе исследования, предполагают, что нужно просто выталкивать сертификаты и ключи для подписания кода в системный брелок. Если вы запустите security list-keychains как проект свободного стиля в Jenkins, вы увидите, что единственная доступная цепочка ключей - это системный брелок; Я думаю, что там, где большинство людей придумали поставить свой сертификат и ключ там. Но это просто кажется очень плохой идеей - особенно учитывая, что вам нужно создать простой текст script с паролем, чтобы открыть цепочку ключей.

Проблема 2: Добавление сертификатов подписи кода и закрытого ключа

Вот где я действительно начинаю брезгливо. У меня есть ощущение, что я должен создать новый открытый/закрытый ключ, уникальный для использования с Дженкинсом. Мой мыслительный процесс заключается в том, что демон jenkins скомпрометирован, тогда я могу легко отменить сертификат в Apple Provisioning Portal и создать еще один открытый/закрытый ключ. Если я использую тот же ключ и сертификат для моей учетной записи пользователя и Jenkins, значит, это означает больше хлопот (ущерб?), Если атакует служба jenkins.

Указывая на Simon Urbanek answer, вы будете разблокировать брелок из script с помощью обычного текстового пароля. Кажется безответственным сохранить что-либо, кроме "одноразовых" сертификатов и ключей в брелках дзенкин-демона.

Меня очень интересует любое обсуждение обратного. Я слишком осторожен?

Чтобы создать новый CSR как демон дженкинсов в терминале, я сделал следующее...

  • sudo su jenkins
  • certtool r CertificateSigningRequest.certSigningRequest Вам будет предложено следующее (большинство из них я получил обоснованные догадки при правильном ответе, у вас есть лучшее понимание? Пожалуйста, поделитесь.)...
    • Введите метку ключа и сертификата:
    • Выберите алгоритм: r (для RSA)
    • Введите размер ключа в битах: 2048
    • Выбор алгоритма подписи: 5 (для MD5)
    • Введите строку запроса:
    • Затем куча вопросов для RDN
  • Отправьте созданный файл CSR (CertificateSigningRequest.certSigningRequest) на портал Apple Provisioning Portal под новым идентификатором Apple
  • Утвердить запрос и загрузить файл .cer
  • security unlock-keychain
  • security add-certificate ios_development.cer

Это делает нас на один шаг ближе...

Проблема 3: Профилирование и разблокировка брелка

Я сделал специальный профиль обеспечения в портале Provisioning Portal только для использования с CI в надежде, что если что-то случится, я сделаю удар немного меньшим. Лучшая практика или слишком осторожная?

  • sudo su jenkins
  • mkdir ~/Library/MobileDevice
  • mkdir ~/Library/MobileDevice/Provisioning\ Profiles
  • Переместите профиль настройки, который вы настроили на портале Provisioning Portal, в эту новую папку. Теперь мы находимся в двух шагах от возможности запускать xcodebuild из командной строки как jenkins, и это значит, что мы также близки к возможности запуска JS-версий JI-CIN.
  • security unlock-keychain -p <keychain password>
  • xcodebuild -target MyTarget -sdk iphoneos

Теперь мы получаем успешную сборку из командной строки при входе в систему как демон дженкинсов, поэтому, если мы создадим проект в свободном стиле и добавим эти последние два шага (# 5 и # 6 выше), мы сможем автоматизировать здание нашего проекта iOS!

Это может быть необязательно, но я чувствовал, что лучше настроить jenkins UserShell на /usr/bin/false после того, как я успешно получил всю эту настройку. Я параноик?

Проблема 4: брелок по умолчанию все еще недоступен!

(EDIT: я опубликовал изменения на свой вопрос, перезагрузился, чтобы убедиться, что мое решение было на 100%, и, конечно, я не сделал ни одного шага)

Даже после всех вышеперечисленных шагов вам нужно будет модифицировать Plunch Launch Daemon в /Library/LaunchDaemons/org.jenkins-ci.plist, как указано в этом ответе. Обратите внимание, что это также ошибка openrdar.

Он должен выглядеть так:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>EnvironmentVariables</key>
        <dict>
                <key>JENKINS_HOME</key>
                <string>/Users/Shared/Jenkins/Home</string>
        </dict>
        <key>GroupName</key>
        <string>daemon</string>
        <key>KeepAlive</key>
        <true/>
        <key>Label</key>
        <string>org.jenkins-ci</string>
        <key>ProgramArguments</key>
        <array>
                <string>/bin/bash</string>
                <string>/Library/Application Support/Jenkins/jenkins-runner.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>UserName</key>
        <string>jenkins</string>
        <!-- **NEW STUFF** -->
        <key>SessionCreate</key>
        <true />
</dict>
</plist>

С этой настройкой я также рекомендую Xcode plugin для Jenkins, что упрощает настройку xcodebuild script. На этом этапе я также рекомендую прочитать man-страницы для xcodebuild - черт возьми, вы сделали это до сих пор в терминале, правильно?

Эта настройка не идеальна, и любые советы или прозрения очень ценятся.

Мне было трудно выбрать "правильный" ответ, так как то, что я придумал для решения моей проблемы, было сборником почти каждого ввода. Я пытался дать всем по крайней мере досрочное голосование, но присудил ответ Саймону, потому что он в основном отвечал на исходный вопрос. Кроме того, Сами Тикка заслуживает большого уважения за свои усилия, заставляя Дженкинса работать AppleScript как обычное приложение OS X. Если вы заинтересованы только в том, чтобы Jenkins быстро и быстро продвигался в вашей пользовательской сессии (то есть не как безголовый сервер), его решение намного больше похоже на Mac.

Я надеюсь, что мои усилия заткнут дальнейшую дискуссию и помогут следующей бедной душе, которая приходит, думая, что они могут получить настройку Jenkins CI для своих проектов iOS в выходные из-за всех замечательных вещей, которые они слышали об этом.


Обновление: 9 августа 2013 г.

С таким количеством фаворитов и фаворитов, я думал, что вернусь к этому 18 месяцев спустя с некоторыми краткими уроками.

Урок 1: Не подвергайте Дженкинса публичному интернету

На WWDC 2012 года я взял этот вопрос инженерам Xcode и OS X Server. Я получил какофонию "не делай этого!". от кого я спросил. Все они согласились с тем, что процесс автоматической сборки был отличным, но сервер должен быть доступен только в локальной сети. Инженеры OS X Server предложили разрешить удаленный доступ через VPN.

Урок 2: теперь есть новые параметры установки

Недавно я рассказал о своем опыте работы с Jenkins, и, к моему удивлению, нашел некоторые новые методы установки - Homebrew и даже Bitnami Mac App Storeверсия. Это, безусловно, стоит проверить. Джонатан Райт имеет подробный отчет о получении Homebrew Jenkins.

Урок 3: Нет, серьезно, не открывайте окно сборки в Интернете

Из исходного сообщения довольно ясно, что я не системный администратор и эксперт по безопасности. Здравый смысл в отношении личных вещей (брелоки, учетные данные, сертификаты и т.д.) Заставил меня чувствовать себя довольно неловко о том, чтобы положить ящик Jenkins в Интернет. Ник Арнотт в "Пренебреженном потенциале" очень легко подтвердил мои хеби-джеи в этой статьи.

TL; DR

Моя рекомендация другим лицам, пытающимся автоматизировать процесс их сборки, изменилась за последние полтора года. Убедитесь, что ваша машина Jenkins находится за вашим брандмауэром. Установите и установите Jenkins в качестве отдельного пользователя Jenkins либо с помощью установщика, версии Bitnami Mac App Store, Sami Tikka AppleScript и т.д.; это устраняет большую часть головной боли, о которой я подробно рассказывал выше. Если вам нужен удаленный доступ, настройка VPN-сервисов в OS X Server занимает десять минут. Я использую эту установку уже более года, и я очень доволен ею. Удачи!

Ответ 1

Брелки должны быть разблокированы, прежде чем их можно будет использовать. Вы можете использовать security unlock-keychain для разблокировки. Вы можете сделать это в интерактивном режиме (безопаснее) или указав пароль в командной строке (небезопасно), например:

security unlock-keychain -p mySecretPassword...

Очевидно, что включение этой функции в script ставит под угрозу безопасность этой связки ключей, поэтому люди часто настраивают отдельную цепочку ключей только с учетными данными для подписи, чтобы свести к минимуму такой ущерб.

Обычно в Terminal цепочка ключей уже разблокирована вашей сессией, так как по умолчанию цепочка ключей разблокирована при входе в систему, поэтому вам не нужно это делать. Тем не менее, любой процесс, который не запускается в вашем сеансе, не будет разблокировать цепочку ключей, даже если у вас есть пользователь (чаще всего это влияет на ssh, но также и на любой другой процесс).

Ответ 2

Предположим, что вы также хотите использовать ad hoc-дистрибуцию через Jenkins, это требует, чтобы у Jenkins был доступ к сертификату Distribution и идентификатору команды администратора в дополнение к профилям подготовки.

Используя экспортированный идентификатор в файле .cer, вы можете программно импортировать его так же, что -A-переключатель должен разрешить всем программам доступ к этой записи. В качестве альтернативы вы можете использовать несколько переключателей -T /path/to/program для доступа к codesign и xcodebuild.:

$ security import devcertificate.cer -k jenkins.keychain -A

Конечно, мы также должны иметь сертификат Apple WWDCRA, импортированный почти так же:

$ security import AppleWWDRCA.cer -k jenkins.keychain -A

Однако нам также нужен закрытый ключ для devcertificate.cer. Для этого вам необходимо экспортировать соответствующий закрытый ключ в качестве ключа .p12 и установить пароль. Поместите его где-нибудь, вы можете получить доступ к нему из своей оболочки Jenkins, разблокировать брелок и импортировать его:

$ security unlock-keychain -p YourKeychainPass jenkins.keychain
$ security import devprivatekey.p12 -k login.keychain -P ThePasswordYouSetWhenExporting -A

Импортирование сертификата распространения работает одинаково. Я не знаю, почему вам нужно разблокировать брелок для импорта .p12, а не для .cer, но хорошо.

Вам также понадобится доступ к профилям подготовки, я скоро отредактирую эти инструкции в этом сообщении.

Ответ 3

Чтобы изменить пароль, вы можете использовать sudo passwd jenkins <new-pw>. Однако я думаю, что было бы лучше использовать команду dscl для изменения пароля.

В моей установке jenkins (официальный установщик) имеет пользовательскую оболочку /usr/bin/false. Изменение его на bash решило проблему невозможности входа в систему:

sudo dscl . -change /Users/jenkins UserShell /usr/bin/false /bin/bash

Теперь вы можете войти в систему с помощью su jenkins.

Ответ 4

У меня была такая же проблема, и я уже некоторое время искал ответ. Вот одна вещь, которую я узнал.

Я запускаю jenkins в качестве пользователя jenkins, пользователя, созданного установщиком, и, как все говорят, он не имеет доступа к той же цепочке ключей, что и ваш обычный пользователь. Вместо того, чтобы пытаться войти в систему как пользователь jenkins, я создал второй проект сборки, который просто имеет один шаг сборки, который является "Execute Shell", в котором я запускаю команды, которые я хочу проверить как пользователь jenkins.

Как только я установил эту настройку, я мог запустить команду

security list-keychains

И это показало мне, что единственное, что могли видеть дженкинсы, это системный брелок.

+ security list-keychains
    "/Library/Keychains/System.keychain"
    "/Library/Keychains/System.keychain"

С этими знаниями я открыл приложение Keychain Access и скопировал свой сертификат "iPhone Developer: xxxx" в системную цепочку ключей (щелкните правой кнопкой мыши, скопируйте из брелка "login" ).

Это заставило меня передать ошибку кода знака пары сертификатов/закрытых ключей, но открыла еще один с профилем подготовки (похоже, подобная, но другая проблема).

Ответ 5

Для людей, имеющих проблемы с цепочками ключей, я бы порекомендовал вам попробовать мой альтернативный установщик Jenkins в https://github.com/stisti/jenkins-app, загружает https://github.com/stisti/jenkins-app/downloads

Jenkins.app запускает Jenkins в сеансе пользователя, поэтому проблемы с доступом к цепочке ключей не являются проблемой:)

Ответ 6

Я использовал плагин Xcode для создания приложения iOS. В конфигурации проекта.

выберите "Добавить шаг сборки" > "Xcode" > "Подписание кода" и опции Keychain OS X.

tick Разблокируйте коробку для ключей и добавьте, как следует (на примерах) enter image description here

раз, если я получаю ошибку

Ошибка кодового знака:...

Я снова открою Дженкинса и снова введите пароль, чтобы разблокировать

Ответ 7

Если у вас есть sudo, вы можете использовать passwd для изменения пароля пользователя Jenkins. Затем вы можете получить пароль Дженкинса.

Кроме того, я не уверен, что это проблема для вас, но ANT Script, который я использую через Jenkins, имеет следующее:

<target name="unlock_keychain">
    <exec executable="security">
        <arg value="-v"/>
        <arg value="unlock-keychain"/>          
        <arg value="-p"/>
        <arg value="<My Password>"/>
        <arg value="/Users/macbuild/Library/Keychains/login.keychain"/>
    </exec>
</target>

Ответ 8

По какой-то причине утилита "security" не работала для меня на Lion со свежей установкой Jenkins.

После "sudo su jenkins" он смог создать новый брелок, но молча игнорировал все команды "default-keychain -s..." или "unlock", которые возвращали нулевой статус выхода и ничего не печатали на консоли. Листинг по умолчанию или логин для ключей ничего не дал, список поиска по ключевым словам содержал только системный брелок, и я не мог изменить это, что бы я ни печатал.

После того, как я вошел в этот рабочий стол пользователя и запустил утилиту Keychain Utility, он показал мою созданную цепочку ключей, и после этого все работало, как описано в верхних сообщениях.

Мне интересно, изменилось ли какое-то из начальных правил в Lion, или я что-то пропустил?

Ответ 9

Я добавил частный и открытый ключ для компании к цепочке ключей. Я добавил профили обеспечения для производства, которое я буду строить.

Поскольку у этого пользователя не было учетной записи, я зарегистрировался в devcenter с моей учетной записью. Загрузили сертификаты подготовки и загрузили их в Xcode.

Я не добавлял сертификат специально для учетной записи роли сборки, например. Дженкинс.

Я добавил это в конструкцию script: разблокировка ключа-keychain -p mySecretPassword, как указано выше, но...

Я создал файл ~/.ssh/mypass и добавил пароль к файлу.

Затем команда становится: ключ-разблокировка безопасности -p cat ~/.ssh/mypass

Сборка работает как чемпион. Я получаю файл ipa, он загружается в центральное приложение и работает на устройстве.

Ответ 10

Также можно установить и запустить JenkinsCI в качестве пользователя OS X вместо демона:

  • установить jenkins с помощью официального установщика (https://jenkins-ci.org/)
    • Нажмите следующий
    • Нажмите "Настроить"
    • Отмените выбор "Начать при загрузке как" jenkins "" - * ВАЖНО * эта опция обычно позволяет безгласным дженкинсам, который не работает с доступом к keychain.
  • Запуск http://127.0.0.1:8080
    • проверить, не запускается ли
    • может потребоваться остановить jenkins sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
  • Дважды щелкните /Applications/Jenkins/jenkins.war
    • Конечно, это должно быть автоматизировано для запуска @пуска
  • Откройте http://127.0.0.1:8080
    • проверить, запущен ли он