Grails:如何通过 SSL 访问 mongodb
Grails: how to access mongodb via SSL
我写了一个 grails 3.3 + mongo 4.0.4 应用程序,但在生产中 mongo 服务器只接受通过 SSL(自签名证书)的连接。我还没有在任何地方找到关于如何为 mongo (http://gorm.grails.org/latest/mongodb/manual/) 配置 GORM 的文档。有一个选项(sslEnabled,我想我应该使用 socketFactory)在 grails 中使用启用 SSL 的连接,但我不确定如何配置连接
对谁来说它与我有完全相同的问题,我仍然没有正确的方法直接使用 SSL 从 grails 连接到 mongodb。我发现的间接解决方案是在运行 grails 的机器上部署一个 mongos 客户端(mongo 分片客户端)启用 SSL 以连接到数据库,但不加密本地连接.因此,我可以通过 SSL 安全地访问远程数据库,但仍然使用 mongos 和 grails 之间的清晰连接进行连接。 mongos 配置应如下所示:
net:
ssl:
mode: preferSSL
PEMKeyFile: /installDir/cert.pem
CAFile: /installDir/chain.pem
clusterFile: /installDir/cert.pem
port: 27017
bindIp: 0.0.0.0
security:
clusterAuthMode: x509
preferSSL 允许 mongos 使用 SSL 连接到数据库,并且仍然允许 grails 应用程序将明文连接到 mongos
我找到了一种不用 mongos 连接的方法。
您需要在 grails-app/conf/runtime.groovy
中指定 socketFactory
个实例来验证服务器证书
import com.mongodb.ConnectionString
import grails.mongodb.MongoSSLContextBuilder
grails.mongodb = [
url : new ConnectionString("mongodb+srv://username:password@hostname/dbname?authSource=admin&tls=true"),
options: [
autoConnectRetry: true,
connectTimeout : 300,
sslEnabled : true,
socketFactory : new MongoSSLContextBuilder().getSSLContext("private/mongo/ca-certificate.crt").getSocketFactory()
]
]
实施MongoSSLContextBuilder
package grails.mongodb
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.grails.io.support.ClassPathResource
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import java.security.KeyStore
import java.security.SecureRandom
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
@CompileStatic
@Slf4j
class MongoSSLContextBuilder {
SSLContext getSSLContext(String pathToCert) {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) cf.generateCertificate(getCert(pathToCert));
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null);
ks.setCertificateEntry("caCert", caCert);
tmf.init(ks);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
return sslContext;
} catch (Exception e) {
log.error("Error during building mongo ssl context: ", e);
throw new RuntimeException(e);
}
}
private InputStream getCert(String pathToCert) throws IOException {
return new ClassPathResource(pathToCert).getInputStream();
}
}
将你的ca-certificate.crt
放在src/main/resources
目录下
如果您需要 mongodb+srv://
协议工作,您需要将 build.gradle
中的 org.mongodb:mongodb-driver
库更新到至少 3.6.0
版本
// https://mvnrepository.com/artifact/org.mongodb/mongodb-driver
compile 'org.mongodb:mongodb-driver:3.6.4'
compile('org.grails.plugins:mongodb:6.1.6') {
exclude group: 'org.mongodb', module: 'mongodb-driver'
}
我写了一个 grails 3.3 + mongo 4.0.4 应用程序,但在生产中 mongo 服务器只接受通过 SSL(自签名证书)的连接。我还没有在任何地方找到关于如何为 mongo (http://gorm.grails.org/latest/mongodb/manual/) 配置 GORM 的文档。有一个选项(sslEnabled,我想我应该使用 socketFactory)在 grails 中使用启用 SSL 的连接,但我不确定如何配置连接
对谁来说它与我有完全相同的问题,我仍然没有正确的方法直接使用 SSL 从 grails 连接到 mongodb。我发现的间接解决方案是在运行 grails 的机器上部署一个 mongos 客户端(mongo 分片客户端)启用 SSL 以连接到数据库,但不加密本地连接.因此,我可以通过 SSL 安全地访问远程数据库,但仍然使用 mongos 和 grails 之间的清晰连接进行连接。 mongos 配置应如下所示:
net:
ssl:
mode: preferSSL
PEMKeyFile: /installDir/cert.pem
CAFile: /installDir/chain.pem
clusterFile: /installDir/cert.pem
port: 27017
bindIp: 0.0.0.0
security:
clusterAuthMode: x509
preferSSL 允许 mongos 使用 SSL 连接到数据库,并且仍然允许 grails 应用程序将明文连接到 mongos
我找到了一种不用 mongos 连接的方法。
您需要在 grails-app/conf/runtime.groovy
中指定 socketFactory
个实例来验证服务器证书
import com.mongodb.ConnectionString
import grails.mongodb.MongoSSLContextBuilder
grails.mongodb = [
url : new ConnectionString("mongodb+srv://username:password@hostname/dbname?authSource=admin&tls=true"),
options: [
autoConnectRetry: true,
connectTimeout : 300,
sslEnabled : true,
socketFactory : new MongoSSLContextBuilder().getSSLContext("private/mongo/ca-certificate.crt").getSocketFactory()
]
]
实施MongoSSLContextBuilder
package grails.mongodb
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.grails.io.support.ClassPathResource
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import java.security.KeyStore
import java.security.SecureRandom
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
@CompileStatic
@Slf4j
class MongoSSLContextBuilder {
SSLContext getSSLContext(String pathToCert) {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) cf.generateCertificate(getCert(pathToCert));
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null);
ks.setCertificateEntry("caCert", caCert);
tmf.init(ks);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
return sslContext;
} catch (Exception e) {
log.error("Error during building mongo ssl context: ", e);
throw new RuntimeException(e);
}
}
private InputStream getCert(String pathToCert) throws IOException {
return new ClassPathResource(pathToCert).getInputStream();
}
}
将你的ca-certificate.crt
放在src/main/resources
目录下
如果您需要 mongodb+srv://
协议工作,您需要将 build.gradle
中的 org.mongodb:mongodb-driver
库更新到至少 3.6.0
// https://mvnrepository.com/artifact/org.mongodb/mongodb-driver
compile 'org.mongodb:mongodb-driver:3.6.4'
compile('org.grails.plugins:mongodb:6.1.6') {
exclude group: 'org.mongodb', module: 'mongodb-driver'
}