我想以编程方式安全地连接到我的PostgreSQL服务器
Scala使用基于JDBC的库。此外,我想存储所有的
由openssl
生成的格式的SSL证书和密钥文件
(即。,不本机Java生成的KeyStore
格式
库)。
我该怎么做?
我正在使用:
答案 0 :(得分:2)
延长
org.postgresql.ssl.WrappedFactory
属于的一部分
PostgreSQL JDBC Driver,然后通过
扩展类的名称作为setSslfactory()
方法的参数
BaseDataSource的适当子类。
假设您使用自签名证书作为PostgreSQL
服务器的证书( N.B。,服务器的证书在文件中
其名称指定为配置参数的值
ssl_cert_file
)和
假设您将使用PostgreSQL login role建立
连接名为database_user
:
使用PostgreSQL服务器的证书签署客户端证书
具有通用名称(CN
)属性database_user
。
然后,使用服务器的证书,客户端的证书和
客户端计算机上的openssl
PEM格式的客户端私钥,
以下内容将实现安全的双边身份验证连接
到PostgreSQL服务器:
package mypackage
import org.postgresql.ssl.WrappedFactory
import org.bouncycastle.util.io.pem.PemReader
import java.io.{FileInputStream,FileReader}
import javax.net.ssl.{SSLContext,KeyManagerFactory,TrustManagerFactory}
import java.security.{KeyStore,KeyFactory,SecureRandom}
import java.security.cert.CertificateFactory
import java.security.spec.PKCS8EncodedKeySpec
object SocketFactory {
final val PRIVATE_KEY_FILENAME = "private.key"
final val CLIENT_CERT_FILENAME = "client.crt"
final val SERVER_CERT_FILENAME = "/home/me/.ssl/postgres_server.crt"
def certFromFile(fileName: String) =
CertificateFactory getInstance "X.509" generateCertificate {
new FileInputStream(fileName)
}
}
class SocketFactory extends WrappedFactory {
import SocketFactory._
val sslContext = SSLContext getInstance "TLS"
sslContext init (
{ // key managers: Array[KeyManager]
val kmf = KeyManagerFactory getInstance "SunX509"
kmf init ({
val keyStore = KeyStore getInstance KeyStore.getDefaultType
keyStore load (null, null)
keyStore setKeyEntry ( "",
KeyFactory getInstance "RSA" generatePrivate (
new PKCS8EncodedKeySpec (
new PemReader (
new FileReader(PRIVATE_KEY_FILENAME)
).readPemObject.getContent
)
),
Array[Char](), // no password for this entry
Array(certFromFile(CLIENT_CERT_FILENAME))
)
keyStore
}, Array[Char]())
kmf.getKeyManagers
},
{ // trust managers: Array[TrustManager]
val tmf = TrustManagerFactory getInstance "PKIX"
tmf init {
val keyStore = KeyStore getInstance KeyStore.getDefaultType
keyStore load (null, null)
keyStore setCertificateEntry ("", certFromFile(SERVER_CERT_FILENAME))
keyStore
}
tmf.getTrustManagers
},
SecureRandom getInstance "SHA1PRNG"
)
_factory = sslContext.getSocketFactory
}
使用上述内容,您可以获得Java
DataSource
像这样的东西:
def dataSource = {
val ds = new PGSimpleDataSource
ds.setDatabaseName("my_database")
ds.setServerName("myHost.com")
ds.setUser("database_user")
ds.setSsl(true)
ds.setSslfactory("mypackage.SocketFactory")
ds
}
null
有意义
参数。如果你发现了奇怪的行为,请确保你不是
意外地在某处传递了null
方法参数。openssl
可以使用椭圆曲线加密。实现目标 forward secrecy, 考虑在PostgreSQL中指定适当的密码套件 配置,例如:
ssl_ciphers = 'DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA'
前面的示例使用了以下库依赖项
build.sbt
档案:
libraryDependencies ++= Seq(
"org.bouncycastle" % "bcpkix-jdk15on" % "1.50",
"org.postgresql" % "postgresql" % "9.3-1100-jdbc4"
)
您
pg_hba.conf
文件将需要一个适当的条目,如:
hostssl my_database database_user <client.ip.number>/32 trust clientcert=1