Дженкинс в OS X: xcodebuild выдает ошибку со знаком кода

107

Резюме:

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

Мотивация:

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

Задний план:

Обработать:

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

Обсуждение:

Наивное ожидание на тот момент заключалось в том, что проект в свободном стиле со сценарием сборки 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: нет связки ключей по умолчанию для демона jenkins

sudo -u jenkins security default-keychain ... выдает "Связку ключей по умолчанию не удалось найти"

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

  1. sudo su jenkins
  2. cd ~/Library
  3. mkdir Keychains
  4. cd Keychains
  5. security create-keychain <keychain-name>.keychain
  6. security default-keychain -s <keychain-name>.keychain

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

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

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

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

Указывая на ответ Саймона Урбанека, вы разблокируете связку ключей из сценария с паролем в виде простого текста. Кажется безответственным хранить что-либо, кроме «одноразовых» сертификатов и ключей в связке ключей демона jenkins.

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

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

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

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

Проблема 3: профиль инициализации и разблокировка связки ключей

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

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

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

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

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

( РЕДАКТИРОВАТЬ: я опубликовал правки в свой вопрос, перезагрузился, чтобы убедиться, что мое решение было на 100%, и, конечно же, я пропустил шаг )

Даже после всех вышеперечисленных шагов вам нужно будет изменить список 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 для Jenkins , который немного упрощает настройку скрипта xcodebuild. На этом этапе я также рекомендую прочитать страницы руководства по xcodebuild - черт возьми, вы так далеко зашли в Терминале, верно?

Эта установка не идеальна, и мы будем благодарны за любые советы или идеи.

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

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


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

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

Урок 1. Не раскрывайте Дженкинса в Интернете

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

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

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

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

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

TL; DR

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

edelaney05
источник
10
Мне грустно, что я могу дать только один голос за этот краткий и полный вопрос-с-ответами-редактированием :)
Zsub
Что-то сорвало запуск Jenkins на OS X Yosemite - использовал установщик Jenkins.
Джонни,
Перенесите свой сертификат в Системную связку ключей и будьте счастливы;)
Джулиан Ф. Вайнерт

Ответы:

30

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

security unlock-keychain -p mySecretPassword...

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

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

Саймон Урбанек
источник
Но у меня также возникают трудности с загрузкой какой-либо связки ключей за пределами системной связки ключей. security unlock-keychain -p password -k /path/codesign.keychainне работает.
edelaney05
Вы использовали связку ключей по умолчанию, как в моем примере выше? Обратите внимание, что для настраиваемых цепочек для ключей сначала необходимо настроить их так, чтобы они находились в пути поиска, поэтому сначала попробуйте цепочку для ключей по умолчанию. Также обратите внимание, что нет никаких -kаргументов в пользу unlock-keychainтого, что все, что вы пытаетесь сделать, кажется неправильным (см. security help unlock-keychain).
Саймон Урбанек,
Я пробовал что-то немного другое, но в конечном итоге снова оказался на том же месте. Я отредактировал свой вопрос, надеюсь он немного понятнее?
edelaney05
Это полностью отличается от исходного вопроса ... Для начала вы должны войти в систему как jenkins (например, через sudo -u jenkins bash) и убедиться, что у вас есть права на весь путь. Вы сделали много вещей, о которых не говорили (например, использовали dsclдля создания пользователя), так что вы действительно сами по себе. Вы также захотите проверить домашнюю настройку (в зависимости от того, установлена ​​ли у вас оболочка или нет, которую вы можете использовать sudo -u jenkins -iдля получения соответствующих настроек входа).
Саймон Урбанек,
12

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

Используя экспортированный идентификатор в файле .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, но хорошо.

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

Zsub
источник
1
Не могли бы вы обновить инструкции по доступу к профилю обеспечения?
Люк,
См. Modeset.com/what-we-know/2013/03/11/jenkins_keychain_timeouts для соответствующего подхода.
Gili
5

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

Я запускаю 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» в системную цепочку ключей (щелкните правой кнопкой мыши, скопируйте из цепочки ключей «логин»).

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

Brianestey
источник
Я сталкиваюсь с той же проблемой профиля обеспечения, есть мысли о том, как ее решить?
Santthosh
2
Я обнаружил, что профили обеспечения для пользователя Jenkins хранятся в '/ Users / Shared / Jenkins / Library / MobileDevice / Provisioning Profiles', и поэтому я сделал шаг в моей сборке, чтобы скопировать профиль обеспечения из моего репозитория git в это место. Это позволяет мне обновлять профиль обеспечения и отправлять его в SCM, и Jenkins автоматически принимает это изменение.
brianestey
если вы скопируете файл login.keychain в свою библиотеку jenkins Keychain, вам нужно будет его перехватить, чтобы пользователь jenkins мог разблокировать его безопасностью
ganoro
1
Ты герой, я 2 дня рвал волосы на голове, копирование сертификатов в систему помогло
Роман Бобелюк
5

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

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

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

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

Иво Дансет
источник
Это было очень полезно для меня - у меня была аналогичная проблема с create-keychainкомандой, не работающей с пользователем jenkins. Казалось, выполнение этой команды устранило проблему.
lxt 09
Когда я запускаю команду для изменения пароля пользователя jenkins, меня запрашивают текущий пароль. Я понятия не имею, что это, и не могу нажать Enter. Какие-либо предложения?
CMVR 04
4

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

выберите « Добавить шаг сборки»> «Xcode»> «Подпись кода» и параметры связки ключей OS X.

тик разблокировки связки ключей окно и добавить следующим образом (для примера) введите описание изображения здесь

Иногда, если я получаю сообщение об ошибке

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

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

биолин
источник
3

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

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

sti
источник
Проблема заключается в том, что этот пользователь Jenkins находится в пользовательском пространстве, а не в пространстве демона ... поэтому, если злоумышленник сможет скомпрометировать вашего пользователя Jenkins, он получит полный доступ к вашему компьютеру.
edelaney05
Это могло бы решить мои проблемы. Проблема в том, что у меня уже установлен Jenkins (сделано наоборот), и я не хочу потерять все свои сборки и т. Д. Что произойдет в моем casE?
Mike S
2

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

Кроме того, я не уверен, что это проблема для вас, но сценарий ANT, который я использую через 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>
Феасорон
источник
1
Похоже, у вас есть установка Jenkins под пользователем "macbuild"; Я предполагаю, что этот пользователь - пользователь, а не демон. Я определенно понимаю (сейчас), что связку ключей нужно будет разблокировать с помощью аргументов командной строки (см. Комментарии Саймона Урбанека), но я все еще не уверен, как создать связку ключей по умолчанию для демона jenkins.
edelaney05
1

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

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

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

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

jazzcat
источник
Я выполнил вышеупомянутые шаги при «чистой» установке Lion, так что, может быть, перед вами возникла проблема с безопасностью? Другая возможность заключается в том, что с тех пор, как я изначально опубликовал, было обновление безопасности / OS X?
edelaney05
0

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

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

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

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

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

Затем команда принимает следующий вид: security unlock-keychain -p cat ~/.ssh/mypass

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

Mpechner
источник
0

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

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

Чтобы решить эту проблему, попробуйте войти в систему на http://appleid.apple.com и обновите свои вопросы безопасности.

Мне это помогло.

Влад
источник