diff --git a/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/service/credentials/AbstractCredentialsService.java b/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/service/credentials/AbstractCredentialsService.java index 72d89ed60b..57b4e147d8 100644 --- a/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/service/credentials/AbstractCredentialsService.java +++ b/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/service/credentials/AbstractCredentialsService.java @@ -19,10 +19,10 @@ import org.eclipse.hono.client.ServiceInvocationException; import org.eclipse.hono.deviceregistry.service.tenant.NoopTenantInformationService; import org.eclipse.hono.deviceregistry.service.tenant.TenantInformationService; -import org.eclipse.hono.deviceregistry.service.tenant.TenantKey; import org.eclipse.hono.deviceregistry.util.DeviceRegistryUtils; import org.eclipse.hono.service.credentials.CredentialsService; import org.eclipse.hono.service.management.device.DeviceAndGatewayAutoProvisioner; +import org.eclipse.hono.service.management.tenant.Tenant; import org.eclipse.hono.tracing.TracingHelper; import org.eclipse.hono.util.CacheDirective; import org.eclipse.hono.util.Constants; @@ -98,7 +98,7 @@ public final Future stop() { /** * Get credentials for a device. * - * @param tenant The tenant key object. + * @param tenant The tenant information. * @param key The credentials key object. * @param clientContext Optional bag of properties that can be used to identify the device. * @param span The active OpenTracing span for this operation. @@ -106,7 +106,7 @@ public final Future stop() { * @throws NullPointerException if any of the parameters other than client context are {@code null}. */ protected abstract Future> processGet( - TenantKey tenant, + Tenant tenant, CredentialKey key, JsonObject clientContext, Span span); @@ -153,7 +153,7 @@ public final Future> get( .compose(tenant -> { LOG.trace("retrieving credentials by auth-id"); return processGet( - TenantKey.from(tenantId), + tenant, CredentialKey.from(tenantId, authId, type), clientContext, span) diff --git a/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/util/DeviceRegistryUtils.java b/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/util/DeviceRegistryUtils.java index fce48b0730..5779df2a58 100644 --- a/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/util/DeviceRegistryUtils.java +++ b/services/device-registry-base/src/main/java/org/eclipse/hono/deviceregistry/util/DeviceRegistryUtils.java @@ -28,6 +28,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import javax.security.auth.x500.X500Principal; + import org.eclipse.hono.auth.HonoPasswordEncoder; import org.eclipse.hono.client.ClientErrorException; import org.eclipse.hono.service.management.credentials.CommonCredential; @@ -37,6 +39,7 @@ import org.eclipse.hono.tracing.TracingHelper; import org.eclipse.hono.util.CacheDirective; import org.eclipse.hono.util.CredentialsConstants; +import org.eclipse.hono.util.IdentityTemplate; import org.eclipse.hono.util.RegistryManagementConstants; import org.eclipse.hono.util.TenantConstants; import org.eclipse.hono.util.TenantObject; @@ -343,6 +346,45 @@ public static boolean matchesWithClientContext(final JsonObject credential, fina } + /** + * todo. + * + * @param credential The credential object to match. + * @param tenant The tenant information. + * @param clientContext todo. + * @return todo. + */ + public static JsonObject applyAuthIdTemplate(final JsonObject credential, final Tenant tenant, + final JsonObject clientContext) { + Objects.requireNonNull(credential); + + final String type = credential.getString(RegistryManagementConstants.FIELD_TYPE); + if (CredentialsConstants.SECRETS_TYPE_X509_CERT.equals(type)) { + // TODO this is just to show that that issuer DN is taken from the client context for draft purpose and not + // final implementation + if (clientContext != null && !clientContext.isEmpty()) { + final byte[] bytes = clientContext.getBinary(CredentialsConstants.FIELD_CLIENT_CERT); + if (bytes != null) { + try { + final CertificateFactory factory = CertificateFactory.getInstance("X.509"); + final X509Certificate cert = (X509Certificate) factory + .generateCertificate(new ByteArrayInputStream(bytes)); + final String issuerDN = cert.getIssuerX500Principal().getName(X500Principal.RFC2253); + final String subjectDN = credential.getString(RegistryManagementConstants.FIELD_AUTH_ID); + tenant.getAuthIdTemplate(issuerDN) + .map(IdentityTemplate::new) + .map(t -> t.apply(subjectDN)) + .map(generatedAuthId -> credential.put(RegistryManagementConstants.FIELD_AUTH_ID, + generatedAuthId)); + } catch (final CertificateException e) { + // TODO. + } + } + } + } + return credential; + } + /** * Returns a regex expression based on the given filter value which can be used by the device registry * implementations to support wildcard matching during search operations. diff --git a/services/device-registry-base/src/test/java/org/eclipse/hono/deviceregistry/service/credentials/AbstractCredentialsServiceTest.java b/services/device-registry-base/src/test/java/org/eclipse/hono/deviceregistry/service/credentials/AbstractCredentialsServiceTest.java index 9ba7d8b083..7c304bfc93 100644 --- a/services/device-registry-base/src/test/java/org/eclipse/hono/deviceregistry/service/credentials/AbstractCredentialsServiceTest.java +++ b/services/device-registry-base/src/test/java/org/eclipse/hono/deviceregistry/service/credentials/AbstractCredentialsServiceTest.java @@ -21,10 +21,10 @@ import java.util.concurrent.TimeUnit; import org.eclipse.hono.client.util.MessagingClientProvider; -import org.eclipse.hono.deviceregistry.service.tenant.TenantKey; import org.eclipse.hono.service.management.credentials.CredentialsManagementService; import org.eclipse.hono.service.management.device.DeviceAndGatewayAutoProvisioner; import org.eclipse.hono.service.management.device.DeviceManagementService; +import org.eclipse.hono.service.management.tenant.Tenant; import org.eclipse.hono.util.CacheDirective; import org.eclipse.hono.util.CredentialsConstants; import org.eclipse.hono.util.CredentialsResult; @@ -59,7 +59,7 @@ public void testGetCredentialsPreservesOriginalErrorStatus(final VertxTestContex final AbstractCredentialsService credentialsService = new AbstractCredentialsService() { @Override - protected Future> processGet(final TenantKey tenant, final CredentialKey key, + protected Future> processGet(final Tenant tenant, final CredentialKey key, final JsonObject clientContext, final Span span) { return Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_BAD_GATEWAY)); } diff --git a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/impl/CredentialsServiceImpl.java b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/impl/CredentialsServiceImpl.java index cf8fcc734f..fe8ebc52ce 100644 --- a/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/impl/CredentialsServiceImpl.java +++ b/services/device-registry-jdbc/src/main/java/org/eclipse/hono/deviceregistry/jdbc/impl/CredentialsServiceImpl.java @@ -26,9 +26,9 @@ import org.eclipse.hono.deviceregistry.jdbc.config.DeviceServiceProperties; import org.eclipse.hono.deviceregistry.service.credentials.AbstractCredentialsService; import org.eclipse.hono.deviceregistry.service.credentials.CredentialKey; -import org.eclipse.hono.deviceregistry.service.tenant.TenantKey; import org.eclipse.hono.deviceregistry.util.DeviceRegistryUtils; import org.eclipse.hono.service.base.jdbc.store.device.TableAdapterStore; +import org.eclipse.hono.service.management.tenant.Tenant; import org.eclipse.hono.util.Constants; import org.eclipse.hono.util.CredentialsConstants; import org.eclipse.hono.util.CredentialsResult; @@ -60,7 +60,7 @@ public CredentialsServiceImpl(final TableAdapterStore store, final DeviceService @Override protected Future> processGet( - final TenantKey tenant, + final Tenant tenant, final CredentialKey key, final JsonObject clientContext, final Span span) { @@ -77,6 +77,7 @@ protected Future> processGet( final var secrets = result.getCredentials() .stream() .map(JsonObject::mapFrom) + .map(c -> DeviceRegistryUtils.applyAuthIdTemplate(c, tenant, clientContext)) .filter(filter(key.getType(), key.getAuthId())) .filter(credential -> DeviceRegistryUtils.matchesWithClientContext(credential, clientContext)) .flatMap(c -> c.getJsonArray(CredentialsConstants.FIELD_SECRETS) diff --git a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedCredentialsService.java b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedCredentialsService.java index d5ea99b6dd..1cf3845119 100644 --- a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedCredentialsService.java +++ b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/service/MongoDbBasedCredentialsService.java @@ -22,8 +22,8 @@ import org.eclipse.hono.deviceregistry.mongodb.model.CredentialsDao; import org.eclipse.hono.deviceregistry.service.credentials.AbstractCredentialsService; import org.eclipse.hono.deviceregistry.service.credentials.CredentialKey; -import org.eclipse.hono.deviceregistry.service.tenant.TenantKey; import org.eclipse.hono.deviceregistry.util.DeviceRegistryUtils; +import org.eclipse.hono.service.management.tenant.Tenant; import org.eclipse.hono.util.CacheDirective; import org.eclipse.hono.util.CredentialsConstants; import org.eclipse.hono.util.CredentialsResult; @@ -87,7 +87,7 @@ private CacheDirective getCacheDirective(final String type) { */ @Override protected Future> processGet( - final TenantKey tenant, + final Tenant tenant, final CredentialKey key, final JsonObject clientContext, final Span span) { @@ -96,7 +96,8 @@ protected Future> processGet( Objects.requireNonNull(key); Objects.requireNonNull(span); - return dao.getByAuthIdAndType(tenant.getTenantId(), key.getAuthId(), key.getType(), span.context()) + //todo to make use of the tenant to apply the auth-id template in case of X509 certificate credential. + return dao.getByAuthIdAndType(key.getTenantId(), key.getAuthId(), key.getType(), span.context()) .map(dto -> { LOG.trace("found credentials matching criteria"); final var json = JsonObject.mapFrom(dto.getCredentials().get(0)); @@ -109,7 +110,7 @@ protected Future> processGet( credential, getCacheDirective(key.getType()))) .orElseThrow(() -> new ClientErrorException( - tenant.getTenantId(), + key.getTenantId(), HttpURLConnection.HTTP_NOT_FOUND, "no matching credentials on record")); })