13 changed files with 419 additions and 457 deletions
@ -0,0 +1,76 @@ |
|||
/** |
|||
* 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.transport.lwm2m.ota; |
|||
|
|||
import org.springframework.mock.web.MockMultipartFile; |
|||
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; |
|||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; |
|||
import org.thingsboard.server.common.data.OtaPackageInfo; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
import org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest; |
|||
|
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE; |
|||
import static org.thingsboard.server.common.data.ota.OtaPackageType.SOFTWARE; |
|||
|
|||
@DaoSqlTest |
|||
public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
|||
|
|||
private final String[] resources = new String[]{"3.xml", "5.xml", "9.xml"}; |
|||
|
|||
public AbstractOtaLwM2MIntegrationTest() { |
|||
setResources(this.resources); |
|||
} |
|||
|
|||
protected OtaPackageInfo createFirmware() throws Exception { |
|||
String CHECKSUM = "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a"; |
|||
|
|||
OtaPackageInfo firmwareInfo = new OtaPackageInfo(); |
|||
firmwareInfo.setDeviceProfileId(deviceProfile.getId()); |
|||
firmwareInfo.setType(FIRMWARE); |
|||
firmwareInfo.setTitle("My firmware"); |
|||
firmwareInfo.setVersion("v1.0"); |
|||
|
|||
OtaPackageInfo savedFirmwareInfo = doPost("/api/otaPackage", firmwareInfo, OtaPackageInfo.class); |
|||
|
|||
MockMultipartFile testData = new MockMultipartFile("file", "filename.txt", "text/plain", new byte[]{1}); |
|||
|
|||
return savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, "SHA256"); |
|||
} |
|||
|
|||
protected OtaPackageInfo createSoftware() throws Exception { |
|||
String CHECKSUM = "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a"; |
|||
|
|||
OtaPackageInfo swInfo = new OtaPackageInfo(); |
|||
swInfo.setDeviceProfileId(deviceProfile.getId()); |
|||
swInfo.setType(SOFTWARE); |
|||
swInfo.setTitle("My sw"); |
|||
swInfo.setVersion("v1.0"); |
|||
|
|||
OtaPackageInfo savedFirmwareInfo = doPost("/api/otaPackage", swInfo, OtaPackageInfo.class); |
|||
|
|||
MockMultipartFile testData = new MockMultipartFile("file", "filename.txt", "text/plain", new byte[]{1}); |
|||
|
|||
return savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, "SHA256"); |
|||
} |
|||
|
|||
protected OtaPackageInfo savaData(String urlTemplate, MockMultipartFile content, String... params) throws Exception { |
|||
MockMultipartHttpServletRequestBuilder postRequest = MockMvcRequestBuilders.multipart(urlTemplate, params); |
|||
postRequest.file(content); |
|||
setJwtToken(postRequest); |
|||
return readResponse(mockMvc.perform(postRequest).andExpect(status().isOk()), OtaPackageInfo.class); |
|||
} |
|||
} |
|||
@ -0,0 +1,176 @@ |
|||
/** |
|||
* 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.transport.lwm2m.security; |
|||
|
|||
import org.eclipse.leshan.core.util.Hex; |
|||
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MBootstrapCredentials; |
|||
import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecServerCredentials; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
import org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest; |
|||
import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; |
|||
|
|||
import java.io.IOException; |
|||
import java.io.InputStream; |
|||
import java.math.BigInteger; |
|||
import java.security.AlgorithmParameters; |
|||
import java.security.GeneralSecurityException; |
|||
import java.security.KeyFactory; |
|||
import java.security.KeyStore; |
|||
import java.security.PrivateKey; |
|||
import java.security.PublicKey; |
|||
import java.security.cert.Certificate; |
|||
import java.security.cert.X509Certificate; |
|||
import java.security.spec.ECGenParameterSpec; |
|||
import java.security.spec.ECParameterSpec; |
|||
import java.security.spec.ECPoint; |
|||
import java.security.spec.ECPrivateKeySpec; |
|||
import java.security.spec.ECPublicKeySpec; |
|||
import java.security.spec.KeySpec; |
|||
|
|||
@DaoSqlTest |
|||
public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
|||
|
|||
protected final String pskIdentity; // client public key or id used for PSK
|
|||
protected final String pskKey; // client private/secret key used for PSK
|
|||
protected final PublicKey clientPublicKey; // client public key used for RPK
|
|||
protected final PrivateKey clientPrivateKey; // client private key used for RPK
|
|||
protected final PublicKey serverPublicKey; // server public key used for RPK
|
|||
protected final PrivateKey serverPrivateKey; // server private key used for RPK
|
|||
|
|||
// client private key used for X509
|
|||
protected final PrivateKey clientPrivateKeyFromCert; |
|||
// server private key used for X509
|
|||
protected final PrivateKey serverPrivateKeyFromCert; |
|||
// client certificate signed by rootCA with a good CN (CN start by leshan_integration_test)
|
|||
protected final X509Certificate clientX509Cert; |
|||
// client certificate signed by rootCA but with bad CN (CN does not start by leshan_integration_test)
|
|||
protected final X509Certificate clientX509CertWithBadCN; |
|||
// client certificate self-signed with a good CN (CN start by leshan_integration_test)
|
|||
protected final X509Certificate clientX509CertSelfSigned; |
|||
// client certificate signed by another CA (not rootCA) with a good CN (CN start by leshan_integration_test)
|
|||
protected final X509Certificate clientX509CertNotTrusted; |
|||
// server certificate signed by rootCA
|
|||
protected final X509Certificate serverX509Cert; |
|||
// self-signed server certificate
|
|||
protected final X509Certificate serverX509CertSelfSigned; |
|||
// rootCA used by the server
|
|||
protected final X509Certificate rootCAX509Cert; |
|||
// certificates trustedby the server (should contain rootCA)
|
|||
protected final Certificate[] trustedCertificates = new Certificate[1]; |
|||
|
|||
protected static final String ENDPOINT = "deviceAEndpoint"; |
|||
|
|||
protected LwM2MTestClient client; |
|||
|
|||
private final LwM2MBootstrapCredentials defaultBootstrapCredentials; |
|||
|
|||
private final String[] resources = new String[]{"1.xml", "2.xml", "3.xml", "5.xml", "9.xml"}; |
|||
|
|||
public AbstractSecurityLwM2MIntegrationTest() { |
|||
// create client credentials
|
|||
setResources(this.resources); |
|||
setEndpoint(ENDPOINT); |
|||
try { |
|||
// Get keys PSK
|
|||
this.pskIdentity = "SOME_PSK_ID"; |
|||
this.pskKey = "73656372657450534b73656372657450"; |
|||
|
|||
// Get point values
|
|||
byte[] publicX = Hex |
|||
.decodeHex("89c048261979208666f2bfb188be1968fc9021c416ce12828c06f4e314c167b5".toCharArray()); |
|||
byte[] publicY = Hex |
|||
.decodeHex("cbf1eb7587f08e01688d9ada4be859137ca49f79394bad9179326b3090967b68".toCharArray()); |
|||
byte[] privateS = Hex |
|||
.decodeHex("e67b68d2aaeb6550f19d98cade3ad62b39532e02e6b422e1f7ea189dabaea5d2".toCharArray()); |
|||
|
|||
// Get Elliptic Curve Parameter spec for secp256r1
|
|||
AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); |
|||
algoParameters.init(new ECGenParameterSpec("secp256r1")); |
|||
ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); |
|||
|
|||
// Create key specs
|
|||
KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), |
|||
parameterSpec); |
|||
KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec); |
|||
|
|||
// Get keys RPK
|
|||
clientPublicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); |
|||
clientPrivateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec); |
|||
|
|||
// Get certificates from key store
|
|||
char[] clientKeyStorePwd = "client".toCharArray(); |
|||
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
|||
try (InputStream clientKeyStoreFile = this.getClass().getClassLoader().getResourceAsStream("lwm2m/credentials/clientKeyStore.jks")) { |
|||
clientKeyStore.load(clientKeyStoreFile, clientKeyStorePwd); |
|||
} |
|||
|
|||
clientPrivateKeyFromCert = (PrivateKey) clientKeyStore.getKey("client", clientKeyStorePwd); |
|||
clientX509Cert = (X509Certificate) clientKeyStore.getCertificate("client"); |
|||
clientX509CertWithBadCN = (X509Certificate) clientKeyStore.getCertificate("client_bad_cn"); |
|||
clientX509CertSelfSigned = (X509Certificate) clientKeyStore.getCertificate("client_self_signed"); |
|||
clientX509CertNotTrusted = (X509Certificate) clientKeyStore.getCertificate("client_not_trusted"); |
|||
} catch (GeneralSecurityException | IOException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
|
|||
// create server credentials
|
|||
try { |
|||
// Get point values
|
|||
byte[] publicX = Hex |
|||
.decodeHex("fcc28728c123b155be410fc1c0651da374fc6ebe7f96606e90d927d188894a73".toCharArray()); |
|||
byte[] publicY = Hex |
|||
.decodeHex("d2ffaa73957d76984633fc1cc54d0b763ca0559a9dff9706e9f4557dacc3f52a".toCharArray()); |
|||
byte[] privateS = Hex |
|||
.decodeHex("1dae121ba406802ef07c193c1ee4df91115aabd79c1ed7f4c0ef7ef6a5449400".toCharArray()); |
|||
|
|||
// Get Elliptic Curve Parameter spec for secp256r1
|
|||
AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); |
|||
algoParameters.init(new ECGenParameterSpec("secp256r1")); |
|||
ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); |
|||
|
|||
// Create key specs
|
|||
KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), |
|||
parameterSpec); |
|||
KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec); |
|||
|
|||
// Get keys
|
|||
serverPublicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); |
|||
serverPrivateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec); |
|||
|
|||
// Get certificates from key store
|
|||
char[] serverKeyStorePwd = "server".toCharArray(); |
|||
KeyStore serverKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
|||
try (InputStream serverKeyStoreFile = this.getClass().getClassLoader().getResourceAsStream("lwm2m/credentials/serverKeyStore.jks")) { |
|||
serverKeyStore.load(serverKeyStoreFile, serverKeyStorePwd); |
|||
} |
|||
|
|||
serverPrivateKeyFromCert = (PrivateKey) serverKeyStore.getKey("server", serverKeyStorePwd); |
|||
rootCAX509Cert = (X509Certificate) serverKeyStore.getCertificate("rootCA"); |
|||
serverX509Cert = (X509Certificate) serverKeyStore.getCertificate("server"); |
|||
serverX509CertSelfSigned = (X509Certificate) serverKeyStore.getCertificate("server_self_signed"); |
|||
trustedCertificates[0] = rootCAX509Cert; |
|||
} catch (GeneralSecurityException | IOException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
|
|||
defaultBootstrapCredentials = new LwM2MBootstrapCredentials(); |
|||
|
|||
NoSecServerCredentials serverCredentials = new NoSecServerCredentials(); |
|||
|
|||
defaultBootstrapCredentials.setBootstrapServer(serverCredentials); |
|||
defaultBootstrapCredentials.setLwm2mServer(serverCredentials); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue