Support TLS of gRPC between agent and server. (#968)
* Finish the prototype of TLS of gRPC between agent and server. * Fix for rat check. * Update GRPCChannelManager.java * Update AgentModuleGRPCProvider.java * Upgrade netty version (#971) * Make sure end user can't start gRPC server with and without SSL in the same port.
This commit is contained in:
parent
0e60d40d01
commit
d8d28a0b33
|
|
@ -18,7 +18,9 @@
|
||||||
|
|
||||||
package org.apache.skywalking.apm.collector.agent.grpc.provider;
|
package org.apache.skywalking.apm.collector.agent.grpc.provider;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.apache.skywalking.apm.collector.agent.grpc.define.AgentGRPCModule;
|
import org.apache.skywalking.apm.collector.agent.grpc.define.AgentGRPCModule;
|
||||||
import org.apache.skywalking.apm.collector.agent.grpc.provider.handler.ApplicationRegisterServiceHandler;
|
import org.apache.skywalking.apm.collector.agent.grpc.provider.handler.ApplicationRegisterServiceHandler;
|
||||||
import org.apache.skywalking.apm.collector.agent.grpc.provider.handler.InstanceDiscoveryServiceHandler;
|
import org.apache.skywalking.apm.collector.agent.grpc.provider.handler.InstanceDiscoveryServiceHandler;
|
||||||
|
|
@ -41,6 +43,7 @@ import org.apache.skywalking.apm.collector.grpc.manager.service.GRPCManagerServi
|
||||||
import org.apache.skywalking.apm.collector.naming.NamingModule;
|
import org.apache.skywalking.apm.collector.naming.NamingModule;
|
||||||
import org.apache.skywalking.apm.collector.naming.service.NamingHandlerRegisterService;
|
import org.apache.skywalking.apm.collector.naming.service.NamingHandlerRegisterService;
|
||||||
import org.apache.skywalking.apm.collector.server.Server;
|
import org.apache.skywalking.apm.collector.server.Server;
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author peng-yongsheng
|
* @author peng-yongsheng
|
||||||
|
|
@ -50,22 +53,44 @@ public class AgentModuleGRPCProvider extends ModuleProvider {
|
||||||
public static final String NAME = "gRPC";
|
public static final String NAME = "gRPC";
|
||||||
private static final String HOST = "host";
|
private static final String HOST = "host";
|
||||||
private static final String PORT = "port";
|
private static final String PORT = "port";
|
||||||
|
private static final String SSL_CERT_CHAIN_FILEPATH = "ssl_cert_chain_file";
|
||||||
|
private static final String SSL_PRIVATE_KEY_FILE = "ssl_private_key_file";
|
||||||
|
|
||||||
@Override public String name() {
|
@Override
|
||||||
|
public String name() {
|
||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Class<? extends Module> module() {
|
@Override
|
||||||
|
public Class<? extends Module> module() {
|
||||||
return AgentGRPCModule.class;
|
return AgentGRPCModule.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void prepare(Properties config) throws ServiceNotProvidedException {
|
@Override
|
||||||
|
public void prepare(Properties config) throws ServiceNotProvidedException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void start(Properties config) throws ServiceNotProvidedException {
|
@Override
|
||||||
|
public void start(Properties config) throws ServiceNotProvidedException {
|
||||||
String host = config.getProperty(HOST);
|
String host = config.getProperty(HOST);
|
||||||
Integer port = (Integer)config.get(PORT);
|
Integer port = (Integer) config.get(PORT);
|
||||||
|
String sslCertChainFilePath = config.getProperty(SSL_CERT_CHAIN_FILEPATH);
|
||||||
|
String sslPrivateKeyFilePath = config.getProperty(SSL_PRIVATE_KEY_FILE);
|
||||||
|
File sslCertChainFile = null;
|
||||||
|
File sslPrivateKeyFile = null;
|
||||||
|
if (StringUtil.isNotBlank(sslCertChainFilePath)) {
|
||||||
|
sslCertChainFile = new File(sslCertChainFilePath);
|
||||||
|
if (!(sslCertChainFile.exists() && sslCertChainFile.isFile())) {
|
||||||
|
sslCertChainFile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StringUtil.isNotBlank(sslPrivateKeyFilePath)) {
|
||||||
|
sslPrivateKeyFile = new File(sslPrivateKeyFilePath);
|
||||||
|
if (!(sslPrivateKeyFile.exists() && sslPrivateKeyFile.isFile())) {
|
||||||
|
sslPrivateKeyFile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ModuleRegisterService moduleRegisterService = getManager().find(ClusterModule.NAME).getService(ModuleRegisterService.class);
|
ModuleRegisterService moduleRegisterService = getManager().find(ClusterModule.NAME).getService(ModuleRegisterService.class);
|
||||||
moduleRegisterService.register(AgentGRPCModule.NAME, this.name(), new AgentModuleGRPCRegistration(host, port));
|
moduleRegisterService.register(AgentGRPCModule.NAME, this.name(), new AgentModuleGRPCRegistration(host, port));
|
||||||
|
|
@ -78,17 +103,24 @@ public class AgentModuleGRPCProvider extends ModuleProvider {
|
||||||
namingHandlerRegisterService.register(new AgentGRPCNamingHandler(namingListener));
|
namingHandlerRegisterService.register(new AgentGRPCNamingHandler(namingListener));
|
||||||
|
|
||||||
GRPCManagerService managerService = getManager().find(GRPCManagerModule.NAME).getService(GRPCManagerService.class);
|
GRPCManagerService managerService = getManager().find(GRPCManagerModule.NAME).getService(GRPCManagerService.class);
|
||||||
Server gRPCServer = managerService.createIfAbsent(host, port);
|
Server gRPCServer;
|
||||||
|
if (sslCertChainFile != null && sslPrivateKeyFile != null) {
|
||||||
|
gRPCServer = managerService.createIfAbsent(host, port, sslCertChainFile, sslPrivateKeyFile);
|
||||||
|
} else {
|
||||||
|
gRPCServer = managerService.createIfAbsent(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
addHandlers(gRPCServer);
|
addHandlers(gRPCServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void notifyAfterCompleted() throws ServiceNotProvidedException {
|
@Override
|
||||||
|
public void notifyAfterCompleted() throws ServiceNotProvidedException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String[] requiredModules() {
|
@Override
|
||||||
return new String[] {ClusterModule.NAME, NamingModule.NAME, GRPCManagerModule.NAME, AnalysisSegmentParserModule.NAME, AnalysisMetricModule.NAME};
|
public String[] requiredModules() {
|
||||||
|
return new String[]{ClusterModule.NAME, NamingModule.NAME, GRPCManagerModule.NAME, AnalysisSegmentParserModule.NAME, AnalysisMetricModule.NAME};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addHandlers(Server gRPCServer) {
|
private void addHandlers(Server gRPCServer) {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ agent_gRPC:
|
||||||
gRPC:
|
gRPC:
|
||||||
host: localhost
|
host: localhost
|
||||||
port: 11800
|
port: 11800
|
||||||
|
#Set these two setting to open ssl
|
||||||
|
#ssl_cert_chain_file: $path
|
||||||
|
#ssl_private_key_file: $path
|
||||||
agent_jetty:
|
agent_jetty:
|
||||||
jetty:
|
jetty:
|
||||||
host: localhost
|
host: localhost
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
package org.apache.skywalking.apm.collector.server;
|
package org.apache.skywalking.apm.collector.server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author peng-yongsheng
|
* @author peng-yongsheng, wusheng
|
||||||
*/
|
*/
|
||||||
public interface Server {
|
public interface Server {
|
||||||
|
|
||||||
|
|
@ -33,4 +33,8 @@ public interface Server {
|
||||||
void start() throws ServerException;
|
void start() throws ServerException;
|
||||||
|
|
||||||
void addHandler(ServerHandler handler);
|
void addHandler(ServerHandler handler);
|
||||||
|
|
||||||
|
boolean isSSLOpen();
|
||||||
|
|
||||||
|
boolean isStatusEqual(Server target);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,23 @@
|
||||||
|
|
||||||
package org.apache.skywalking.apm.collector.server.grpc;
|
package org.apache.skywalking.apm.collector.server.grpc;
|
||||||
|
|
||||||
|
import io.grpc.netty.GrpcSslContexts;
|
||||||
import io.grpc.netty.NettyServerBuilder;
|
import io.grpc.netty.NettyServerBuilder;
|
||||||
import java.io.IOException;
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
import java.net.InetSocketAddress;
|
import io.netty.handler.ssl.SslProvider;
|
||||||
import org.apache.skywalking.apm.collector.server.Server;
|
import org.apache.skywalking.apm.collector.server.Server;
|
||||||
import org.apache.skywalking.apm.collector.server.ServerException;
|
import org.apache.skywalking.apm.collector.server.ServerException;
|
||||||
import org.apache.skywalking.apm.collector.server.ServerHandler;
|
import org.apache.skywalking.apm.collector.server.ServerHandler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author peng-yongsheng
|
* @author peng-yongsheng, wusheng
|
||||||
*/
|
*/
|
||||||
public class GRPCServer implements Server {
|
public class GRPCServer implements Server {
|
||||||
|
|
||||||
|
|
@ -39,28 +45,57 @@ public class GRPCServer implements Server {
|
||||||
private final int port;
|
private final int port;
|
||||||
private io.grpc.Server server;
|
private io.grpc.Server server;
|
||||||
private NettyServerBuilder nettyServerBuilder;
|
private NettyServerBuilder nettyServerBuilder;
|
||||||
|
private SslContextBuilder sslContextBuilder;
|
||||||
|
private File certChainFile;
|
||||||
|
private File privateKeyFile;
|
||||||
|
|
||||||
public GRPCServer(String host, int port) {
|
public GRPCServer(String host, int port) {
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String hostPort() {
|
/**
|
||||||
|
* Require for `server.crt` and `server.pem` for open ssl at server side.
|
||||||
|
*
|
||||||
|
* @param host
|
||||||
|
* @param port
|
||||||
|
* @param certChainFile `server.crt` file
|
||||||
|
* @param privateKeyFile `server.pem` file
|
||||||
|
*/
|
||||||
|
public GRPCServer(String host, int port, File certChainFile, File privateKeyFile) {
|
||||||
|
this.host = host;
|
||||||
|
this.port = port;
|
||||||
|
this.certChainFile = certChainFile;
|
||||||
|
this.privateKeyFile = privateKeyFile;
|
||||||
|
this.sslContextBuilder = SslContextBuilder.forServer(certChainFile,
|
||||||
|
privateKeyFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String hostPort() {
|
||||||
return host + ":" + port;
|
return host + ":" + port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String serverClassify() {
|
@Override
|
||||||
|
public String serverClassify() {
|
||||||
return "Google-RPC";
|
return "Google-RPC";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void initialize() throws ServerException {
|
@Override
|
||||||
|
public void initialize() throws ServerException {
|
||||||
InetSocketAddress address = new InetSocketAddress(host, port);
|
InetSocketAddress address = new InetSocketAddress(host, port);
|
||||||
nettyServerBuilder = NettyServerBuilder.forAddress(address);
|
nettyServerBuilder = NettyServerBuilder.forAddress(address);
|
||||||
logger.info("Server started, host {} listening on {}", host, port);
|
logger.info("Server started, host {} listening on {}", host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void start() throws ServerException {
|
@Override
|
||||||
|
public void start() throws ServerException {
|
||||||
try {
|
try {
|
||||||
|
if (sslContextBuilder != null) {
|
||||||
|
nettyServerBuilder = nettyServerBuilder.sslContext(
|
||||||
|
GrpcSslContexts.configure(sslContextBuilder,
|
||||||
|
SslProvider.OPENSSL).build());
|
||||||
|
}
|
||||||
server = nettyServerBuilder.build();
|
server = nettyServerBuilder.build();
|
||||||
server.start();
|
server.start();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
@ -68,7 +103,24 @@ public class GRPCServer implements Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void addHandler(ServerHandler handler) {
|
@Override
|
||||||
nettyServerBuilder.addService((io.grpc.BindableService)handler);
|
public void addHandler(ServerHandler handler) {
|
||||||
|
nettyServerBuilder.addService((io.grpc.BindableService) handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSSLOpen() {
|
||||||
|
return sslContextBuilder == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatusEqual(Server target) {
|
||||||
|
if (this == target) return true;
|
||||||
|
if (target == null || getClass() != target.getClass()) return false;
|
||||||
|
GRPCServer that = (GRPCServer) target;
|
||||||
|
return port == that.port &&
|
||||||
|
Objects.equals(host, that.host) &&
|
||||||
|
Objects.equals(certChainFile, that.certChainFile) &&
|
||||||
|
Objects.equals(privateKeyFile, that.privateKeyFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
package org.apache.skywalking.apm.collector.server.jetty;
|
package org.apache.skywalking.apm.collector.server.jetty;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Objects;
|
||||||
import javax.servlet.http.HttpServlet;
|
import javax.servlet.http.HttpServlet;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
|
@ -31,7 +32,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author peng-yongsheng
|
* @author peng-yongsheng, wusheng
|
||||||
*/
|
*/
|
||||||
public class JettyServer implements Server {
|
public class JettyServer implements Server {
|
||||||
|
|
||||||
|
|
@ -73,6 +74,16 @@ public class JettyServer implements Server {
|
||||||
servletContextHandler.addServlet(servletHolder, ((JettyHandler)handler).pathSpec());
|
servletContextHandler.addServlet(servletHolder, ((JettyHandler)handler).pathSpec());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSSLOpen() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStatusEqual(Server target) {
|
||||||
|
return equals(target);
|
||||||
|
}
|
||||||
|
|
||||||
@Override public void start() throws ServerException {
|
@Override public void start() throws ServerException {
|
||||||
logger.info("start server, host: {}, port: {}", host, port);
|
logger.info("start server, host: {}, port: {}", host, port);
|
||||||
try {
|
try {
|
||||||
|
|
@ -84,4 +95,18 @@ public class JettyServer implements Server {
|
||||||
throw new JettyServerException(e.getMessage(), e);
|
throw new JettyServerException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
JettyServer that = (JettyServer) o;
|
||||||
|
return port == that.port &&
|
||||||
|
Objects.equals(host, that.host);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(host, port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,13 @@ package org.apache.skywalking.apm.collector.grpc.manager.service;
|
||||||
import org.apache.skywalking.apm.collector.core.module.Service;
|
import org.apache.skywalking.apm.collector.core.module.Service;
|
||||||
import org.apache.skywalking.apm.collector.server.Server;
|
import org.apache.skywalking.apm.collector.server.Server;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author peng-yongsheng
|
* @author peng-yongsheng, wusheng
|
||||||
*/
|
*/
|
||||||
public interface GRPCManagerService extends Service {
|
public interface GRPCManagerService extends Service {
|
||||||
Server createIfAbsent(String host, int port);
|
Server createIfAbsent(String host, int port) throws ServerCanNotBeCreatedException;
|
||||||
|
|
||||||
|
Server createIfAbsent(String host, int port, File certChainFile, File privateKeyFile) throws ServerCanNotBeCreatedException;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.skywalking.apm.collector.grpc.manager.service;
|
||||||
|
|
||||||
|
import org.apache.skywalking.apm.collector.core.module.ServiceNotProvidedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gRPC Server can't be created under certain circumstance
|
||||||
|
*
|
||||||
|
* @author wusheng
|
||||||
|
*/
|
||||||
|
public class ServerCanNotBeCreatedException extends ServiceNotProvidedException {
|
||||||
|
public ServerCanNotBeCreatedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,13 +19,15 @@
|
||||||
|
|
||||||
package org.apache.skywalking.apm.collector.grpc.manager.service;
|
package org.apache.skywalking.apm.collector.grpc.manager.service;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.skywalking.apm.collector.server.Server;
|
import org.apache.skywalking.apm.collector.server.Server;
|
||||||
import org.apache.skywalking.apm.collector.server.ServerException;
|
import org.apache.skywalking.apm.collector.server.ServerException;
|
||||||
import org.apache.skywalking.apm.collector.server.grpc.GRPCServer;
|
import org.apache.skywalking.apm.collector.server.grpc.GRPCServer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author peng-yongsheng
|
* @author peng-yongsheng
|
||||||
*/
|
*/
|
||||||
|
|
@ -39,19 +41,33 @@ public class GRPCManagerServiceImpl implements GRPCManagerService {
|
||||||
this.servers = servers;
|
this.servers = servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Server createIfAbsent(String host, int port) {
|
@Override
|
||||||
|
public Server createIfAbsent(String host, int port) throws ServerCanNotBeCreatedException {
|
||||||
|
return createOrChooseServer(host, port, new GRPCServer(host, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Server createIfAbsent(String host, int port, File certChainFile, File privateKeyFile) throws ServerCanNotBeCreatedException {
|
||||||
|
return createOrChooseServer(host, port, new GRPCServer(host, port, certChainFile, privateKeyFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Server createOrChooseServer(String host, int port, GRPCServer newServer) throws ServerCanNotBeCreatedException {
|
||||||
String id = host + String.valueOf(port);
|
String id = host + String.valueOf(port);
|
||||||
if (servers.containsKey(id)) {
|
GRPCServer existServer = servers.get(id);
|
||||||
return servers.get(id);
|
if (existServer != null) {
|
||||||
|
if (existServer.isStatusEqual(newServer)) {
|
||||||
|
return existServer;
|
||||||
|
} else {
|
||||||
|
throw new ServerCanNotBeCreatedException("Can't create server with same port but different setting. SSL setting must equal too.");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
GRPCServer server = new GRPCServer(host, port);
|
|
||||||
try {
|
try {
|
||||||
server.initialize();
|
newServer.initialize();
|
||||||
} catch (ServerException e) {
|
} catch (ServerException e) {
|
||||||
logger.error(e.getMessage(), e);
|
logger.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
servers.put(id, server);
|
servers.put(id, newServer);
|
||||||
return server;
|
return newServer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<grpc.version>1.8.0</grpc.version>
|
<grpc.version>1.10.0</grpc.version>
|
||||||
<netty.version>4.1.17.Final</netty.version>
|
<netty.version>4.1.17.Final</netty.version>
|
||||||
<compiler.version>1.6</compiler.version>
|
<compiler.version>1.6</compiler.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
@ -39,20 +39,6 @@
|
||||||
<groupId>io.grpc</groupId>
|
<groupId>io.grpc</groupId>
|
||||||
<artifactId>grpc-netty</artifactId>
|
<artifactId>grpc-netty</artifactId>
|
||||||
<version>${grpc.version}</version>
|
<version>${grpc.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty-codec-http2</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty-transport-native-epoll</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty-handler-proxy</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.grpc</groupId>
|
<groupId>io.grpc</groupId>
|
||||||
|
|
@ -66,18 +52,8 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.netty</groupId>
|
<groupId>io.netty</groupId>
|
||||||
<artifactId>netty-codec-http2</artifactId>
|
<artifactId>netty-tcnative-boringssl-static</artifactId>
|
||||||
<version>${netty.version}</version>
|
<version>2.0.7.Final</version>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty-handler-proxy</artifactId>
|
|
||||||
<version>${netty.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty-transport-native-epoll</artifactId>
|
|
||||||
<version>${netty.version}</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<jetty.version>9.4.2.v20170220</jetty.version>
|
<jetty.version>9.4.2.v20170220</jetty.version>
|
||||||
<grpc.version>1.8.0</grpc.version>
|
<grpc.version>1.10.0</grpc.version>
|
||||||
<bytebuddy.version>1.7.9</bytebuddy.version>
|
<bytebuddy.version>1.7.9</bytebuddy.version>
|
||||||
|
|
||||||
<shade.package>org.apache.skywalking.apm.dependencies</shade.package>
|
<shade.package>org.apache.skywalking.apm.dependencies</shade.package>
|
||||||
|
|
@ -219,6 +219,25 @@
|
||||||
</tasks>
|
</tasks>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>unpack</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<configuration>
|
||||||
|
<target>
|
||||||
|
<echo message="unjar" />
|
||||||
|
<unzip src="${project.build.directory}/${artifactId}-${version}.jar" dest="${project.build.directory}/unpacked/" />
|
||||||
|
<echo message="rename service providers in META-INF/services" />
|
||||||
|
<move file="${project.build.directory}/unpacked/META-INF/native/libnetty_tcnative_osx_x86_64.jnilib" tofile="${project.build.directory}/unpacked/META-INF/native/liborg_apache_skywalking_apm_dependencies_netty_tcnative_osx_x86_64.jnilib"/>
|
||||||
|
<move file="${project.build.directory}/unpacked/META-INF/native/libnetty_tcnative_linux_x86_64.so" tofile="${project.build.directory}/unpacked/META-INF/native/liborg_apache_skywalking_apm_dependencies_netty_tcnative_linux_x86_64.so"/>
|
||||||
|
<move file="${project.build.directory}/unpacked/META-INF/native/netty_tcnative_windows_x86_64.dll" tofile="${project.build.directory}/unpacked/META-INF/native/org_apache_skywalking_apm_dependencies_netty_tcnative_windows_x86_64.dll"/>
|
||||||
|
<echo message="jar back" />
|
||||||
|
<jar destfile="${project.build.directory}/${artifactId}-${version}.jar" basedir="${project.build.directory}/unpacked" />
|
||||||
|
</target>
|
||||||
|
</configuration>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,11 @@
|
||||||
package org.apache.skywalking.apm.agent.core.remote;
|
package org.apache.skywalking.apm.agent.core.remote;
|
||||||
|
|
||||||
import io.grpc.ManagedChannel;
|
import io.grpc.ManagedChannel;
|
||||||
import io.grpc.ManagedChannelBuilder;
|
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
import io.grpc.StatusRuntimeException;
|
import io.grpc.StatusRuntimeException;
|
||||||
import io.grpc.internal.DnsNameResolverProvider;
|
import io.grpc.internal.DnsNameResolverProvider;
|
||||||
import io.grpc.netty.NettyChannelBuilder;
|
import io.grpc.netty.NettyChannelBuilder;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -32,6 +32,7 @@ import java.util.Random;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.skywalking.apm.agent.core.boot.BootService;
|
import org.apache.skywalking.apm.agent.core.boot.BootService;
|
||||||
import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory;
|
import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory;
|
||||||
import org.apache.skywalking.apm.agent.core.conf.RemoteDownstreamConfig;
|
import org.apache.skywalking.apm.agent.core.conf.RemoteDownstreamConfig;
|
||||||
|
|
@ -60,12 +61,13 @@ public class GRPCChannelManager implements BootService, Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void boot() throws Throwable {
|
public void boot() throws Throwable {
|
||||||
connectCheckFuture = Executors
|
connectCheckFuture = Executors
|
||||||
.newSingleThreadScheduledExecutor(new DefaultNamedThreadFactory("GRPCChannelManager"))
|
.newSingleThreadScheduledExecutor(new DefaultNamedThreadFactory("GRPCChannelManager"))
|
||||||
.scheduleAtFixedRate(new RunnableWithExceptionProtection(this, new RunnableWithExceptionProtection.CallbackWhenException() {
|
.scheduleAtFixedRate(new RunnableWithExceptionProtection(this, new RunnableWithExceptionProtection.CallbackWhenException() {
|
||||||
@Override public void handle(Throwable t) {
|
@Override
|
||||||
logger.error("unexpected exception.", t);
|
public void handle(Throwable t) {
|
||||||
}
|
logger.error("unexpected exception.", t);
|
||||||
}), 0, Config.Collector.GRPC_CHANNEL_CHECK_INTERVAL, TimeUnit.SECONDS);
|
}
|
||||||
|
}), 0, Config.Collector.GRPC_CHANNEL_CHECK_INTERVAL, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -92,11 +94,13 @@ public class GRPCChannelManager implements BootService, Runnable {
|
||||||
int index = Math.abs(random.nextInt()) % RemoteDownstreamConfig.Collector.GRPC_SERVERS.size();
|
int index = Math.abs(random.nextInt()) % RemoteDownstreamConfig.Collector.GRPC_SERVERS.size();
|
||||||
server = RemoteDownstreamConfig.Collector.GRPC_SERVERS.get(index);
|
server = RemoteDownstreamConfig.Collector.GRPC_SERVERS.get(index);
|
||||||
String[] ipAndPort = server.split(":");
|
String[] ipAndPort = server.split(":");
|
||||||
ManagedChannelBuilder<?> channelBuilder =
|
NettyChannelBuilder channelBuilder =
|
||||||
NettyChannelBuilder.forAddress(ipAndPort[0], Integer.parseInt(ipAndPort[1]))
|
new TLSChannelBuilder(
|
||||||
.nameResolverFactory(new DnsNameResolverProvider())
|
NettyChannelBuilder.forAddress(ipAndPort[0], Integer.parseInt(ipAndPort[1]))
|
||||||
.maxInboundMessageSize(1024 * 1024 * 50)
|
.nameResolverFactory(new DnsNameResolverProvider())
|
||||||
.usePlaintext(true);
|
.maxInboundMessageSize(1024 * 1024 * 50)
|
||||||
|
.usePlaintext(true)
|
||||||
|
).buildTLS();
|
||||||
managedChannel = channelBuilder.build();
|
managedChannel = channelBuilder.build();
|
||||||
if (!managedChannel.isShutdown() && !managedChannel.isTerminated()) {
|
if (!managedChannel.isShutdown() && !managedChannel.isTerminated()) {
|
||||||
reconnect = false;
|
reconnect = false;
|
||||||
|
|
@ -146,13 +150,13 @@ public class GRPCChannelManager implements BootService, Runnable {
|
||||||
|
|
||||||
private boolean isNetworkError(Throwable throwable) {
|
private boolean isNetworkError(Throwable throwable) {
|
||||||
if (throwable instanceof StatusRuntimeException) {
|
if (throwable instanceof StatusRuntimeException) {
|
||||||
StatusRuntimeException statusRuntimeException = (StatusRuntimeException)throwable;
|
StatusRuntimeException statusRuntimeException = (StatusRuntimeException) throwable;
|
||||||
return statusEquals(statusRuntimeException.getStatus(),
|
return statusEquals(statusRuntimeException.getStatus(),
|
||||||
Status.UNAVAILABLE,
|
Status.UNAVAILABLE,
|
||||||
Status.PERMISSION_DENIED,
|
Status.PERMISSION_DENIED,
|
||||||
Status.UNAUTHENTICATED,
|
Status.UNAUTHENTICATED,
|
||||||
Status.RESOURCE_EXHAUSTED,
|
Status.RESOURCE_EXHAUSTED,
|
||||||
Status.UNKNOWN
|
Status.UNKNOWN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.skywalking.apm.agent.core.remote;
|
||||||
|
|
||||||
|
import io.grpc.netty.GrpcSslContexts;
|
||||||
|
import io.grpc.netty.NegotiationType;
|
||||||
|
import io.grpc.netty.NettyChannelBuilder;
|
||||||
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
|
import org.apache.skywalking.apm.agent.core.boot.AgentPackageNotFoundException;
|
||||||
|
import org.apache.skywalking.apm.agent.core.boot.AgentPackagePath;
|
||||||
|
import org.apache.skywalking.apm.agent.core.conf.Constants;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect the `/ca` folder in agent package, if `ca.crt` exists, start TLS (no mutual auth).
|
||||||
|
*
|
||||||
|
* @author wusheng
|
||||||
|
*/
|
||||||
|
public class TLSChannelBuilder {
|
||||||
|
private static String CA_FILE_NAME = "ca" + Constants.PATH_SEPARATOR + "ca.crt";
|
||||||
|
|
||||||
|
private NettyChannelBuilder nettyChannelBuilder;
|
||||||
|
|
||||||
|
public TLSChannelBuilder(NettyChannelBuilder nettyChannelBuilder) {
|
||||||
|
this.nettyChannelBuilder = nettyChannelBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a TLS supported channel is necessary.
|
||||||
|
*
|
||||||
|
* @return chanel builder
|
||||||
|
* @throws AgentPackageNotFoundException
|
||||||
|
* @throws SSLException
|
||||||
|
*/
|
||||||
|
NettyChannelBuilder buildTLS() throws AgentPackageNotFoundException, SSLException {
|
||||||
|
File caFile = new File(AgentPackagePath.getPath(), CA_FILE_NAME);
|
||||||
|
if (caFile.exists() && caFile.isFile()) {
|
||||||
|
SslContextBuilder builder = GrpcSslContexts.forClient();
|
||||||
|
builder.trustManager(caFile);
|
||||||
|
nettyChannelBuilder = nettyChannelBuilder.negotiationType(NegotiationType.TLS)
|
||||||
|
.sslContext(builder.build());
|
||||||
|
}
|
||||||
|
return nettyChannelBuilder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
#
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Changes these CN's to match your hosts in your environment if needed.
|
||||||
|
SERVER_CN=localhost
|
||||||
|
CLIENT_CN=localhost # Used when doing mutual TLS
|
||||||
|
|
||||||
|
echo Generate CA key:
|
||||||
|
openssl genrsa -passout pass:1111 -des3 -out ca.key 4096
|
||||||
|
echo Generate CA certificate:
|
||||||
|
# Generates ca.crt which is the trustCertCollectionFile
|
||||||
|
openssl req -passin pass:1111 -new -x509 -days 365 -key ca.key -out ca.crt -subj "/CN=${SERVER_CN}"
|
||||||
|
echo Generate server key:
|
||||||
|
openssl genrsa -passout pass:1111 -des3 -out server.key 4096
|
||||||
|
echo Generate server signing request:
|
||||||
|
openssl req -passin pass:1111 -new -key server.key -out server.csr -subj "/CN=${SERVER_CN}"
|
||||||
|
echo Self-signed server certificate:
|
||||||
|
# Generates server.crt which is the certChainFile for the server
|
||||||
|
openssl x509 -req -passin pass:1111 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
|
||||||
|
echo Remove passphrase from server key:
|
||||||
|
openssl rsa -passin pass:1111 -in server.key -out server.key
|
||||||
|
echo Generate client key
|
||||||
|
openssl genrsa -passout pass:1111 -des3 -out client.key 4096
|
||||||
|
echo Generate client signing request:
|
||||||
|
openssl req -passin pass:1111 -new -key client.key -out client.csr -subj "/CN=${CLIENT_CN}"
|
||||||
|
echo Self-signed client certificate:
|
||||||
|
# Generates client.crt which is the clientCertChainFile for the client (need for mutual TLS only)
|
||||||
|
openssl x509 -passin pass:1111 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
|
||||||
|
echo Remove passphrase from client key:
|
||||||
|
openssl rsa -passin pass:1111 -in client.key -out client.key
|
||||||
|
echo Converting the private keys to X.509:
|
||||||
|
# Generates client.pem which is the clientPrivateKeyFile for the Client (needed for mutual TLS only)
|
||||||
|
openssl pkcs8 -topk8 -nocrypt -in client.key -out client.pem
|
||||||
|
# Generates server.pem which is the privateKeyFile for the Server
|
||||||
|
openssl pkcs8 -topk8 -nocrypt -in server.key -out server.pem
|
||||||
Loading…
Reference in New Issue