Skip to content

Commit

Permalink
Exact to support dynamic cert (#11578)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlbumenJ authored Mar 8, 2023
1 parent 92a1051 commit 0a9b19c
Show file tree
Hide file tree
Showing 53 changed files with 2,550 additions and 82 deletions.
1 change: 1 addition & 0 deletions .licenserc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ header:
- 'CNAME'
- 'Jenkinsfile'
- '**/vendor/**'
- '**/src/test/resources/certs/**'
- 'dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocal.java'
- 'dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalMap.java'
- 'dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java'
Expand Down
3 changes: 2 additions & 1 deletion codestyle/checkstyle-suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<suppressions>
<suppress files="[\\/]src[\\/]main[\\/]java[\\/]com[\\/]alibaba[\\/]com[\\/]caucho[\\/]hessian" checks=".*"/>
<suppress files="[\\/]build[\\/]generated[\\/]source[\\/]proto" checks=".*"/>
<suppress files="[\\/]target[\\/]generated-sources[\\/]protobuf" checks=".*"/>
<suppress files="Yylex\.java" checks="AvoidEscapedUnicodeCharacters"/>
</suppressions>
</suppressions>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.apache.dubbo.common.config.ConfigurationCache;
import org.apache.dubbo.common.convert.ConverterUtil;
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.ssl.CertManager;
import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService;
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
import org.apache.dubbo.common.utils.DefaultSerializeClassChecker;
Expand All @@ -38,6 +39,7 @@ public void initializeFrameworkModel(FrameworkModel frameworkModel) {
beanFactory.registerBean(ConverterUtil.class);
beanFactory.registerBean(SerializeSecurityManager.class);
beanFactory.registerBean(DefaultSerializeClassChecker.class);
beanFactory.registerBean(CertManager.class);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,12 @@ public interface LoggerCodeConstants {

String CONFIG_DUBBO_BEAN_NOT_FOUND = "5-40";

String CONFIG_SSL_PATH_LOAD_FAILED = "5-41";

String CONFIG_SSL_CERT_GENERATE_FAILED = "5-42";

String CONFIG_SSL_CONNECT_INSECURE = "5-43";

// Transport module
String TRANSPORT_FAILED_CONNECT_PROVIDER = "6-1";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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.dubbo.common.ssl;

public enum AuthPolicy {
NONE,
SERVER_AUTH,
CLIENT_AUTH
}
67 changes: 67 additions & 0 deletions dubbo-common/src/main/java/org/apache/dubbo/common/ssl/Cert.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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.dubbo.common.ssl;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

public class Cert {
private final byte[] keyCertChain;
private final byte[] privateKey;
private final byte[] trustCert;

private final String password;

public Cert(byte[] keyCertChain, byte[] privateKey, byte[] trustCert) {
this(keyCertChain, privateKey, trustCert, null);
}

public Cert(byte[] keyCertChain, byte[] privateKey, byte[] trustCert, String password) {
this.keyCertChain = keyCertChain;
this.privateKey = privateKey;
this.trustCert = trustCert;
this.password = password;
}

public byte[] getKeyCertChain() {
return keyCertChain;
}

public InputStream getKeyCertChainInputStream() {
return keyCertChain != null ? new ByteArrayInputStream(keyCertChain) : null;
}

public byte[] getPrivateKey() {
return privateKey;
}

public InputStream getPrivateKeyInputStream() {
return privateKey != null ? new ByteArrayInputStream(privateKey) : null;
}

public byte[] getTrustCert() {
return trustCert;
}

public InputStream getTrustCertInputStream() {
return trustCert != null ? new ByteArrayInputStream(trustCert) : null;
}

public String getPassword() {
return password;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.dubbo.common.ssl;

import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.model.FrameworkModel;

import java.net.SocketAddress;
import java.util.List;

public class CertManager {
private final List<CertProvider> certProviders;

public CertManager(FrameworkModel frameworkModel) {
this.certProviders = frameworkModel.getExtensionLoader(CertProvider.class).getActivateExtensions();
}

public ProviderCert getProviderConnectionConfig(URL localAddress, SocketAddress remoteAddress) {
for (CertProvider certProvider : certProviders) {
if (certProvider.isSupport(localAddress)) {
ProviderCert cert = certProvider.getProviderConnectionConfig(localAddress);
if (cert != null) {
return cert;
}
}
}
return null;
}

public Cert getConsumerConnectionConfig(URL remoteAddress) {
for (CertProvider certProvider : certProviders) {
if (certProvider.isSupport(remoteAddress)) {
Cert cert = certProvider.getConsumerConnectionConfig(remoteAddress);
if (cert != null) {
return cert;
}
}
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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.dubbo.common.ssl;

import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;

@SPI(scope = ExtensionScope.FRAMEWORK)
public interface CertProvider {
boolean isSupport(URL address);

ProviderCert getProviderConnectionConfig(URL localAddress);

Cert getConsumerConnectionConfig(URL remoteAddress);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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.dubbo.common.ssl;

public class ProviderCert extends Cert {
private final AuthPolicy authPolicy;

public ProviderCert(byte[] keyCertChain, byte[] privateKey, byte[] trustCert, AuthPolicy authPolicy) {
super(keyCertChain, privateKey, trustCert);
this.authPolicy = authPolicy;
}

public ProviderCert(byte[] keyCertChain, byte[] privateKey, byte[] trustCert, String password, AuthPolicy authPolicy) {
super(keyCertChain, privateKey, trustCert, password);
this.authPolicy = authPolicy;
}

public AuthPolicy getAuthPolicy() {
return authPolicy;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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.dubbo.common.ssl.impl;

import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.LoggerCodeConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.ssl.AuthPolicy;
import org.apache.dubbo.common.ssl.Cert;
import org.apache.dubbo.common.ssl.CertProvider;
import org.apache.dubbo.common.ssl.ProviderCert;
import org.apache.dubbo.common.utils.IOUtils;

import java.io.IOException;
import java.util.Objects;

@Activate(order = Integer.MAX_VALUE - 10000)
public class SSLConfigCertProvider implements CertProvider {
private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(SSLConfigCertProvider.class);

@Override
public boolean isSupport(URL address) {
return address.getOrDefaultApplicationModel().getApplicationConfigManager().getSsl()
.isPresent();
}

@Override
public ProviderCert getProviderConnectionConfig(URL localAddress) {
return localAddress.getOrDefaultApplicationModel().getApplicationConfigManager().getSsl()
.filter(sslConfig -> Objects.nonNull(sslConfig.getServerKeyCertChainPath()))
.filter(sslConfig -> Objects.nonNull(sslConfig.getServerPrivateKeyPath()))
.map(sslConfig -> {
try {
return new ProviderCert(
IOUtils.toByteArray(sslConfig.getServerKeyCertChainPathStream()),
IOUtils.toByteArray(sslConfig.getServerPrivateKeyPathStream()),
sslConfig.getServerTrustCertCollectionPath() != null ? IOUtils.toByteArray(sslConfig.getServerTrustCertCollectionPathStream()) : null,
sslConfig.getServerKeyPassword(), AuthPolicy.CLIENT_AUTH);
} catch (IOException e) {
logger.warn(LoggerCodeConstants.CONFIG_SSL_PATH_LOAD_FAILED, "", "", "Failed to load ssl config.", e);
return null;
}
}).orElse(null);
}

@Override
public Cert getConsumerConnectionConfig(URL remoteAddress) {
return remoteAddress.getOrDefaultApplicationModel().getApplicationConfigManager().getSsl()
.filter(sslConfig -> Objects.nonNull(sslConfig.getClientKeyCertChainPath()))
.filter(sslConfig -> Objects.nonNull(sslConfig.getClientPrivateKeyPath()))
.map(sslConfig -> {
try {
return new Cert(
IOUtils.toByteArray(sslConfig.getClientKeyCertChainPathStream()),
IOUtils.toByteArray(sslConfig.getClientPrivateKeyPathStream()),
sslConfig.getClientTrustCertCollectionPath() != null ? IOUtils.toByteArray(sslConfig.getClientTrustCertCollectionPathStream()) : null,
sslConfig.getClientKeyPassword());
} catch (IOException e) {
logger.warn(LoggerCodeConstants.CONFIG_SSL_PATH_LOAD_FAILED, "", "", "Failed to load ssl config.", e);
return null;
}
}).orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.apache.dubbo.common.constants.CommonConstants;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
Expand Down Expand Up @@ -277,4 +278,15 @@ public static URL getURL(String resourceLocation) throws FileNotFoundException {
}
}
}

public static byte[] toByteArray(final InputStream inputStream) throws IOException {
try (final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024];
int n;
while (-1 != (n = inputStream.read(buffer))) {
byteArrayOutputStream.write(buffer, 0, n);
}
return byteArrayOutputStream.toByteArray();
}
}
}
Loading

0 comments on commit 0a9b19c

Please sign in to comment.