From 09cc371670c0cdaf36e29f88a0110819c34f6f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harri=20Sm=C3=A5tt?= Date: Sun, 2 Jun 2024 10:51:02 +0300 Subject: [PATCH] [#3608] Verify that auto-provisioned device ids match device id pattern --- .../AbstractDeviceManagementService.java | 19 ++++++++- .../AbstractDeviceManagementServiceTest.java | 8 ++-- .../AbstractRegistrationServiceTest.java | 7 +++- .../jdbc/app/HttpServerFactory.java | 12 +++--- .../jdbc/app/ManagementServicesProducer.java | 14 +++++-- .../JdbcBasedHttpServiceConfigOptions.java | 35 ++++++++++++++++ .../JdbcBasedHttpServiceConfigProperties.java | 40 +++++++++++++++++++ .../impl/DeviceManagementServiceImpl.java | 12 ++++-- .../jdbc/impl/AbstractJdbcRegistryTest.java | 6 ++- .../JdbcBasedRegistrationServiceTest.java | 16 +++++++- .../app/ManagementServicesProducer.java | 11 +++-- .../MongoDbBasedDeviceManagementService.java | 10 +++-- ...asedDeviceManagementSearchDevicesTest.java | 4 +- .../MongoDbBasedCredentialServiceTest.java | 8 +++- .../MongoDbBasedRegistrationServiceTest.java | 26 +++++++++++- .../registry/DeviceRegistrationApiTests.java | 28 ++++++++++++- 16 files changed, 224 insertions(+), 32 deletions(-) create mode 100644 services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/config/JdbcBasedHttpServiceConfigOptions.java create mode 100644 services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/config/JdbcBasedHttpServiceConfigProperties.java 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..dec73b1511 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 = serviceConfig.getDeviceIdPattern().matcher(deviceIdValue); + + if (!matcher.matches()) { + return Future.failedFuture(new ClientErrorException( + tenantId, + HttpURLConnection.HTTP_BAD_REQUEST, + "invalid device ID: %s".formatted(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..22a2291abe 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 @@ -28,6 +28,7 @@ import java.util.List; import java.util.Optional; +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; @@ -67,7 +68,8 @@ void setUp() { eventBus = mock(EventBus.class); final Vertx vertx = mock(Vertx.class); when(vertx.eventBus()).thenReturn(eventBus); - deviceManagementService = new TestDeviceManagementService(vertx); + final ServiceConfigProperties serviceConfig = new ServiceConfigProperties(); + deviceManagementService = new TestDeviceManagementService(vertx, serviceConfig); } /** @@ -223,8 +225,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/HttpServerFactory.java b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/HttpServerFactory.java index 1907257003..11c39669eb 100644 --- a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/HttpServerFactory.java +++ b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/HttpServerFactory.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,10 +14,10 @@ package org.eclipse.hono.deviceregistry.jdbc.app; import org.eclipse.hono.deviceregistry.app.AbstractHttpServerFactory; -import org.eclipse.hono.service.http.HttpServiceConfigOptions; +import org.eclipse.hono.deviceregistry.jdbc.config.JdbcBasedHttpServiceConfigOptions; +import org.eclipse.hono.deviceregistry.jdbc.config.JdbcBasedHttpServiceConfigProperties; import org.eclipse.hono.service.http.HttpServiceConfigProperties; -import io.smallrye.config.ConfigMapping; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -31,10 +31,8 @@ public class HttpServerFactory extends AbstractHttpServerFactory { private HttpServiceConfigProperties httpServerProperties; @Inject - void setHttpServerProperties( - @ConfigMapping(prefix = "hono.registry.http") - final HttpServiceConfigOptions endpointOptions) { - this.httpServerProperties = new HttpServiceConfigProperties(endpointOptions); + void setHttpServerProperties(final JdbcBasedHttpServiceConfigOptions endpointOptions) { + this.httpServerProperties = new JdbcBasedHttpServiceConfigProperties(endpointOptions); } @Override 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..dc9a9cbd4f 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,10 +11,11 @@ * SPDX-License-Identifier: EPL-2.0 */ - package org.eclipse.hono.deviceregistry.jdbc.app; import org.eclipse.hono.deviceregistry.jdbc.config.DeviceServiceOptions; +import org.eclipse.hono.deviceregistry.jdbc.config.JdbcBasedHttpServiceConfigOptions; +import org.eclipse.hono.deviceregistry.jdbc.config.JdbcBasedHttpServiceConfigProperties; import org.eclipse.hono.deviceregistry.jdbc.impl.CredentialsManagementServiceImpl; import org.eclipse.hono.deviceregistry.jdbc.impl.DeviceManagementServiceImpl; import org.eclipse.hono.deviceregistry.jdbc.impl.StoreBasedTenantInformationService; @@ -44,6 +45,9 @@ public class ManagementServicesProducer { @Inject Vertx vertx; + @Inject + JdbcBasedHttpServiceConfigOptions jdbcBasedHttpServiceConfigOptions; + /** * Creates a service for retrieving tenant information. * @@ -84,7 +88,11 @@ public DeviceManagementService deviceManagementService( final DeviceServiceOptions deviceServiceOptions, final TenantInformationService tenantInformationService) { - final var service = new DeviceManagementServiceImpl(vertx, devicesManagementStore, deviceServiceOptions); + final var service = new DeviceManagementServiceImpl( + vertx, + devicesManagementStore, + deviceServiceOptions, + new JdbcBasedHttpServiceConfigProperties(jdbcBasedHttpServiceConfigOptions)); service.setTenantInformationService(tenantInformationService); return service; } diff --git a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/config/JdbcBasedHttpServiceConfigOptions.java b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/config/JdbcBasedHttpServiceConfigOptions.java new file mode 100644 index 0000000000..7c17cd0ac0 --- /dev/null +++ b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/config/JdbcBasedHttpServiceConfigOptions.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.eclipse.hono.deviceregistry.jdbc.config; + +import org.eclipse.hono.service.http.HttpServiceConfigOptions; + +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithParentName; + +/** + * Configuration properties for the JDBC based registry's HTTP endpoint. + */ +@ConfigMapping(prefix = "hono.registry.http", namingStrategy = ConfigMapping.NamingStrategy.VERBATIM) +public interface JdbcBasedHttpServiceConfigOptions { + + /** + * Gets the HTTP service configuration. + * + * @return The options. + */ + @WithParentName + HttpServiceConfigOptions commonOptions(); + +} diff --git a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/config/JdbcBasedHttpServiceConfigProperties.java b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/config/JdbcBasedHttpServiceConfigProperties.java new file mode 100644 index 0000000000..91cc83f17a --- /dev/null +++ b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/config/JdbcBasedHttpServiceConfigProperties.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.eclipse.hono.deviceregistry.jdbc.config; + +import org.eclipse.hono.service.http.HttpServiceConfigProperties; + +/** + * Configuration properties for the registry's HTTP endpoint. + */ +public class JdbcBasedHttpServiceConfigProperties extends HttpServiceConfigProperties { + + /** + * Creates default properties. + */ + public JdbcBasedHttpServiceConfigProperties() { + super(); + } + + /** + * Creates properties from existing options. + * + * @param options The options. + * @throws NullPointerException if options are {@code null}. + */ + public JdbcBasedHttpServiceConfigProperties(final JdbcBasedHttpServiceConfigOptions options) { + super(options.commonOptions()); + } + +} 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..01ea9778bb 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; @@ -53,9 +54,14 @@ public class DeviceManagementServiceImpl extends AbstractDeviceManagementService * @param vertx The vert.x instance to use. * @param store The backing store to use. * @param properties The service properties. + * @param serviceConfig The service config to use. */ - 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..139df9601d 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020, 2021 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. @@ -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..044c5b7be9 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. @@ -11,10 +11,11 @@ * SPDX-License-Identifier: EPL-2.0 */ - package org.eclipse.hono.deviceregistry.mongodb.app; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedCredentialsConfigProperties; +import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedHttpServiceConfigOptions; +import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedHttpServiceConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedRegistrationConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedTenantsConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.model.CredentialsDao; @@ -55,6 +56,9 @@ public class ManagementServicesProducer { @Inject MongoDbBasedCredentialsConfigProperties credentialsServiceProperties; + @Inject + MongoDbBasedHttpServiceConfigOptions mongoDbBasedHttpServiceConfigOptions; + /** * Creates a service for retrieving tenant information. * @@ -102,7 +106,8 @@ public DeviceManagementService deviceManagementService( vertx, deviceDao, credentialsDao, - registrationServiceProperties); + registrationServiceProperties, + new MongoDbBasedHttpServiceConfigProperties(mongoDbBasedHttpServiceConfigOptions)); 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..548c2c8a3a 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2021 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.deviceregistry.mongodb.service; import java.net.HttpURLConnection; @@ -17,6 +18,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; @@ -62,14 +64,16 @@ public final class MongoDbBasedDeviceManagementService extends AbstractDeviceMan * @param deviceDao The data access object to use for accessing device data in the MongoDB. * @param credentialsDao The data access object to use for accessing credentials data in the MongoDB. * @param config The properties for configuring this service. + * @param serviceConfig The service config to use. * @throws NullPointerException if any of the parameters are {@code null}. */ 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..f4b7324678 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 @@ -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. @@ -10,6 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ + package org.eclipse.hono.deviceregistry.mongodb.service; import static org.mockito.ArgumentMatchers.any; @@ -25,6 +26,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 +82,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 +115,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..587b64520a 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 @@ -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. @@ -10,6 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ + package org.eclipse.hono.deviceregistry.mongodb.service; import static org.mockito.ArgumentMatchers.any; @@ -24,6 +25,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 +76,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 +96,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 +233,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). diff --git a/tests/src/test/java/org/eclipse/hono/tests/registry/DeviceRegistrationApiTests.java b/tests/src/test/java/org/eclipse/hono/tests/registry/DeviceRegistrationApiTests.java index 6845e1649b..bcdfd18be1 100644 --- a/tests/src/test/java/org/eclipse/hono/tests/registry/DeviceRegistrationApiTests.java +++ b/tests/src/test/java/org/eclipse/hono/tests/registry/DeviceRegistrationApiTests.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019, 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2019 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import org.eclipse.hono.client.registry.DeviceRegistrationClient; @@ -315,4 +316,29 @@ public void testAssertRegistrationFailsForDisabledDevice(final VertxTestContext ctx.completeNow(); })); } + + /** + * Verifies that device auto-provisioning fails to assert with an invalid device id with a 400 error code. + * + * @param ctx The vert.x test context. + */ + @Timeout(value = 5, timeUnit = TimeUnit.SECONDS) + @Test + public void testAssertRegistrationAutoProvisionFailsForInvalidDeviceId(final VertxTestContext ctx) { + + final String deviceId = getHelper().getRandomDeviceId(tenantId) + "++££"; + final String gatewayId = getHelper().getRandomDeviceId(tenantId); + + final Device device = new Device(); + device.setAuthorities(Set.of("auto-provisioning-enabled")); + + getHelper().registry + .registerDevice(tenantId, gatewayId, device) + .compose(ok -> getClient().assertRegistration(tenantId, deviceId, gatewayId, NoopSpan.INSTANCE.context())) + .onComplete(ctx.failing(t -> { + ctx.verify(() -> assertErrorCode(t, HttpURLConnection.HTTP_BAD_REQUEST)); + ctx.completeNow(); + })); + } + }