Как подписать профиль конфигурации iOS, сгенерированный программно?

контекст

У меня есть веб-приложение (внешний JS / backend PHP), которое генерирует некоторые профили конфигурации MDM iOS (*.mobileconfig) программно.

Пользователи веб-сайта вводят некоторую информацию, называют мой PHP API, а мой PHP-сервер генерирует профиль конфигурации "на лету" с пользовательскими данными, сохраняет их на сервере и возвращает URL-адрес сгенерированного профиля, поэтому пользователь может щелкнуть эту ссылку и установить ее на своем устройстве iOS.

Вкратце: этот профиль содержит в своем материале только веб-клип (ярлык safari).

Все работает нормально, ссылка на профиль конфигурации открывает приложение iOS Settings, которое просит пользователя установить этот профиль на свое устройство.

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

Мне бы хотелось, чтобы сгенерированные профили были подписаны, чтобы пользователь мог установить их проще и быстрее.

Вопросы

  • Является ли это возможным?
  • если да, возможно ли это с помощью PHP?
  • если да, как я могу это сделать?

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

Это не ясно для меня!

Любая помощь приветствуется, спасибо заранее!

1 ответ

Я могу подтвердить, что это работает, используя ответ zvi. Спасибо!

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

1. Получить сертификат

Я использовал бесплатный сертификат Let's Encrypt через ZeroSSL, чтобы легко получить 2 необходимых файла (сертификат и закрытый ключ).

Вам нужно будет доказать, что домен принадлежит вам (используя метод FTP или DNS)

Я сохранил сертификат как "certificate.crt" и закрытый ключ как "private-key.pem". Загрузите их где-нибудь на свой сервер.

2. Получить файл цепочки сертификатов

Если вы просто используете 2 файла выше, ваш профиль будет подписан, но не "проверен" в iOS (зеленый флажок, который я искал)

Загрузите "Сеть доверия" с этой страницы.

Я использовал "Let's Encrypt Authority X3 (IdenTrust cross -signature)" и сохранил его в "ca-chain.pem". Загрузите его на свой сервер вместе с двумя другими.

3. Сделайте метод входа в PHP

Чтобы подписать его через PHP-скрипт, я создал для этого метод, взяв файл входного профиля (не подписанный) и записав его в файл выходного профиля (подписанный).

Я использовал описанный здесь метод для вызова команды openssl из PHP с использованием shell_exec

<?php
function sslSignProfileToFile($inputFile, $outputFile)
{
    $sslPath = '/absolute/path/to/your/cert/files';
    shell_exec("openssl smime -sign -signer ".$sslPath."/certificate.crt -inkey ".$sslPath."/private-key.pem -certfile ".$sslPath."/ca-chain.pem -nodetach -outform der -in ".$inputFile." -out ".$outputFile);
}
?>

4. Создайте свой профиль и подпишите его

Создайте его, как вам нужно, и затем вызовите метод выше, чтобы сделать его копию с подписью.

<?php
sslSignProfileToFile( "/path/to/your/unsigned-profile.mobileconfig", "/path/to/your/signed-profile.mobileconfig");
?>

5. НАСЛАЖДАЙТЕСЬ!

Тогда вам решать:

  • если вы в AJAX-запросе, как я, вы можете вернуть обратно в теле URL-адрес подписанного профиля для загрузки

  • если вы использовали POST-действие классической формы, вы можете просто выполнить перенаправление заголовка, как описано здесь (не проверено мной)

Да, ты можешь. Также с PHP.

Как?

  1. Сохраните профиль, который хотите подписать, во временный файл:

    file_put_contents ($ tmp_file_name, $ profile_data);

  2. Подпишите файл, который вы только что создали:

    $ data = shell_exec ("openssl smime -sign -in $ tmp_file_name {добавьте сюда другие параметры, которые вам нужны...}");

  3. Отправьте данные клиенту:

    echo $ data;

  4. Удалить файл tmp...

    unlink ($ tmp_file_name);

Если только для проблемы со знаком, я уже ответил на один раньше, см. /questions/35293014/podpishitemobileconfig-na-servere-php/55190616#55190616

/**
 * Sign MobileConfig
 *
 * @return string
 */
function signMobileConfig (
    string $file_full_pathname,
    string $certificate_pathname,
    string $private_key_pathname,
    bool $remove_file = true
) {
    openssl_pkcs7_sign(
        $file_full_pathname,
        $file_full_pathname.'.sig',
        file_get_contents($certificate_pathname),
        file_get_contents($private_key_pathname),
        [], 0
    );

    $signed = file_get_contents($file_full_pathname.'.sig');

    if ($remove_file) {
        unlink($file_full_pathname.'.sig');
        unlink($file_full_pathname);
    }

    $trimmed = preg_replace('/(.+\n)+\n/', '', $signed, 1);
    return base64_decode($trimmed);
}

результат подписанного файла конфигурации (репутация <10, поэтому нажмите, чтобы увидеть результат)

Не стесняйтесь изменять приведенный выше код в соответствии со своими требованиями.

Другие вопросы по тегам