Skip to content

Commit

Permalink
nacos grpc connection supports TLS Encryption (#9980)
Browse files Browse the repository at this point in the history
support tls encryption on grpc transport on client and server side

---------

Co-authored-by: githubcheng2978 <yeliang.cheng@freemud.com>
  • Loading branch information
githubcheng2978 and githubcheng2978 authored Mar 15, 2023
1 parent 81dda26 commit 214e0c9
Show file tree
Hide file tree
Showing 59 changed files with 3,387 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.api.remote.response.Response;
import com.alibaba.nacos.client.env.NacosClientProperties;
import com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;
import com.alibaba.nacos.plugin.auth.api.RequestResource;
import com.alibaba.nacos.client.config.common.GroupKey;
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
Expand Down Expand Up @@ -877,13 +878,12 @@ public void executeConfigListen() {

private RpcClient ensureRpcClient(String taskId) throws NacosException {
synchronized (ClientWorker.this) {

Map<String, String> labels = getLabels();
Map<String, String> newLabels = new HashMap<>(labels);
newLabels.put("taskId", taskId);

RpcClient rpcClient = RpcClientFactory.createClient(uuid + "_config-" + taskId, getConnectionType(),
newLabels);
newLabels, RpcClientTlsConfig.properties(this.properties));
if (rpcClient.isWaitInitiated()) {
initRpcClientHandler(rpcClient);
rpcClient.setTenant(getTenant());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import com.alibaba.nacos.common.remote.client.RpcClient;
import com.alibaba.nacos.common.remote.client.RpcClientFactory;
import com.alibaba.nacos.common.remote.client.ServerListFactory;
import com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.JacksonUtils;

Expand Down Expand Up @@ -92,7 +93,7 @@ public NamingGrpcClientProxy(String namespaceId, SecurityProxy securityProxy, Se
Map<String, String> labels = new HashMap<>();
labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_SDK);
labels.put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_NAMING);
this.rpcClient = RpcClientFactory.createClient(uuid, ConnectionType.GRPC, labels);
this.rpcClient = RpcClientFactory.createClient(uuid, ConnectionType.GRPC, labels, RpcClientTlsConfig.properties(properties.asProperties()));
this.redoService = new NamingGrpcRedoService(this);
start(serverListFactory, serviceInfoHolder);
}
Expand Down
156 changes: 156 additions & 0 deletions common/src/main/java/com/alibaba/nacos/common/remote/TlsConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* Licensed 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 com.alibaba.nacos.common.remote;

/**
* gRPC config.
*
* @author githubcheng2978
*/
public class TlsConfig {
/**
* ssl provider,default OPENSSL,JDK,OPENSSL_REFCNT.
*/
private String sslProvider = "OPENSSL";

/**
* enable tls.
*/
private Boolean enableTls = false;

/**
* tls version: TLSv1.1,TLSv1.2,TLSv1.3
* if want to support multi protocol, use comma seperated. like TLSv1.1,TLSv1.2,TLSv1.3
*/
private String protocols;

/**
* cipherList, same of usage protocols.
*/
private String ciphers;

/**
* private key.
*/
private String certPrivateKey;

/**
* certificate file.
*/
private String certChainFile;

/**
* read certPrivateKey file when need password.
*/
private String certPrivateKeyPassword;

/**
* mutualAuth,if true,need provider certPrivateKey and certChainFile.
*/
private Boolean mutualAuthEnable = false;

/**
* ignore certificate valid.
*/
private Boolean trustAll = false;

/**
* collection of trust certificate file.
*/
private String trustCollectionCertFile;

public Boolean getEnableTls() {
return enableTls;
}

public void setEnableTls(Boolean enableTls) {
this.enableTls = enableTls;
}

public Boolean getMutualAuthEnable() {
return mutualAuthEnable;
}

public void setMutualAuthEnable(Boolean mutualAuthEnable) {
this.mutualAuthEnable = mutualAuthEnable;
}

public String getProtocols() {
return protocols;
}

public void setProtocols(String protocols) {
this.protocols = protocols;
}

public Boolean getTrustAll() {
return trustAll;
}

public void setTrustAll(Boolean trustAll) {
this.trustAll = trustAll;
}

public String getCiphers() {
return ciphers;
}

public void setCiphers(String ciphers) {
this.ciphers = ciphers;
}

public String getTrustCollectionCertFile() {
return trustCollectionCertFile;
}

public void setTrustCollectionCertFile(String trustCollectionCertFile) {
this.trustCollectionCertFile = trustCollectionCertFile;
}

public String getCertPrivateKeyPassword() {
return certPrivateKeyPassword;
}

public void setCertPrivateKeyPassword(String certPrivateKeyPassword) {
this.certPrivateKeyPassword = certPrivateKeyPassword;
}

public String getCertPrivateKey() {
return certPrivateKey;
}

public void setCertPrivateKey(String certPrivateKey) {
this.certPrivateKey = certPrivateKey;
}

public String getCertChainFile() {
return certChainFile;
}

public void setCertChainFile(String certChainFile) {
this.certChainFile = certChainFile;
}

public String getSslProvider() {
return sslProvider;
}

public void setSslProvider(String sslProvider) {
this.sslProvider = sslProvider;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import com.alibaba.nacos.api.remote.response.ErrorResponse;
import com.alibaba.nacos.api.remote.response.Response;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.packagescan.resource.DefaultResourceLoader;
import com.alibaba.nacos.common.packagescan.resource.ResourceLoader;
import com.alibaba.nacos.common.remote.ConnectionType;
import com.alibaba.nacos.common.remote.PayloadRegistry;
import com.alibaba.nacos.common.utils.CollectionUtils;
Expand Down Expand Up @@ -99,7 +101,9 @@ public abstract class RpcClient implements Closeable {
private static final Pattern EXCLUDE_PROTOCOL_PATTERN = Pattern.compile("(?<=\\w{1,5}://)(.*)");

protected RpcClientConfig rpcClientConfig;


protected final ResourceLoader resourceLoader = new DefaultResourceLoader();

static {
PayloadRegistry.init();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,26 +74,40 @@ public static RpcClient getClient(String clientName) {
public static RpcClient createClient(String clientName, ConnectionType connectionType, Map<String, String> labels) {
return createClient(clientName, connectionType, null, null, labels);
}


public static RpcClient createClient(String clientName, ConnectionType connectionType, Map<String, String> labels,
RpcClientTlsConfig tlsConfig) {
return createClient(clientName, connectionType, null, null, labels, tlsConfig);

}

public static RpcClient createClient(String clientName, ConnectionType connectionType, Integer
threadPoolCoreSize,
Integer threadPoolMaxSize, Map<String, String> labels) {
return createClient(clientName, connectionType, threadPoolCoreSize, threadPoolMaxSize, labels, null);
}

/**
* create a rpc client.
*
* @param clientName client name.
* @param connectionType client type.
* @param threadPoolCoreSize grpc thread pool core size
* @param threadPoolMaxSize grpc thread pool max size
* @param tlsConfig tlsconfig
* @return rpc client.
*/
public static RpcClient createClient(String clientName, ConnectionType connectionType, Integer threadPoolCoreSize,
Integer threadPoolMaxSize, Map<String, String> labels) {
Integer threadPoolMaxSize, Map<String, String> labels, RpcClientTlsConfig tlsConfig) {

if (!ConnectionType.GRPC.equals(connectionType)) {
throw new UnsupportedOperationException("unsupported connection type :" + connectionType.getType());
}

return CLIENT_MAP.computeIfAbsent(clientName, clientNameInner -> {
LOGGER.info("[RpcClientFactory] create a new rpc client of " + clientName);
try {
return new GrpcSdkClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize, labels);
return new GrpcSdkClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize, labels, tlsConfig);
} catch (Throwable throwable) {
LOGGER.error("Error to init GrpcSdkClient for client name :" + clientName, throwable);
throw throwable;
Expand All @@ -110,10 +124,15 @@ public static RpcClient createClient(String clientName, ConnectionType connectio
* @return rpc client.
*/
public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,
Map<String, String> labels) {
Map<String, String> labels) {
return createClusterClient(clientName, connectionType, null, null, labels);
}


public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,
Map<String, String> labels, RpcClientTlsConfig tlsConfig) {
return createClusterClient(clientName, connectionType, null, null, labels, tlsConfig);
}

/**
* create a rpc client.
*
Expand All @@ -124,14 +143,29 @@ public static RpcClient createClusterClient(String clientName, ConnectionType co
* @return rpc client.
*/
public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,
Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels) {
Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels) {
return createClusterClient(clientName, connectionType, threadPoolCoreSize, threadPoolMaxSize, labels, null);
}

/**
* createClusterClient.
* @param clientName client name.
* @param connectionType connectionType.
* @param threadPoolCoreSize coreSize.
* @param threadPoolMaxSize threadPoolSize.
* @param labels tables.
* @param tlsConfig tlsConfig.
* @return
*/

public static RpcClient createClusterClient(String clientName, ConnectionType connectionType, Integer threadPoolCoreSize,
Integer threadPoolMaxSize, Map<String, String> labels, RpcClientTlsConfig tlsConfig) {
if (!ConnectionType.GRPC.equals(connectionType)) {
throw new UnsupportedOperationException("unsupported connection type :" + connectionType.getType());
}

return CLIENT_MAP.computeIfAbsent(clientName,
clientNameInner -> new GrpcClusterClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize,
labels));
labels, tlsConfig));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* Licensed 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 com.alibaba.nacos.common.remote.client;

import com.alibaba.nacos.common.remote.TlsConfig;

import java.util.Properties;

/**
* gRPC config for sdk.
*
* @author githubcheng2978
*/
public class RpcClientTlsConfig extends TlsConfig {

/**
* get tls config from properties.
* @param properties Properties.
* @return tls of config.
*/
public static RpcClientTlsConfig properties(Properties properties) {
RpcClientTlsConfig tlsConfig = new RpcClientTlsConfig();
if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_ENABLE)) {
tlsConfig.setEnableTls(Boolean.parseBoolean(
properties.getProperty(RpcConstants.RPC_CLIENT_TLS_ENABLE)));
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_PROVIDER)) {
tlsConfig.setSslProvider(properties.getProperty(RpcConstants.RPC_CLIENT_TLS_PROVIDER));
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_MUTUAL_AUTH)) {
tlsConfig.setMutualAuthEnable(Boolean.parseBoolean(
properties.getProperty(RpcConstants.RPC_CLIENT_MUTUAL_AUTH)));
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_PROTOCOLS)) {
tlsConfig.setProtocols(RpcConstants.RPC_CLIENT_TLS_PROTOCOLS);
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_CIPHERS)) {
tlsConfig.setCiphers(properties.getProperty(RpcConstants.RPC_CLIENT_TLS_CIPHERS));
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_TRUST_COLLECTION_CHAIN_PATH)) {
tlsConfig.setTrustCollectionCertFile(properties.getProperty(RpcConstants.RPC_CLIENT_TLS_TRUST_COLLECTION_CHAIN_PATH));
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_CERT_CHAIN_PATH)) {
tlsConfig.setCertChainFile(properties.getProperty(RpcConstants.RPC_CLIENT_TLS_CERT_CHAIN_PATH));
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_CERT_KEY)) {
tlsConfig.setCertPrivateKey(properties.getProperty(RpcConstants.RPC_CLIENT_TLS_CERT_KEY));
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_TRUST_ALL)) {
tlsConfig.setTrustAll(Boolean.parseBoolean(properties.getProperty(RpcConstants.RPC_CLIENT_TLS_TRUST_ALL)));
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_TRUST_PWD)) {
tlsConfig.setCertPrivateKeyPassword(properties.getProperty(RpcConstants.RPC_CLIENT_TLS_TRUST_PWD));
}

if (properties.containsKey(RpcConstants.RPC_CLIENT_TLS_PROVIDER)) {
tlsConfig.setSslProvider(properties.getProperty(RpcConstants.RPC_CLIENT_TLS_PROVIDER));
}
return tlsConfig;
}

}
Loading

0 comments on commit 214e0c9

Please sign in to comment.