diff --git a/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/service/device/AbstractDeviceManagementService.java b/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/service/device/AbstractDeviceManagementService.java index 2eb134b444..762573463a 100644 --- a/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/service/device/AbstractDeviceManagementService.java +++ b/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/service/device/AbstractDeviceManagementService.java @@ -10,6 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ + package org.eclipse.hono.deviceregistry.service.device; import java.net.HttpURLConnection; @@ -19,10 +20,13 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; +import java.util.regex.Matcher; +import org.eclipse.hono.client.ClientErrorException; import org.eclipse.hono.client.ServerErrorException; import org.eclipse.hono.client.ServiceInvocationException; import org.eclipse.hono.client.util.StatusCodeMapper; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.deviceregistry.service.tenant.NoopTenantInformationService; import org.eclipse.hono.deviceregistry.service.tenant.TenantInformationService; import org.eclipse.hono.deviceregistry.util.DeviceRegistryUtils; @@ -64,15 +68,19 @@ public abstract class AbstractDeviceManagementService implements DeviceManagemen private final Handler notificationSender; + private final ServiceConfigProperties serviceConfig; + /** * Creates a new AbstractDeviceManagementService. * * @param vertx The vert.x instance to use. + * @param serviceConfig The service config instance to use for device id validation. * @throws NullPointerException if vertx is {@code null}. */ - protected AbstractDeviceManagementService(final Vertx vertx) { + protected AbstractDeviceManagementService(final Vertx vertx, final ServiceConfigProperties serviceConfig) { this.vertx = Objects.requireNonNull(vertx); this.notificationSender = NotificationEventBusSupport.getNotificationSender(vertx); + this.serviceConfig = serviceConfig; } /** @@ -276,6 +284,15 @@ public final Future> createDevice( Objects.requireNonNull(span); final String deviceIdValue = deviceId.orElseGet(() -> generateDeviceId(tenantId)); + final Matcher matcher = Objects.requireNonNull(serviceConfig.getDeviceIdPattern()).matcher(deviceIdValue); + + if (!matcher.matches()) { + return Future.failedFuture(new ClientErrorException( + tenantId, + HttpURLConnection.HTTP_BAD_REQUEST, + "invalid device id \"" + deviceIdValue + "\"" + )); + } return this.tenantInformationService .tenantExists(tenantId, span) diff --git a/services/device-registry-base/src/test/java/org/eclipse/hono/deviceregistry/service/device/AbstractDeviceManagementServiceTest.java b/services/device-registry-base/src/test/java/org/eclipse/hono/deviceregistry/service/device/AbstractDeviceManagementServiceTest.java index da27a38349..68409c9afd 100644 --- a/services/device-registry-base/src/test/java/org/eclipse/hono/deviceregistry/service/device/AbstractDeviceManagementServiceTest.java +++ b/services/device-registry-base/src/test/java/org/eclipse/hono/deviceregistry/service/device/AbstractDeviceManagementServiceTest.java @@ -27,7 +27,9 @@ import java.net.HttpURLConnection; import java.util.List; import java.util.Optional; +import java.util.regex.Pattern; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.notification.NotificationEventBusSupport; import org.eclipse.hono.notification.deviceregistry.AllDevicesOfTenantDeletedNotification; import org.eclipse.hono.notification.deviceregistry.DeviceChangeNotification; @@ -36,6 +38,7 @@ import org.eclipse.hono.service.management.OperationResult; import org.eclipse.hono.service.management.Result; import org.eclipse.hono.service.management.device.Device; +import org.eclipse.hono.util.RegistryManagementConstants; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -67,7 +70,10 @@ void setUp() { eventBus = mock(EventBus.class); final Vertx vertx = mock(Vertx.class); when(vertx.eventBus()).thenReturn(eventBus); - deviceManagementService = new TestDeviceManagementService(vertx); + final ServiceConfigProperties serviceConfig = mock(ServiceConfigProperties.class); + when(serviceConfig.getDeviceIdPattern()) + .thenReturn(Pattern.compile(RegistryManagementConstants.DEFAULT_REGEX_DEVICE_ID)); + deviceManagementService = new TestDeviceManagementService(vertx, serviceConfig); } /** @@ -223,8 +229,8 @@ public void testNotificationOnDeleteDevicesOfTenant(final VertxTestContext conte private static class TestDeviceManagementService extends AbstractDeviceManagementService { - TestDeviceManagementService(final Vertx vertx) { - super(vertx); + TestDeviceManagementService(final Vertx vertx, final ServiceConfigProperties serviceConfig) { + super(vertx, serviceConfig); } @Override diff --git a/services/device-registry-base/src/test/java/org/eclipse/hono/service/registration/AbstractRegistrationServiceTest.java b/services/device-registry-base/src/test/java/org/eclipse/hono/service/registration/AbstractRegistrationServiceTest.java index 19840ebe06..b1501a7e5e 100644 --- a/services/device-registry-base/src/test/java/org/eclipse/hono/service/registration/AbstractRegistrationServiceTest.java +++ b/services/device-registry-base/src/test/java/org/eclipse/hono/service/registration/AbstractRegistrationServiceTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2016 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -10,6 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ + package org.eclipse.hono.service.registration; import static com.google.common.truth.Truth.assertThat; @@ -61,6 +62,10 @@ public interface AbstractRegistrationServiceTest { * The device identifier used in tests. */ String DEVICE = "4711"; + /** + * Invalid device identifier used in tests. + */ + String INVALID_DEVICE = "**4711++"; /** * The gateway identifier used in the tests. */ diff --git a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/ManagementServicesProducer.java b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/ManagementServicesProducer.java index c307939d7d..89976b32b9 100644 --- a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/ManagementServicesProducer.java +++ b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/ManagementServicesProducer.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -11,9 +11,9 @@ * SPDX-License-Identifier: EPL-2.0 */ - package org.eclipse.hono.deviceregistry.jdbc.app; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.deviceregistry.jdbc.config.DeviceServiceOptions; import org.eclipse.hono.deviceregistry.jdbc.impl.CredentialsManagementServiceImpl; import org.eclipse.hono.deviceregistry.jdbc.impl.DeviceManagementServiceImpl; @@ -82,9 +82,14 @@ public TenantManagementService tenantManagementService( public DeviceManagementService deviceManagementService( final TableManagementStore devicesManagementStore, final DeviceServiceOptions deviceServiceOptions, - final TenantInformationService tenantInformationService) { + final TenantInformationService tenantInformationService, + final ServiceConfigProperties serviceConfigProperties) { - final var service = new DeviceManagementServiceImpl(vertx, devicesManagementStore, deviceServiceOptions); + final var service = new DeviceManagementServiceImpl( + vertx, + devicesManagementStore, + deviceServiceOptions, + serviceConfigProperties); service.setTenantInformationService(tenantInformationService); return service; } diff --git a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/impl/DeviceManagementServiceImpl.java b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/impl/DeviceManagementServiceImpl.java index d8a569ffec..954c3c1e49 100644 --- a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/impl/DeviceManagementServiceImpl.java +++ b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/impl/DeviceManagementServiceImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020, 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2020 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -20,6 +20,7 @@ import java.util.UUID; import org.eclipse.hono.client.ClientErrorException; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.deviceregistry.jdbc.config.DeviceServiceOptions; import org.eclipse.hono.deviceregistry.service.device.AbstractDeviceManagementService; import org.eclipse.hono.deviceregistry.service.device.DeviceKey; @@ -54,8 +55,12 @@ public class DeviceManagementServiceImpl extends AbstractDeviceManagementService * @param store The backing store to use. * @param properties The service properties. */ - public DeviceManagementServiceImpl(final Vertx vertx, final TableManagementStore store, final DeviceServiceOptions properties) { - super(vertx); + public DeviceManagementServiceImpl( + final Vertx vertx, + final TableManagementStore store, + final DeviceServiceOptions properties, + final ServiceConfigProperties serviceConfig) { + super(vertx, serviceConfig); this.store = store; this.ttl = Optional.of(CacheDirective.maxAgeDirective(properties.registrationTtl())); this.config = properties; diff --git a/services/device-registry-jdbc/src/test/java/org/eclipse/hono/deviceregistry/jdbc/impl/AbstractJdbcRegistryTest.java b/services/device-registry-jdbc/src/test/java/org/eclipse/hono/deviceregistry/jdbc/impl/AbstractJdbcRegistryTest.java index 584087fe37..22ab9e00ca 100644 --- a/services/device-registry-jdbc/src/test/java/org/eclipse/hono/deviceregistry/jdbc/impl/AbstractJdbcRegistryTest.java +++ b/services/device-registry-jdbc/src/test/java/org/eclipse/hono/deviceregistry/jdbc/impl/AbstractJdbcRegistryTest.java @@ -36,6 +36,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.deviceregistry.jdbc.config.DeviceServiceOptions; import org.eclipse.hono.deviceregistry.jdbc.config.TenantServiceOptions; import org.eclipse.hono.deviceregistry.service.tenant.TenantInformationService; @@ -129,6 +130,8 @@ void startDevices(final Vertx vertx) throws IOException, SQLException { when(properties.credentialsTtl()).thenReturn(Duration.ofMinutes(1)); when(properties.registrationTtl()).thenReturn(Duration.ofMinutes(1)); + final ServiceConfigProperties serviceConfig = new ServiceConfigProperties(); + this.credentialsAdapter = new CredentialsServiceImpl( DeviceStores.adapterStoreFactory().createTable(vertx, TRACER, jdbc, Optional.empty(), Optional.empty(), Optional.empty()), properties @@ -147,7 +150,8 @@ void startDevices(final Vertx vertx) throws IOException, SQLException { this.registrationManagement = new DeviceManagementServiceImpl( vertx, DeviceStores.managementStoreFactory().createTable(vertx, TRACER, jdbc, Optional.empty(), Optional.empty(), Optional.empty()), - properties + properties, + serviceConfig ); tenantInformationService = mock(TenantInformationService.class); diff --git a/services/device-registry-jdbc/src/test/java/org/eclipse/hono/deviceregistry/jdbc/impl/JdbcBasedRegistrationServiceTest.java b/services/device-registry-jdbc/src/test/java/org/eclipse/hono/deviceregistry/jdbc/impl/JdbcBasedRegistrationServiceTest.java index e7facbdaa2..358e23109e 100644 --- a/services/device-registry-jdbc/src/test/java/org/eclipse/hono/deviceregistry/jdbc/impl/JdbcBasedRegistrationServiceTest.java +++ b/services/device-registry-jdbc/src/test/java/org/eclipse/hono/deviceregistry/jdbc/impl/JdbcBasedRegistrationServiceTest.java @@ -73,4 +73,18 @@ public void testCreateDeviceFailsIfTenantLevelDeviceLimitHasBeenReached(final Ve ctx.completeNow(); })); } + + /** + * Verifies that a request to create device with device id which does not match the device id pattern fails with a 400. + * + * @param ctx The vert.x test context. + */ + @Test + public void testCreateDeviceFailsIfDeviceIdDoesNotMatchDeviceIdPattern(final VertxTestContext ctx) { + getDeviceManagementService().createDevice(TENANT, Optional.of(INVALID_DEVICE), new Device(), NoopSpan.INSTANCE) + .onComplete(ctx.failing(t -> { + ctx.verify(() -> Assertions.assertServiceInvocationException(t, HttpURLConnection.HTTP_BAD_REQUEST)); + ctx.completeNow(); + })); + } } diff --git a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/ManagementServicesProducer.java b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/ManagementServicesProducer.java index 9b5f3d9a59..4f18cebaa0 100644 --- a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/ManagementServicesProducer.java +++ b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/ManagementServicesProducer.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -14,6 +14,7 @@ package org.eclipse.hono.deviceregistry.mongodb.app; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedCredentialsConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedRegistrationConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedTenantsConfigProperties; @@ -55,6 +56,9 @@ public class ManagementServicesProducer { @Inject MongoDbBasedCredentialsConfigProperties credentialsServiceProperties; + @Inject + ServiceConfigProperties serviceConfigProperties; + /** * Creates a service for retrieving tenant information. * @@ -102,7 +106,8 @@ public DeviceManagementService deviceManagementService( vertx, deviceDao, credentialsDao, - registrationServiceProperties); + registrationServiceProperties, + serviceConfigProperties); service.setTenantInformationService(tenantInformationService); return service; } diff --git a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedDeviceManagementService.java b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedDeviceManagementService.java index abd979fc3c..b6ae83fb9c 100644 --- a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedDeviceManagementService.java +++ b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedDeviceManagementService.java @@ -17,6 +17,7 @@ import java.util.Objects; import java.util.Optional; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedRegistrationConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.model.CredentialsDao; import org.eclipse.hono.deviceregistry.mongodb.model.DeviceDao; @@ -68,8 +69,9 @@ public MongoDbBasedDeviceManagementService( final Vertx vertx, final DeviceDao deviceDao, final CredentialsDao credentialsDao, - final MongoDbBasedRegistrationConfigProperties config) { - super(vertx); + final MongoDbBasedRegistrationConfigProperties config, + final ServiceConfigProperties serviceConfig) { + super(vertx, serviceConfig); Objects.requireNonNull(deviceDao); Objects.requireNonNull(credentialsDao); Objects.requireNonNull(config); diff --git a/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDBBasedDeviceManagementSearchDevicesTest.java b/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDBBasedDeviceManagementSearchDevicesTest.java index 5dc1c61b54..9006a5633f 100644 --- a/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDBBasedDeviceManagementSearchDevicesTest.java +++ b/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDBBasedDeviceManagementSearchDevicesTest.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedRegistrationConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.model.MongoDbBasedCredentialsDao; import org.eclipse.hono.deviceregistry.mongodb.model.MongoDbBasedDeviceDao; @@ -49,6 +50,7 @@ public final class MongoDBBasedDeviceManagementSearchDevicesTest implements Abst private static final String DB_NAME = "hono-search-devices-test"; private static final Logger LOG = LoggerFactory.getLogger(MongoDBBasedDeviceManagementSearchDevicesTest.class); private final MongoDbBasedRegistrationConfigProperties config = new MongoDbBasedRegistrationConfigProperties(); + private final ServiceConfigProperties serviceConfig = new ServiceConfigProperties(); private MongoDbBasedDeviceDao deviceDao; private MongoDbBasedCredentialsDao credentialsDao; private MongoDbBasedDeviceManagementService service; @@ -65,7 +67,7 @@ public void setup(final VertxTestContext testContext) { vertx = Vertx.vertx(); deviceDao = MongoDbTestUtils.getDeviceDao(vertx, DB_NAME); credentialsDao = MongoDbTestUtils.getCredentialsDao(vertx, DB_NAME); - service = new MongoDbBasedDeviceManagementService(vertx, deviceDao, credentialsDao, config); + service = new MongoDbBasedDeviceManagementService(vertx, deviceDao, credentialsDao, config, serviceConfig); Future.all(deviceDao.createIndices(), credentialsDao.createIndices()).onComplete(testContext.succeedingThenComplete()); } diff --git a/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedCredentialServiceTest.java b/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedCredentialServiceTest.java index 18b350efe6..e53ca6d414 100644 --- a/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedCredentialServiceTest.java +++ b/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedCredentialServiceTest.java @@ -25,6 +25,7 @@ import java.util.UUID; import java.util.concurrent.TimeUnit; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedCredentialsConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedRegistrationConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.model.MongoDbBasedCredentialsDao; @@ -80,6 +81,7 @@ public class MongoDbBasedCredentialServiceTest implements CredentialsServiceTest private final MongoDbBasedCredentialsConfigProperties credentialsServiceConfig = new MongoDbBasedCredentialsConfigProperties(); private final MongoDbBasedRegistrationConfigProperties registrationServiceConfig = new MongoDbBasedRegistrationConfigProperties(); + private final ServiceConfigProperties serviceConfig = new ServiceConfigProperties(); private MongoDbBasedCredentialsDao credentialsDao; private MongoDbBasedDeviceDao deviceDao; @@ -112,7 +114,8 @@ public void createServices(final VertxTestContext ctx) { vertx, deviceDao, credentialsDao, - registrationServiceConfig); + registrationServiceConfig, + serviceConfig); Future.all(deviceDao.createIndices(), credentialsDao.createIndices()) .onComplete(ctx.succeedingThenComplete()); diff --git a/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedRegistrationServiceTest.java b/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedRegistrationServiceTest.java index 3c44373d4d..ca3639cfab 100644 --- a/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedRegistrationServiceTest.java +++ b/services/device-registry-mongodb/src/test/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedRegistrationServiceTest.java @@ -24,6 +24,7 @@ import org.eclipse.hono.client.telemetry.EventSender; import org.eclipse.hono.client.util.MessagingClientProvider; +import org.eclipse.hono.config.ServiceConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedRegistrationConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.model.MongoDbBasedCredentialsDao; import org.eclipse.hono.deviceregistry.mongodb.model.MongoDbBasedDeviceDao; @@ -74,6 +75,7 @@ public class MongoDbBasedRegistrationServiceTest implements AbstractRegistration private static final Logger LOG = LoggerFactory.getLogger(MongoDbBasedRegistrationServiceTest.class); private final MongoDbBasedRegistrationConfigProperties config = new MongoDbBasedRegistrationConfigProperties(); + private final ServiceConfigProperties serviceConfig = new ServiceConfigProperties(); private MongoDbBasedDeviceDao deviceDao; private MongoDbBasedCredentialsDao credentialsDao; @@ -93,7 +95,12 @@ public void startService(final VertxTestContext testContext) { vertx = Vertx.vertx(); deviceDao = MongoDbTestUtils.getDeviceDao(vertx, DB_NAME); credentialsDao = MongoDbTestUtils.getCredentialsDao(vertx, DB_NAME); - deviceManagementService = new MongoDbBasedDeviceManagementService(vertx, deviceDao, credentialsDao, config); + deviceManagementService = new MongoDbBasedDeviceManagementService( + vertx, + deviceDao, + credentialsDao, + config, + serviceConfig); final EdgeDeviceAutoProvisioner edgeDeviceAutoProvisioner = new EdgeDeviceAutoProvisioner( vertx, @@ -225,6 +232,20 @@ public void testCreateDeviceFailsIfTenantLevelDeviceLimitHasBeenReached(final Ve })); } + /** + * Verifies that a request to create device with device id which does not match the device id pattern fails with a 400. + * + * @param ctx The vert.x test context. + */ + @Test + public void testCreateDeviceFailsIfDeviceIdDoesNotMatchDeviceIdPattern(final VertxTestContext ctx) { + getDeviceManagementService().createDevice(TENANT, Optional.of(INVALID_DEVICE), new Device(), NoopSpan.INSTANCE) + .onComplete(ctx.failing(t -> { + ctx.verify(() -> Assertions.assertServiceInvocationException(t, HttpURLConnection.HTTP_BAD_REQUEST)); + ctx.completeNow(); + })); + } + /** * Verifies that a request to delete a device succeeds even if the tenant that the device belongs to does not * exist (anymore).