Commit 362ccf9f31a026a7195eb42c2774402e7767bc74

Authored by Igor Kulikov
1 parent 70fdc7d0

Unified transport SSL credentials

Showing 21 changed files with 883 additions and 239 deletions
@@ -22,28 +22,11 @@ import org.eclipse.leshan.core.util.Hex; @@ -22,28 +22,11 @@ import org.eclipse.leshan.core.util.Hex;
22 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 22 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
23 import org.springframework.stereotype.Service; 23 import org.springframework.stereotype.Service;
24 import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; 24 import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig;
  25 +import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
25 import org.thingsboard.server.transport.lwm2m.config.LwM2MSecureServerConfig; 26 import org.thingsboard.server.transport.lwm2m.config.LwM2MSecureServerConfig;
26 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig; 27 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig;
27 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 28 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
28 29
29 -import java.math.BigInteger;  
30 -import java.security.AlgorithmParameters;  
31 -import java.security.GeneralSecurityException;  
32 -import java.security.KeyFactory;  
33 -import java.security.KeyStore;  
34 -import java.security.KeyStoreException;  
35 -import java.security.NoSuchAlgorithmException;  
36 -import java.security.PrivateKey;  
37 -import java.security.PublicKey;  
38 -import java.security.UnrecoverableKeyException;  
39 -import java.security.cert.CertificateEncodingException;  
40 -import java.security.cert.X509Certificate;  
41 -import java.security.spec.ECGenParameterSpec;  
42 -import java.security.spec.ECParameterSpec;  
43 -import java.security.spec.ECPoint;  
44 -import java.security.spec.ECPublicKeySpec;  
45 -import java.security.spec.KeySpec;  
46 -  
47 @Slf4j 30 @Slf4j
48 @Service 31 @Service
49 @RequiredArgsConstructor 32 @RequiredArgsConstructor
@@ -72,10 +55,9 @@ public class LwM2MServerSecurityInfoRepository { @@ -72,10 +55,9 @@ public class LwM2MServerSecurityInfoRepository {
72 55
73 private String getPublicKey(LwM2MSecureServerConfig config) { 56 private String getPublicKey(LwM2MSecureServerConfig config) {
74 try { 57 try {
75 - KeyStore keyStore = serverConfig.getKeyStoreValue();  
76 - if (keyStore != null) {  
77 - X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(config.getCertificateAlias());  
78 - return Hex.encodeHexString(serverCertificate.getPublicKey().getEncoded()); 58 + SslCredentials sslCredentials = config.getSslCredentials();
  59 + if (sslCredentials != null) {
  60 + return Hex.encodeHexString(sslCredentials.getPublicKey().getEncoded());
79 } 61 }
80 } catch (Exception e) { 62 } catch (Exception e) {
81 log.trace("Failed to fetch public key from key store!", e); 63 log.trace("Failed to fetch public key from key store!", e);
@@ -619,14 +619,28 @@ transport: @@ -619,14 +619,28 @@ transport:
619 bind_port: "${MQTT_SSL_BIND_PORT:8883}" 619 bind_port: "${MQTT_SSL_BIND_PORT:8883}"
620 # SSL protocol: See http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext 620 # SSL protocol: See http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext
621 protocol: "${MQTT_SSL_PROTOCOL:TLSv1.2}" 621 protocol: "${MQTT_SSL_PROTOCOL:TLSv1.2}"
622 - # Path to the key store that holds the SSL certificate  
623 - key_store: "${MQTT_SSL_KEY_STORE:mqttserver.jks}"  
624 - # Password used to access the key store  
625 - key_store_password: "${MQTT_SSL_KEY_STORE_PASSWORD:server_ks_password}"  
626 - # Password used to access the key  
627 - key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}"  
628 - # Type of the key store  
629 - key_store_type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}" 622 + # Server SSL credentials
  623 + credentials:
  624 + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
  625 + type: "${MQTT_SSL_CREDENTIALS_TYPE:PEM}"
  626 + # PEM server credentials
  627 + pem:
  628 + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
  629 + cert_file: "${MQTT_SSL_PEM_CERT:mqttserver.pem}"
  630 + # Path to the server certificate private key file (optional)
  631 + key_file: "${MQTT_SSL_PEM_KEY:mqttserver_key.pem}"
  632 + # Server certificate private key password (optional)
  633 + key_password: "${MQTT_SSL_PEM_KEY_PASSWORD:server_key_password}"
  634 + # Keystore server credentials
  635 + keystore:
  636 + # Type of the key store
  637 + type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}"
  638 + # Path to the key store that holds the SSL certificate
  639 + store_file: "${MQTT_SSL_KEY_STORE:mqttserver.jks}"
  640 + # Password used to access the key store
  641 + store_password: "${MQTT_SSL_KEY_STORE_PASSWORD:server_ks_password}"
  642 + # Password used to access the key
  643 + key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}"
630 # Skip certificate validity check for client certificates. 644 # Skip certificate validity check for client certificates.
631 skip_validity_check_for_client_cert: "${MQTT_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" 645 skip_validity_check_for_client_cert: "${MQTT_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
632 # Local CoAP transport parameters 646 # Local CoAP transport parameters
@@ -645,14 +659,30 @@ transport: @@ -645,14 +659,30 @@ transport:
645 bind_address: "${COAP_DTLS_BIND_ADDRESS:0.0.0.0}" 659 bind_address: "${COAP_DTLS_BIND_ADDRESS:0.0.0.0}"
646 # CoAP DTLS bind port 660 # CoAP DTLS bind port
647 bind_port: "${COAP_DTLS_BIND_PORT:5684}" 661 bind_port: "${COAP_DTLS_BIND_PORT:5684}"
648 - # Path to the key store that holds the certificate  
649 - key_store: "${COAP_DTLS_KEY_STORE:coapserver.jks}"  
650 - # Password used to access the key store  
651 - key_store_password: "${COAP_DTLS_KEY_STORE_PASSWORD:server_ks_password}"  
652 - # Password used to access the key  
653 - key_password: "${COAP_DTLS_KEY_PASSWORD:server_key_password}"  
654 - # Key alias  
655 - key_alias: "${COAP_DTLS_KEY_ALIAS:serveralias}" 662 + # Server DTLS credentials
  663 + credentials:
  664 + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
  665 + type: "${COAP_DTLS_CREDENTIALS_TYPE:PEM}"
  666 + # PEM server credentials
  667 + pem:
  668 + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
  669 + cert_file: "${COAP_DTLS_PEM_CERT:coapserver.pem}"
  670 + # Path to the server certificate private key file (optional)
  671 + key_file: "${COAP_DTLS_PEM_KEY:coapserver_key.pem}"
  672 + # Server certificate private key password (optional)
  673 + key_password: "${COAP_DTLS_PEM_KEY_PASSWORD:server_key_password}"
  674 + # Keystore server credentials
  675 + keystore:
  676 + # Type of the key store
  677 + type: "${COAP_DTLS_KEY_STORE_TYPE:JKS}"
  678 + # Path to the key store that holds the SSL certificate
  679 + store_file: "${COAP_DTLS_KEY_STORE:coapserver.jks}"
  680 + # Password used to access the key store
  681 + store_password: "${COAP_DTLS_KEY_STORE_PASSWORD:server_ks_password}"
  682 + # Password used to access the key
  683 + key_password: "${COAP_DTLS_KEY_PASSWORD:server_key_password}"
  684 + # Key alias
  685 + key_alias: "${COAP_DTLS_KEY_ALIAS:serveralias}"
656 x509: 686 x509:
657 # Skip certificate validity check for client certificates. 687 # Skip certificate validity check for client certificates.
658 skip_validity_check_for_client_cert: "${TB_COAP_X509_DTLS_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" 688 skip_validity_check_for_client_cert: "${TB_COAP_X509_DTLS_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
@@ -669,9 +699,33 @@ transport: @@ -669,9 +699,33 @@ transport:
669 security: 699 security:
670 bind_address: "${LWM2M_SECURITY_BIND_ADDRESS:0.0.0.0}" 700 bind_address: "${LWM2M_SECURITY_BIND_ADDRESS:0.0.0.0}"
671 bind_port: "${LWM2M_SECURITY_BIND_PORT:5686}" 701 bind_port: "${LWM2M_SECURITY_BIND_PORT:5686}"
  702 + # Server X509 Certificates support
  703 + credentials:
  704 + # Whether to enable LWM2M server X509 Certificate/RPK support
  705 + enabled: "${LWM2M_SERVER_CREDENTIALS_ENABLED:false}"
  706 + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
  707 + type: "${LWM2M_SERVER_CREDENTIALS_TYPE:PEM}"
  708 + # PEM server credentials
  709 + pem:
  710 + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
  711 + cert_file: "${LWM2M_SERVER_PEM_CERT:lwm2mserver.pem}"
  712 + # Path to the server certificate private key file (optional)
  713 + key_file: "${LWM2M_SERVER_PEM_KEY:lwm2mserver_key.pem}"
  714 + # Server certificate private key password (optional)
  715 + key_password: "${LWM2M_SERVER_PEM_KEY_PASSWORD:server_key_password}"
  716 + # Keystore server credentials
  717 + keystore:
  718 + # Type of the key store
  719 + type: "${LWM2M_SERVER_KEY_STORE_TYPE:JKS}"
  720 + # Path to the key store that holds the SSL certificate
  721 + store_file: "${LWM2M_SERVER_KEY_STORE:lwm2mserver.jks}"
  722 + # Password used to access the key store
  723 + store_password: "${LWM2M_SERVER_KEY_STORE_PASSWORD:server_ks_password}"
  724 + # Password used to access the key
  725 + key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_key_password}"
  726 + # Key alias
  727 + key_alias: "${LWM2M_SERVER_KEY_ALIAS:server}"
672 # Only Certificate_x509: 728 # Only Certificate_x509:
673 - key_alias: "${LWM2M_SERVER_KEY_ALIAS:server}"  
674 - key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_ks_password}"  
675 skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" 729 skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
676 bootstrap: 730 bootstrap:
677 enable: "${LWM2M_ENABLED_BS:true}" 731 enable: "${LWM2M_ENABLED_BS:true}"
@@ -681,18 +735,51 @@ transport: @@ -681,18 +735,51 @@ transport:
681 security: 735 security:
682 bind_address: "${LWM2M_BS_SECURITY_BIND_ADDRESS:0.0.0.0}" 736 bind_address: "${LWM2M_BS_SECURITY_BIND_ADDRESS:0.0.0.0}"
683 bind_port: "${LWM2M_BS_SECURITY_BIND_PORT:5688}" 737 bind_port: "${LWM2M_BS_SECURITY_BIND_PORT:5688}"
684 - # Only Certificate_x509:  
685 - key_alias: "${LWM2M_BS_KEY_ALIAS:bootstrap}"  
686 - key_password: "${LWM2M_BS_KEY_PASSWORD:server_ks_password}" 738 + # Bootstrap server X509 Certificates support
  739 + credentials:
  740 + # Whether to enable LWM2M bootstrap server X509 Certificate/RPK support
  741 + enabled: "${LWM2M_BS_CREDENTIALS_ENABLED:false}"
  742 + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
  743 + type: "${LWM2M_BS_CREDENTIALS_TYPE:PEM}"
  744 + # PEM server credentials
  745 + pem:
  746 + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
  747 + cert_file: "${LWM2M_BS_PEM_CERT:lwm2mserver.pem}"
  748 + # Path to the server certificate private key file (optional)
  749 + key_file: "${LWM2M_BS_PEM_KEY:lwm2mserver_key.pem}"
  750 + # Server certificate private key password (optional)
  751 + key_password: "${LWM2M_BS_PEM_KEY_PASSWORD:server_key_password}"
  752 + # Keystore server credentials
  753 + keystore:
  754 + # Type of the key store
  755 + type: "${LWM2M_BS_KEY_STORE_TYPE:JKS}"
  756 + # Path to the key store that holds the SSL certificate
  757 + store_file: "${LWM2M_BS_KEY_STORE:lwm2mserver.jks}"
  758 + # Password used to access the key store
  759 + store_password: "${LWM2M_BS_KEY_STORE_PASSWORD:server_ks_password}"
  760 + # Password used to access the key
  761 + key_password: "${LWM2M_BS_KEY_PASSWORD:server_key_password}"
  762 + # Key alias
  763 + key_alias: "${LWM2M_BS_KEY_ALIAS:bootstrap}"
