From 483a69fed1981ee07e14b9b00f15f6f515828b82 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 27 Oct 2021 14:19:50 +0300 Subject: [PATCH] Use SSL credentials configuration to setup HTTPS. Enable Lwm2m credentials by default. --- .../server/ThingsboardInstallApplication.java | 1 + .../src/main/resources/thingsboard.yml | 50 +++++++---- .../server/common/data/ResourceUtils.java | 81 +++++++++++------- .../lwm2m/src/main/resources/lwm2mserver.jks | Bin 3953 -> 3849 bytes .../config/ssl/AbstractSslCredentials.java | 12 ++- .../config/ssl/KeystoreSslCredentials.java | 5 ++ .../config/ssl/PemSslCredentials.java | 15 +++- .../transport/config/ssl/SslCredentials.java | 7 ++ .../SslCredentialsWebServerCustomizer.java | 71 +++++++++++++++ .../src/main/resources/tb-coap-transport.yml | 4 +- .../src/main/resources/tb-http-transport.yml | 30 ++++++- .../src/main/resources/tb-lwm2m-transport.yml | 14 +-- 12 files changed, 225 insertions(+), 65 deletions(-) create mode 100644 common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentialsWebServerCustomizer.java diff --git a/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java b/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java index 32c995ac82..996ca23e9c 100644 --- a/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java +++ b/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java @@ -31,6 +31,7 @@ import java.util.Arrays; "org.thingsboard.server.service.install", "org.thingsboard.server.dao", "org.thingsboard.server.common.stats", + "org.thingsboard.server.common.transport.config.ssl", "org.thingsboard.server.cache"}) public class ThingsboardInstallApplication { diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index f88d5f297c..b9f9feec7b 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -23,14 +23,30 @@ server: ssl: # Enable/disable SSL support enabled: "${SSL_ENABLED:false}" - # Path to the key store that holds the SSL certificate - key-store: "${SSL_KEY_STORE:classpath:keystore/keystore.p12}" - # Password used to access the key store - key-store-password: "${SSL_KEY_STORE_PASSWORD:thingsboard}" - # Type of the key store - key-store-type: "${SSL_KEY_STORE_TYPE:PKCS12}" - # Alias that identifies the key in the key store - key-alias: "${SSL_KEY_ALIAS:tomcat}" + # Server SSL credentials + credentials: + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) + type: "${SSL_CREDENTIALS_TYPE:PEM}" + # PEM server credentials + pem: + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key) + cert_file: "${SSL_PEM_CERT:server.pem}" + # Path to the server certificate private key file (optional) + key_file: "${SSL_PEM_KEY:server_key.pem}" + # Server certificate private key password (optional) + key_password: "${SSL_PEM_KEY_PASSWORD:server_key_password}" + # Keystore server credentials + keystore: + # Type of the key store + type: "${SSL_KEY_STORE_TYPE:PKCS12}" + # Path to the key store that holds the SSL certificate + store_file: "${SSL_KEY_STORE:classpath:keystore/keystore.p12}" + # Password used to access the key store + store_password: "${SSL_KEY_STORE_PASSWORD:thingsboard}" + # Key alias + key_alias: "${SSL_KEY_ALIAS:tomcat}" + # Password used to access the key + key_password: "${SSL_KEY_PASSWORD:thingsboard}" log_controller_error_stack_trace: "${HTTP_LOG_CONTROLLER_ERROR_STACK_TRACE:false}" ws: send_timeout: "${TB_SERVER_WS_SEND_TIMEOUT:5000}" @@ -679,10 +695,10 @@ transport: store_file: "${COAP_DTLS_KEY_STORE:coapserver.jks}" # Password used to access the key store store_password: "${COAP_DTLS_KEY_STORE_PASSWORD:server_ks_password}" - # Password used to access the key - key_password: "${COAP_DTLS_KEY_PASSWORD:server_key_password}" # Key alias key_alias: "${COAP_DTLS_KEY_ALIAS:serveralias}" + # Password used to access the key + key_password: "${COAP_DTLS_KEY_PASSWORD:server_key_password}" x509: # Skip certificate validity check for client certificates. skip_validity_check_for_client_cert: "${TB_COAP_X509_DTLS_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" @@ -702,7 +718,7 @@ transport: # Server X509 Certificates support credentials: # Whether to enable LWM2M server X509 Certificate/RPK support - enabled: "${LWM2M_SERVER_CREDENTIALS_ENABLED:false}" + enabled: "${LWM2M_SERVER_CREDENTIALS_ENABLED:true}" # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) type: "${LWM2M_SERVER_CREDENTIALS_TYPE:PEM}" # PEM server credentials @@ -721,10 +737,10 @@ transport: store_file: "${LWM2M_SERVER_KEY_STORE:lwm2mserver.jks}" # Password used to access the key store store_password: "${LWM2M_SERVER_KEY_STORE_PASSWORD:server_ks_password}" - # Password used to access the key - key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_key_password}" # Key alias key_alias: "${LWM2M_SERVER_KEY_ALIAS:server}" + # Password used to access the key + key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_ks_password}" # Only Certificate_x509: skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" bootstrap: @@ -738,7 +754,7 @@ transport: # Bootstrap server X509 Certificates support credentials: # Whether to enable LWM2M bootstrap server X509 Certificate/RPK support - enabled: "${LWM2M_BS_CREDENTIALS_ENABLED:false}" + enabled: "${LWM2M_BS_CREDENTIALS_ENABLED:true}" # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) type: "${LWM2M_BS_CREDENTIALS_TYPE:PEM}" # PEM server credentials @@ -757,15 +773,15 @@ transport: store_file: "${LWM2M_BS_KEY_STORE:lwm2mserver.jks}" # Password used to access the key store store_password: "${LWM2M_BS_KEY_STORE_PASSWORD:server_ks_password}" - # Password used to access the key - key_password: "${LWM2M_BS_KEY_PASSWORD:server_key_password}" # Key alias key_alias: "${LWM2M_BS_KEY_ALIAS:bootstrap}" + # Password used to access the key + key_password: "${LWM2M_BS_KEY_PASSWORD:server_ks_password}" security: # X509 trust certificates trust-credentials: # Whether to load X509 trust certificates - enabled: "${LWM2M_TRUST_CREDENTIALS_ENABLED:false}" + enabled: "${LWM2M_TRUST_CREDENTIALS_ENABLED:true}" # Trust certificates store type (PEM - pem certificates file; KEYSTORE - java keystore) type: "${LWM2M_TRUST_CREDENTIALS_TYPE:PEM}" # PEM certificates diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ResourceUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/ResourceUtils.java index b354b98bdb..e4b7cf3c1b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ResourceUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ResourceUtils.java @@ -27,27 +27,36 @@ import java.net.URL; @Slf4j public class ResourceUtils { + public static final String CLASSPATH_URL_PREFIX = "classpath:"; + public static boolean resourceExists(Object classLoaderSource, String filePath) { return resourceExists(classLoaderSource.getClass().getClassLoader(), filePath); } public static boolean resourceExists(ClassLoader classLoader, String filePath) { - File resourceFile = new File(filePath); - if (resourceFile.exists()) { - return true; - } else { - InputStream classPathStream = classLoader.getResourceAsStream(filePath); - if (classPathStream != null) { + boolean classPathResource = false; + String path = filePath; + if (path.startsWith(CLASSPATH_URL_PREFIX)) { + path = path.substring(CLASSPATH_URL_PREFIX.length()); + classPathResource = true; + } + if (!classPathResource) { + File resourceFile = new File(path); + if (resourceFile.exists()) { return true; - } else { - try { - URL url = Resources.getResource(filePath); - if (url != null) { - return true; - } - } catch (IllegalArgumentException e) {} } } + InputStream classPathStream = classLoader.getResourceAsStream(path); + if (classPathStream != null) { + return true; + } else { + try { + URL url = Resources.getResource(path); + if (url != null) { + return true; + } + } catch (IllegalArgumentException e) {} + } return false; } @@ -56,32 +65,40 @@ public class ResourceUtils { } public static InputStream getInputStream(ClassLoader classLoader, String filePath) { + boolean classPathResource = false; + String path = filePath; + if (path.startsWith(CLASSPATH_URL_PREFIX)) { + path = path.substring(CLASSPATH_URL_PREFIX.length()); + classPathResource = true; + } try { - InputStream keyStoreInputStream; - File keyStoreFile = new File(filePath); - if (keyStoreFile.exists()) { - log.info("Reading key store from file {}", filePath); - keyStoreInputStream = new FileInputStream(keyStoreFile); + if (!classPathResource) { + File resourceFile = new File(path); + if (resourceFile.exists()) { + log.info("Reading resource data from file {}", filePath); + return new FileInputStream(resourceFile); + } + } + InputStream classPathStream = classLoader.getResourceAsStream(path); + if (classPathStream != null) { + log.info("Reading resource data from class path {}", filePath); + return classPathStream; } else { - InputStream classPathStream = classLoader.getResourceAsStream(filePath); - if (classPathStream != null) { - log.info("Reading key store from class path {}", filePath); - keyStoreInputStream = classPathStream; - } else { - URI uri = Resources.getResource(filePath).toURI(); - log.info("Reading key store from URI {}", filePath); - keyStoreInputStream = new FileInputStream(new File(uri)); + URL url = Resources.getResource(path); + if (url != null) { + URI uri = url.toURI(); + log.info("Reading resource data from URI {}", filePath); + return new FileInputStream(new File(uri)); } } - return keyStoreInputStream; } catch (Exception e) { if (e instanceof NullPointerException) { log.warn("Unable to find resource: " + filePath); } else { log.warn("Unable to find resource: " + filePath, e); } - throw new RuntimeException("Unable to find resource: " + filePath); } + throw new RuntimeException("Unable to find resource: " + filePath); } public static String getUri(Object classLoaderSource, String filePath) { @@ -90,10 +107,10 @@ public class ResourceUtils { public static String getUri(ClassLoader classLoader, String filePath) { try { - File keyStoreFile = new File(filePath); - if (keyStoreFile.exists()) { - log.info("Reading key store from file {}", filePath); - return keyStoreFile.getAbsolutePath(); + File resourceFile = new File(filePath); + if (resourceFile.exists()) { + log.info("Reading resource data from file {}", filePath); + return resourceFile.getAbsolutePath(); } else { URL url = classLoader.getResource(filePath); return url.toURI().toString(); diff --git a/common/transport/lwm2m/src/main/resources/lwm2mserver.jks b/common/transport/lwm2m/src/main/resources/lwm2mserver.jks index 9f6748f8fdab7179b895eccd71421fe1565d27db..5fab824aa1b19928fe711701cd27857472a9e739 100644 GIT binary patch delta 3653 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 X_d}DEK0Izji}dfgHE9+C0|ADhaZ(kz delta 3758 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 z path = certPath.getCertificates(); Certificate[] x509Certificates = path.toArray(new Certificate[0]); - keyStore.setKeyEntry(this.keyAlias, privateKey, keyPasswordArray, x509Certificates); + keyStore.setKeyEntry(DEFAULT_KEY_ALIAS, privateKey, keyPasswordArray, x509Certificates); } return keyStore; } + + @Override + public String getKeyAlias() { + return DEFAULT_KEY_ALIAS; + } + + @Override + protected void updateKeyAlias(String keyAlias) { + } } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentials.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentials.java index ef412815d7..c6207b877d 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentials.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentials.java @@ -19,6 +19,7 @@ import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; import java.io.IOException; import java.security.GeneralSecurityException; +import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; @@ -30,6 +31,12 @@ public interface SslCredentials { void init(boolean trustsOnly) throws IOException, GeneralSecurityException; + KeyStore getKeyStore(); + + String getKeyPassword(); + + String getKeyAlias(); + PrivateKey getPrivateKey(); PublicKey getPublicKey(); diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentialsWebServerCustomizer.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentialsWebServerCustomizer.java new file mode 100644 index 0000000000..054d4f6195 --- /dev/null +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentialsWebServerCustomizer.java @@ -0,0 +1,71 @@ +/** + * Copyright © 2016-2021 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.transport.config.ssl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.web.server.Ssl; +import org.springframework.boot.web.server.SslStoreProvider; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +import java.security.KeyStore; + +@Component +@ConditionalOnExpression("'${spring.main.web-environment:true}'=='true' && '${server.ssl.enabled:false}'=='true'") +public class SslCredentialsWebServerCustomizer implements WebServerFactoryCustomizer { + + @Bean + @ConfigurationProperties(prefix = "server.ssl.credentials") + public SslCredentialsConfig httpServerSslCredentials() { + return new SslCredentialsConfig("HTTP Server SSL Credentials", false); + } + + @Autowired + @Qualifier("httpServerSslCredentials") + private SslCredentialsConfig httpServerSslCredentialsConfig; + + private final ServerProperties serverProperties; + + public SslCredentialsWebServerCustomizer(ServerProperties serverProperties) { + this.serverProperties = serverProperties; + } + + @Override + public void customize(ConfigurableServletWebServerFactory factory) { + SslCredentials sslCredentials = this.httpServerSslCredentialsConfig.getCredentials(); + Ssl ssl = serverProperties.getSsl(); + ssl.setKeyAlias(sslCredentials.getKeyAlias()); + ssl.setKeyPassword(sslCredentials.getKeyPassword()); + factory.setSsl(ssl); + factory.setSslStoreProvider(new SslStoreProvider() { + @Override + public KeyStore getKeyStore() { + return sslCredentials.getKeyStore(); + } + + @Override + public KeyStore getTrustStore() { + return null; + } + }); + } +} diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index adaffed7de..0caf66a36e 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -118,10 +118,10 @@ transport: store_file: "${COAP_DTLS_KEY_STORE:coapserver.jks}" # Password used to access the key store store_password: "${COAP_DTLS_KEY_STORE_PASSWORD:server_ks_password}" - # Password used to access the key - key_password: "${COAP_DTLS_KEY_PASSWORD:server_key_password}" # Key alias key_alias: "${COAP_DTLS_KEY_ALIAS:serveralias}" + # Password used to access the key + key_password: "${COAP_DTLS_KEY_PASSWORD:server_key_password}" x509: # Skip certificate validity check for client certificates. skip_validity_check_for_client_cert: "${TB_COAP_X509_DTLS_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" diff --git a/transport/http/src/main/resources/tb-http-transport.yml b/transport/http/src/main/resources/tb-http-transport.yml index f35f4136e7..603698c2df 100644 --- a/transport/http/src/main/resources/tb-http-transport.yml +++ b/transport/http/src/main/resources/tb-http-transport.yml @@ -19,6 +19,34 @@ server: address: "${HTTP_BIND_ADDRESS:0.0.0.0}" # Server bind port port: "${HTTP_BIND_PORT:8081}" + # Server SSL configuration + ssl: + # Enable/disable SSL support + enabled: "${SSL_ENABLED:false}" + # Server SSL credentials + credentials: + # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) + type: "${SSL_CREDENTIALS_TYPE:PEM}" + # PEM server credentials + pem: + # Path to the server certificate file (holds server certificate or certificate chain, may include server private key) + cert_file: "${SSL_PEM_CERT:server.pem}" + # Path to the server certificate private key file (optional) + key_file: "${SSL_PEM_KEY:server_key.pem}" + # Server certificate private key password (optional) + key_password: "${SSL_PEM_KEY_PASSWORD:server_key_password}" + # Keystore server credentials + keystore: + # Type of the key store + type: "${SSL_KEY_STORE_TYPE:PKCS12}" + # Path to the key store that holds the SSL certificate + store_file: "${SSL_KEY_STORE:classpath:keystore/keystore.p12}" + # Password used to access the key store + store_password: "${SSL_KEY_STORE_PASSWORD:thingsboard}" + # Key alias + key_alias: "${SSL_KEY_ALIAS:tomcat}" + # Password used to access the key + key_password: "${SSL_KEY_PASSWORD:thingsboard}" # Zookeeper connection parameters. Used for service discovery. zk: @@ -283,4 +311,4 @@ management: web: exposure: # Expose metrics endpoint (use value 'prometheus' to enable prometheus metrics). - include: '${METRICS_ENDPOINTS_EXPOSE:info}' \ No newline at end of file + include: '${METRICS_ENDPOINTS_EXPOSE:info}' diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index be5bb62a00..be51848337 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -114,7 +114,7 @@ transport: # Server X509 Certificates support credentials: # Whether to enable LWM2M server X509 Certificate/RPK support - enabled: "${LWM2M_SERVER_CREDENTIALS_ENABLED:false}" + enabled: "${LWM2M_SERVER_CREDENTIALS_ENABLED:true}" # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) type: "${LWM2M_SERVER_CREDENTIALS_TYPE:PEM}" # PEM server credentials @@ -133,10 +133,10 @@ transport: store_file: "${LWM2M_SERVER_KEY_STORE:lwm2mserver.jks}" # Password used to access the key store store_password: "${LWM2M_SERVER_KEY_STORE_PASSWORD:server_ks_password}" - # Password used to access the key - key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_key_password}" # Key alias key_alias: "${LWM2M_SERVER_KEY_ALIAS:server}" + # Password used to access the key + key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_ks_password}" # Only Certificate_x509: skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" bootstrap: @@ -150,7 +150,7 @@ transport: # Bootstrap server X509 Certificates support credentials: # Whether to enable LWM2M bootstrap server X509 Certificate/RPK support - enabled: "${LWM2M_BS_CREDENTIALS_ENABLED:false}" + enabled: "${LWM2M_BS_CREDENTIALS_ENABLED:true}" # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) type: "${LWM2M_BS_CREDENTIALS_TYPE:PEM}" # PEM server credentials @@ -169,15 +169,15 @@ transport: store_file: "${LWM2M_BS_KEY_STORE:lwm2mserver.jks}" # Password used to access the key store store_password: "${LWM2M_BS_KEY_STORE_PASSWORD:server_ks_password}" - # Password used to access the key - key_password: "${LWM2M_BS_KEY_PASSWORD:server_key_password}" # Key alias key_alias: "${LWM2M_BS_KEY_ALIAS:bootstrap}" + # Password used to access the key + key_password: "${LWM2M_BS_KEY_PASSWORD:server_ks_password}" security: # X509 trust certificates trust-credentials: # Whether to load X509 trust certificates - enabled: "${LWM2M_TRUST_CREDENTIALS_ENABLED:false}" + enabled: "${LWM2M_TRUST_CREDENTIALS_ENABLED:true}" # Trust certificates store type (PEM - pem certificates file; KEYSTORE - java keystore) type: "${LWM2M_TRUST_CREDENTIALS_TYPE:PEM}" # PEM certificates