Search in sources :

Example 76 with Tenant

use of org.eclipse.hono.service.management.tenant.Tenant in project hono by eclipse.

the class MqttConnectionIT method testConnectSucceedsForRegisteredDevice.

/**
 * Verifies that the adapter opens a connection to registered devices with credentials.
 *
 * @param tlsVersion The TLS protocol version to use for connecting to the adapter.
 * @param ctx The test context
 */
@ParameterizedTest(name = IntegrationTestSupport.PARAMETERIZED_TEST_NAME_PATTERN)
@ValueSource(strings = { IntegrationTestSupport.TLS_VERSION_1_2, IntegrationTestSupport.TLS_VERSION_1_3 })
public void testConnectSucceedsForRegisteredDevice(final String tlsVersion, final VertxTestContext ctx) {
    final Tenant tenant = new Tenant();
    helper.registry.addDeviceForTenant(tenantId, tenant, deviceId, password).compose(ok -> connectToAdapter(tlsVersion, IntegrationTestSupport.getUsername(deviceId, tenantId), password)).onComplete(ctx.succeeding(conAckMsg -> {
        ctx.verify(() -> assertThat(conAckMsg.code()).isEqualTo(MqttConnectReturnCode.CONNECTION_ACCEPTED));
        ctx.completeNow();
    }));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) VertxTestContext(io.vertx.junit5.VertxTestContext) BeforeEach(org.junit.jupiter.api.BeforeEach) X500Principal(javax.security.auth.x500.X500Principal) MqttConnectReturnCode(io.netty.handler.codec.mqtt.MqttConnectReturnCode) SelfSignedCertificate(io.vertx.core.net.SelfSignedCertificate) X509CertificateCredential(org.eclipse.hono.service.management.credentials.X509CertificateCredential) Supplier(java.util.function.Supplier) Constants(org.eclipse.hono.util.Constants) Tenant(org.eclipse.hono.service.management.tenant.Tenant) Timeout(io.vertx.junit5.Timeout) IntegrationTestSupport(org.eclipse.hono.tests.IntegrationTestSupport) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) JsonObject(io.vertx.core.json.JsonObject) MqttConnectionException(io.vertx.mqtt.MqttConnectionException) Tenants(org.eclipse.hono.tests.Tenants) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) ValueSource(org.junit.jupiter.params.provider.ValueSource) Device(org.eclipse.hono.service.management.device.Device) Promise(io.vertx.core.Promise) X509CertificateSecret(org.eclipse.hono.service.management.credentials.X509CertificateSecret) RegistrationConstants(org.eclipse.hono.util.RegistrationConstants) UUID(java.util.UUID) Truth.assertThat(com.google.common.truth.Truth.assertThat) VertxExtension(io.vertx.junit5.VertxExtension) Future(io.vertx.core.Future) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) List(java.util.List) Adapter(org.eclipse.hono.util.Adapter) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Collections(java.util.Collections) PasswordCredential(org.eclipse.hono.service.management.credentials.PasswordCredential) Tenant(org.eclipse.hono.service.management.tenant.Tenant) ValueSource(org.junit.jupiter.params.provider.ValueSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 77 with Tenant

use of org.eclipse.hono.service.management.tenant.Tenant in project hono by eclipse.

the class CredentialsApiTests method testAutoProvisioningSucceeds.

private void testAutoProvisioningSucceeds(final VertxTestContext ctx, final Tenant tenant, final X509Certificate cert, final boolean isGateway, final String expectedDeviceId) throws CertificateEncodingException {
    final Checkpoint autoProvisioningEventReceived = ctx.checkpoint(1);
    final Checkpoint autoProvisioningCompleted = ctx.checkpoint(1);
    // GIVEN a client context that contains a client certificate
    final JsonObject clientCtx = new JsonObject().put(CredentialsConstants.FIELD_CLIENT_CERT, cert.getEncoded());
    final String authId = cert.getSubjectX500Principal().getName(X500Principal.RFC2253);
    tenantId = getHelper().getRandomTenantId();
    getHelper().applicationClient.createEventConsumer(tenantId, msg -> ctx.verify(() -> {
        // VERIFY that the auto-provisioning event for the device has been received
        verifyAutoProvisioningEventNotification(tenantId, expectedDeviceId, msg);
        autoProvisioningEventReceived.flag();
    }), close -> {
    }).compose(ok -> getHelper().registry.addTenant(tenantId, tenant)).compose(ok -> getClient().get(tenantId, CredentialsConstants.SECRETS_TYPE_X509_CERT, authId, clientCtx, spanContext)).compose(result -> {
        if (LOG.isDebugEnabled()) {
            LOG.debug("received get Credentials result from Credentials service:{}{}", System.lineSeparator(), JsonObject.mapFrom(result).encodePrettily());
        }
        // VERIFY the newly created credentials
        ctx.verify(() -> {
            assertThat(result).isNotNull();
            assertThat(result.isEnabled()).isTrue();
            assertThat(result.getDeviceId()).isNotNull();
            assertThat(result.getAuthId()).isEqualTo(authId);
            assertThat(result.getType()).isEqualTo(CredentialsConstants.SECRETS_TYPE_X509_CERT);
            assertThat(result.getSecrets()).isNotNull();
            assertThat(result.getSecrets()).hasSize(1);
            if (expectedDeviceId != null) {
                // VERIFY the generated device-id
                assertThat(result.getDeviceId()).isEqualTo(expectedDeviceId);
            }
        });
        // WHEN getting device registration information
        return getHelper().registry.getRegistrationInfo(tenantId, result.getDeviceId());
    }).onComplete(ctx.succeeding(result -> {
        ctx.verify(() -> {
            final JsonObject resultBody = result.bodyAsJsonObject();
            if (LOG.isDebugEnabled()) {
                LOG.debug("received get Device result from Registry Management API:{}{}", System.lineSeparator(), resultBody.encodePrettily());
            }
            // VERIFY that the device/gateway has been registered as well
            final Device device = resultBody.mapTo(Device.class);
            assertThat(device.isEnabled()).isTrue();
            if (isGateway) {
                // VERIFY that the gateway related attributes are set
                assertThat(device.getAuthorities()).contains(RegistryManagementConstants.AUTHORITY_AUTO_PROVISIONING_ENABLED);
            }
            // VERIFY that the property "auto-provisioning-notification-sent" is updated to true.
            final DeviceStatus deviceStatus = resultBody.getJsonObject(RegistryManagementConstants.FIELD_STATUS).mapTo(DeviceStatus.class);
            assertWithMessage("device auto-provisioned").that(deviceStatus.isAutoProvisioned()).isTrue();
            assertWithMessage("auto-provisioning notification for device sent").that(deviceStatus.isAutoProvisioningNotificationSent()).isTrue();
        });
        autoProvisioningCompleted.flag();
    }));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) X509Certificate(java.security.cert.X509Certificate) VertxTestContext(io.vertx.junit5.VertxTestContext) BeforeEach(org.junit.jupiter.api.BeforeEach) X500Principal(javax.security.auth.x500.X500Principal) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) CertificateFactory(java.security.cert.CertificateFactory) LoggerFactory(org.slf4j.LoggerFactory) Credentials(org.eclipse.hono.service.management.credentials.Credentials) SelfSignedCertificate(io.vertx.core.net.SelfSignedCertificate) OptionalInt(java.util.OptionalInt) Tenant(org.eclipse.hono.service.management.tenant.Tenant) Timeout(io.vertx.junit5.Timeout) IntegrationTestSupport(org.eclipse.hono.tests.IntegrationTestSupport) CredentialsClient(org.eclipse.hono.client.registry.CredentialsClient) JsonObject(io.vertx.core.json.JsonObject) Tenants(org.eclipse.hono.tests.Tenants) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) Device(org.eclipse.hono.service.management.device.Device) Logger(org.slf4j.Logger) Truth.assertWithMessage(com.google.common.truth.Truth.assertWithMessage) Vertx(io.vertx.core.Vertx) FileInputStream(java.io.FileInputStream) CertificateException(java.security.cert.CertificateException) UUID(java.util.UUID) Truth.assertThat(com.google.common.truth.Truth.assertThat) Instant(java.time.Instant) DeviceStatus(org.eclipse.hono.service.management.device.DeviceStatus) MessageHelper(org.eclipse.hono.util.MessageHelper) EventConstants(org.eclipse.hono.util.EventConstants) FileNotFoundException(java.io.FileNotFoundException) CredentialsConstants(org.eclipse.hono.util.CredentialsConstants) AuthenticationConstants(org.eclipse.hono.util.AuthenticationConstants) SpanContext(io.opentracing.SpanContext) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) List(java.util.List) CommonCredential(org.eclipse.hono.service.management.credentials.CommonCredential) Checkpoint(io.vertx.junit5.Checkpoint) NoopSpan(io.opentracing.noop.NoopSpan) Collections(java.util.Collections) CredentialsObject(org.eclipse.hono.util.CredentialsObject) PasswordCredential(org.eclipse.hono.service.management.credentials.PasswordCredential) CertificateEncodingException(java.security.cert.CertificateEncodingException) Checkpoint(io.vertx.junit5.Checkpoint) Device(org.eclipse.hono.service.management.device.Device) JsonObject(io.vertx.core.json.JsonObject) DeviceStatus(org.eclipse.hono.service.management.device.DeviceStatus)

