引入:在之前自己手动编译部署的 ovirt-engine 和后台管理系统是通过 http 协议进行沟通的,因此没有发现这个 SSL 主机名验证这个问题;现在公司需要部署 ovirt-engine 集群,试验了 ovirt-engine 的安装版,部署到服务器后,发现后台管理系统连接 ovirt-engine 时会提示报错,无法联通;
ovirt-engine-java-sdk源码定位到 ConnectionBuilder45
这是个基于 HttpClient 4.5 的 connection 生成器,其中的 [连接节点工厂注册器生成器中] 对 [SSL 连接] 指定了 [主机名认证策略]
private Registry createConnectionSocketFactoryRegistry() {
String protocol = getProtocol();
Registry registry = null;
// Create SSL/TLS or plain connection:
if (HTTP_PROTOCOL.equals(protocol)) {
ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register(HTTP_PROTOCOL, plainsf)
.build();
} else if (HTTPS_PROTOCOL.equals(protocol)) {
try {
LayeredConnectionSocketFactory sslsf = null;
if (this.insecure) {
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, new TrustManager[]{noCaTrustManager}, null);
sslsf = new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE);
} else {
SSLContextBuilder sslContextBuilder = SSLContexts.custom();
if (trustStoreFile != null) {
sslContextBuilder.loadTrustMaterial(
new File(trustStoreFile),
this.trustStorePassword != null ? this.trustStorePassword.toCharArray() : null
);
}
SSLContext sslContext = sslContextBuilder.build();
// todo 默认主机名认证 修改为 不对主机名进行认证
// sslsf = new SSLConnectionSocketFactory(sslContext, new DefaultHostnameVerifier());
sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
}
registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register(HTTPS_PROTOCOL, sslsf)
.build();
} catch (NoSuchAlgorithmException e) {
throw new Error(NO_TLS_ERROR, e);
} catch (KeyManagementException e) {
throw new Error(BAD_KEY_ERROR, e);
} catch (KeyStoreException e) {
throw new Error(KEY_STORE_ERROR, e);
} catch (FileNotFoundException e) {
throw new Error(KEY_STORE_FILE_NOT_FOUND_ERROR, e);
} catch (CertificateException e) {
throw new Error(CERTIFICATE_ERROR, e);
} catch (IOException e) {
throw new Error(IO_ERROR, e);
}
} else {
throw new Error(BAD_PROTOCOL_ERROR + protocol);
}
return registry;
}
修改后,可以连接!
导入 ovirt-engine TLS 证书
在之前进行连接时,并没有指定证书,源码在没有指定证书的情况下默认使用 java 本地的trust store进行验证
The truststore.jks file is required when connecting to a server protected with TLS. In an usual oVirt installation it will be in /etc/pki/ovirt-engine/.truststore. The default password for keystore is mypass. If you don’t specify trustStoreFile, then default Java trust store location is used, which is defined by javax.net.ssl.trustStore system property.