Commit 7ca626a0868422018a8489dce417b02ee31ef4c5
Committed by
GitHub
1 parent
38af4d5d
Created LwM2M credentials (#4546)
* Created LwM2M credentials * psk endpoint
Showing
17 changed files
with
199 additions
and
168 deletions
... | ... | @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.ObjectMapper; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | +import org.eclipse.leshan.core.SecurityMode; | |
20 | 21 | import org.springframework.security.access.prepost.PreAuthorize; |
21 | 22 | import org.springframework.web.bind.annotation.PathVariable; |
22 | 23 | import org.springframework.web.bind.annotation.RequestBody; |
... | ... | @@ -46,9 +47,11 @@ public class Lwm2mController extends BaseController { |
46 | 47 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
47 | 48 | @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{securityMode}/{bootstrapServerIs}", method = RequestMethod.GET) |
48 | 49 | @ResponseBody |
49 | - public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(@PathVariable("securityMode") String securityMode, | |
50 | + public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(@PathVariable("securityMode") String strSecurityMode, | |
50 | 51 | @PathVariable("bootstrapServerIs") boolean bootstrapServer) throws ThingsboardException { |
52 | + checkNotNull(strSecurityMode); | |
51 | 53 | try { |
54 | + SecurityMode securityMode = SecurityMode.valueOf(strSecurityMode); | |
52 | 55 | return lwM2MServerSecurityInfoRepository.getServerSecurityInfo(securityMode, bootstrapServer); |
53 | 56 | } catch (Exception e) { |
54 | 57 | throw handleException(e); | ... | ... |
... | ... | @@ -18,6 +18,7 @@ package org.thingsboard.server.service.lwm2m; |
18 | 18 | |
19 | 19 | import lombok.RequiredArgsConstructor; |
20 | 20 | import lombok.extern.slf4j.Slf4j; |
21 | +import org.eclipse.leshan.core.SecurityMode; | |
21 | 22 | import org.eclipse.leshan.core.util.Hex; |
22 | 23 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
23 | 24 | import org.springframework.stereotype.Service; |
... | ... | @@ -25,7 +26,6 @@ import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; |
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 | -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | |
29 | 29 | |
30 | 30 | import java.math.BigInteger; |
31 | 31 | import java.security.AlgorithmParameters; |
... | ... | @@ -55,17 +55,16 @@ public class LwM2MServerSecurityInfoRepository { |
55 | 55 | * @param bootstrapServer |
56 | 56 | * @return ServerSecurityConfig more value is default: Important - port, host, publicKey |
57 | 57 | */ |
58 | - public ServerSecurityConfig getServerSecurityInfo(String securityMode, boolean bootstrapServer) { | |
59 | - LwM2MSecurityMode lwM2MSecurityMode = LwM2MSecurityMode.fromSecurityMode(securityMode.toLowerCase()); | |
60 | - ServerSecurityConfig result = getServerSecurityConfig(bootstrapServer ? bootstrapConfig : serverConfig, lwM2MSecurityMode); | |
58 | + public ServerSecurityConfig getServerSecurityInfo(SecurityMode securityMode, boolean bootstrapServer) { | |
59 | + ServerSecurityConfig result = getServerSecurityConfig(bootstrapServer ? bootstrapConfig : serverConfig, securityMode); | |
61 | 60 | result.setBootstrapServerIs(bootstrapServer); |
62 | 61 | return result; |
63 | 62 | } |
64 | 63 | |
65 | - private ServerSecurityConfig getServerSecurityConfig(LwM2MSecureServerConfig serverConfig, LwM2MSecurityMode mode) { | |
64 | + private ServerSecurityConfig getServerSecurityConfig(LwM2MSecureServerConfig serverConfig, SecurityMode securityMode) { | |
66 | 65 | ServerSecurityConfig bsServ = new ServerSecurityConfig(); |
67 | 66 | bsServ.setServerId(serverConfig.getId()); |
68 | - switch (mode) { | |
67 | + switch (securityMode) { | |
69 | 68 | case NO_SEC: |
70 | 69 | bsServ.setHost(serverConfig.getHost()); |
71 | 70 | bsServ.setPort(serverConfig.getPort()); | ... | ... |
... | ... | @@ -73,17 +73,17 @@ public class LwM2MBootstrapConfig { |
73 | 73 | configBs.servers.put(0, server0); |
74 | 74 | /* Security Configuration (object 0) as defined in LWM2M 1.0.x TS. Bootstrap instance = 0 */ |
75 | 75 | this.bootstrapServer.setBootstrapServerIs(true); |
76 | - configBs.security.put(0, setServerSecuruty(this.bootstrapServer.getHost(), this.bootstrapServer.getPort(), this.bootstrapServer.isBootstrapServerIs(), this.bootstrapServer.getSecurityMode(), this.bootstrapServer.getClientPublicKeyOrId(), this.bootstrapServer.getServerPublicKey(), this.bootstrapServer.getClientSecretKey(), this.bootstrapServer.getServerId())); | |
76 | + configBs.security.put(0, setServerSecurity(this.bootstrapServer.getHost(), this.bootstrapServer.getPort(), this.bootstrapServer.isBootstrapServerIs(), this.bootstrapServer.getSecurityMode(), this.bootstrapServer.getClientPublicKeyOrId(), this.bootstrapServer.getServerPublicKey(), this.bootstrapServer.getClientSecretKey(), this.bootstrapServer.getServerId())); | |
77 | 77 | /* Security Configuration (object 0) as defined in LWM2M 1.0.x TS. Server instance = 1 */ |
78 | - configBs.security.put(1, setServerSecuruty(this.lwm2mServer.getHost(), this.lwm2mServer.getPort(), this.lwm2mServer.isBootstrapServerIs(), this.lwm2mServer.getSecurityMode(), this.lwm2mServer.getClientPublicKeyOrId(), this.lwm2mServer.getServerPublicKey(), this.lwm2mServer.getClientSecretKey(), this.lwm2mServer.getServerId())); | |
78 | + configBs.security.put(1, setServerSecurity(this.lwm2mServer.getHost(), this.lwm2mServer.getPort(), this.lwm2mServer.isBootstrapServerIs(), this.lwm2mServer.getSecurityMode(), this.lwm2mServer.getClientPublicKeyOrId(), this.lwm2mServer.getServerPublicKey(), this.lwm2mServer.getClientSecretKey(), this.lwm2mServer.getServerId())); | |
79 | 79 | return configBs; |
80 | 80 | } |
81 | 81 | |
82 | - private BootstrapConfig.ServerSecurity setServerSecuruty(String host, Integer port, boolean bootstrapServer, String securityMode, String clientPublicKey, String serverPublicKey, String secretKey, int serverId) { | |
82 | + private BootstrapConfig.ServerSecurity setServerSecurity(String host, Integer port, boolean bootstrapServer, SecurityMode securityMode, String clientPublicKey, String serverPublicKey, String secretKey, int serverId) { | |
83 | 83 | BootstrapConfig.ServerSecurity serverSecurity = new BootstrapConfig.ServerSecurity(); |
84 | 84 | serverSecurity.uri = "coaps://" + host + ":" + Integer.toString(port); |
85 | 85 | serverSecurity.bootstrapServer = bootstrapServer; |
86 | - serverSecurity.securityMode = SecurityMode.valueOf(securityMode); | |
86 | + serverSecurity.securityMode = securityMode; | |
87 | 87 | serverSecurity.publicKeyOrId = setPublicKeyOrId(clientPublicKey, securityMode); |
88 | 88 | serverSecurity.serverPublicKey = (serverPublicKey != null && !serverPublicKey.isEmpty()) ? Hex.decodeHex(serverPublicKey.toCharArray()) : new byte[]{}; |
89 | 89 | serverSecurity.secretKey = (secretKey != null && !secretKey.isEmpty()) ? Hex.decodeHex(secretKey.toCharArray()) : new byte[]{}; |
... | ... | @@ -91,9 +91,9 @@ public class LwM2MBootstrapConfig { |
91 | 91 | return serverSecurity; |
92 | 92 | } |
93 | 93 | |
94 | - private byte[] setPublicKeyOrId(String publicKeyOrIdStr, String securityMode) { | |
94 | + private byte[] setPublicKeyOrId(String publicKeyOrIdStr, SecurityMode securityMode) { | |
95 | 95 | return (publicKeyOrIdStr == null || publicKeyOrIdStr.isEmpty()) ? new byte[]{} : |
96 | - SecurityMode.valueOf(securityMode).equals(SecurityMode.PSK) ? publicKeyOrIdStr.getBytes(StandardCharsets.UTF_8) : | |
96 | + SecurityMode.PSK.equals(securityMode) ? publicKeyOrIdStr.getBytes(StandardCharsets.UTF_8) : | |
97 | 97 | Hex.decodeHex(publicKeyOrIdStr.toCharArray()); |
98 | 98 | } |
99 | 99 | } | ... | ... |
... | ... | @@ -31,7 +31,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
31 | 31 | import org.springframework.stereotype.Service; |
32 | 32 | import org.thingsboard.server.gen.transport.TransportProtos; |
33 | 33 | import org.thingsboard.server.transport.lwm2m.secure.EndpointSecurityInfo; |
34 | -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | |
35 | 34 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; |
36 | 35 | import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener; |
37 | 36 | import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; |
... | ... | @@ -73,7 +72,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
73 | 72 | @Override |
74 | 73 | public List<SecurityInfo> getAllByEndpoint(String endPoint) { |
75 | 74 | EndpointSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endPoint, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP); |
76 | - if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { | |
75 | + if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) { | |
77 | 76 | /* add value to store from BootstrapJson */ |
78 | 77 | this.setBootstrapConfigScurityInfo(store); |
79 | 78 | BootstrapConfig bsConfigNew = store.getBootstrapConfig(); |
... | ... | @@ -97,7 +96,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
97 | 96 | @Override |
98 | 97 | public SecurityInfo getByIdentity(String identity) { |
99 | 98 | EndpointSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(identity, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP); |
100 | - if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { | |
99 | + if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) { | |
101 | 100 | /* add value to store from BootstrapJson */ |
102 | 101 | this.setBootstrapConfigScurityInfo(store); |
103 | 102 | BootstrapConfig bsConfig = store.getBootstrapConfig(); |
... | ... | @@ -118,29 +117,29 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
118 | 117 | LwM2MBootstrapConfig lwM2MBootstrapConfig = this.getParametersBootstrap(store); |
119 | 118 | if (lwM2MBootstrapConfig != null) { |
120 | 119 | /* Security info */ |
121 | - switch (SecurityMode.valueOf(lwM2MBootstrapConfig.getBootstrapServer().getSecurityMode())) { | |
120 | + switch (lwM2MBootstrapConfig.getBootstrapServer().getSecurityMode()) { | |
122 | 121 | /* Use RPK only */ |
123 | 122 | case PSK: |
124 | 123 | store.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(store.getEndpoint(), |
125 | 124 | lwM2MBootstrapConfig.getBootstrapServer().getClientPublicKeyOrId(), |
126 | 125 | Hex.decodeHex(lwM2MBootstrapConfig.getBootstrapServer().getClientSecretKey().toCharArray()))); |
127 | - store.setSecurityMode(SecurityMode.PSK.code); | |
126 | + store.setSecurityMode(SecurityMode.PSK); | |
128 | 127 | break; |
129 | 128 | case RPK: |
130 | 129 | try { |
131 | 130 | store.setSecurityInfo(SecurityInfo.newRawPublicKeyInfo(store.getEndpoint(), |
132 | 131 | SecurityUtil.publicKey.decode(Hex.decodeHex(lwM2MBootstrapConfig.getBootstrapServer().getClientPublicKeyOrId().toCharArray())))); |
133 | - store.setSecurityMode(SecurityMode.RPK.code); | |
132 | + store.setSecurityMode(SecurityMode.RPK); | |
134 | 133 | break; |
135 | 134 | } catch (IOException | GeneralSecurityException e) { |
136 | 135 | log.error("Unable to decode Client public key for [{}] [{}]", store.getEndpoint(), e.getMessage()); |
137 | 136 | } |
138 | 137 | case X509: |
139 | 138 | store.setSecurityInfo(SecurityInfo.newX509CertInfo(store.getEndpoint())); |
140 | - store.setSecurityMode(SecurityMode.X509.code); | |
139 | + store.setSecurityMode(SecurityMode.X509); | |
141 | 140 | break; |
142 | 141 | case NO_SEC: |
143 | - store.setSecurityMode(SecurityMode.NO_SEC.code); | |
142 | + store.setSecurityMode(SecurityMode.NO_SEC); | |
144 | 143 | store.setSecurityInfo(null); |
145 | 144 | break; |
146 | 145 | default: |
... | ... | @@ -152,10 +151,9 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
152 | 151 | |
153 | 152 | private LwM2MBootstrapConfig getParametersBootstrap(EndpointSecurityInfo store) { |
154 | 153 | try { |
155 | - JsonObject bootstrapJsonCredential = store.getBootstrapJsonCredential(); | |
156 | - if (bootstrapJsonCredential != null) { | |
154 | + LwM2MBootstrapConfig lwM2MBootstrapConfig = store.getBootstrapCredentialConfig(); | |
155 | + if (lwM2MBootstrapConfig != null) { | |
157 | 156 | ObjectMapper mapper = new ObjectMapper(); |
158 | - LwM2MBootstrapConfig lwM2MBootstrapConfig = mapper.readValue(bootstrapJsonCredential.toString(), LwM2MBootstrapConfig.class); | |
159 | 157 | JsonObject bootstrapObject = getBootstrapParametersFromThingsboard(store.getDeviceProfile()); |
160 | 158 | lwM2MBootstrapConfig.servers = mapper.readValue(bootstrapObject.get(SERVERS).toString(), LwM2MBootstrapServers.class); |
161 | 159 | LwM2MServerBootstrap profileServerBootstrap = mapper.readValue(bootstrapObject.get(BOOTSTRAP_SERVER).toString(), LwM2MServerBootstrap.class); | ... | ... |
... | ... | @@ -32,7 +32,7 @@ public class LwM2MServerBootstrap { |
32 | 32 | String host = "0.0.0.0"; |
33 | 33 | Integer port = 0; |
34 | 34 | |
35 | - String securityMode = SecurityMode.NO_SEC.name(); | |
35 | + SecurityMode securityMode = SecurityMode.NO_SEC; | |
36 | 36 | |
37 | 37 | Integer serverId = 123; |
38 | 38 | boolean bootstrapServerIs = false; | ... | ... |
... | ... | @@ -15,25 +15,23 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.secure; |
17 | 17 | |
18 | -import com.google.gson.JsonObject; | |
19 | 18 | import lombok.Data; |
19 | +import org.eclipse.leshan.core.SecurityMode; | |
20 | 20 | import org.eclipse.leshan.server.bootstrap.BootstrapConfig; |
21 | 21 | import org.eclipse.leshan.server.security.SecurityInfo; |
22 | 22 | import org.thingsboard.server.common.data.DeviceProfile; |
23 | 23 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
24 | -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; | |
25 | - | |
26 | -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.DEFAULT_MODE; | |
24 | +import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapConfig; | |
27 | 25 | |
28 | 26 | @Data |
29 | 27 | public class EndpointSecurityInfo { |
30 | 28 | private ValidateDeviceCredentialsResponse msg; |
31 | 29 | private SecurityInfo securityInfo; |
32 | - private int securityMode = DEFAULT_MODE.code; | |
30 | + private SecurityMode securityMode; | |
33 | 31 | |
34 | 32 | /** bootstrap */ |
35 | 33 | private DeviceProfile deviceProfile; |
36 | - private JsonObject bootstrapJsonCredential; | |
34 | + private LwM2MBootstrapConfig bootstrapCredentialConfig; | |
37 | 35 | private String endpoint; |
38 | 36 | private BootstrapConfig bootstrapConfig; |
39 | 37 | } | ... | ... |
... | ... | @@ -33,16 +33,6 @@ import java.util.Arrays; |
33 | 33 | @Slf4j |
34 | 34 | public class LWM2MGenerationPSkRPkECC { |
35 | 35 | |
36 | - public LWM2MGenerationPSkRPkECC(Integer dtlsMode) { | |
37 | - switch (LwM2MSecurityMode.fromSecurityMode(dtlsMode)) { | |
38 | - case PSK: | |
39 | - generationPSkKey(); | |
40 | - break; | |
41 | - case RPK: | |
42 | - generationRPKECCKey(); | |
43 | - } | |
44 | - } | |
45 | - | |
46 | 36 | public LWM2MGenerationPSkRPkECC() { |
47 | 37 | generationPSkKey(); |
48 | 38 | generationRPKECCKey(); |
... | ... | @@ -102,12 +92,12 @@ public class LWM2MGenerationPSkRPkECC { |
102 | 92 | /* Get Curves params */ |
103 | 93 | String privHex = Hex.encodeHexString(privKey.getEncoded()); |
104 | 94 | log.info("\nCreating new RPK for the next start... \n" + |
105 | - " Public Key (Hex): [{}]\n" + | |
106 | - " Private Key (Hex): [{}]" + | |
107 | - " public_x : [{}] \n" + | |
108 | - " public_y : [{}] \n" + | |
109 | - " private_encode : [{}] \n" + | |
110 | - " Elliptic Curve parameters : [{}] \n", | |
95 | + " Public Key (Hex): [{}]\n" + | |
96 | + " Private Key (Hex): [{}]" + | |
97 | + " public_x : [{}] \n" + | |
98 | + " public_y : [{}] \n" + | |
99 | + " private_encode : [{}] \n" + | |
100 | + " Elliptic Curve parameters : [{}] \n", | |
111 | 101 | Hex.encodeHexString(pubKey.getEncoded()), |
112 | 102 | privHex, |
113 | 103 | Hex.encodeHexString(x), | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2MSecurityMode.java
deleted
100644 → 0
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.transport.lwm2m.secure; | |
17 | - | |
18 | -public enum LwM2MSecurityMode { | |
19 | - | |
20 | - PSK(0, "psk"), | |
21 | - RPK(1, "rpk"), | |
22 | - X509(2, "x509"), | |
23 | - NO_SEC(3, "no_sec"), | |
24 | - X509_EST(4, "x509_est"), | |
25 | - REDIS(7, "redis"), | |
26 | - DEFAULT_MODE(255, "default_mode"); | |
27 | - | |
28 | - public int code; | |
29 | - public String subEndpoint; | |
30 | - | |
31 | - LwM2MSecurityMode(int code, String subEndpoint) { | |
32 | - this.code = code; | |
33 | - this.subEndpoint = subEndpoint; | |
34 | - } | |
35 | - | |
36 | - public static LwM2MSecurityMode fromSecurityMode(long code) { | |
37 | - return fromSecurityMode((int) code); | |
38 | - } | |
39 | - | |
40 | - public static LwM2MSecurityMode fromSecurityMode(int code) { | |
41 | - for (LwM2MSecurityMode sm : LwM2MSecurityMode.values()) { | |
42 | - if (sm.code == code) { | |
43 | - return sm; | |
44 | - } | |
45 | - } | |
46 | - throw new IllegalArgumentException(String.format("Unsupported security code : %d", code)); | |
47 | - } | |
48 | - | |
49 | - | |
50 | - public static LwM2MSecurityMode fromSecurityMode(String subEndpoint) { | |
51 | - for (LwM2MSecurityMode sm : LwM2MSecurityMode.values()) { | |
52 | - if (sm.subEndpoint.equals(subEndpoint)) { | |
53 | - return sm; | |
54 | - } | |
55 | - } | |
56 | - throw new IllegalArgumentException(String.format("Unsupported security subEndpoint : %d", subEndpoint)); | |
57 | - } | |
58 | -} |
... | ... | @@ -15,34 +15,36 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.secure; |
17 | 17 | |
18 | -import com.google.gson.JsonObject; | |
19 | 18 | import lombok.RequiredArgsConstructor; |
20 | 19 | import lombok.extern.slf4j.Slf4j; |
21 | -import org.eclipse.leshan.core.util.Hex; | |
20 | +import org.eclipse.leshan.core.SecurityMode; | |
22 | 21 | import org.eclipse.leshan.core.util.SecurityUtil; |
23 | 22 | import org.eclipse.leshan.server.security.SecurityInfo; |
24 | 23 | import org.springframework.stereotype.Component; |
25 | -import org.thingsboard.server.common.data.DeviceProfile; | |
24 | +import org.thingsboard.common.util.JacksonUtil; | |
25 | +import org.thingsboard.server.common.data.StringUtils; | |
26 | 26 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
27 | 27 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
28 | -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; | |
29 | 28 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; |
30 | 29 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
31 | 30 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
31 | +import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MClientCredentialsConfig; | |
32 | +import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; | |
33 | +import org.thingsboard.server.transport.lwm2m.secure.credentials.PSKClientCredentialsConfig; | |
34 | +import org.thingsboard.server.transport.lwm2m.secure.credentials.RPKClientCredentialsConfig; | |
32 | 35 | import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; |
33 | 36 | import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; |
34 | 37 | |
35 | 38 | import java.io.IOException; |
36 | 39 | import java.security.GeneralSecurityException; |
37 | 40 | import java.security.PublicKey; |
38 | -import java.util.Optional; | |
39 | 41 | import java.util.concurrent.CountDownLatch; |
40 | 42 | import java.util.concurrent.TimeUnit; |
41 | 43 | |
42 | -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; | |
43 | -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.PSK; | |
44 | -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.RPK; | |
45 | -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X509; | |
44 | +import static org.eclipse.leshan.core.SecurityMode.NO_SEC; | |
45 | +import static org.eclipse.leshan.core.SecurityMode.PSK; | |
46 | +import static org.eclipse.leshan.core.SecurityMode.RPK; | |
47 | +import static org.eclipse.leshan.core.SecurityMode.X509; | |
46 | 48 | |
47 | 49 | @Slf4j |
48 | 50 | @Component |
... | ... | @@ -53,7 +55,6 @@ public class LwM2mCredentialsSecurityInfoValidator { |
53 | 55 | private final LwM2mTransportContext context; |
54 | 56 | private final LwM2MTransportServerConfig config; |
55 | 57 | |
56 | - | |
57 | 58 | public EndpointSecurityInfo getEndpointSecurityInfo(String endpoint, LwM2mTransportUtil.LwM2mTypeServer keyValue) { |
58 | 59 | CountDownLatch latch = new CountDownLatch(1); |
59 | 60 | final EndpointSecurityInfo[] resultSecurityStore = new EndpointSecurityInfo[1]; |
... | ... | @@ -92,39 +93,32 @@ public class LwM2mCredentialsSecurityInfoValidator { |
92 | 93 | */ |
93 | 94 | private EndpointSecurityInfo createSecurityInfo(String endpoint, String jsonStr, LwM2mTransportUtil.LwM2mTypeServer keyValue) { |
94 | 95 | EndpointSecurityInfo result = new EndpointSecurityInfo(); |
95 | - JsonObject objectMsg = LwM2mTransportUtil.validateJson(jsonStr); | |
96 | - if (objectMsg != null && !objectMsg.isJsonNull()) { | |
97 | - JsonObject object = (objectMsg.has(keyValue.type) && !objectMsg.get(keyValue.type).isJsonNull()) ? objectMsg.get(keyValue.type).getAsJsonObject() : null; | |
98 | - /** | |
99 | - * Only PSK | |
100 | - */ | |
101 | - String endpointPsk = (objectMsg.has("client") | |
102 | - && objectMsg.get("client").getAsJsonObject().has("endpoint") | |
103 | - && objectMsg.get("client").getAsJsonObject().get("endpoint").isJsonPrimitive()) ? objectMsg.get("client").getAsJsonObject().get("endpoint").getAsString() : null; | |
104 | - endpoint = (endpointPsk == null || endpointPsk.isEmpty()) ? endpoint : endpointPsk; | |
105 | - if (object != null && !object.isJsonNull()) { | |
106 | - if (keyValue.equals(LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP)) { | |
107 | - result.setBootstrapJsonCredential(object); | |
108 | - result.setEndpoint(endpoint); | |
109 | - result.setSecurityMode(LwM2MSecurityMode.fromSecurityMode(object.get("bootstrapServer").getAsJsonObject().get("securityMode").getAsString().toLowerCase()).code); | |
110 | - } else { | |
111 | - LwM2MSecurityMode lwM2MSecurityMode = LwM2MSecurityMode.fromSecurityMode(object.get("securityConfigClientMode").getAsString().toLowerCase()); | |
112 | - switch (lwM2MSecurityMode) { | |
113 | - case NO_SEC: | |
114 | - createClientSecurityInfoNoSec(result); | |
115 | - break; | |
116 | - case PSK: | |
117 | - createClientSecurityInfoPSK(result, endpoint, object); | |
118 | - break; | |
119 | - case RPK: | |
120 | - createClientSecurityInfoRPK(result, endpoint, object); | |
121 | - break; | |
122 | - case X509: | |
123 | - createClientSecurityInfoX509(result, endpoint); | |
124 | - break; | |
125 | - default: | |
126 | - break; | |
127 | - } | |
96 | + LwM2MCredentials credentials = JacksonUtil.fromString(jsonStr, LwM2MCredentials.class); | |
97 | + if (credentials != null) { | |
98 | + if (keyValue.equals(LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP)) { | |
99 | + result.setBootstrapCredentialConfig(credentials.getBootstrap()); | |
100 | + if (SecurityMode.PSK.equals(credentials.getClient().getSecurityConfigClientMode())) { | |
101 | + PSKClientCredentialsConfig pskClientConfig = (PSKClientCredentialsConfig) credentials.getClient(); | |
102 | + endpoint = StringUtils.isNotEmpty(pskClientConfig.getEndpoint()) ? pskClientConfig.getEndpoint() : endpoint; | |
103 | + } | |
104 | + result.setEndpoint(endpoint); | |
105 | + result.setSecurityMode(credentials.getBootstrap().getBootstrapServer().getSecurityMode()); | |
106 | + } else { | |
107 | + switch (credentials.getClient().getSecurityConfigClientMode()) { | |
108 | + case NO_SEC: | |
109 | + createClientSecurityInfoNoSec(result); | |
110 | + break; | |
111 | + case PSK: | |
112 | + createClientSecurityInfoPSK(result, endpoint, credentials.getClient()); | |
113 | + break; | |
114 | + case RPK: | |
115 | + createClientSecurityInfoRPK(result, endpoint, credentials.getClient()); | |
116 | + break; | |
117 | + case X509: | |
118 | + createClientSecurityInfoX509(result, endpoint, credentials.getClient()); | |
119 | + break; | |
120 | + default: | |
121 | + break; | |
128 | 122 | } |
129 | 123 | } |
130 | 124 | } |
... | ... | @@ -133,19 +127,18 @@ public class LwM2mCredentialsSecurityInfoValidator { |
133 | 127 | |
134 | 128 | private void createClientSecurityInfoNoSec(EndpointSecurityInfo result) { |
135 | 129 | result.setSecurityInfo(null); |
136 | - result.setSecurityMode(NO_SEC.code); | |
130 | + result.setSecurityMode(NO_SEC); | |
137 | 131 | } |
138 | 132 | |
139 | - private void createClientSecurityInfoPSK(EndpointSecurityInfo result, String endpoint, JsonObject object) { | |
140 | - /** PSK Deserialization */ | |
141 | - String identity = (object.has("identity") && object.get("identity").isJsonPrimitive()) ? object.get("identity").getAsString() : null; | |
142 | - if (identity != null && !identity.isEmpty()) { | |
133 | + private void createClientSecurityInfoPSK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentialsConfig clientCredentialsConfig) { | |
134 | + PSKClientCredentialsConfig pskConfig = (PSKClientCredentialsConfig) clientCredentialsConfig; | |
135 | + if (StringUtils.isNotEmpty(pskConfig.getIdentity())) { | |
143 | 136 | try { |
144 | - byte[] key = (object.has("key") && object.get("key").isJsonPrimitive()) ? Hex.decodeHex(object.get("key").getAsString().toCharArray()) : null; | |
145 | - if (key != null && key.length > 0) { | |
137 | + if (pskConfig.getKey() != null && pskConfig.getKey().length > 0) { | |
138 | + endpoint = StringUtils.isNotEmpty(pskConfig.getEndpoint()) ? pskConfig.getEndpoint() : endpoint; | |
146 | 139 | if (endpoint != null && !endpoint.isEmpty()) { |
147 | - result.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(endpoint, identity, key)); | |
148 | - result.setSecurityMode(PSK.code); | |
140 | + result.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(endpoint, pskConfig.getIdentity(), pskConfig.getKey())); | |
141 | + result.setSecurityMode(PSK); | |
149 | 142 | } |
150 | 143 | } |
151 | 144 | } catch (IllegalArgumentException e) { |
... | ... | @@ -156,13 +149,13 @@ public class LwM2mCredentialsSecurityInfoValidator { |
156 | 149 | } |
157 | 150 | } |
158 | 151 | |
159 | - private void createClientSecurityInfoRPK(EndpointSecurityInfo result, String endpoint, JsonObject object) { | |
152 | + private void createClientSecurityInfoRPK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentialsConfig clientCredentialsConfig) { | |
153 | + RPKClientCredentialsConfig rpkConfig = (RPKClientCredentialsConfig) clientCredentialsConfig; | |
160 | 154 | try { |
161 | - if (object.has("key") && object.get("key").isJsonPrimitive()) { | |
162 | - byte[] rpkkey = Hex.decodeHex(object.get("key").getAsString().toLowerCase().toCharArray()); | |
163 | - PublicKey key = SecurityUtil.publicKey.decode(rpkkey); | |
155 | + if (rpkConfig.getKey() != null) { | |
156 | + PublicKey key = SecurityUtil.publicKey.decode(rpkConfig.getKey()); | |
164 | 157 | result.setSecurityInfo(SecurityInfo.newRawPublicKeyInfo(endpoint, key)); |
165 | - result.setSecurityMode(RPK.code); | |
158 | + result.setSecurityMode(RPK); | |
166 | 159 | } else { |
167 | 160 | log.error("Missing RPK key"); |
168 | 161 | } |
... | ... | @@ -171,8 +164,8 @@ public class LwM2mCredentialsSecurityInfoValidator { |
171 | 164 | } |
172 | 165 | } |
173 | 166 | |
174 | - private void createClientSecurityInfoX509(EndpointSecurityInfo result, String endpoint) { | |
167 | + private void createClientSecurityInfoX509(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentialsConfig clientCredentialsConfig) { | |
175 | 168 | result.setSecurityInfo(SecurityInfo.newX509CertInfo(endpoint)); |
176 | - result.setSecurityMode(X509.code); | |
169 | + result.setSecurityMode(X509); | |
177 | 170 | } |
178 | 171 | } | ... | ... |
1 | +package org.thingsboard.server.transport.lwm2m.secure.credentials; | |
2 | + | |
3 | +import org.eclipse.leshan.core.util.Hex; | |
4 | + | |
5 | +public class HasKey { | |
6 | + private byte[] key; | |
7 | + | |
8 | + public void setKey(String key) { | |
9 | + if (key != null) { | |
10 | + this.key = Hex.decodeHex(key.toLowerCase().toCharArray()); | |
11 | + } | |
12 | + } | |
13 | + | |
14 | + public byte[] getKey() { | |
15 | + return key; | |
16 | + } | |
17 | +} | ... | ... |
1 | +package org.thingsboard.server.transport.lwm2m.secure.credentials; | |
2 | + | |
3 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
4 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |
5 | +import com.fasterxml.jackson.annotation.JsonSubTypes; | |
6 | +import com.fasterxml.jackson.annotation.JsonTypeInfo; | |
7 | +import org.eclipse.leshan.core.SecurityMode; | |
8 | + | |
9 | +@JsonIgnoreProperties(ignoreUnknown = true) | |
10 | +@JsonTypeInfo( | |
11 | + use = JsonTypeInfo.Id.NAME, | |
12 | + property = "securityConfigClientMode") | |
13 | +@JsonSubTypes({ | |
14 | + @JsonSubTypes.Type(value = NoSecClientCredentialsConfig.class, name = "NO_SEC"), | |
15 | + @JsonSubTypes.Type(value = PSKClientCredentialsConfig.class, name = "PSK"), | |
16 | + @JsonSubTypes.Type(value = RPKClientCredentialsConfig.class, name = "RPK"), | |
17 | + @JsonSubTypes.Type(value = X509ClientCredentialsConfig.class, name = "X509")}) | |
18 | +public interface LwM2MClientCredentialsConfig { | |
19 | + | |
20 | + @JsonIgnore | |
21 | + SecurityMode getSecurityConfigClientMode(); | |
22 | +} | ... | ... |
1 | +package org.thingsboard.server.transport.lwm2m.secure.credentials; | |
2 | + | |
3 | +import lombok.Data; | |
4 | +import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapConfig; | |
5 | + | |
6 | +@Data | |
7 | +public class LwM2MCredentials { | |
8 | + private LwM2MClientCredentialsConfig client; | |
9 | + private LwM2MBootstrapConfig bootstrap; | |
10 | +} | ... | ... |
1 | +package org.thingsboard.server.transport.lwm2m.secure.credentials; | |
2 | + | |
3 | +import org.eclipse.leshan.core.SecurityMode; | |
4 | + | |
5 | +import static org.eclipse.leshan.core.SecurityMode.NO_SEC; | |
6 | + | |
7 | +public class NoSecClientCredentialsConfig implements LwM2MClientCredentialsConfig { | |
8 | + | |
9 | + @Override | |
10 | + public SecurityMode getSecurityConfigClientMode() { | |
11 | + return NO_SEC; | |
12 | + } | |
13 | +} | ... | ... |
1 | +package org.thingsboard.server.transport.lwm2m.secure.credentials; | |
2 | + | |
3 | +import lombok.Data; | |
4 | +import org.eclipse.leshan.core.SecurityMode; | |
5 | + | |
6 | +import static org.eclipse.leshan.core.SecurityMode.PSK; | |
7 | + | |
8 | +@Data | |
9 | +public class PSKClientCredentialsConfig extends HasKey implements LwM2MClientCredentialsConfig { | |
10 | + private String identity; | |
11 | + private String endpoint; | |
12 | + | |
13 | + @Override | |
14 | + public SecurityMode getSecurityConfigClientMode() { | |
15 | + return PSK; | |
16 | + } | |
17 | +} | ... | ... |
1 | +package org.thingsboard.server.transport.lwm2m.secure.credentials; | |
2 | + | |
3 | +import org.eclipse.leshan.core.SecurityMode; | |
4 | + | |
5 | +import static org.eclipse.leshan.core.SecurityMode.RPK; | |
6 | + | |
7 | +public class RPKClientCredentialsConfig extends HasKey implements LwM2MClientCredentialsConfig { | |
8 | + | |
9 | + @Override | |
10 | + public SecurityMode getSecurityConfigClientMode() { | |
11 | + return RPK; | |
12 | + } | |
13 | +} | ... | ... |
1 | +package org.thingsboard.server.transport.lwm2m.secure.credentials; | |
2 | + | |
3 | +import lombok.Data; | |
4 | +import org.eclipse.leshan.core.SecurityMode; | |
5 | + | |
6 | +import static org.eclipse.leshan.core.SecurityMode.X509; | |
7 | + | |
8 | +@Data | |
9 | +public class X509ClientCredentialsConfig implements LwM2MClientCredentialsConfig { | |
10 | + private boolean allowTrustedOnly; | |
11 | + private String cert; | |
12 | + | |
13 | + @Override | |
14 | + public SecurityMode getSecurityConfigClientMode() { | |
15 | + return X509; | |
16 | + } | |
17 | +} | ... | ... |
... | ... | @@ -25,7 +25,6 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes |
25 | 25 | import org.thingsboard.server.gen.transport.TransportProtos; |
26 | 26 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
27 | 27 | import org.thingsboard.server.transport.lwm2m.secure.EndpointSecurityInfo; |
28 | -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | |
29 | 28 | import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; |
30 | 29 | import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; |
31 | 30 | import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; |
... | ... | @@ -38,7 +37,7 @@ import java.util.Set; |
38 | 37 | import java.util.UUID; |
39 | 38 | import java.util.concurrent.ConcurrentHashMap; |
40 | 39 | |
41 | -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; | |
40 | +import static org.eclipse.leshan.core.SecurityMode.NO_SEC; | |
42 | 41 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; |
43 | 42 | |
44 | 43 | @Service |
... | ... | @@ -111,7 +110,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { |
111 | 110 | @Override |
112 | 111 | public LwM2mClient fetchClientByEndpoint(String endpoint) { |
113 | 112 | EndpointSecurityInfo securityInfo = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endpoint, LwM2mTransportUtil.LwM2mTypeServer.CLIENT); |
114 | - if (securityInfo.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { | |
113 | + if (securityInfo.getSecurityMode() != null) { | |
115 | 114 | if (securityInfo.getDeviceProfile() != null) { |
116 | 115 | toClientProfile(securityInfo.getDeviceProfile()); |
117 | 116 | UUID profileUuid = securityInfo.getDeviceProfile().getUuidId(); |
... | ... | @@ -120,7 +119,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { |
120 | 119 | client = new LwM2mClient(context.getNodeId(), securityInfo.getSecurityInfo().getEndpoint(), |
121 | 120 | securityInfo.getSecurityInfo().getIdentity(), securityInfo.getSecurityInfo(), |
122 | 121 | securityInfo.getMsg(), profileUuid, UUID.randomUUID()); |
123 | - } else if (securityInfo.getSecurityMode() == NO_SEC.code) { | |
122 | + } else if (NO_SEC.equals(securityInfo.getSecurityMode())) { | |
124 | 123 | client = new LwM2mClient(context.getNodeId(), endpoint, |
125 | 124 | null, null, |
126 | 125 | securityInfo.getMsg(), profileUuid, UUID.randomUUID()); | ... | ... |