Example 78 with Tenant

use of org.eclipse.hono.service.management.tenant.Tenant in project hono by eclipse.

the class EdgeDeviceAutoProvisioner method performAutoProvisioning.

/**
 * Auto-provisions the edge device using the given device id and the given registration data.
 *
 * @param tenantId The id of the tenant for which the edge device should be provisioned.
 * @param tenant The tenant information.
 * @param deviceId The id of the edge device which should be provisioned, may be {@code null}.
 * @param gatewayId The id of the edge device's gateway.
 * @param device The registration data for the device to be auto-provisioned.
 * @param spanContext The tracing context to be used by this operation.
 *
 * @return A future indicating the outcome of the operation.
 *
 * @throws NullPointerException if any argument except deviceId is {@code null}.
 */
public Future<Device> performAutoProvisioning(final String tenantId, final Tenant tenant, final String deviceId, final String gatewayId, final Device device, final SpanContext spanContext) {
    Objects.requireNonNull(tenantId);
    Objects.requireNonNull(tenant);
    Objects.requireNonNull(gatewayId);
    Objects.requireNonNull(device);
    Objects.requireNonNull(spanContext);
    final Span span = TracingHelper.buildChildSpan(tracer, spanContext, "auto-provision edge device connected via gateway", Constants.PROTOCOL_ADAPTER_TYPE_DEVICE_REGISTRY).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).withTag(TracingHelper.TAG_GATEWAY_ID, gatewayId).start();
    TracingHelper.setDeviceTags(span, tenantId, deviceId);
    return deviceManagementService.createDevice(tenantId, Optional.of(deviceId), device, span).recover(thr -> ServiceInvocationException.extractStatusCode(thr) == HttpURLConnection.HTTP_CONFLICT ? Future.succeededFuture(OperationResult.empty(HttpURLConnection.HTTP_CONFLICT)) : Future.failedFuture(thr)).compose(addEdgeDeviceResult -> {
        if (addEdgeDeviceResult.isError()) {
            if (addEdgeDeviceResult.getStatus() != HttpURLConnection.HTTP_CONFLICT) {
                return Future.failedFuture(StatusCodeMapper.from(addEdgeDeviceResult.getStatus(), String.format("failed to add edge device (status %d)", addEdgeDeviceResult.getStatus())));
            }
            // handle HTTP_CONFLICT, meaning the device already exists
            span.log("device already exists");
            LOG.debug("device [{}] for gateway [{}] already created by concurrent auto-provisioning [tenant-id: {}]", deviceId, gatewayId, tenantId);
            return deviceManagementService.readDevice(tenantId, deviceId, span).compose(readDeviceResult -> {
                if (!readDeviceResult.isOk()) {
                    span.log("reading device after conflict failed");
                    LOG.warn("reading device after conflict failed for device [{}] of gateway [{}] of tenant [{}]: status: {}", deviceId, gatewayId, tenantId, readDeviceResult.getStatus());
                    return Future.failedFuture(StatusCodeMapper.from(readDeviceResult.getStatus(), String.format("reading device after conflict failed (status %d)", readDeviceResult.getStatus())));
                }
                if (!readDeviceResult.getPayload().getVia().contains(gatewayId)) {
                    span.log("attempted to auto-provision same device via two different gateways at the same time");
                    LOG.info("attempted to auto-provision device [{}] via gateway [{}] of tenant [{}] but the registration data's via contains only {}", deviceId, gatewayId, tenantId, readDeviceResult.getPayload().getVia());
                    return Future.failedFuture(StatusCodeMapper.from(HttpURLConnection.HTTP_FORBIDDEN, "device already auto-provisioned for another gateway"));
                }
                final Device readDevice = readDeviceResult.getPayload();
                // ensure that a notification event gets sent (even if we might send duplicate events)
                return sendDelayedAutoProvisioningNotificationIfNeeded(tenantId, tenant, deviceId, gatewayId, readDevice, span).map(readDevice);
            });
        }
        span.log("device created");
        LOG.trace("device [{}] for gateway [{}] successfully created by auto-provisioning [tenant-id: {}]", deviceId, gatewayId, tenantId);
        return sendAutoProvisioningEvent(tenantId, tenant, deviceId, gatewayId, span).compose(sendEmptyEventOk -> deviceManagementService.readDevice(tenantId, deviceId, span).compose(readDeviceResult -> {
            if (!readDeviceResult.isOk()) {
                LOG.warn("notification flag of device [{}] for gateway [{}] of tenant [tenant-id: {}] could not be updated", deviceId, gatewayId, tenantId);
                return Future.failedFuture(StatusCodeMapper.from(readDeviceResult.getStatus(), String.format("update of notification flag failed (status %d)", readDeviceResult.getStatus())));
            }
            final Device deviceData = readDeviceResult.getPayload();
            return updateAutoProvisioningNotificationSent(tenantId, deviceId, deviceData, readDeviceResult.getResourceVersion(), span).recover(error -> Future.succeededFuture()).map(deviceData);
        }));
    }).onFailure(thr -> TracingHelper.logError(span, thr)).onComplete(ar -> span.finish());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) Device(org.eclipse.hono.service.management.device.Device) Tracer(io.opentracing.Tracer) EventSender(org.eclipse.hono.client.telemetry.EventSender) MessagingClientProvider(org.eclipse.hono.client.util.MessagingClientProvider) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) Constants(org.eclipse.hono.util.Constants) Tags(io.opentracing.tag.Tags) Future(io.vertx.core.Future) Tenant(org.eclipse.hono.service.management.tenant.Tenant) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) DeviceManagementService(org.eclipse.hono.service.management.device.DeviceManagementService) StatusCodeMapper(org.eclipse.hono.client.StatusCodeMapper) Optional(java.util.Optional) OperationResult(org.eclipse.hono.service.management.OperationResult) Span(io.opentracing.Span) TracingHelper(org.eclipse.hono.tracing.TracingHelper) Device(org.eclipse.hono.service.management.device.Device) Span(io.opentracing.Span)

