Merge branch 'lwm2m_fix_bug_release'

This commit is contained in:
Igor Kulikov 2022-01-13 10:41:40 +02:00
commit cffb657af7
6 changed files with 67 additions and 26 deletions

View File

@ -14,6 +14,7 @@
-- limitations under the License.
--
CREATE OR REPLACE PROCEDURE update_profile_bootstrap()
LANGUAGE plpgsql AS
$$
@ -25,9 +26,11 @@ BEGIN
profile_data,
'{transportConfiguration}',
get_bootstrap(
profile_data::jsonb #> '{transportConfiguration}',
subquery.publickey_bs,
subquery.publickey_lw),
profile_data::jsonb #> '{transportConfiguration}',
subquery.publickey_bs,
subquery.publickey_lw,
profile_data::json #>> '{transportConfiguration, bootstrap, bootstrapServer, securityMode}',
profile_data::json #>> '{transportConfiguration, bootstrap, lwm2mServer, securityMode}'),
true)
FROM (
SELECT id,
@ -48,7 +51,8 @@ END;
$$;
CREATE OR REPLACE FUNCTION get_bootstrap(transport_configuration_in jsonb, publickey_bs text,
publickey_lw text) RETURNS jsonb AS
publickey_lw text, security_mode_bs text,
security_mode_lw text) RETURNS jsonb AS
$$
DECLARE
@ -56,10 +60,19 @@ DECLARE
bootstrap_in jsonb;
BEGIN
IF security_mode_lw IS NULL THEN
security_mode_lw := 'NO_SEC';
END IF;
IF security_mode_bs IS NULL THEN
security_mode_bs := 'NO_SEC';
END IF;
bootstrap_in := transport_configuration_in::jsonb #> '{bootstrap}';
bootstrap_new := json_build_array(
json_build_object('shortServerId', bootstrap_in::json #> '{bootstrapServer}' -> 'serverId',
'securityMode', bootstrap_in::json #> '{bootstrapServer}' ->> 'securityMode',
'securityMode', security_mode_bs,
'binding', bootstrap_in::json #> '{servers}' ->> 'binding',
'lifetime', bootstrap_in::json #> '{servers}' -> 'lifetime',
'notifIfDisabled', bootstrap_in::json #> '{servers}' -> 'notifIfDisabled',
@ -73,7 +86,7 @@ BEGIN
bootstrap_in::json #> '{bootstrapServer}' -> 'bootstrapServerAccountTimeout'
),
json_build_object('shortServerId', bootstrap_in::json #> '{lwm2mServer}' -> 'serverId',
'securityMode', bootstrap_in::json #> '{lwm2mServer}' ->> 'securityMode',
'securityMode', security_mode_lw,
'binding', bootstrap_in::json #> '{servers}' ->> 'binding',
'lifetime', bootstrap_in::json #> '{servers}' -> 'lifetime',
'notifIfDisabled', bootstrap_in::json #> '{servers}' -> 'notifIfDisabled',
@ -93,7 +106,7 @@ BEGIN
bootstrap_new,
true) || '{"bootstrapServerUpdateEnable": true}';
END ;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE PROCEDURE update_device_credentials_to_base64_and_bootstrap()
@ -102,9 +115,9 @@ $$
BEGIN
UPDATE device_credentials
SET credentials_value = get_device_and_bootstrap(credentials_value::text)
WHERE credentials_type = 'LWM2M_CREDENTIALS';
UPDATE device_credentials
SET credentials_value = get_device_and_bootstrap(credentials_value::text)
WHERE credentials_type = 'LWM2M_CREDENTIALS';
END;
$$;
@ -112,7 +125,7 @@ CREATE OR REPLACE FUNCTION get_device_and_bootstrap(IN credentials_value text, O
LANGUAGE plpgsql AS
$$
DECLARE
client_secret_key text;
client_secret_key text;
client_public_key_or_id text;
client_key_value_object jsonb;
client_bootstrap_server_value_object jsonb;
@ -130,7 +143,7 @@ BEGIN
'key', client_public_key_or_id);
credentials_value_new :=
credentials_value_new::jsonb || json_build_object('client', client_key_value_object)::jsonb;
END IF;
END IF;
IF credentials_value::jsonb #> '{client}' ->> 'securityConfigClientMode' = 'X509' AND
NULLIF((credentials_value::jsonb #> '{client}' ->> 'cert' ~ '^[0-9a-fA-F]+$')::text, 'false') = 'true' THEN
client_public_key_or_id :=
@ -141,8 +154,8 @@ END IF;
'cert', client_public_key_or_id);
credentials_value_new :=
credentials_value_new::jsonb || json_build_object('client', client_key_value_object)::jsonb;
END IF;
END IF;
IF credentials_value::jsonb #> '{bootstrap,lwm2mServer}' ->> 'securityMode' = 'RPK' OR
credentials_value::jsonb #> '{bootstrap,lwm2mServer}' ->> 'securityMode' = 'X509' THEN
IF NULLIF((credentials_value::jsonb #> '{bootstrap,lwm2mServer}' ->> 'clientSecretKey' ~ '^[0-9a-fA-F]+$')::text,
@ -165,9 +178,9 @@ END IF;
client_bootstrap_object := credentials_value_new::jsonb #> '{bootstrap}' || client_bootstrap_server_object::jsonb;
credentials_value_new :=
jsonb_set(credentials_value_new::jsonb, '{bootstrap}', client_bootstrap_object::jsonb, false)::jsonb;
END IF;
END IF;
END IF;
END IF;
IF credentials_value::jsonb #> '{bootstrap,bootstrapServer}' ->> 'securityMode' = 'RPK' OR
credentials_value::jsonb #> '{bootstrap,bootstrapServer}' ->> 'securityMode' = 'X509' THEN
IF NULLIF(
@ -193,8 +206,8 @@ END IF;
client_bootstrap_object := credentials_value_new::jsonb #> '{bootstrap}' || client_bootstrap_server_object::jsonb;
credentials_value_new :=
jsonb_set(credentials_value_new::jsonb, '{bootstrap}', client_bootstrap_object::jsonb, false)::jsonb;
END IF;
END IF;
END IF;
END IF;
END;
$$;

View File

@ -63,6 +63,12 @@ public class LwM2MServiceImpl implements LwM2MService {
} else {
bsServ.setServerPublicKey(Base64.encodeBase64String(publicKeyBase64));
}
byte[] certificateBase64 = getCertificate(bsServerConfig);
if (certificateBase64 == null) {
bsServ.setServerCertificate("");
} else {
bsServ.setServerCertificate(Base64.encodeBase64String(certificateBase64));
}
return bsServ;
}
@ -77,5 +83,17 @@ public class LwM2MServiceImpl implements LwM2MService {
}
return null;
}
private byte[] getCertificate(LwM2MSecureServerConfig config) {
try {
SslCredentials sslCredentials = config.getSslCredentials();
if (sslCredentials != null) {
return sslCredentials.getCertificateChain()[0].getEncoded();
}
} catch (Exception e) {
log.trace("Failed to fetch certificate from key store!", e);
}
return null;
}
}

View File

@ -42,17 +42,23 @@ public class LwM2MServerSecurityConfig {
@ApiModelProperty(position = 8, value = "Server Public Key for 'Security' mode (DTLS): RPK or X509. Format: base64 encoded", example = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAZ0pSaGKHk/GrDaUDnQZpeEdGwX7m3Ws+U/kiVat\n" +
"+44sgk3c8g0LotfMpLlZJPhPwJ6ipXV+O1r7IZUjBs3LNA==", readOnly = true)
protected String serverPublicKey;
@ApiModelProperty(position = 9, value = "Bootstrap Server Account Timeout (If the value is set to 0, or if this resource is not instantiated, the Bootstrap-Server Account lifetime is infinite.)", example = "0", readOnly = true)
@ApiModelProperty(position = 9, value = "Server Public Key for 'Security' mode (DTLS): X509. Format: base64 encoded", example = "MMIICODCCAd6gAwIBAgIUI88U1zowOdrxDK/dOV+36gJxI2MwCgYIKoZIzj0EAwIwejELMAkGA1UEBhMCVUs\n" +
"xEjAQBgNVBAgTCUt5aXYgY2l0eTENMAsGA1UEBxMES3lpdjEUMBIGA1UEChMLVGhpbmdzYm9hcmQxFzAVBgNVBAsMDkRFVkVMT1BFUl9URVNUMRkwFwYDVQQDDBBpbnRlcm1lZGlhdGVfY2EwMB4XDTIyMDEwOTEzMDMwMFoXDTI3MDEwODEzMDMwMFowFDESMBAGA1UEAxM\n" +
"JbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUO3vBo/JTv0eooY7XHiKAIVDoWKFqtrU7C6q8AIKqpLcqhCdW+haFeBOH3PjY6EwaWkY04Bir4oanU0s7tz2uKOBpzCBpDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/\n" +
"BAIwADAdBgNVHQ4EFgQUEjc3Q4a0TxzP/3x3EV4fHxYUg0YwHwYDVR0jBBgwFoAUuSquGycMU6Q0SYNcbtSkSD3TfH0wLwYDVR0RBCgwJoIVbG9jYWxob3N0LmxvY2FsZG9tYWlugglsb2NhbGhvc3SCAiAtMAoGCCqGSM49BAMCA0gAMEUCIQD7dbZObyUaoDiNbX+9fUNp\n" +
"AWrD7N7XuJUwZ9FcN75R3gIgb2RNjDkHoyUyF1YajwkBk+7XmIXNClmizNJigj908mw=", readOnly = true)
protected String serverCertificate;
@ApiModelProperty(position = 10, value = "Bootstrap Server Account Timeout (If the value is set to 0, or if this resource is not instantiated, the Bootstrap-Server Account lifetime is infinite.)", example = "0", readOnly = true)
Integer bootstrapServerAccountTimeout = 0;
/** Config -> ObjectId = 1 'LwM2M Server' */
@ApiModelProperty(position = 10, value = "Specify the lifetime of the registration in seconds.", example = "300", readOnly = true)
@ApiModelProperty(position = 11, value = "Specify the lifetime of the registration in seconds.", example = "300", readOnly = true)
private Integer lifetime = 300;
@ApiModelProperty(position = 11, value = "The default value the LwM2M Client should use for the Minimum Period of an Observation in the absence of this parameter being included in an Observation. " +
@ApiModelProperty(position = 12, value = "The default value the LwM2M Client should use for the Minimum Period of an Observation in the absence of this parameter being included in an Observation. " +
"If this Resource doesnt exist, the default value is 0.", example = "1", readOnly = true)
private Integer defaultMinPeriod = 1;
/** ResourceID=6 'Notification Storing When Disabled or Offline' */
@ApiModelProperty(position = 12, value = "If true, the LwM2M Client stores “Notify” operations to the LwM2M Server while the LwM2M Server account is disabled or the LwM2M Client is offline. After the LwM2M Server account is enabled or the LwM2M Client is online, the LwM2M Client reports the stored “Notify” operations to the Server. " +
@ApiModelProperty(position = 13, value = "If true, the LwM2M Client stores “Notify” operations to the LwM2M Server while the LwM2M Server account is disabled or the LwM2M Client is offline. After the LwM2M Server account is enabled or the LwM2M Client is online, the LwM2M Client reports the stored “Notify” operations to the Server. " +
"If false, the LwM2M Client discards all the “Notify” operations or temporarily disables the Observe function while the LwM2M Server is disabled or the LwM2M Client is offline. " +
"The default value is true.", example = "true", readOnly = true)
private boolean notifIfDisabled = true;

View File

@ -765,15 +765,15 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
X509LwM2MBootstrapServerCredential x509ServerCredentials = (X509LwM2MBootstrapServerCredential) bootstrapServerConfig;
server = x509ServerCredentials.isBootstrapServerIs() ? "Bootstrap Server" : "LwM2M Server";
if (StringUtils.isEmpty(x509ServerCredentials.getServerPublicKey())) {
throw new DeviceCredentialsValidationException(server + " X509 public key must be specified!");
throw new DeviceCredentialsValidationException(server + " X509 certificate must be specified!");
}
try {
String certServer = EncryptionUtil.certTrimNewLines(x509ServerCredentials.getServerPublicKey());
x509ServerCredentials.setServerPublicKey(certServer);
SecurityUtil.publicKey.decode(x509ServerCredentials.getDecodedCServerPublicKey());
SecurityUtil.certificate.decode(x509ServerCredentials.getDecodedCServerPublicKey());
} catch (Exception e) {
throw new DeviceCredentialsValidationException(server + " X509 public key must be in standard [RFC7250] and then encoded to Base64 format!");
throw new DeviceCredentialsValidationException(server + " X509 certificate must be in DER-encoded X509v3 format and support only EC algorithm and then encoded to Base64 format!");
}
break;
}

View File

@ -112,6 +112,9 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc
this.changeSecurityHostPortFields(serverSecurityConfig);
}
this.serverFormGroup.patchValue(serverSecurityConfig, {emitEvent: false});
if (this.currentSecurityMode === Lwm2mSecurityType.X509) {
this.serverFormGroup.get('serverPublicKey').patchValue(serverSecurityConfig.serverCertificate, {emitEvent: false});
}
});
this.serverFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)

View File

@ -129,6 +129,7 @@ export interface ServerSecurityConfig {
securityHost?: string;
securityPort?: number;
serverPublicKey?: string;
serverCertificate?: string;
clientHoldOffTime?: number;
shortServerId?: number;
bootstrapServerAccountTimeout: number;