ActionMailer_X509: подписываем и шифруем письма прямо в Ruby On Rails

    В одном из последних проектов понадобилось подписывать и шифровать с помощью сертификатов X.509 письма, отправляемые приложением на Ruby on Rails 3. Беглый поиск привёл к плагину actionmailer_x509, а вот дальше начались проблемы.

    Выяснилось, что он не обновлялся с 2008 года, скорее всего не работает с Rails 3 (в частности, смущал комментарий автора: «It has been tested with Rails 2.0.1») и умеет только подписывать, но не шифровать письма. Поиск альтернативных решений ничего не дал, и пришлось знакомиться с плагином поближе.



    Знакомство осложнилось очень быстро: набор тестов, шедший в комплекте с плагином падал при прогоне. Как оказалось, хотя сходу заметить это было не просто, дело было в том, что истёк срок действия сертификатов, которые автор включил в тестовый набор. Пересоздал сертификаты. Далее, я убрал из тестового хелпера библиотеки от Rails 2 и добавил соответствующие от Rails 3, сделал ещё ряд изменений

    Тут же выяснилось, что Mail, новый gem обработки почты, который теперь используется в Ruby on Rails 3, существенно отличается от Tmail. Пришлось врубаться во внутреннее устройство Mail и Tmail, переписывать все части, затрагивающие Tmail. Ок, готово. Конечно, повозился, и попереносил неперенесённые заголовки письма, но это было решаемо.

    Новая проблема: в комментариях к коду автор пишет «NOTE: we can not reparse the whole mail, TMail adds a \r\n which breaks the signature...». И действительно, проверка подписи не работает и в результирующем теле объекта Mail \r\n стоят через каждые 60 символов, в то время как в оригинальном, через каждые 64. Вот над этой проблемой пришлось биться очень долго. Я пытался gsub'ом вернуть всё на место, изучал код gem'а Mail, оставлял баг-репорты в Mail, писал в список расслыки, но всё было тщетно. В конце концов меня спас вопрос на stackoverflow. Оказалось, что Mail добавляет content-id, который меняет заголовки письма, и, следовательно, подпись становится неверна, и это никак не связано с \r\n, о которых писал автор оригинального actionmailer_x509.

    После исправления и принудительной установки content_id всё пошло как по маслу: я почистил код, завернул всё в отдельный gem, поправил rake-задания и дописал код, отвечающий за шифрование письма.

    Результатом моих трудов можете наслаждаться в моём форке actionmailer_x509 на github'е или с помощью строчки gem 'actionmailer_x509' в вашем Gemfile.

    Он позволяет следующим незатейливым кодом включить подпись и\или шифрование исходящего письма

    class FooMailer < ActionMailer::Base
      def sending_method(email, from , subject = "Empty subject for signed")
        # Для включения подписи
        x509_sign  true
        x509_sign_cert  "certs/yourwebsite.crt"
        x509_sign_key   "certs/yourwebsite.key"
        # Пароль для приватного ключа
        x509_sign_passphrase "my passphrase for the certificate"
        # Для включения шифрования
        x509_crypt  true
        x509_crypt_cert  "certs/crypt.crt"
        # Можно изменить алгоритм шифрования, если не устраивает стандартный DES
        x509_crypt_cipher "AES-128-CBC"
    
        mail(:subject => subject, :to => email, :from => from)
      end
    end
    


    Кроме того плагин позволяет выставить все эти настройки ключей для всего приложения в целом и предоставляет несколько rake задач для тестирования настроек и скорости работы. Подробнее об этом читайте в README.

    Вместо заключения

    Я потратил больше месяца на адаптацию actionmailer_x509 к особенностям Ruby on Rails 3. Я изучил smime openssl, gem Mail, gem Tmail и ActionMailer. Я узнал, как заворачивать код в gem и как вообще должна выглядеть структура gem'а; как правильно, с помощью railtie, подгружать rake задачи, что б они стали видны в итоговом Rails приложении. Были моменты, когда я был готов сдаться, и искал обходные пути решения моей проблемы, но, к счастью, я сумел дожать gem.

    Я не жалею о потраченном времени, и смотрю на новосозданный gem с чувством удовлетворения. Теперь я гораздо лучше чувствую всю почтовую кухню Ruby on Rails, и я стал гораздо подкованней в вопросах, связанных с OpenSSL. Если вам вдруг придётся выбирать допилить\создать существующее решение или попытаться обойти проблему как-то иначе — попробуйте сделать что-то новое для сообщества, вам должно понравиться!
    Поделиться публикацией

    Комментарии 6

      0
      достаточно специфичная у вас возникла задача)

      все-таки приятно, что для рельсов появляется огромное количество полезных и нужных гемов
        0
        Да уж весьма специфическая :)

        Но, к сожалению, партнёр представляет себе межистемное взаимодействие как периодический обмен шифрованными и подписанными письмами :)
          0
          Не один ваш партнер представляет себе так межсистемное взаимодействие. Точно так же действуют налоговая / ПФР / сбербанк и иже с ними.
          В данное время взаимодействие с ними может осуществляться только с помощью Windows + IE, потому что, в связи с требованиями закона, все данные должны быть зашифрованы и подписаны прежде чем быть переданными по открытым сетям. Что, в общем-то логично и правильно, но держать терминальный сервер с виндовс только ради такого рода ПО как-то не кошерно, тем более что основная деятельность предприятия отнюдь не связана с постоянным взаимодействием с такого рода структурами.
          Так вот, идея такова.
          Делаем маленький неттоп, в него ставим любой кастомизируемый линукс, который допиливаем до состояния «получили почту с определенного адреса, зашифровали / подписали ключами с флэшки, отправили по другому адресу».
          В результате бухгалтерия любого предприятия может купить себе такой неттоп, включить его в любую структуру сети, и без установки дополнительных программ на клиентские компьютеры мы можем отправлять валидные письма во все государственные (или полугосударственные) организации.
          Как вам?
            0
            Про налоговуя / ПФР / сбербанк не знал.

            По второй части: отличная идея! Главное, что б было на уровне воткнул — заработало.
              0
              Да, именно так — из коробки.
              А по всяким налоговым и прочим — как ни грустно, так оно и есть.
              Я работаю в типографии, у нас дизайнеры / пре-пресс — на Mac`ах, менеджеры — на убунтах, и только одна бухгалтерия вечно со своими виндовыми проблемами. С введением терминального серва для 1С-а, СБИС++ и прочих таких проблем стало меньше, но они таки остались.
              Самая главная проблема в производстве таких штук — это не настройка / программирование, а лицензии ФСБ на производство шифровального ПО. Я не сталкивался близко с этим всем, но глядя на окружающую действительность, не думаю, что все легко и просто.
              0
              > налоговая / ПФР / сбербанк

              Но там же вся это содомия завязана на Windows + IE + КриптоПРО (седьмая винда причем вроде всё еще не поддерживается)

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое