From 778a8e3e88bfe4bf1adbbbf4fdaff3fd5baae2a4 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/ConfigPropertiesProducer.java | 18 +++++++++++- .../jdbc/app/HttpServerFactory.java | 14 ++-------- .../jdbc/app/ManagementServicesProducer.java | 14 +++++++--- .../impl/DeviceManagementServiceImpl.java | 12 ++++++-- .../jdbc/impl/AbstractJdbcRegistryTest.java | 6 +++- .../JdbcBasedRegistrationServiceTest.java | 16 ++++++++++- .../mongodb/app/ConfigPropertiesProducer.java | 17 ++++++++++- .../mongodb/app/HttpServerFactory.java | 7 +---- .../app/ManagementServicesProducer.java | 11 +++++--- .../MongoDbBasedDeviceManagementService.java | 10 +++++-- ...asedDeviceManagementSearchDevicesTest.java | 4 ++- .../MongoDbBasedCredentialServiceTest.java | 8 ++++-- .../MongoDbBasedRegistrationServiceTest.java | 26 +++++++++++++++-- .../registry/DeviceRegistrationApiTests.java | 28 ++++++++++++++++++- 17 files changed, 179 insertions(+), 46 deletions(-) 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/ConfigPropertiesProducer.java b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/ConfigPropertiesProducer.java index ab235f4bbe..566b36df93 100644 --- a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/ConfigPropertiesProducer.java +++ b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/app/ConfigPropertiesProducer.java @@ -11,14 +11,16 @@ * SPDX-License-Identifier: EPL-2.0 */ - package org.eclipse.hono.deviceregistry.jdbc.app; import org.eclipse.hono.service.base.jdbc.config.JdbcDeviceStoreOptions; import org.eclipse.hono.service.base.jdbc.config.JdbcDeviceStoreProperties; import org.eclipse.hono.service.base.jdbc.config.JdbcTenantStoreOptions; import org.eclipse.hono.service.base.jdbc.config.JdbcTenantStoreProperties; +import org.eclipse.hono.service.http.HttpServiceConfigOptions; +import org.eclipse.hono.service.http.HttpServiceConfigProperties; +import io.smallrye.config.ConfigMapping; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; import jakarta.inject.Singleton; @@ -53,4 +55,18 @@ public JdbcTenantStoreProperties tenantsProperties(final JdbcTenantStoreOptions public JdbcDeviceStoreProperties devicesProperties(final JdbcDeviceStoreOptions options) { return new JdbcDeviceStoreProperties(options); } + + /** + * Creates HTTP service configuration properties from existing options. + * + * @param options The options. + * @return The properties. + */ + @Produces + @Singleton + public HttpServiceConfigProperties httpServiceConfigProperties( + @ConfigMapping(prefix = "hono.registry.http") + final HttpServiceConfigOptions options) { + return new HttpServiceConfigProperties(options); + } } 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..f095800850 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,8 @@ 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.service.http.HttpServiceConfigProperties; -import io.smallrye.config.ConfigMapping; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -28,17 +26,11 @@ @ApplicationScoped public class HttpServerFactory extends AbstractHttpServerFactory { - private HttpServiceConfigProperties httpServerProperties; - @Inject - void setHttpServerProperties( - @ConfigMapping(prefix = "hono.registry.http") - final HttpServiceConfigOptions endpointOptions) { - this.httpServerProperties = new HttpServiceConfigProperties(endpointOptions); - } + HttpServiceConfigProperties httpServerConfigProperties; @Override protected final HttpServiceConfigProperties getHttpServerProperties() { - return httpServerProperties; + return httpServerConfigProperties; } } 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..c80eebb68f 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,7 +11,6 @@ * SPDX-License-Identifier: EPL-2.0 */ - package org.eclipse.hono.deviceregistry.jdbc.app; import org.eclipse.hono.deviceregistry.jdbc.config.DeviceServiceOptions; @@ -24,6 +23,7 @@ import org.eclipse.hono.service.base.jdbc.store.device.TableManagementStore; import org.eclipse.hono.service.base.jdbc.store.tenant.AdapterStore; import org.eclipse.hono.service.base.jdbc.store.tenant.ManagementStore; +import org.eclipse.hono.service.http.HttpServiceConfigProperties; import org.eclipse.hono.service.management.credentials.CredentialsManagementService; import org.eclipse.hono.service.management.device.DeviceManagementService; import org.eclipse.hono.service.management.tenant.TenantManagementService; @@ -75,6 +75,7 @@ public TenantManagementService tenantManagementService( * @param devicesManagementStore The data store for accessing device data. * @param deviceServiceOptions The device management service configuration. * @param tenantInformationService The service for retrieving tenant information. + * @param httpServiceConfigProperties The HTTP service configuration. * @return The service. */ @Produces @@ -82,9 +83,14 @@ public TenantManagementService tenantManagementService( public DeviceManagementService deviceManagementService( final TableManagementStore devicesManagementStore, final DeviceServiceOptions deviceServiceOptions, - final TenantInformationService tenantInformationService) { + final TenantInformationService tenantInformationService, + final HttpServiceConfigProperties httpServiceConfigProperties) { - final var service = new DeviceManagementServiceImpl(vertx, devicesManagementStore, deviceServiceOptions); + final var service = new DeviceManagementServiceImpl( + vertx, + devicesManagementStore, + deviceServiceOptions, + httpServiceConfigProperties); 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..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/ConfigPropertiesProducer.java b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/ConfigPropertiesProducer.java index ed18cffb7b..2bf339521c 100644 --- a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/ConfigPropertiesProducer.java +++ b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/ConfigPropertiesProducer.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. @@ -15,6 +15,8 @@ import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedCredentialsConfigOptions; 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.MongoDbBasedRegistrationConfigOptions; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedRegistrationConfigProperties; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedTenantsConfigOptions; @@ -69,4 +71,17 @@ public MongoDbBasedCredentialsConfigProperties credentialsServiceProperties( final MongoDbBasedCredentialsConfigOptions options) { return new MongoDbBasedCredentialsConfigProperties(options); } + + /** + * Creates HTTP service configuration properties from existing options. + * + * @param options The options. + * @return The properties. + */ + @Produces + @Singleton + public MongoDbBasedHttpServiceConfigProperties httpServiceProperties( + final MongoDbBasedHttpServiceConfigOptions options) { + return new MongoDbBasedHttpServiceConfigProperties(options); + } } diff --git a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/HttpServerFactory.java b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/HttpServerFactory.java index 711fa79951..f92692f4a5 100644 --- a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/HttpServerFactory.java +++ b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/HttpServerFactory.java @@ -17,7 +17,6 @@ import java.util.Optional; import org.eclipse.hono.deviceregistry.app.AbstractHttpServerFactory; -import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedHttpServiceConfigOptions; import org.eclipse.hono.deviceregistry.mongodb.config.MongoDbBasedHttpServiceConfigProperties; import org.eclipse.hono.deviceregistry.server.DeviceRegistryHttpServer; import org.eclipse.hono.service.http.HttpServiceConfigProperties; @@ -44,12 +43,8 @@ public class HttpServerFactory extends AbstractHttpServerFactory { @Inject MongoClient mongoClient; - private MongoDbBasedHttpServiceConfigProperties httpServerProperties; - @Inject - void setHttpServerProperties(final MongoDbBasedHttpServiceConfigOptions endpointOptions) { - this.httpServerProperties = new MongoDbBasedHttpServiceConfigProperties(endpointOptions); - } + MongoDbBasedHttpServiceConfigProperties httpServerProperties; @Override protected final HttpServiceConfigProperties getHttpServerProperties() { 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..5e95a9e28c 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,10 @@ * 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.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; @@ -89,6 +89,7 @@ public TenantManagementService tenantManagementService(final TenantDao tenantDao * @param deviceDao The DAO for accessing device data. * @param credentialsDao The DAO for accessing credentials data. * @param tenantInformationService The service for retrieving tenant information. + * @param httpServiceConfigProperties The HTTP service configuration. * @return The service. */ @Produces @@ -96,13 +97,15 @@ public TenantManagementService tenantManagementService(final TenantDao tenantDao public DeviceManagementService deviceManagementService( final DeviceDao deviceDao, final CredentialsDao credentialsDao, - final TenantInformationService tenantInformationService) { + final TenantInformationService tenantInformationService, + final MongoDbBasedHttpServiceConfigProperties httpServiceConfigProperties) { final var service = new MongoDbBasedDeviceManagementService( vertx, deviceDao, credentialsDao, - registrationServiceProperties); + registrationServiceProperties, + httpServiceConfigProperties); 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(); + })); + } + }