687 security: 764 security:
688 - # Certificate_x509:  
689 - # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format  
690 - # Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh  
691 - key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}"  
692 - # key_store_path_file: "${KEY_STORE_PATH_FILE:/common/transport/lwm2m/src/main/resources/credentials/serverKeyStore.jks"  
693 - key_store: "${LWM2M_KEYSTORE:lwm2mserver.jks}"  
694 - key_store_password: "${LWM2M_KEYSTORE_PASSWORD:server_ks_password}"  
695 - root_alias: "${LWM2M_SERVER_ROOT_CA_ALIAS:rootca}" 765 + # X509 trust certificates
  766 + trust-credentials:
  767 + # Whether to load X509 trust certificates
  768 + enabled: "${LWM2M_TRUST_CREDENTIALS_ENABLED:false}"
  769 + # Trust certificates store type (PEM - pem certificates file; KEYSTORE - java keystore)
  770 + type: "${LWM2M_TRUST_CREDENTIALS_TYPE:PEM}"
  771 + # PEM certificates
  772 + pem:
  773 + # Path to the certificates file (holds trust certificates)
  774 + cert_file: "${LWM2M_TRUST_PEM_CERT:lwm2mserver.pem}"
  775 + # Keystore with trust certificates
  776 + keystore:
  777 + # Type of the key store
  778 + type: "${LWM2M_TRUST_KEY_STORE_TYPE:JKS}"
  779 + # Path to the key store that holds the X509 certificates
  780 + store_file: "${LWM2M_TRUST_KEY_STORE:lwm2mserver.jks}"
  781 + # Password used to access the key store
  782 + store_password: "${LWM2M_TRUST_KEY_STORE_PASSWORD:server_ks_password}"
696 recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}" 783 recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}"
697 recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" 784 recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}"
698 timeout: "${LWM2M_TIMEOUT:120000}" 785 timeout: "${LWM2M_TIMEOUT:120000}"
@@ -20,11 +20,16 @@ import org.eclipse.californium.elements.util.SslContextUtil; @@ -20,11 +20,16 @@ import org.eclipse.californium.elements.util.SslContextUtil;
20 import org.eclipse.californium.scandium.config.DtlsConnectorConfig; 20 import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
21 import org.eclipse.californium.scandium.dtls.CertificateType; 21 import org.eclipse.californium.scandium.dtls.CertificateType;
22 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.beans.factory.annotation.Qualifier;
23 import org.springframework.beans.factory.annotation.Value; 24 import org.springframework.beans.factory.annotation.Value;
24 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 25 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  26 +import org.springframework.boot.context.properties.ConfigurationProperties;
  27 +import org.springframework.context.annotation.Bean;
25 import org.springframework.stereotype.Component; 28 import org.springframework.stereotype.Component;
26 import org.thingsboard.server.common.data.ResourceUtils; 29 import org.thingsboard.server.common.data.ResourceUtils;
27 import org.thingsboard.server.common.transport.TransportService; 30 import org.thingsboard.server.common.transport.TransportService;
  31 +import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
  32 +import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig;