Example 79 with Tenant

use of org.eclipse.hono.service.management.tenant.Tenant in project hono by eclipse.

the class AbstractTenantManagementService method updateTenant.

@Override
public final Future<OperationResult<Void>> updateTenant(final String tenantId, final Tenant tenantObj, final Optional<String> resourceVersion, final Span span) {
    Objects.requireNonNull(tenantId);
    Objects.requireNonNull(tenantObj);
    Objects.requireNonNull(resourceVersion);
    Objects.requireNonNull(span);
    final Promise<Void> tenantCheck = Promise.promise();
    try {
        tenantObj.assertTrustAnchorIdUniquenessAndCreateMissingIds();
        tenantCheck.complete();
    } catch (final IllegalStateException e) {
        log.debug("error updating tenant", e);
        TracingHelper.logError(span, e);
        tenantCheck.fail(new ClientErrorException(tenantId, HttpURLConnection.HTTP_BAD_REQUEST, e.getMessage()));
    }
    return tenantCheck.future().compose(ok -> processUpdateTenant(tenantId, tenantObj, resourceVersion, span)).onSuccess(result -> NotificationEventBusSupport.sendNotification(vertx, new TenantChangeNotification(LifecycleChange.UPDATE, tenantId, Instant.now(), tenantObj.isEnabled()))).recover(t -> DeviceRegistryUtils.mapError(t, tenantId));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) LifecycleChange(org.eclipse.hono.notification.deviceregistry.LifecycleChange) Filter(org.eclipse.hono.service.management.Filter) LoggerFactory(org.slf4j.LoggerFactory) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Tenant(org.eclipse.hono.service.management.tenant.Tenant) Sort(org.eclipse.hono.service.management.Sort) SearchResult(org.eclipse.hono.service.management.SearchResult) TenantManagementService(org.eclipse.hono.service.management.tenant.TenantManagementService) TracingHelper(org.eclipse.hono.tracing.TracingHelper) TenantChangeNotification(org.eclipse.hono.notification.deviceregistry.TenantChangeNotification) Logger(org.slf4j.Logger) Promise(io.vertx.core.Promise) TenantWithId(org.eclipse.hono.service.management.tenant.TenantWithId) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) Instant(java.time.Instant) Result(org.eclipse.hono.service.management.Result) Future(io.vertx.core.Future) Objects(java.util.Objects) List(java.util.List) Optional(java.util.Optional) OperationResult(org.eclipse.hono.service.management.OperationResult) Span(io.opentracing.Span) NotificationEventBusSupport(org.eclipse.hono.notification.NotificationEventBusSupport) DeviceRegistryUtils(org.eclipse.hono.deviceregistry.util.DeviceRegistryUtils) Id(org.eclipse.hono.service.management.Id) ClientErrorException(org.eclipse.hono.client.ClientErrorException) TenantChangeNotification(org.eclipse.hono.notification.deviceregistry.TenantChangeNotification)

