Showing
21 changed files
with
883 additions
and
239 deletions
... | ... | @@ -22,28 +22,11 @@ import org.eclipse.leshan.core.util.Hex; |
22 | 22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
23 | 23 | import org.springframework.stereotype.Service; |
24 | 24 | import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; |
25 | +import org.thingsboard.server.common.transport.config.ssl.SslCredentials; | |
25 | 26 | import org.thingsboard.server.transport.lwm2m.config.LwM2MSecureServerConfig; |
26 | 27 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig; |
27 | 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 | 30 | @Slf4j |
48 | 31 | @Service |
49 | 32 | @RequiredArgsConstructor |
... | ... | @@ -72,10 +55,9 @@ public class LwM2MServerSecurityInfoRepository { |
72 | 55 | |
73 | 56 | private String getPublicKey(LwM2MSecureServerConfig config) { |
74 | 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 | 62 | } catch (Exception e) { |
81 | 63 | log.trace("Failed to fetch public key from key store!", e); | ... | ... |
... | ... | @@ -619,14 +619,28 @@ transport: |
619 | 619 | bind_port: "${MQTT_SSL_BIND_PORT:8883}" |
620 | 620 | # SSL protocol: See http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext |
621 | 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 | 644 | # Skip certificate validity check for client certificates. |
631 | 645 | skip_validity_check_for_client_cert: "${MQTT_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" |
632 | 646 | # Local CoAP transport parameters |
... | ... | @@ -645,14 +659,30 @@ transport: |
645 | 659 | bind_address: "${COAP_DTLS_BIND_ADDRESS:0.0.0.0}" |
646 | 660 | # CoAP DTLS bind port |
647 | 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 | 686 | x509: |
657 | 687 | # Skip certificate validity check for client certificates. |
658 | 688 | skip_validity_check_for_client_cert: "${TB_COAP_X509_DTLS_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" |
... | ... | @@ -669,9 +699,33 @@ transport: |
669 | 699 | security: |
670 | 700 | bind_address: "${LWM2M_SECURITY_BIND_ADDRESS:0.0.0.0}" |
671 | 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 | 728 | # Only Certificate_x509: |
673 | - key_alias: "${LWM2M_SERVER_KEY_ALIAS:server}" | |
674 | - key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_ks_password}" | |
675 | 729 | skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" |
676 | 730 | bootstrap: |
677 | 731 | enable: "${LWM2M_ENABLED_BS:true}" |
... | ... | @@ -681,18 +735,51 @@ transport: |
681 | 735 | security: |
682 | 736 | bind_address: "${LWM2M_BS_SECURITY_BIND_ADDRESS:0.0.0.0}" |
683 | 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 | 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 | 783 | recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}" |
697 | 784 | recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" |
698 | 785 | timeout: "${LWM2M_TIMEOUT:120000}" | ... | ... |
... | ... | @@ -20,11 +20,16 @@ import org.eclipse.californium.elements.util.SslContextUtil; |
20 | 20 | import org.eclipse.californium.scandium.config.DtlsConnectorConfig; |
21 | 21 | import org.eclipse.californium.scandium.dtls.CertificateType; |
22 | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | +import org.springframework.beans.factory.annotation.Qualifier; | |
23 | 24 | import org.springframework.beans.factory.annotation.Value; |
24 | 25 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
26 | +import org.springframework.boot.context.properties.ConfigurationProperties; | |
27 | +import org.springframework.context.annotation.Bean; | |
25 | 28 | import org.springframework.stereotype.Component; |
26 | 29 | import org.thingsboard.server.common.data.ResourceUtils; |
27 | 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 | 33 | import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
29 | 34 | |
30 | 35 | import java.io.IOException; |
... | ... | @@ -45,17 +50,15 @@ public class TbCoapDtlsSettings { |
45 | 50 | @Value("${transport.coap.dtls.bind_port}") |
46 | 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 | 63 | @Value("${transport.coap.dtls.x509.skip_validity_check_for_client_cert:false}") |
61 | 64 | private boolean skipValidityCheckForClientCert; |
... | ... | @@ -75,8 +78,9 @@ public class TbCoapDtlsSettings { |
75 | 78 | public DtlsConnectorConfig dtlsConnectorConfig() throws UnknownHostException { |
76 | 79 | DtlsConnectorConfig.Builder configBuilder = new DtlsConnectorConfig.Builder(); |
77 | 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 | 84 | configBuilder.setServerOnly(true); |
81 | 85 | configBuilder.setClientAuthenticationRequired(false); |
82 | 86 | configBuilder.setClientAuthenticationWanted(true); |
... | ... | @@ -94,15 +98,6 @@ public class TbCoapDtlsSettings { |
94 | 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 | 101 | private InetSocketAddress getInetSocketAddress() throws UnknownHostException { |
107 | 102 | InetAddress addr = InetAddress.getByName(host); |
108 | 103 | return new InetSocketAddress(addr, port); | ... | ... |
... | ... | @@ -27,6 +27,30 @@ import java.net.URL; |
27 | 27 | @Slf4j |
28 | 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 | 54 | public static InputStream getInputStream(Object classLoaderSource, String filePath) { |
31 | 55 | return getInputStream(classLoaderSource.getClass().getClassLoader(), filePath); |
32 | 56 | } | ... | ... |
... | ... | @@ -27,6 +27,7 @@ import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer; |
27 | 27 | import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServerBuilder; |
28 | 28 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
29 | 29 | import org.springframework.stereotype.Component; |
30 | +import org.thingsboard.server.common.transport.config.ssl.SslCredentials; | |
30 | 31 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore; |
31 | 32 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore; |
32 | 33 | import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigurationAdapter; |
... | ... | @@ -114,49 +115,22 @@ public class LwM2MTransportBootstrapService { |
114 | 115 | } |
115 | 116 | |
116 | 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 | 125 | } else { |
132 | 126 | /* by default trust all */ |
133 | 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 | 15 | */ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.config; |
17 | 17 | |
18 | +import org.thingsboard.server.common.transport.config.ssl.SslCredentials; | |
19 | + | |
18 | 20 | public interface LwM2MSecureServerConfig { |
19 | 21 | |
20 | 22 | Integer getId(); |
... | ... | @@ -27,8 +29,6 @@ public interface LwM2MSecureServerConfig { |
27 | 29 | |
28 | 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 | 17 | |
18 | 18 | import lombok.Getter; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | +import org.springframework.beans.factory.annotation.Autowired; | |
21 | +import org.springframework.beans.factory.annotation.Qualifier; | |
20 | 22 | import org.springframework.beans.factory.annotation.Value; |
21 | 23 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
24 | +import org.springframework.boot.context.properties.ConfigurationProperties; | |
25 | +import org.springframework.context.annotation.Bean; | |
22 | 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 | 30 | @Slf4j |
25 | 31 | @Component |
... | ... | @@ -46,12 +52,18 @@ public class LwM2MTransportBootstrapConfig implements LwM2MSecureServerConfig { |
46 | 52 | @Value("${transport.lwm2m.bootstrap.security.bind_port:}") |
47 | 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 | 18 | import lombok.Getter; |
19 | 19 | import lombok.Setter; |
20 | 20 | import lombok.extern.slf4j.Slf4j; |
21 | +import org.springframework.beans.factory.annotation.Autowired; | |
22 | +import org.springframework.beans.factory.annotation.Qualifier; | |
21 | 23 | import org.springframework.beans.factory.annotation.Value; |
22 | 24 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
25 | +import org.springframework.boot.context.properties.ConfigurationProperties; | |
26 | +import org.springframework.context.annotation.Bean; | |
23 | 27 | import org.springframework.stereotype.Component; |
24 | 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 | 32 | import javax.annotation.PostConstruct; |
27 | 33 | import java.io.InputStream; |
... | ... | @@ -65,26 +71,6 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { |
65 | 71 | private int cleanPeriodInSec; |
66 | 72 | |
67 | 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 | 74 | @Value("${transport.lwm2m.server.id:}") |
89 | 75 | private Integer id; |
90 | 76 | |
... | ... | @@ -105,14 +91,6 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { |
105 | 91 | private Integer securePort; |
106 | 92 | |
107 | 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 | 94 | @Value("${transport.lwm2m.log_max_length:}") |
117 | 95 | private int logMaxLength; |
118 | 96 | |
... | ... | @@ -124,15 +102,32 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { |
124 | 102 | @Value("${transport.lwm2m.paging_transmission_window:10000}") |
125 | 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 | 87 | try { |
88 | 88 | /* by default trust all */ |
89 | 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 | 93 | staticCertificateVerifier = new StaticCertificateVerifier(trustedCertificates); |
98 | 94 | } catch (Exception e) { | ... | ... |
... | ... | @@ -29,6 +29,7 @@ import org.eclipse.leshan.server.model.LwM2mModelProvider; |
29 | 29 | import org.springframework.stereotype.Component; |
30 | 30 | import org.thingsboard.server.cache.ota.OtaPackageDataCache; |
31 | 31 | import org.thingsboard.server.common.data.DataConstants; |
32 | +import org.thingsboard.server.common.transport.config.ssl.SslCredentials; | |
32 | 33 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
33 | 34 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
34 | 35 | import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer; |
... | ... | @@ -141,7 +142,11 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { |
141 | 142 | } |
142 | 143 | |
143 | 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 | 150 | dtlsConfig.setAdvancedCertificateVerifier(certificateVerifier); |
146 | 151 | builder.setAuthorizer(authorizer); |
147 | 152 | dtlsConfig.setSupportedCipherSuites(RPK_OR_X509_CIPHER_SUITES); |
... | ... | @@ -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 | 161 | @Override |
177 | 162 | public String getName() { |
178 | 163 | return DataConstants.LWM2M_TRANSPORT_NAME; | ... | ... |
... | ... | @@ -18,16 +18,20 @@ package org.thingsboard.server.transport.mqtt; |
18 | 18 | import io.netty.handler.ssl.SslHandler; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | 20 | import org.springframework.beans.factory.annotation.Autowired; |
21 | +import org.springframework.beans.factory.annotation.Qualifier; | |
21 | 22 | import org.springframework.beans.factory.annotation.Value; |
22 | 23 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
24 | +import org.springframework.boot.context.properties.ConfigurationProperties; | |
25 | +import org.springframework.context.annotation.Bean; | |
23 | 26 | import org.springframework.stereotype.Component; |
24 | 27 | import org.springframework.util.StringUtils; |
25 | 28 | import org.thingsboard.server.common.data.DeviceTransportType; |
26 | -import org.thingsboard.server.common.data.ResourceUtils; | |
27 | 29 | import org.thingsboard.server.common.msg.EncryptionUtil; |
28 | 30 | import org.thingsboard.server.common.transport.TransportService; |
29 | 31 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
30 | 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 | 35 | import org.thingsboard.server.common.transport.util.SslUtil; |
32 | 36 | import org.thingsboard.server.gen.transport.TransportProtos; |
33 | 37 | |
... | ... | @@ -38,8 +42,6 @@ import javax.net.ssl.SSLEngine; |
38 | 42 | import javax.net.ssl.TrustManager; |
39 | 43 | import javax.net.ssl.TrustManagerFactory; |
40 | 44 | import javax.net.ssl.X509TrustManager; |
41 | -import java.io.InputStream; | |
42 | -import java.security.KeyStore; | |
43 | 45 | import java.security.cert.CertificateEncodingException; |
44 | 46 | import java.security.cert.CertificateException; |
45 | 47 | import java.security.cert.X509Certificate; |
... | ... | @@ -56,18 +58,20 @@ public class MqttSslHandlerProvider { |
56 | 58 | |
57 | 59 | @Value("${transport.mqtt.ssl.protocol}") |
58 | 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 | 62 | @Autowired |
69 | 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 | 75 | private SSLContext sslContext; |
72 | 76 | |
73 | 77 | public SslHandler getSslHandler() { |
... | ... | @@ -86,19 +90,9 @@ public class MqttSslHandlerProvider { |
86 | 90 | |
87 | 91 | private SSLContext createSslContext() { |
88 | 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 | 97 | KeyManager[] km = kmf.getKeyManagers(); |
104 | 98 | TrustManager x509wrapped = getX509TrustManager(tmFactory); | ... | ... |
... | ... | @@ -129,6 +129,14 @@ |
129 | 129 | <groupId>org.eclipse.leshan</groupId> |
130 | 130 | <artifactId>leshan-server-cf</artifactId> |
131 | 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 | 140 | </dependencies> |
133 | 141 | |
134 | 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 | 98 | bind_address: "${COAP_DTLS_BIND_ADDRESS:0.0.0.0}" |
99 | 99 | # CoAP DTLS bind port |
100 | 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 | 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 | 128 | dtls_session_inactivity_timeout: "${TB_COAP_X509_DTLS_SESSION_INACTIVITY_TIMEOUT:86400000}" |
113 | 129 | dtls_session_report_timeout: "${TB_COAP_X509_DTLS_SESSION_REPORT_TIMEOUT:1800000}" |
114 | 130 | sessions: | ... | ... |
... | ... | @@ -111,9 +111,33 @@ transport: |
111 | 111 | security: |
112 | 112 | bind_address: "${LWM2M_SECURITY_BIND_ADDRESS:0.0.0.0}" |
113 | 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 | 140 | # Only Certificate_x509: |
115 | - key_alias: "${LWM2M_SERVER_KEY_ALIAS:server}" | |
116 | - key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_ks_password}" | |
117 | 141 | skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" |
118 | 142 | bootstrap: |
119 | 143 | enable: "${LWM2M_ENABLED_BS:true}" |
... | ... | @@ -123,18 +147,51 @@ transport: |
123 | 147 | security: |
124 | 148 | bind_address: "${LWM2M_BS_SECURITY_BIND_ADDRESS:0.0.0.0}" |
125 | 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 | 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 | 195 | recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}" |
139 | 196 | recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" |
140 | 197 | timeout: "${LWM2M_TIMEOUT:120000}" | ... | ... |
... | ... | @@ -106,14 +106,28 @@ transport: |
106 | 106 | bind_port: "${MQTT_SSL_BIND_PORT:8883}" |
107 | 107 | # SSL protocol: See http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext |
108 | 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 | 131 | # Skip certificate validity check for client certificates. |
118 | 132 | skip_validity_check_for_client_cert: "${MQTT_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" |
119 | 133 | sessions: | ... | ... |