问题
我正在尝试使用gRPC
在Java中建立客户端。我已获得对kubernetes
命名空间的访问权以测试客户端。但是,我所拥有的只是该群集的证书颁发机构和一个承载令牌。
apiVersion: v1
clusters:
- cluster:
certificate-authority: /etc/ssl/certs/devwat-dal13-cruiser15-ca-bundle.pem
server: https://<host-ip>:<port>
name: devwat-dal13-cruiser15
contexts:
- context:
cluster: devwat-dal13-cruiser15
namespace: interns
user: devwat-dal13-cruiser15-sa-interns-editor
name: devwat-dal13-cruiser15-interns
current-context: devwat-dal13-cruiser15-interns
kind: Config
preferences: {}
users:
- name: devwat-dal13-cruiser15-sa-interns-editor
user:
token: <token>
代码
我对SSL
和证书了解不多,但是我尝试遵循在线使用SSL/TLS
和gRPC
与Java的文档,并提出了以下建议:
public class TrainerClient {
private ManagedChannel channel;
private TrainerGrpc.TrainerBlockingStub stub;
//private final String OVERRIDE_AUTHORITY = "24164dfe5c7842c98de431e53b6111d9-kubernetes-ca";
private final String CERT_FILE_PATH = Paths.get("/etc", "ssl", "certs", "devwat-dal13-cruiser15-ca-bundle.pem").toString();
private static final Logger logger = Logger.getLogger(TrainerClient.class.getName());
public TrainerClient(URL serviceUrl) {
File certFile = new File(CERT_FILE_PATH);
try {
logger.info("Initializing channel using SSL...");
this.channel = NettyChannelBuilder.forAddress(serviceUrl.getHost(), serviceUrl.getPort())
//.overrideAuthority(OVERRIDE_AUTHORITY)
.sslContext(getSslContext(certFile))
.build();
logger.info("Initializing new blocking stub...");
this.stub = TrainerGrpc.newBlockingStub(channel);
} catch (Exception ex) {
logger.log(Level.SEVERE, "Channel build failed: {0}", ex.toString());
System.exit(1);
}
}
public static void main(String[] args) {
TrainerClient client = null;
URL url = null;
String fullUrl = "http://localhost:8443";
try {
logger.info("Forming URL...");
url = new URL(fullUrl);
logger.info("Initializing client...");
client = new TrainerClient(url);
// Client Function Calls
TrainerOuterClass.GetAllRequest request = TrainerOuterClass.GetAllRequest.newBuilder().setUserId("").build();
TrainerOuterClass.GetAllResponse response = client.getAllTrainingsJobs(request);
} catch (Exception ex) {
if (ex instanceof MalformedURLException) {
logger.log(Level.SEVERE, "URL is malformed.");
} else {
logger.log(Level.SEVERE, "Exception has occurred: {0}", ex.getStackTrace());
ex.printStackTrace();
}
} finally {
if (client != null) {
try {
logger.info("Shutting down client...");
client.shutdown();
} catch (InterruptedException ex) {
logger.log(Level.WARNING, "Channel shutdown was interrupted.");
}
}
}
}
public SslContext getSslContext(File certFile) throws SSLException {
return GrpcSslContexts.forClient()
.trustManager(certFile)
.build();
}
private void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
}
吊舱类型为ClusterIP
,并且正在通过端口localhost
端口转发到8443
。
错误
运行此命令时,得到以下堆栈跟踪:
SEVERE: Exception has occurred:
io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:210)
io.grpc.StatusRuntimeException: UNAVAILABLE
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:210)
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:191)
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:124)
at grpc.trainer.v2.TrainerGrpc$TrainerBlockingStub.getAllTrainingsJobs(TrainerGrpc.java:695)
at me.mikeygulati.grpc.TrainerClient.getAllTrainingsJobs(TrainerClient.java:70)
at me.mikeygulati.grpc.TrainerClient.main(TrainerClient.java:138)
Caused by: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem
at io.netty.handler.ssl.ReferenceCountedOpenSslContext$AbstractCertificateVerifier.verify(ReferenceCountedOpenSslContext.java:648)
at io.netty.internal.tcnative.SSL.readFromSSL(Native Method)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.readPlaintextData(ReferenceCountedOpenSslEngine.java:482)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1020)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1127)
at io.netty.handler.ssl.SslHandler$SslEngineType$1.unwrap(SslHandler.java:210)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1215)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1127)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1162)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1359)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:935)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.security.cert.CertificateException: No name matching localhost found
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:231)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:96)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:252)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:136)
at io.netty.handler.ssl.ReferenceCountedOpenSslClientContext$ExtendedTrustManagerVerifyCallback.verify(ReferenceCountedOpenSslClientContext.java:221)
at io.netty.handler.ssl.ReferenceCountedOpenSslContext$AbstractCertificateVerifier.verify(ReferenceCountedOpenSslContext.java:644)
... 26 more
Jul 24, 2018 10:52:05 AM me.mikeygulati.grpc.TrainerClient main
根据我在网上阅读的内容,发生这种情况是因为Common Name
上的CA
与主机名(在我的情况下为localhost
)不匹配。我尝试使用Override Authority
使其与Common Name
中的CA
匹配,但是出现相同的错误。
因此,我相当确定这不是正确的方法。我觉得应该为kubernetes
群集提供客户端证书和客户端密钥,但是我没有,我想问一下我做的事情是否有问题。
答案 0 :(得分:0)
想通了。
我的公司周围有一个我应该使用的客户证书(client.crt
,而不是CA
。当我使用该证书而不是具有适当的替代权限的证书时,该错误消失了。