暗号化されていないパスワードをアプリケーション構成ファイルに入れたくありません。
This question: Encrypting db password in application.confには問題の優れた解決策がありますが、Play 1 でのみ機能します。
Play 2.0 で動作するソリューションを知っている人はいますか? Play 2.0.2 の Scala バージョンで anorm を使用しています。
暗号化されていないパスワードをアプリケーション構成ファイルに入れたくありません。
This question: Encrypting db password in application.confには問題の優れた解決策がありますが、Play 1 でのみ機能します。
Play 2.0 で動作するソリューションを知っている人はいますか? Play 2.0.2 の Scala バージョンで anorm を使用しています。
少し遅れていることは承知していますが、この問題についての新しい議論はありません。ドキュメントで提案されているように、実際のソリューション (Play v.2.5.X) を共有したいと思います。これは、初期構成を処理GuiceApplicationLoader
するように構成するためにオーバーライドできるようになりました。GuiceApplicationBuilder
新しいクラスでmodules/ApplicationLoaderConfig.scala
:
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec
import javax.xml.bind.DatatypeConverter
import play.api.inject.guice._
import play.api.{ApplicationLoader, Configuration}
class ApplicationLoaderConfig extends GuiceApplicationLoader() {
override def builder(context: ApplicationLoader.Context): GuiceApplicationBuilder = {
// Decrypt secrets
val decryptedConfig = context.initialConfiguration ++
Configuration("config.to.descrypt.1" -> decryptDES(context.initialConfiguration.getString("config.to.descrypt.1").get)) ++
Configuration("config.to.descrypt.2" -> decryptDES(context.initialConfiguration.getString("config.to.descrypt.2").get))
initialBuilder
.in(context.environment)
.loadConfig(decryptedConfig)
.overrides(overrides(context): _*)
}
private def decryptDES(secret: String): String = {
val key = "12345678"
val skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "DES")
val cipher = Cipher.getInstance("DES/ECB/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, skeySpec)
new String(cipher.doFinal(DatatypeConverter.parseBase64Binary(secret)))
}
}
にも追加application.config
:
play.application.loader = "modules.ApplicationLoaderConfig"
すべての努力は無意味です。ハッシュ化されたパスワードをデータベースに入れるのは、人間がパスワードを脳内に保持できるためであり、脳が読み取れないからです。これを非対称暗号化と呼びます。
あなたが話していることは、対称暗号化でのみ可能です。プログラムは実行時にキーを持ち、このキーを使用してdbパスワードを復号化します。しかし、キーで暗号化された db パスワードを保存し、このキーを公開したままにしておくことに何の意味があるのでしょうか? (これは、Java ソースとコンパイル済みクラスの両方に当てはまります)。チェーンは、その最も弱いリンクと同じくらい強力です。
マシンがデータベースに接続する必要がある場合、パスワードが必要です。プログラムはパスワードをそのまま使用する必要があり、人間の入力は必要ないため、このパスワードをプレーンテキストで保存します。セキュリティを強化するためにできることは、このプレーン テキスト ファイルへのアクセスを制限し、最終的には管理者の頭の中にのみ保存されているパスワードで保護することです (ちなみに、管理者はすべてのパスワードをデータベースに保持する可能性が高く、おそらくマスターパスワード)。上記の Play プラグインを使用しても状況は変わらないことに注意してください。
私の頭に浮かぶ唯一の他のことは、管理者がdbパスワードを入力したときにのみdbに接続するPlayアプリです(ただし、実際にはこれは単なる思考練習です)
Raffaele との議論とコードの私自身の調査のおかげで、Play 2.0 では DB パスワードを暗号化できないようです。
何か見逃した場合はお知らせください。
編集: 次の方法でカスタム データベース ドライバーを使用して、問題を回避できます。
// Just redirect everything to the delegate
class DelegatingDriver(delegate: Driver) extends Driver
{
def connect(url: String, info: Properties) = delegate.connect(url, info)
def acceptsURL(url: String) = delegate.acceptsURL(url)
def getPropertyInfo(url: String, info: Properties) = delegate.getPropertyInfo(url, info)
def getMajorVersion = delegate.getMajorVersion
def getMinorVersion = delegate.getMinorVersion
def jdbcCompliant() = delegate.jdbcCompliant()
}
// Replace password in properties with the decrypted one
class MyDecryptingDriver extends DelegatingDriver(Class.forName("<my.original.Driver>").newInstance().asInstanceOf[Driver])
{
override def connect(url: String, info: Properties)= {
// copy Properties
val overriddenProperties= clone(info)
// override password property with the decrypted value
Option(info.getProperty("password")).foreach(value => overriddenProperties.setProperty("password", decryptPassword(value)))
super.connect(url, overriddenProperties)
}
def clone(orig: Properties)= {
val result= new Properties()
orig.propertyNames().map(_.asInstanceOf[String]).foreach(pName => result.setProperty(pName, orig.getProperty(pName)))
result
}
def decryptPassword(encrypted: String)= ...
}
次に、application.conf/db..driver を my.com.MyDecrypting ドライバーに置き換えます。完璧ではありませんが、私にとってはうまくいきます...