28 import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; 33 import org.thingsboard.server.queue.discovery.TbServiceInfoProvider;
29 34
30 import java.io.IOException; 35 import java.io.IOException;
@@ -45,17 +50,15 @@ public class TbCoapDtlsSettings { @@ -45,17 +50,15 @@ public class TbCoapDtlsSettings {
45 @Value("${transport.coap.dtls.bind_port}") 50 @Value("${transport.coap.dtls.bind_port}")
46 private Integer port; 51 private Integer port;
47 52
48 - @Value("${transport.coap.dtls.key_store}")  
49 - private String keyStoreFile;  
50 -  
51 - @Value("${transport.coap.dtls.key_store_password}")  
52 - private String keyStorePassword;  
53 -  
54 - @Value("${transport.coap.dtls.key_password}")  
55 - private String keyPassword; 53 + @Bean
  54 + @ConfigurationProperties(prefix = "transport.coap.dtls.credentials")
  55 + public SslCredentialsConfig coapDtlsCredentials() {
  56 + return new SslCredentialsConfig("COAP DTLS Credentials", false);
  57 + }
56 58
57 - @Value("${transport.coap.dtls.key_alias}")  
58 - private String keyAlias; 59 + @Autowired
  60 + @Qualifier("coapDtlsCredentials")
  61 + private SslCredentialsConfig coapDtlsCredentialsConfig;
59 62
60 @Value("${transport.coap.dtls.x509.skip_validity_check_for_client_cert:false}") 63 @Value("${transport.coap.dtls.x509.skip_validity_check_for_client_cert:false}")
61 private boolean skipValidityCheckForClientCert; 64 private boolean skipValidityCheckForClientCert;
@@ -75,8 +78,9 @@ public class TbCoapDtlsSettings { @@ -75,8 +78,9 @@ public class TbCoapDtlsSettings {
75 public DtlsConnectorConfig dtlsConnectorConfig() throws UnknownHostException { 78 public DtlsConnectorConfig dtlsConnectorConfig() throws UnknownHostException {
76 DtlsConnectorConfig.Builder configBuilder = new DtlsConnectorConfig.Builder(); 79 DtlsConnectorConfig.Builder configBuilder = new DtlsConnectorConfig.Builder();
77 configBuilder.setAddress(getInetSocketAddress()); 80 configBuilder.setAddress(getInetSocketAddress());
78 - String keyStoreFilePath = ResourceUtils.getUri(this, keyStoreFile);  
79 - SslContextUtil.Credentials serverCredentials = loadServerCredentials(keyStoreFilePath); 81 + SslCredentials sslCredentials = this.coapDtlsCredentialsConfig.getCredentials();
  82 + SslContextUtil.Credentials serverCredentials =
  83 + new SslContextUtil.Credentials(sslCredentials.getPrivateKey(), null, sslCredentials.getCertificateChain());
80 configBuilder.setServerOnly(true); 84 configBuilder.setServerOnly(true);
81 configBuilder.setClientAuthenticationRequired(false); 85 configBuilder.setClientAuthenticationRequired(false);
82 configBuilder.setClientAuthenticationWanted(true); 86 configBuilder.setClientAuthenticationWanted(true);
@@ -94,15 +98,6 @@ public class TbCoapDtlsSettings { @@ -94,15 +98,6 @@ public class TbCoapDtlsSettings {
94 return configBuilder.build(); 98 return configBuilder.build();
95 } 99 }
96 100
97 - private SslContextUtil.Credentials loadServerCredentials(String keyStoreFilePath) {  
98 - try {  
99 - return SslContextUtil.loadCredentials(keyStoreFilePath, keyAlias, keyStorePassword.toCharArray(),  
100 - keyPassword.toCharArray());  
101 - } catch (GeneralSecurityException | IOException e) {  
102 - throw new RuntimeException("Failed to load serverCredentials due to: ", e);  
103 - }  
104 - }  
105 -  
106 private InetSocketAddress getInetSocketAddress() throws UnknownHostException { 101 private InetSocketAddress getInetSocketAddress() throws UnknownHostException {
107 InetAddress addr = InetAddress.getByName(host); 102 InetAddress addr = InetAddress.getByName(host);
108 return new InetSocketAddress(addr, port); 103 return new InetSocketAddress(addr, port);
@@ -27,6 +27,30 @@ import java.net.URL; @@ -27,6 +27,30 @@ import java.net.URL;
27 @Slf4j 27 @Slf4j
28 public class ResourceUtils { 28 public class ResourceUtils {
29 29
  30 + public static boolean resourceExists(Object classLoaderSource, String filePath) {
  31 + return resourceExists(classLoaderSource.getClass().getClassLoader(), filePath);
  32 + }
  33 +
  34 + public static boolean resourceExists(ClassLoader classLoader, String filePath) {
  35 + File resourceFile = new File(filePath);
  36 + if (resourceFile.exists()) {
  37 + return true;
  38 + } else {
  39 + InputStream classPathStream = classLoader.getResourceAsStream(filePath);
  40 + if (classPathStream != null) {
  41 + return true;
  42 + } else {
  43 + try {
  44 + URL url = Resources.getResource(filePath);
  45 + if (url != null) {
  46 + return true;
  47 + }
  48 + } catch (IllegalArgumentException e) {}
  49 + }
  50 + }
  51 + return false;
  52 + }
  53 +
30 public static InputStream getInputStream(Object classLoaderSource, String filePath) { 54 public static InputStream getInputStream(Object classLoaderSource, String filePath) {
31 return getInputStream(classLoaderSource.getClass().getClassLoader(), filePath); 55 return getInputStream(classLoaderSource.getClass().getClassLoader(), filePath);
32 } 56 }
@@ -27,6 +27,7 @@ import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer; @@ -27,6 +27,7 @@ import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer;
27 import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServerBuilder; 27 import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServerBuilder;
28 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 28 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
29 import org.springframework.stereotype.Component; 29 import org.springframework.stereotype.Component;
  30 +import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
30 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore; 31 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore;
31 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore; 32 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore;
32 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigurationAdapter; 33 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigurationAdapter;
@@ -114,49 +115,22 @@ public class LwM2MTransportBootstrapService { @@ -114,49 +115,22 @@ public class LwM2MTransportBootstrapService {
114 } 115 }
115 116
116 private void setServerWithCredentials(LeshanBootstrapServerBuilder builder) { 117 private void setServerWithCredentials(LeshanBootstrapServerBuilder builder) {
117 - try {  
118 - if (serverConfig.getKeyStoreValue() != null) {  
119 - KeyStore keyStoreServer = serverConfig.getKeyStoreValue();  
120 - if (this.setBuilderX509(builder)) {  
121 - X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(serverConfig.getRootCertificateAlias());  
122 - if (rootCAX509Cert != null) {  
123 - X509Certificate[] trustedCertificates = new X509Certificate[1];  
124 - trustedCertificates[0] = rootCAX509Cert;  
125 - builder.setTrustedCertificates(trustedCertificates);  
126 - } else {  
127 - /* by default trust all */  
128 - builder.setTrustedCertificates(new X509Certificate[0]);  
129 - }  
130 - } 118 + if (this.bootstrapConfig.getSslCredentials() != null) {
  119 + SslCredentials sslCredentials = this.bootstrapConfig.getSslCredentials();
  120 + builder.setPublicKey(sslCredentials.getPublicKey());
  121 + builder.setPrivateKey(sslCredentials.getPrivateKey());
  122 + builder.setCertificateChain(sslCredentials.getCertificateChain());
  123 + if (this.serverConfig.getTrustSslCredentials() != null) {
  124 + builder.setTrustedCertificates(this.serverConfig.getTrustSslCredentials().getTrustedCertificates());
131 } else { 125 } else {
132 /* by default trust all */ 126 /* by default trust all */
133 builder.setTrustedCertificates(new X509Certificate[0]); 127 builder.setTrustedCertificates(new X509Certificate[0]);
134 - log.info("Unable to load X509 files for BootStrapServer");  
135 - this.pskMode = true;  
136 } 128 }
137 - } catch (KeyStoreException ex) {  
138 - log.error("[{}] Unable to load X509 files server", ex.getMessage()); 129 + } else {
  130 + /* by default trust all */
  131 + builder.setTrustedCertificates(new X509Certificate[0]);
  132 + log.info("Unable to load X509 files for BootStrapServer");
  133 + this.pskMode = true;
139 } 134 }
140 } 135 }
141 -  
142 - private boolean setBuilderX509(LeshanBootstrapServerBuilder builder) {  
143 - try {  
144 - X509Certificate[] certificateChain = SslContextUtil.asX509Certificates(serverConfig.getKeyStoreValue().getCertificateChain(this.bootstrapConfig.getCertificateAlias()));  
145 - X509Certificate serverCertificate = certificateChain[0];  
146 - PrivateKey privateKey = (PrivateKey) serverConfig.getKeyStoreValue().getKey(this.bootstrapConfig.getCertificateAlias(), serverConfig.getCertificatePassword() == null ? null : serverConfig.getCertificatePassword().toCharArray());  
147 - PublicKey publicKey = serverCertificate.getPublicKey();  
148 - if (privateKey != null && privateKey.getEncoded().length > 0 && publicKey != null && publicKey.getEncoded().length > 0) {  
149 - builder.setPublicKey(serverCertificate.getPublicKey());  
150 - builder.setPrivateKey(privateKey);  
151 - builder.setCertificateChain(certificateChain);  
152 - return true;  
153 - } else {  
154 - return false;  
155 - }  
156 - } catch (Exception ex) {  
157 - log.error("[{}] Unable to load KeyStore files server", ex.getMessage());  
158 - return false;  
159 - }  
160 - }  
161 -  
162 } 136 }
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.transport.lwm2m.config; 16 package org.thingsboard.server.transport.lwm2m.config;
17 17
  18 +import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
  19 +
18 public interface LwM2MSecureServerConfig { 20 public interface LwM2MSecureServerConfig {
19 21
20 Integer getId(); 22 Integer getId();
@@ -27,8 +29,6 @@ public interface LwM2MSecureServerConfig { @@ -27,8 +29,6 @@ public interface LwM2MSecureServerConfig {
27 29
28 Integer getSecurePort(); 30 Integer getSecurePort();
29 31
30 - String getCertificateAlias();  
31 -  
32 - String getCertificatePassword(); 32 + SslCredentials getSslCredentials();
33 33
34 } 34 }
@@ -17,9 +17,15 @@ package org.thingsboard.server.transport.lwm2m.config; @@ -17,9 +17,15 @@ package org.thingsboard.server.transport.lwm2m.config;
17 17
18 import lombok.Getter; 18 import lombok.Getter;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
  20 +import org.springframework.beans.factory.annotation.Autowired;
  21 +import org.springframework.beans.factory.annotation.Qualifier;
20 import org.springframework.beans.factory.annotation.Value; 22 import org.springframework.beans.factory.annotation.Value;
21 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 23 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
  24 +import org.springframework.boot.context.properties.ConfigurationProperties;
  25 +import org.springframework.context.annotation.Bean;
22 import org.springframework.stereotype.Component; 26 import org.springframework.stereotype.Component;
  27 +import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
  28 +import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig;
23 29
24 @Slf4j 30 @Slf4j
25 @Component 31 @Component
@@ -46,12 +52,18 @@ public class LwM2MTransportBootstrapConfig implements LwM2MSecureServerConfig { @@ -46,12 +52,18 @@ public class LwM2MTransportBootstrapConfig implements LwM2MSecureServerConfig {
46 @Value("${transport.lwm2m.bootstrap.security.bind_port:}") 52 @Value("${transport.lwm2m.bootstrap.security.bind_port:}")
47 private Integer securePort; 53 private Integer securePort;
48 54
49 - @Getter  
50 - @Value("${transport.lwm2m.bootstrap.security.key_alias:}")  
51 - private String certificateAlias; 55 + @Bean
  56 + @ConfigurationProperties(prefix = "transport.lwm2m.bootstrap.security.credentials")
  57 + public SslCredentialsConfig lwm2mBootstrapCredentials() {
  58 + return new SslCredentialsConfig("LWM2M Bootstrap DTLS Credentials", false);
  59 + }
52 60
53 - @Getter  
54 - @Value("${transport.lwm2m.bootstrap.security.key_password:}")  
55 - private String certificatePassword; 61 + @Autowired
  62 + @Qualifier("lwm2mBootstrapCredentials")
  63 + private SslCredentialsConfig credentialsConfig;
56 64
  65 + @Override
  66 + public SslCredentials getSslCredentials() {
  67 + return this.credentialsConfig.getCredentials();
  68 + }
57 } 69 }
@@ -18,10 +18,16 @@ package org.thingsboard.server.transport.lwm2m.config; @@ -18,10 +18,16 @@ package org.thingsboard.server.transport.lwm2m.config;
18 import lombok.Getter; 18 import lombok.Getter;
19 import lombok.Setter; 19 import lombok.Setter;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.beans.factory.annotation.Qualifier;
21 import org.springframework.beans.factory.annotation.Value; 23 import org.springframework.beans.factory.annotation.Value;
22 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 24 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
  25 +import org.springframework.boot.context.properties.ConfigurationProperties;
  26 +import org.springframework.context.annotation.Bean;
23 import org.springframework.stereotype.Component; 27 import org.springframework.stereotype.Component;
24 import org.thingsboard.server.common.data.ResourceUtils; 28 import org.thingsboard.server.common.data.ResourceUtils;
  29 +import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
  30 +import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig;
25 31
26 import javax.annotation.PostConstruct; 32 import javax.annotation.PostConstruct;
27 import java.io.InputStream; 33 import java.io.InputStream;
@@ -65,26 +71,6 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @@ -65,26 +71,6 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
65 private int cleanPeriodInSec; 71 private int cleanPeriodInSec;
66 72
67 @Getter 73 @Getter
68 - @Value("${transport.lwm2m.security.key_store_type:}")  
69 - private String keyStoreType;  
70 -  
71 - @Getter  
72 - @Value("${transport.lwm2m.security.key_store:}")  
73 - private String keyStoreFilePath;  
74 -  
75 - @Getter  
76 - @Setter  
77 - private KeyStore keyStoreValue;  
78 -  
79 - @Getter  
80 - @Value("${transport.lwm2m.security.key_store_password:}")  
81 - private String keyStorePassword;  
82 -  
83 - @Getter  
84 - @Value("${transport.lwm2m.security.root_alias:}")  
85 - private String rootCertificateAlias;  
86 -  
87 - @Getter  
88 @Value("${transport.lwm2m.server.id:}") 74 @Value("${transport.lwm2m.server.id:}")
89 private Integer id; 75 private Integer id;
90 76
@@ -105,14 +91,6 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @@ -105,14 +91,6 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
105 private Integer securePort; 91 private Integer securePort;
106 92
107 @Getter 93 @Getter
108 - @Value("${transport.lwm2m.server.security.key_alias:}")  
109 - private String certificateAlias;  
110 -  
111 - @Getter  
112 - @Value("${transport.lwm2m.server.security.key_password:}")  
113 - private String certificatePassword;  
114 -  
115 - @Getter  
116 @Value("${transport.lwm2m.log_max_length:}") 94 @Value("${transport.lwm2m.log_max_length:}")
117 private int logMaxLength; 95 private int logMaxLength;
118 96
@@ -124,15 +102,32 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @@ -124,15 +102,32 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
124 @Value("${transport.lwm2m.paging_transmission_window:10000}") 102 @Value("${transport.lwm2m.paging_transmission_window:10000}")
125 private long pagingTransmissionWindow; 103 private long pagingTransmissionWindow;
126 104
127 - @PostConstruct  
128 - public void init() {  
129 - try {  
130 - InputStream keyStoreInputStream = ResourceUtils.getInputStream(this, keyStoreFilePath);  
131 - keyStoreValue = KeyStore.getInstance(keyStoreType);  
132 - keyStoreValue.load(keyStoreInputStream, keyStorePassword == null ? null : keyStorePassword.toCharArray());  
133 - } catch (Exception e) {  
134 - log.info("Unable to lookup LwM2M keystore. Reason: {}, {}", keyStoreFilePath, e.getMessage());  
135 - } 105 + @Bean
  106 + @ConfigurationProperties(prefix = "transport.lwm2m.server.security.credentials")
  107 + public SslCredentialsConfig lwm2mServerCredentials() {
  108 + return new SslCredentialsConfig("LWM2M Server DTLS Credentials", false);
  109 + }
  110 +
  111 + @Autowired
  112 + @Qualifier("lwm2mServerCredentials")
  113 + private SslCredentialsConfig credentialsConfig;
  114 +
  115 + @Bean
  116 + @ConfigurationProperties(prefix = "transport.lwm2m.security.trust-credentials")
  117 + public SslCredentialsConfig lwm2mTrustCredentials() {
  118 + return new SslCredentialsConfig("LWM2M Trust Credentials", true);
136 } 119 }
137 120
  121 + @Autowired
  122 + @Qualifier("lwm2mTrustCredentials")
  123 + private SslCredentialsConfig trustCredentialsConfig;
  124 +
  125 + @Override
  126 + public SslCredentials getSslCredentials() {
  127 + return this.credentialsConfig.getCredentials();
  128 + }
  129 +
  130 + public SslCredentials getTrustSslCredentials() {
  131 + return this.trustCredentialsConfig.getCredentials();
  132 + }
138 } 133 }
@@ -87,12 +87,8 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer @@ -87,12 +87,8 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer
87 try { 87 try {
88 /* by default trust all */ 88 /* by default trust all */
89 X509Certificate[] trustedCertificates = new X509Certificate[0]; 89 X509Certificate[] trustedCertificates = new X509Certificate[0];
90 - if (config.getKeyStoreValue() != null) {  
91 - X509Certificate rootCAX509Cert = (X509Certificate) config.getKeyStoreValue().getCertificate(config.getRootCertificateAlias());  
92 - if (rootCAX509Cert != null) {  
93 - trustedCertificates = new X509Certificate[1];  
94 - trustedCertificates[0] = rootCAX509Cert;  
95 - } 90 + if (config.getTrustSslCredentials() != null) {
  91 + trustedCertificates = config.getTrustSslCredentials().getTrustedCertificates();
96 } 92 }
97 staticCertificateVerifier = new StaticCertificateVerifier(trustedCertificates); 93 staticCertificateVerifier = new StaticCertificateVerifier(trustedCertificates);
98 } catch (Exception e) { 94 } catch (Exception e) {
@@ -29,6 +29,7 @@ import org.eclipse.leshan.server.model.LwM2mModelProvider; @@ -29,6 +29,7 @@ import org.eclipse.leshan.server.model.LwM2mModelProvider;
29 import org.springframework.stereotype.Component; 29 import org.springframework.stereotype.Component;
30 import org.thingsboard.server.cache.ota.OtaPackageDataCache; 30 import org.thingsboard.server.cache.ota.OtaPackageDataCache;
31 import org.thingsboard.server.common.data.DataConstants; 31 import org.thingsboard.server.common.data.DataConstants;
  32 +import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
32 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 33 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
33 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 34 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
34 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer; 35 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer;
@@ -141,7 +142,11 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { @@ -141,7 +142,11 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
141 } 142 }
142 143
143 private void setServerWithCredentials(LeshanServerBuilder builder, DtlsConnectorConfig.Builder dtlsConfig) { 144 private void setServerWithCredentials(LeshanServerBuilder builder, DtlsConnectorConfig.Builder dtlsConfig) {
144 - if (config.getKeyStoreValue() != null && this.setBuilderX509(builder)) { 145 + if (this.config.getSslCredentials() != null) {
  146 + SslCredentials sslCredentials = this.config.getSslCredentials();
  147 + builder.setPublicKey(sslCredentials.getPublicKey());
  148 + builder.setPrivateKey(sslCredentials.getPrivateKey());
  149 + builder.setCertificateChain(sslCredentials.getCertificateChain());
145 dtlsConfig.setAdvancedCertificateVerifier(certificateVerifier); 150 dtlsConfig.setAdvancedCertificateVerifier(certificateVerifier);
146 builder.setAuthorizer(authorizer); 151 builder.setAuthorizer(authorizer);
147 dtlsConfig.setSupportedCipherSuites(RPK_OR_X509_CIPHER_SUITES); 152 dtlsConfig.setSupportedCipherSuites(RPK_OR_X509_CIPHER_SUITES);
@@ -153,26 +158,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { @@ -153,26 +158,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
153 } 158 }
154 } 159 }
155 160
156 - private boolean setBuilderX509(LeshanServerBuilder builder) {  
157 - try {  
158 - X509Certificate[] certificateChain = SslContextUtil.asX509Certificates(config.getKeyStoreValue().getCertificateChain(config.getCertificateAlias()));  
159 - X509Certificate serverCertificate = certificateChain[0];  
160 - PrivateKey privateKey = (PrivateKey) config.getKeyStoreValue().getKey(config.getCertificateAlias(), config.getCertificatePassword() == null ? null : config.getCertificatePassword().toCharArray());  
161 - PublicKey publicKey = serverCertificate.getPublicKey();  
162 - if (privateKey != null && privateKey.getEncoded().length > 0 && publicKey != null && publicKey.getEncoded().length > 0) {  
163 - builder.setPublicKey(serverCertificate.getPublicKey());  
164 - builder.setPrivateKey(privateKey);  
165 - builder.setCertificateChain(certificateChain);  
166 - return true;  
167 - } else {  
168 - return false;  
169 - }  
170 - } catch (Exception ex) {  
171 - log.error("[{}] Unable to load KeyStore files server", ex.getMessage());  
172 - return false;  
173 - }  
174 - }  
175 -  
176 @Override 161 @Override
177 public String getName() { 162 public String getName() {
178 return DataConstants.LWM2M_TRANSPORT_NAME; 163 return DataConstants.LWM2M_TRANSPORT_NAME;
@@ -18,16 +18,20 @@ package org.thingsboard.server.transport.mqtt; @@ -18,16 +18,20 @@ package org.thingsboard.server.transport.mqtt;
18 import io.netty.handler.ssl.SslHandler; 18 import io.netty.handler.ssl.SslHandler;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
20 import org.springframework.beans.factory.annotation.Autowired; 20 import org.springframework.beans.factory.annotation.Autowired;
  21 +import org.springframework.beans.factory.annotation.Qualifier;
21 import org.springframework.beans.factory.annotation.Value; 22 import org.springframework.beans.factory.annotation.Value;
22 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 23 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  24 +import org.springframework.boot.context.properties.ConfigurationProperties;
  25 +import org.springframework.context.annotation.Bean;
23 import org.springframework.stereotype.Component; 26 import org.springframework.stereotype.Component;
24 import org.springframework.util.StringUtils; 27 import org.springframework.util.StringUtils;
25 import org.thingsboard.server.common.data.DeviceTransportType; 28 import org.thingsboard.server.common.data.DeviceTransportType;
26 -import org.thingsboard.server.common.data.ResourceUtils;  
27 import org.thingsboard.server.common.msg.EncryptionUtil; 29 import org.thingsboard.server.common.msg.EncryptionUtil;
28 import org.thingsboard.server.common.transport.TransportService; 30 import org.thingsboard.server.common.transport.TransportService;
29 import org.thingsboard.server.common.transport.TransportServiceCallback; 31 import org.thingsboard.server.common.transport.TransportServiceCallback;
30 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; 32 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
  33 +import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
  34 +import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig;
31 import org.thingsboard.server.common.transport.util.SslUtil; 35 import org.thingsboard.server.common.transport.util.SslUtil;
32 import org.thingsboard.server.gen.transport.TransportProtos; 36 import org.thingsboard.server.gen.transport.TransportProtos;
33 37
@@ -38,8 +42,6 @@ import javax.net.ssl.SSLEngine; @@ -38,8 +42,6 @@ import javax.net.ssl.SSLEngine;
38 import javax.net.ssl.TrustManager; 42 import javax.net.ssl.TrustManager;
39 import javax.net.ssl.TrustManagerFactory; 43 import javax.net.ssl.TrustManagerFactory;
40 import javax.net.ssl.X509TrustManager; 44 import javax.net.ssl.X509TrustManager;
41 -import java.io.InputStream;  
42 -import java.security.KeyStore;  
43 import java.security.cert.CertificateEncodingException; 45 import java.security.cert.CertificateEncodingException;
44 import java.security.cert.CertificateException; 46 import java.security.cert.CertificateException;
45 import java.security.cert.X509Certificate; 47 import java.security.cert.X509Certificate;
@@ -56,18 +58,20 @@ public class MqttSslHandlerProvider { @@ -56,18 +58,20 @@ public class MqttSslHandlerProvider {
56 58
57 @Value("${transport.mqtt.ssl.protocol}") 59 @Value("${transport.mqtt.ssl.protocol}")
58 private String sslProtocol; 60 private String sslProtocol;
59 - @Value("${transport.mqtt.ssl.key_store}")  
60 - private String keyStoreFile;  
61 - @Value("${transport.mqtt.ssl.key_store_password}")  
62 - private String keyStorePassword;  
63 - @Value("${transport.mqtt.ssl.key_password}")  
64 - private String keyPassword;  
65 - @Value("${transport.mqtt.ssl.key_store_type}")  
66 - private String keyStoreType;  
67 61
68 @Autowired 62 @Autowired
69 private TransportService transportService; 63 private TransportService transportService;
70 64
  65 + @Bean
  66 + @ConfigurationProperties(prefix = "transport.mqtt.ssl.credentials")
  67 + public SslCredentialsConfig mqttSslCredentials() {
  68 + return new SslCredentialsConfig("MQTT SSL Credentials", false);
  69 + }
  70 +
  71 + @Autowired
  72 + @Qualifier("mqttSslCredentials")
  73 + private SslCredentialsConfig mqttSslCredentialsConfig;
  74 +
71 private SSLContext sslContext; 75 private SSLContext sslContext;
72 76
73 public SslHandler getSslHandler() { 77 public SslHandler getSslHandler() {
@@ -86,19 +90,9 @@ public class MqttSslHandlerProvider { @@ -86,19 +90,9 @@ public class MqttSslHandlerProvider {
86 90
87 private SSLContext createSslContext() { 91 private SSLContext createSslContext() {
88 try { 92 try {
89 - TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());  
90 - KeyStore trustStore = KeyStore.getInstance(keyStoreType);  
91 - try (InputStream tsFileInputStream = ResourceUtils.getInputStream(this, keyStoreFile)) {  
92 - trustStore.load(tsFileInputStream, keyStorePassword.toCharArray());  
93 - }  
94 - tmFactory.init(trustStore);  
95 -  
96 - KeyStore ks = KeyStore.getInstance(keyStoreType);  
97 - try (InputStream ksFileInputStream = ResourceUtils.getInputStream(this, keyStoreFile)) {  
98 - ks.load(ksFileInputStream, keyStorePassword.toCharArray());  
99 - }  
100 - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
101 - kmf.init(ks, keyPassword.toCharArray()); 93 + SslCredentials sslCredentials = this.mqttSslCredentialsConfig.getCredentials();
  94 + TrustManagerFactory tmFactory = sslCredentials.createTrustManagerFactory();
  95 + KeyManagerFactory kmf = sslCredentials.createKeyManagerFactory();
102 96
103 KeyManager[] km = kmf.getKeyManagers(); 97 KeyManager[] km = kmf.getKeyManagers();
104 TrustManager x509wrapped = getX509TrustManager(tmFactory); 98 TrustManager x509wrapped = getX509TrustManager(tmFactory);
@@ -129,6 +129,14 @@ @@ -129,6 +129,14 @@
129 <groupId>org.eclipse.leshan</groupId> 129 <groupId>org.eclipse.leshan</groupId>
130 <artifactId>leshan-server-cf</artifactId> 130 <artifactId>leshan-server-cf</artifactId>
131 </dependency> 131 </dependency>
  132 + <dependency>
  133 + <groupId>org.bouncycastle</groupId>
  134 + <artifactId>bcprov-jdk15on</artifactId>
  135 + </dependency>
  136 + <dependency>
  137 + <groupId>org.bouncycastle</groupId>
  138 + <artifactId>bcpkix-jdk15on</artifactId>
  139 + </dependency>
132 </dependencies> 140 </dependencies>
133 141
134 <build> 142 <build>
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.transport.config.ssl;
  17 +
  18 +import org.thingsboard.server.common.data.StringUtils;
  19 +
  20 +import javax.net.ssl.KeyManagerFactory;
  21 +import javax.net.ssl.TrustManagerFactory;
  22 +import java.io.IOException;
  23 +import java.security.GeneralSecurityException;
  24 +import java.security.KeyStore;
  25 +import java.security.KeyStore.PrivateKeyEntry;
  26 +import java.security.KeyStoreException;
  27 +import java.security.NoSuchAlgorithmException;
  28 +import java.security.PrivateKey;
  29 +import java.security.PublicKey;
  30 +import java.security.UnrecoverableEntryException;
  31 +import java.security.UnrecoverableKeyException;
  32 +import java.security.cert.Certificate;
  33 +import java.security.cert.X509Certificate;
  34 +import java.util.Collections;
  35 +import java.util.Enumeration;
  36 +import java.util.HashSet;
  37 +import java.util.Set;
  38 +
  39 +public abstract class AbstractSslCredentials implements SslCredentials {
  40 +
  41 + private char[] keyPasswordArray;
  42 +
  43 + private KeyStore keyStore;
  44 +
  45 + private PrivateKey privateKey;
  46 +
  47 + private PublicKey publicKey;
  48 +
  49 + private X509Certificate[] chain;
  50 +
  51 + private X509Certificate[] trusts;
  52 +
  53 + @Override
  54 + public void init(boolean trustsOnly) throws IOException, GeneralSecurityException {
  55 + String keyPassword = getKeyPassword();
  56 + if (StringUtils.isEmpty(keyPassword)) {
  57 + this.keyPasswordArray = new char[0];
  58 + } else {
  59 + this.keyPasswordArray = keyPassword.toCharArray();
  60 + }
  61 + this.keyStore = this.loadKeyStore(trustsOnly, this.keyPasswordArray);
  62 + Set<X509Certificate> trustedCerts = getTrustedCerts(this.keyStore);
  63 + this.trusts = trustedCerts.toArray(new X509Certificate[0]);
  64 + if (!trustsOnly) {
  65 + PrivateKeyEntry privateKeyEntry = null;
  66 + String keyAlias = this.getKeyAlias();
  67 + if (!StringUtils.isEmpty(keyAlias)) {
  68 + privateKeyEntry = tryGetPrivateKeyEntry(this.keyStore, keyAlias, this.keyPasswordArray);
  69 + } else {
  70 + for (Enumeration<String> e = this.keyStore.aliases(); e.hasMoreElements(); ) {
  71 + String alias = e.nextElement();
  72 + privateKeyEntry = tryGetPrivateKeyEntry(this.keyStore, alias, this.keyPasswordArray);
  73 + if (privateKeyEntry != null) {
  74 + break;
  75 + }
  76 + }
  77 + }
  78 + if (privateKeyEntry == null) {
  79 + throw new IllegalArgumentException("Failed to get private key from the keystore or pem files. " +
  80 + "Please check if the private key exists in the keystore or pem files and if the provided private key password is valid.");
  81 + }
  82 + this.chain = asX509Certificates(privateKeyEntry.getCertificateChain());
  83 + this.privateKey = privateKeyEntry.getPrivateKey();
  84 + if (this.chain.length > 0) {
  85 + this.publicKey = this.chain[0].getPublicKey();
  86 + }
  87 + }
  88 + }
  89 +
  90 + @Override
  91 + public PrivateKey getPrivateKey() {
  92 + return this.privateKey;
  93 + }
  94 +
  95 + @Override
  96 + public PublicKey getPublicKey() {
  97 + return this.publicKey;
  98 + }
  99 +
  100 + @Override
  101 + public X509Certificate[] getCertificateChain() {
  102 + return this.chain;
  103 + }
  104 +
  105 + @Override
  106 + public X509Certificate[] getTrustedCertificates() {
  107 + return this.trusts;
  108 + }
  109 +
  110 + @Override
  111 + public TrustManagerFactory createTrustManagerFactory() throws NoSuchAlgorithmException, KeyStoreException {
  112 + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
  113 + tmFactory.init(this.keyStore);
  114 + return tmFactory;
  115 + }
  116 +
  117 + @Override
  118 + public KeyManagerFactory createKeyManagerFactory() throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException {
  119 + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
  120 + kmf.init(this.keyStore, this.keyPasswordArray);
  121 + return kmf;
  122 + }
  123 +
  124 + protected abstract boolean canUse();
  125 +
  126 + protected abstract String getKeyPassword();
  127 +
  128 + protected abstract String getKeyAlias();
  129 +
  130 + protected abstract KeyStore loadKeyStore(boolean isPrivateKeyRequired, char[] keyPasswordArray) throws IOException, GeneralSecurityException;
  131 +
  132 + private static X509Certificate[] asX509Certificates(Certificate[] certificates) {
  133 + if (null == certificates || 0 == certificates.length) {
  134 + throw new IllegalArgumentException("certificates missing!");
  135 + }
  136 + X509Certificate[] x509Certificates = new X509Certificate[certificates.length];
  137 + for (int index = 0; certificates.length > index; ++index) {
  138 + if (null == certificates[index]) {
  139 + throw new IllegalArgumentException("[" + index + "] is null!");
  140 + }
  141 + try {
  142 + x509Certificates[index] = (X509Certificate) certificates[index];
  143 + } catch (ClassCastException e) {
  144 + throw new IllegalArgumentException("[" + index + "] is not a x509 certificate! Instead it's a "
  145 + + certificates[index].getClass().getName());
  146 + }
  147 + }
  148 + return x509Certificates;
  149 + }
  150 +
  151 + private static PrivateKeyEntry tryGetPrivateKeyEntry(KeyStore keyStore, String alias, char[] pwd) {
  152 + PrivateKeyEntry entry = null;
  153 + try {
  154 + if (keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
  155 + try {
  156 + entry = (KeyStore.PrivateKeyEntry) keyStore
  157 + .getEntry(alias, new KeyStore.PasswordProtection(pwd));
  158 + } catch (UnsupportedOperationException e) {
  159 + PrivateKey key = (PrivateKey) keyStore.getKey(alias, pwd);
  160 + Certificate[] certs = keyStore.getCertificateChain(alias);
  161 + entry = new KeyStore.PrivateKeyEntry(key, certs);
  162 + }
  163 + }
  164 + } catch (KeyStoreException | UnrecoverableEntryException | NoSuchAlgorithmException ignored) {}
  165 + return entry;
  166 + }
  167 +
  168 + private static Set<X509Certificate> getTrustedCerts(KeyStore ks) {
  169 + Set<X509Certificate> set = new HashSet<>();
  170 + try {
  171 + for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
  172 + String alias = e.nextElement();
  173 + if (ks.isCertificateEntry(alias)) {
  174 + Certificate cert = ks.getCertificate(alias);
  175 + if (cert instanceof X509Certificate) {
  176 + set.add((X509Certificate)cert);
  177 + }
  178 + } else if (ks.isKeyEntry(alias)) {
  179 + Certificate[] certs = ks.getCertificateChain(alias);
  180 + if ((certs != null) && (certs.length > 0) &&
  181 + (certs[0] instanceof X509Certificate)) {
  182 + set.add((X509Certificate)certs[0]);
  183 + }
  184 + }
  185 + }
  186 + } catch (KeyStoreException ignored) {}
  187 + return Collections.unmodifiableSet(set);
  188 + }
  189 +
  190 +
  191 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.transport.config.ssl;
  17 +
  18 +import lombok.Data;
  19 +import lombok.EqualsAndHashCode;
  20 +import org.thingsboard.server.common.data.ResourceUtils;
  21 +import org.thingsboard.server.common.data.StringUtils;
  22 +
  23 +import java.io.IOException;
  24 +import java.io.InputStream;
  25 +import java.security.GeneralSecurityException;
  26 +import java.security.KeyStore;
  27 +
  28 +@Data
  29 +@EqualsAndHashCode(callSuper = false)
  30 +public class KeystoreSslCredentials extends AbstractSslCredentials {
  31 +
  32 + private String type;
  33 + private String storeFile;
  34 + private String storePassword;
  35 + private String keyPassword;
  36 + private String keyAlias;
  37 +
  38 + @Override
  39 + protected boolean canUse() {
  40 + return ResourceUtils.resourceExists(this, this.storeFile);
  41 + }
  42 +
  43 + @Override
  44 + protected KeyStore loadKeyStore(boolean trustsOnly, char[] keyPasswordArray) throws IOException, GeneralSecurityException {
  45 + String keyStoreType = StringUtils.isEmpty(this.type) ? KeyStore.getDefaultType() : this.type;
  46 + KeyStore keyStore = KeyStore.getInstance(keyStoreType);
  47 + try (InputStream tsFileInputStream = ResourceUtils.getInputStream(this, this.storeFile)) {
  48 + keyStore.load(tsFileInputStream, StringUtils.isEmpty(this.storePassword) ? new char[0] : this.storePassword.toCharArray());
  49 + }
  50 + return keyStore;
  51 + }
  52 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.transport.config.ssl;
  17 +
  18 +import lombok.Data;
  19 +import lombok.EqualsAndHashCode;
  20 +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
  21 +import org.bouncycastle.cert.X509CertificateHolder;
  22 +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
  23 +import org.bouncycastle.jce.provider.BouncyCastleProvider;
  24 +import org.bouncycastle.openssl.PEMDecryptorProvider;
  25 +import org.bouncycastle.openssl.PEMEncryptedKeyPair;
  26 +import org.bouncycastle.openssl.PEMKeyPair;
  27 +import org.bouncycastle.openssl.PEMParser;
  28 +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
  29 +import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
  30 +import org.thingsboard.server.common.data.ResourceUtils;
  31 +import org.thingsboard.server.common.data.StringUtils;
  32 +import java.io.IOException;
  33 +import java.io.InputStream;
  34 +import java.io.InputStreamReader;
  35 +import java.security.GeneralSecurityException;
  36 +import java.security.KeyStore;
  37 +import java.security.PrivateKey;
  38 +import java.security.Security;
  39 +import java.security.cert.CertPath;
  40 +import java.security.cert.Certificate;
  41 +import java.security.cert.CertificateFactory;
  42 +import java.security.cert.X509Certificate;
  43 +import java.util.ArrayList;
  44 +import java.util.List;
  45 +import java.util.stream.Collectors;
  46 +
  47 +@Data
  48 +@EqualsAndHashCode(callSuper = false)
  49 +public class PemSslCredentials extends AbstractSslCredentials {
  50 +
  51 + private String certFile;
  52 + private String keyFile;
  53 + private String keyPassword;
  54 + private final String keyAlias = "serveralias";
  55 +
  56 + @Override
  57 + protected boolean canUse() {
  58 + return ResourceUtils.resourceExists(this, this.certFile);
  59 + }
  60 +
  61 + @Override
  62 + protected KeyStore loadKeyStore(boolean trustsOnly, char[] keyPasswordArray) throws IOException, GeneralSecurityException {
  63 + if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
  64 + Security.addProvider(new BouncyCastleProvider());
  65 + }
  66 + List<X509Certificate> certificates = new ArrayList<>();
  67 + PrivateKey privateKey = null;
  68 + JcaX509CertificateConverter certConverter = new JcaX509CertificateConverter();
  69 + JcaPEMKeyConverter keyConverter = new JcaPEMKeyConverter();
  70 + try (InputStream inStream = ResourceUtils.getInputStream(this, this.certFile)) {
  71 + try (PEMParser pemParser = new PEMParser(new InputStreamReader(inStream))) {
  72 + Object object;
  73 + while((object = pemParser.readObject()) != null) {
  74 + if (object instanceof X509CertificateHolder) {
  75 + X509Certificate x509Cert = certConverter.getCertificate((X509CertificateHolder) object);
  76 + certificates.add(x509Cert);
  77 + } else if (object instanceof PEMEncryptedKeyPair) {
  78 + PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(keyPasswordArray);
  79 + privateKey = keyConverter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv)).getPrivate();
  80 + } else if (object instanceof PEMKeyPair) {
  81 + privateKey = keyConverter.getKeyPair((PEMKeyPair) object).getPrivate();
  82 + } else if (object instanceof PrivateKeyInfo) {
  83 + privateKey = keyConverter.getPrivateKey((PrivateKeyInfo) object);
  84 + }
  85 + }
  86 + }
  87 + }
  88 + if (privateKey == null && !StringUtils.isEmpty(this.keyFile)) {
  89 + if (ResourceUtils.resourceExists(this, this.keyFile)) {
  90 + try (InputStream inStream = ResourceUtils.getInputStream(this, this.keyFile)) {
  91 + try (PEMParser pemParser = new PEMParser(new InputStreamReader(inStream))) {
  92 + Object object;
  93 + while ((object = pemParser.readObject()) != null) {
  94 + if (object instanceof PEMEncryptedKeyPair) {
  95 + PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(keyPasswordArray);
  96 + privateKey = keyConverter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv)).getPrivate();
  97 + break;
  98 + } else if (object instanceof PEMKeyPair) {
  99 + privateKey = keyConverter.getKeyPair((PEMKeyPair) object).getPrivate();
  100 + break;
  101 + } else if (object instanceof PrivateKeyInfo) {
  102 + privateKey = keyConverter.getPrivateKey((PrivateKeyInfo) object);
  103 + }
  104 + }
  105 + }
  106 + }
  107 + }
  108 + }
  109 + if (certificates.isEmpty()) {
  110 + throw new IllegalArgumentException("No certificates found in certFile: " + this.certFile);
  111 + }
  112 + if (privateKey == null && !trustsOnly) {
  113 + throw new IllegalArgumentException("Unable to load private key neither from certFile: " + this.certFile + " nor from keyFile: " + this.keyFile);
  114 + }
  115 + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
  116 + keyStore.load(null);
  117 + List<Certificate> unique = certificates.stream().distinct().collect(Collectors.toList());
  118 + for (int i = 0; i < unique.size(); i++) {
  119 + keyStore.setCertificateEntry("root-" + i, unique.get(i));
  120 + }
  121 + if (privateKey != null) {
  122 + CertificateFactory factory = CertificateFactory.getInstance("X.509");
  123 + CertPath certPath = factory.generateCertPath(certificates);
  124 + List<? extends Certificate> path = certPath.getCertificates();
  125 + Certificate[] x509Certificates = path.toArray(new Certificate[0]);
  126 + keyStore.setKeyEntry(this.keyAlias, privateKey, keyPasswordArray, x509Certificates);
  127 + }
  128 + return keyStore;
  129 + }
  130 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.transport.config.ssl;
  17 +
  18 +import javax.net.ssl.KeyManagerFactory;
  19 +import javax.net.ssl.TrustManagerFactory;
  20 +import java.io.IOException;
  21 +import java.security.GeneralSecurityException;
  22 +import java.security.KeyStoreException;
  23 +import java.security.NoSuchAlgorithmException;
  24 +import java.security.PrivateKey;
  25 +import java.security.PublicKey;
  26 +import java.security.UnrecoverableKeyException;
  27 +import java.security.cert.X509Certificate;
  28 +
  29 +public interface SslCredentials {
  30 +
  31 + void init(boolean trustsOnly) throws IOException, GeneralSecurityException;
  32 +
  33 + PrivateKey getPrivateKey();
  34 +
  35 + PublicKey getPublicKey();
  36 +
  37 + X509Certificate[] getCertificateChain();
  38 +
  39 + X509Certificate[] getTrustedCertificates();
  40 +
  41 + TrustManagerFactory createTrustManagerFactory() throws NoSuchAlgorithmException, KeyStoreException;
  42 +
  43 + KeyManagerFactory createKeyManagerFactory() throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException;
  44 +
  45 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.transport.config.ssl;
  17 +
  18 +import lombok.Data;
  19 +import lombok.extern.slf4j.Slf4j;
  20 +
  21 +import javax.annotation.PostConstruct;
  22 +
  23 +@Slf4j
  24 +@Data
  25 +public class SslCredentialsConfig {
  26 +
  27 + private boolean enabled = true;
  28 + private SslCredentialsType type;
  29 + private PemSslCredentials pem;
  30 + private KeystoreSslCredentials keystore;
  31 +
  32 + private SslCredentials credentials;
  33 +
  34 + private final String name;
  35 + private final boolean trustsOnly;
  36 +
  37 + public SslCredentialsConfig(String name, boolean trustsOnly) {
  38 + this.name = name;
  39 + this.trustsOnly = trustsOnly;
  40 + }
  41 +
  42 + @PostConstruct
  43 + public void init() {
  44 + if (this.enabled) {
  45 + log.info("{}: Initializing SSL credentials.", name);
  46 + if (SslCredentialsType.PEM.equals(type) && pem.canUse()) {
  47 + this.credentials = this.pem;
  48 + } else if (keystore.canUse()) {
  49 + if (SslCredentialsType.PEM.equals(type)) {
  50 + log.warn("{}: Specified PEM configuration is not valid. Using SSL keystore configuration as fallback.", name);
  51 + }
  52 + this.credentials = this.keystore;
  53 + } else {
  54 + throw new RuntimeException(name + ": Invalid SSL credentials configuration. None of the PEM or KEYSTORE configurations can be used!");
  55 + }
  56 + try {
  57 + this.credentials.init(this.trustsOnly);
  58 + } catch (Exception e) {
  59 + throw new RuntimeException(name + ": Failed to init SSL credentials configuration.", e);
  60 + }
  61 + } else {
  62 + log.info("{}: Skipping initialization of disabled SSL credentials.", name);
  63 + }
  64 + }
  65 +
  66 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.transport.config.ssl;
  17 +
  18 +public enum SslCredentialsType {
  19 + PEM,
  20 + KEYSTORE
  21 +}
@@ -98,17 +98,33 @@ transport: @@ -98,17 +98,33 @@ transport:
98 bind_address: "${COAP_DTLS_BIND_ADDRESS:0.0.0.0}" 98 bind_address: "${COAP_DTLS_BIND_ADDRESS:0.0.0.0}"
99 # CoAP DTLS bind port 99 # CoAP DTLS bind port
100 bind_port: "${COAP_DTLS_BIND_PORT:5684}" 100 bind_port: "${COAP_DTLS_BIND_PORT:5684}"
101 - # Path to the key store that holds the certificate  
102 - key_store: "${COAP_DTLS_KEY_STORE:coapserver.jks}"  
103 - # Password used to access the key store  
104 - key_store_password: "${COAP_DTLS_KEY_STORE_PASSWORD:server_ks_password}"  
105 - # Password used to access the key  
106 - key_password: "${COAP_DTLS_KEY_PASSWORD:server_key_password}"  
107 - # Key alias  
108 - key_alias: "${COAP_DTLS_KEY_ALIAS:serveralias}"  
109 - # Skip certificate validity check for client certificates.  
110 - skip_validity_check_for_client_cert: "${COAP_DTLS_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" 101 + # Server DTLS credentials
  102 + credentials:
  103 + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
  104 + type: "${COAP_DTLS_CREDENTIALS_TYPE:PEM}"
  105 + # PEM server credentials
  106 + pem:
  107 + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
  108 + cert_file: "${COAP_DTLS_PEM_CERT:coapserver.pem}"
  109 + # Path to the server certificate private key file (optional)
  110 + key_file: "${COAP_DTLS_PEM_KEY:coapserver_key.pem}"
  111 + # Server certificate private key password (optional)
  112 + key_password: "${COAP_DTLS_PEM_KEY_PASSWORD:server_key_password}"
  113 + # Keystore server credentials
  114 + keystore:
  115 + # Type of the key store
  116 + type: "${COAP_DTLS_KEY_STORE_TYPE:JKS}"
  117 + # Path to the key store that holds the SSL certificate
  118 + store_file: "${COAP_DTLS_KEY_STORE:coapserver.jks}"
  119 + # Password used to access the key store
  120 + store_password: "${COAP_DTLS_KEY_STORE_PASSWORD:server_ks_password}"
  121 + # Password used to access the key
  122 + key_password: "${COAP_DTLS_KEY_PASSWORD:server_key_password}"
  123 + # Key alias
  124 + key_alias: "${COAP_DTLS_KEY_ALIAS:serveralias}"
111 x509: 125 x509:
  126 + # Skip certificate validity check for client certificates.
  127 + skip_validity_check_for_client_cert: "${TB_COAP_X509_DTLS_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
112 dtls_session_inactivity_timeout: "${TB_COAP_X509_DTLS_SESSION_INACTIVITY_TIMEOUT:86400000}" 128 dtls_session_inactivity_timeout: "${TB_COAP_X509_DTLS_SESSION_INACTIVITY_TIMEOUT:86400000}"
113 dtls_session_report_timeout: "${TB_COAP_X509_DTLS_SESSION_REPORT_TIMEOUT:1800000}" 129 dtls_session_report_timeout: "${TB_COAP_X509_DTLS_SESSION_REPORT_TIMEOUT:1800000}"
114 sessions: 130 sessions:
@@ -111,9 +111,33 @@ transport: @@ -111,9 +111,33 @@ transport:
111 security: 111 security:
112 bind_address: "${LWM2M_SECURITY_BIND_ADDRESS:0.0.0.0}" 112 bind_address: "${LWM2M_SECURITY_BIND_ADDRESS:0.0.0.0}"
113 bind_port: "${LWM2M_SECURITY_BIND_PORT:5686}" 113 bind_port: "${LWM2M_SECURITY_BIND_PORT:5686}"
  114 + # Server X509 Certificates support
  115 + credentials:
  116 + # Whether to enable LWM2M server X509 Certificate/RPK support
  117 + enabled: "${LWM2M_SERVER_CREDENTIALS_ENABLED:false}"
  118 + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
  119 + type: "${LWM2M_SERVER_CREDENTIALS_TYPE:PEM}"
  120 + # PEM server credentials
  121 + pem:
  122 + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
  123 + cert_file: "${LWM2M_SERVER_PEM_CERT:lwm2mserver.pem}"
  124 + # Path to the server certificate private key file (optional)
  125 + key_file: "${LWM2M_SERVER_PEM_KEY:lwm2mserver_key.pem}"
  126 + # Server certificate private key password (optional)
  127 + key_password: "${LWM2M_SERVER_PEM_KEY_PASSWORD:server_key_password}"
  128 + # Keystore server credentials
  129 + keystore:
  130 + # Type of the key store
  131 + type: "${LWM2M_SERVER_KEY_STORE_TYPE:JKS}"
  132 + # Path to the key store that holds the SSL certificate
  133 + store_file: "${LWM2M_SERVER_KEY_STORE:lwm2mserver.jks}"
  134 + # Password used to access the key store
  135 + store_password: "${LWM2M_SERVER_KEY_STORE_PASSWORD:server_ks_password}"
  136 + # Password used to access the key
  137 + key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_key_password}"
  138 + # Key alias
  139 + key_alias: "${LWM2M_SERVER_KEY_ALIAS:server}"
114 # Only Certificate_x509: 140 # Only Certificate_x509:
115 - key_alias: "${LWM2M_SERVER_KEY_ALIAS:server}"  
116 - key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_ks_password}"  
117 skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" 141 skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
118 bootstrap: 142 bootstrap:
119 enable: "${LWM2M_ENABLED_BS:true}" 143 enable: "${LWM2M_ENABLED_BS:true}"
@@ -123,18 +147,51 @@ transport: @@ -123,18 +147,51 @@ transport:
123 security: 147 security:
124 bind_address: "${LWM2M_BS_SECURITY_BIND_ADDRESS:0.0.0.0}" 148 bind_address: "${LWM2M_BS_SECURITY_BIND_ADDRESS:0.0.0.0}"
125 bind_port: "${LWM2M_BS_SECURITY_BIND_PORT:5688}" 149 bind_port: "${LWM2M_BS_SECURITY_BIND_PORT:5688}"
126 - # Only Certificate_x509:  
127 - key_alias: "${LWM2M_BS_KEY_ALIAS:bootstrap}"  
128 - key_password: "${LWM2M_BS_KEY_PASSWORD:server_ks_password}" 150 + # Bootstrap server X509 Certificates support
  151 + credentials:
  152 + # Whether to enable LWM2M bootstrap server X509 Certificate/RPK support
  153 + enabled: "${LWM2M_BS_CREDENTIALS_ENABLED:false}"
  154 + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
  155 + type: "${LWM2M_BS_CREDENTIALS_TYPE:PEM}"
  156 + # PEM server credentials
  157 + pem:
  158 + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
  159 + cert_file: "${LWM2M_BS_PEM_CERT:lwm2mserver.pem}"
  160 + # Path to the server certificate private key file (optional)
  161 + key_file: "${LWM2M_BS_PEM_KEY:lwm2mserver_key.pem}"
  162 + # Server certificate private key password (optional)
  163 + key_password: "${LWM2M_BS_PEM_KEY_PASSWORD:server_key_password}"
  164 + # Keystore server credentials
  165 + keystore:
  166 + # Type of the key store
  167 + type: "${LWM2M_BS_KEY_STORE_TYPE:JKS}"
  168 + # Path to the key store that holds the SSL certificate
  169 + store_file: "${LWM2M_BS_KEY_STORE:lwm2mserver.jks}"
  170 + # Password used to access the key store
  171 + store_password: "${LWM2M_BS_KEY_STORE_PASSWORD:server_ks_password}"
  172 + # Password used to access the key
  173 + key_password: "${LWM2M_BS_KEY_PASSWORD:server_key_password}"
  174 + # Key alias
  175 + key_alias: "${LWM2M_BS_KEY_ALIAS:bootstrap}"
129 security: 176 security:
130 - # Certificate_x509:  
131 - # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format  
132 - # Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh  
133 - key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}"  
134 - # key_store_path_file: "${KEY_STORE_PATH_FILE:/common/transport/lwm2m/src/main/resources/credentials/serverKeyStore.jks"  
135 - key_store: "${LWM2M_KEYSTORE:lwm2mserver.jks}"  
136 - key_store_password: "${LWM2M_KEYSTORE_PASSWORD:server_ks_password}"  
137 - root_alias: "${LWM2M_SERVER_ROOT_CA_ALIAS:rootca}" 177 + # X509 trust certificates
  178 + trust-credentials:
  179 + # Whether to load X509 trust certificates
  180 + enabled: "${LWM2M_TRUST_CREDENTIALS_ENABLED:false}"
  181 + # Trust certificates store type (PEM - pem certificates file; KEYSTORE - java keystore)
  182 + type: "${LWM2M_TRUST_CREDENTIALS_TYPE:PEM}"
  183 + # PEM certificates
  184 + pem:
  185 + # Path to the certificates file (holds trust certificates)
  186 + cert_file: "${LWM2M_TRUST_PEM_CERT:lwm2mserver.pem}"
  187 + # Keystore with trust certificates
  188 + keystore:
  189 + # Type of the key store
  190 + type: "${LWM2M_TRUST_KEY_STORE_TYPE:JKS}"
  191 + # Path to the key store that holds the X509 certificates
  192 + store_file: "${LWM2M_TRUST_KEY_STORE:lwm2mserver.jks}"
  193 + # Password used to access the key store
  194 + store_password: "${LWM2M_TRUST_KEY_STORE_PASSWORD:server_ks_password}"
138 recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}" 195 recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}"
139 recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" 196 recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}"
140 timeout: "${LWM2M_TIMEOUT:120000}" 197 timeout: "${LWM2M_TIMEOUT:120000}"
@@ -106,14 +106,28 @@ transport: @@ -106,14 +106,28 @@ transport:
106 bind_port: "${MQTT_SSL_BIND_PORT:8883}" 106 bind_port: "${MQTT_SSL_BIND_PORT:8883}"
107 # SSL protocol: See http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext 107 # SSL protocol: See http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext
108 protocol: "${MQTT_SSL_PROTOCOL:TLSv1.2}" 108 protocol: "${MQTT_SSL_PROTOCOL:TLSv1.2}"
109 - # Path to the key store that holds the SSL certificate  
110 - key_store: "${MQTT_SSL_KEY_STORE:mqttserver.jks}"  
111 - # Password used to access the key store  
112 - key_store_password: "${MQTT_SSL_KEY_STORE_PASSWORD:server_ks_password}"  
113 - # Password used to access the key  
114 - key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}"  
115 - # Type of the key store  
116 - key_store_type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}" 109 + # Server SSL credentials
  110 + credentials:
  111 + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
  112 + type: "${MQTT_SSL_CREDENTIALS_TYPE:PEM}"
  113 + # PEM server credentials
  114 + pem:
  115 + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
  116 + cert_file: "${MQTT_SSL_PEM_CERT:mqttserver.pem}"
  117 + # Path to the server certificate private key file (optional)
  118 + key_file: "${MQTT_SSL_PEM_KEY:mqttserver_key.pem}"
  119 + # Server certificate private key password (optional)
  120 + key_password: "${MQTT_SSL_PEM_KEY_PASSWORD:server_key_password}"
  121 + # Keystore server credentials
  122 + keystore:
  123 + # Type of the key store
  124 + type: "${MQTT_SSL_KEY_STORE_TYPE:JKS}"
  125 + # Path to the key store that holds the SSL certificate
  126 + store_file: "${MQTT_SSL_KEY_STORE:mqttserver.jks}"
  127 + # Password used to access the key store
  128 + store_password: "${MQTT_SSL_KEY_STORE_PASSWORD:server_ks_password}"
  129 + # Password used to access the key
  130 + key_password: "${MQTT_SSL_KEY_PASSWORD:server_key_password}"
117 # Skip certificate validity check for client certificates. 131 # Skip certificate validity check for client certificates.
118 skip_validity_check_for_client_cert: "${MQTT_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" 132 skip_validity_check_for_client_cert: "${MQTT_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
119 sessions: 133 sessions: