- Регистрация
- 14.05.16
- Сообщения
- 11.398
- Реакции
- 501
- Репутация
- 0
Допустим, наше Java приложение размещено на платформе "Heroku", и ему требуется подключиться к HTTP серверу, требующему предоставление Клиентского Сертификата.
В этой статье мы рассмотрим вопросы безопасного размещения клиентских хранилищ ключей в облаке, используя переменные окружения.
Обычно приватные ключи содержались в защищённых паролем файлах — контейнерах ключей, таких как .p12 или jks на файловой системе.
Но проблема становится очевидна, как только становится необходимо разместить подобное приложение в облаке:
Рассмотрим предполагаемый процесс с точки зрения теории безопасности:
Применим этот подход на практике:
Экспорт файла .p12
Воспользуйтесь инструкцией, использующей средства, встроенные в Вашу операционную систему:
Импорт в Heroku
Запись файла .p12 используя Gradle
Добавьте нижеприведённое задание в Ваш файл guild.gradle и назначьте его исполнение перед задачей stage:
task initKeyStore() {
doLast {
println("Creating keystore file from environment variables.")
String keyStoreFileName = System.getenv("keyStoreFileName")
if (keyStoreFileName != null) {
String keyStoreBase64 = System.getenv("keyStoreBase64")
new File(keyStoreFileName).withOutputStream {
it.write(Base64.decoder.decode(keyStoreBase64))
}
}
}
}
stage.dependsOn(initKeyStore)
Передача реквизитов через "procfile" Heroku
В "procfile" в Heroku не поддерживаются многострочные команды.
Поэтому, мы рекомендуем создать отдельный shell скрипт — runApp.sh.
runApp.sh:
java \
-Dserver.port=$PORT \
...
-Djavax.net.ssl.keyStoreType=$keyStoreType \
-Djavax.net.ssl.trustStoreType=$trustStoreType \
-Djavax.net.ssl.keyStore=$keyStoreFileName \
-Djavax.net.ssl.keyStorePassword=$keyStorePassword \
$JAVA_OPTS \
...
Не забудьте дать права на выполнение используя git и протолкнуть (push) подтверждение (commit):
git update-index --chmod=+x runApp.sh
git commit -m 'Добавление прав на выполнение runApp.sh'
git push origin master
Ограничения
В общей сложности Heroku позволяет хранить максимально 32 килобайта информации в переменных окружения.
Это накладывает некоторые ограничения, и вопрос их преодоления в настоящий момент прорабатывается в нашей организации.
Заключение
Спасибо за внимание!
В этой статье мы рассмотрим вопросы безопасного размещения клиентских хранилищ ключей в облаке, используя переменные окружения.
- Хранение паролей и других секретных данных в переменных окружения является распространённой практикой для приложений, размещённых в облаке.
Обычно приватные ключи содержались в защищённых паролем файлах — контейнерах ключей, таких как .p12 или jks на файловой системе.
Но проблема становится очевидна, как только становится необходимо разместить подобное приложение в облаке:
Даже защищённые паролем приватные ключи не допустимо размещать в репозитории вместе с исходным кодом
Тоже самое касается образов Docker и любых других подобных артефактов, доступных нескольким лицам
К счастью, это легко исправить в приложениях на Java!
Рассмотрим предполагаемый процесс с точки зрения теории безопасности:
- Офицер безопасности (о.б.) экспортирует приватный ключ как строку в кодировке Base64
- О.б. заходит в консоль управления облака (в нашем случае в Heroku Dashboard)
- О.б. импортирует строку в кодировке Base64 в переменную окружения
- Как часть автоматического процесса размещения приложения, эта же переменная окружения конвертируется в двоичные данные и записывается в физический файл
- Путь к этому файлу передаётся приложению на этапе запуска
- Теперь, только круг лиц, имеющих доступ к консоли управления облака, получают доступ к приватному ключу.
Применим этот подход на практике:
- Язык: Java
- Платформа: Heroku
- Система сборки: Gradle
- Формат хранилища ключей: PKCS12
Экспорт файла .p12
Воспользуйтесь инструкцией, использующей средства, встроенные в Вашу операционную систему:
You must be registered for see links
Никогда не загружайте ваши приватные ключи на сторонние онлайн ресурсы
Импорт в Heroku
- Зайдите в Heroku
- Перейдите в секцию Settings Вашего приложения
- Нажмите "Reveal the config vars"
- Добавьте следующие переменные окружения:
- keyStoreFileName — любое незанятое имя файла, например "private_key.p12"
- keyStoreBase64 — вставьте сюда значение строки закодированной в формате Base64, экспортированной в предыдущем шаге "Экспорт файла .p12"
- keyStorePassword — пароль, ранее использовавшийся с файлом .p12
- keyStoreType — в нашем случае pkcs12
- trustStoreType — jks
Запись файла .p12 используя Gradle
Добавьте нижеприведённое задание в Ваш файл guild.gradle и назначьте его исполнение перед задачей stage:
task initKeyStore() {
doLast {
println("Creating keystore file from environment variables.")
String keyStoreFileName = System.getenv("keyStoreFileName")
if (keyStoreFileName != null) {
String keyStoreBase64 = System.getenv("keyStoreBase64")
new File(keyStoreFileName).withOutputStream {
it.write(Base64.decoder.decode(keyStoreBase64))
}
}
}
}
stage.dependsOn(initKeyStore)
Передача реквизитов через "procfile" Heroku
В "procfile" в Heroku не поддерживаются многострочные команды.
Поэтому, мы рекомендуем создать отдельный shell скрипт — runApp.sh.
runApp.sh:
java \
-Dserver.port=$PORT \
...
-Djavax.net.ssl.keyStoreType=$keyStoreType \
-Djavax.net.ssl.trustStoreType=$trustStoreType \
-Djavax.net.ssl.keyStore=$keyStoreFileName \
-Djavax.net.ssl.keyStorePassword=$keyStorePassword \
$JAVA_OPTS \
...
Не забудьте дать права на выполнение используя git и протолкнуть (push) подтверждение (commit):
git update-index --chmod=+x runApp.sh
git commit -m 'Добавление прав на выполнение runApp.sh'
git push origin master
Ограничения
В общей сложности Heroku позволяет хранить максимально 32 килобайта информации в переменных окружения.
Это накладывает некоторые ограничения, и вопрос их преодоления в настоящий момент прорабатывается в нашей организации.
Заключение
- Теперь каждый раз, когда вы размещаете своё приложение в Heroku, Gradle автоматически создаёт хранилище ключей в виде файла P12 на основе переменной окружения.
- Затем, используя procfile, платформа Heroku передаёт детали этого файла Вашему приложению.
- Приватный ключ становится доступным приложению, и может быть использован для Клиентской аутентификации как обычный файл .p12 в Java
- Никаких изменений исторической кодовой базы приложения не требуется для поддержки этого подхода.
Спасибо за внимание!