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





Что плохого в том, чтобы поместить пароль в файл, который chmod'ed доступен для чтения только пользователю веб-сервера?
Легкий способ сделать это - создать плагин Rails, который принимает аргументы, используя "gets" в своем "init.rb". Позвольте мне приготовить быстрый пример кода:
Создайте каталог: '$ railsRoot / vendor / plugins / startup_args / lib'
Создайте объект для хранения данных аргументов в '$ railsRoot / vendor / plugins / startup_args / lib / startup_args.rb':
module StartupArgs
@@argHash = {}
def self.setArg(key, value)
@@argHash[key.to_sym] = value
end
def self.getArg(key)
return @@argHash[key.to_sym]
end
end
Загрузите модуль StartupArgs в пространство имен проекта Rails и заполните его аргументами в '$ railsRoot / vendor / plugins / startup_args / init.rb':
require "startup_args"
promptString = "Enter arg name (type nothing to continue):"
puts promptString
while (newArg = gets.chomp) != ""
puts "Enter value for '#{newArg}':"
newVal = gets.chomp
StartupArgs.setArg(newArg, newVal)
puts promptString
end
Теперь, в процессе запуска проекта Rails, он попытается получить пары ключ-значение из консоли. Эти пары будут храниться в объекте глобального пространства имен StartupArgs для последующего доступа (через StartupArgs.getArg ()).
Если вы ожидаете, что ваш проект Rails может быть развернут в сценариях, где демон не будет иметь доступа к консоли во время запуска, вы можете читать из именованного канала вместо стандартного ввода консоли.
Сделав еще один шаг, вы можете удалить все части init.rb, кроме оператора require, и добавить действие, которое выполняет эту настройку, в контроллер, который будет принимать соответствующие параметры в виде публикации в Интернете. Обязательно сконфигурируйте Rails, чтобы предотвратить ввод потенциально конфиденциальных параметров (например, паролей) в файлы журнала, записывающие обращения или ошибки (особенно, если он может использоваться как HTTP GET с параметрами в URL-адресе).
(Вы получите тот же эффект, что и в системе, описанной выше, если вы сконфигурируете другие действия Rails для игнорирования запросов, пока действие установки не сохранит соответствующие параметры в глобальном объекте.)
Примечание для Мики: у меня нет репутации, чтобы комментировать ваш пост, поэтому я включу сюда свой комментарий. Может быть несколько причин рассмотреть систему, которая никогда не требует, чтобы пароль был представлен в файловой системе. Например, разработчик может планировать проект Rails, который можно развернуть в разных операционных системах и в разных средах. Если разработчик определяет, что могут существовать сценарии, в которых администратор или пользователь root может быть скомпрометирован, ему нельзя доверять или его нельзя попросить подписать соглашения о конфиденциальности и безопасности, разработчик может решить добавить дополнительную обфускацию для размещения пароля в памяти только (для того, чтобы потребовать немного менее безопасную систему или немного более умную атаку для кражи пароля). Возможно, это можно рассматривать как вопрос относительных затрат: при небольших затратах пароль можно скрыть способом, который требует более дорогих знаний для восстановления.
Любой сценарий Ruby имеет доступ к локальным переменным среды через хеш ENV.
puts ENV['PATH']
Таким образом, с любой системой posix (Linux, Unix, Mac OS) вы можете просто установить ее при вызове скрипта, например:
MY_ARG=supersecret ruby script.rb
То же самое и с рельсами. Если вы поместите puts ENV['MY_ARG'] в свой environment.rb и запустите сервер:
$ MY_ARG=supersecret mongrel_rails start
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
supersecret
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart).
** Rails signals registered. HUP => reload (without restart). It might not work well.
** Mongrel 1.1.5 available at 0.0.0.0:3000
** Use CTRL-C to stop.
На мой взгляд, самым простым решением является переменная окружения.
Определенно проще, чем мое решение. Кто-то может быть обеспокоен тем, что в среде Linux root может тривиально перечислить среду процесса (например, путем чтения / proc / [pid] / environmental), но потребует больше знаний и усилий, чтобы получить строку пароля из памяти Ruby.
Интересно, есть ли способ установить встроенные переменные среды (как в вашем примере) при вызове исполняемых файлов из cmd.exe в Windows.
Хм, хорошее замечание по поводу / proc / [pid] / окружающая среда. Однако это все еще немного больше работы (и менее интуитивно понятно), чем запись ключа в текстовом файле.
Но скажите мне, как ваши мониторы процессов будут перезапускать умирающие процессы? ;-) Как только вы решите автоматизировать перезапуск, вы должны отказаться от такой секретности. В конце концов, вам просто нужно будет правильно защитить доступ к вашему серверу (или машине, которая перезапускает свои процессы).