Example 80 with Tenant

use of org.eclipse.hono.service.management.tenant.Tenant in project hono by eclipse.

the class AbstractTenantStore method readTenant.

/**
 * Read the content of a tenant.
 * <p>
 * This will execute the {@code read} statement and return the unprocessed information.
 * <p>
 * If there are no entries, an empty result will be returned.
 * <p>
 * If more than one entry is being found, the result will be failed with an
 * {@link IllegalStateException} exception.
 *
 * @param id The key to the tenant entry.
 * @param spanContext The span to contribute to.
 * @return The future, tracking the outcome of the operation.
 */
public Future<Optional<TenantReadResult>> readTenant(final String id, final SpanContext spanContext) {
    final Span span = TracingHelper.buildChildSpan(this.tracer, spanContext, "read tenant", getClass().getSimpleName()).withTag(TracingHelper.TAG_TENANT_ID, id).start();
    final var expanded = this.readStatement.expand(map -> {
        map.put("tenant_id", id);
    });
    return SQL.runTransactionally(this.client, this.tracer, span.context(), (connection, context) -> readTenantBy(connection, expanded, context)).onComplete(x -> span.finish());
}
Also used : SQL(org.eclipse.hono.service.base.jdbc.store.SQL) Json(io.vertx.core.json.Json) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) LoggerFactory(org.slf4j.LoggerFactory) AbstractStore(org.eclipse.hono.service.base.jdbc.store.AbstractStore) Collectors(java.util.stream.Collectors) Future(io.vertx.core.Future) Tenant(org.eclipse.hono.service.management.tenant.Tenant) Statement(org.eclipse.hono.service.base.jdbc.store.Statement) ExpandedStatement(org.eclipse.hono.service.base.jdbc.store.Statement.ExpandedStatement) SpanContext(io.opentracing.SpanContext) List(java.util.List) JDBCClient(io.vertx.ext.jdbc.JDBCClient) TrustedCertificateAuthority(org.eclipse.hono.service.management.tenant.TrustedCertificateAuthority) Map(java.util.Map) ResultSet(io.vertx.ext.sql.ResultSet) Optional(java.util.Optional) Span(io.opentracing.Span) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) SQLOperations(io.vertx.ext.sql.SQLOperations) StatementConfiguration(org.eclipse.hono.service.base.jdbc.store.StatementConfiguration) Span(io.opentracing.Span)

Aggregations

Tenant (org.eclipse.hono.service.management.tenant.Tenant)165 Test (org.junit.jupiter.api.Test)138 VertxTestContext (io.vertx.junit5.VertxTestContext)137 HttpURLConnection (java.net.HttpURLConnection)122 Truth.assertThat (com.google.common.truth.Truth.assertThat)113 TimeUnit (java.util.concurrent.TimeUnit)109 JsonObject (io.vertx.core.json.JsonObject)108 Future (io.vertx.core.Future)107 Timeout (io.vertx.junit5.Timeout)99 IntegrationTestSupport (org.eclipse.hono.tests.IntegrationTestSupport)98 RegistryManagementConstants (org.eclipse.hono.util.RegistryManagementConstants)97 Constants (org.eclipse.hono.util.Constants)95 Tenants (org.eclipse.hono.tests.Tenants)92 Optional (java.util.Optional)91 Promise (io.vertx.core.Promise)86 Device (org.eclipse.hono.service.management.device.Device)80 Adapter (org.eclipse.hono.util.Adapter)78 VertxExtension (io.vertx.junit5.VertxExtension)77 ExtendWith (org.junit.jupiter.api.extension.ExtendWith)77 Logger (org.slf4j.Logger)74