Search in sources :

Example 1 with DeviceStatus

use of org.eclipse.hono.service.management.device.DeviceStatus in project hono by eclipse.

the class AbstractAutoProvisioningEventSender method updateAutoProvisioningNotificationSent.

/**
 * Update the device registration information that the auto-provisioning notification has been successfully sent.
 *
 * @param tenantId The tenant identifier.
 * @param deviceId The edge device identifier.
 * @param device The edge device registration information.
 * @param deviceVersion The version of the device registration information to check before update,
 *                      may be {@link Optional#empty()}.
 * @param span The span to be used for tracing this operation.
 * @return A future indicating the outcome of the operation.
 * @throws NullPointerException if any of the parameters are {@code null}.
 */
protected Future<Void> updateAutoProvisioningNotificationSent(final String tenantId, final String deviceId, final Device device, final Optional<String> deviceVersion, final Span span) {
    Objects.requireNonNull(tenantId);
    Objects.requireNonNull(deviceId);
    Objects.requireNonNull(device);
    Objects.requireNonNull(deviceVersion);
    Objects.requireNonNull(span);
    Optional.ofNullable(device.getStatus()).ifPresentOrElse(status -> {
        if (LOG.isTraceEnabled()) {
            LOG.trace("updating existing device status:{}{}", System.lineSeparator(), JsonObject.mapFrom(status).encodePrettily());
        }
        status.setAutoProvisioningNotificationSent(true);
    }, () -> {
        final var newStatus = new DeviceStatus().setAutoProvisioningNotificationSent(true);
        if (LOG.isTraceEnabled()) {
            LOG.trace("setting new device status:{}{}", System.lineSeparator(), JsonObject.mapFrom(newStatus).encodePrettily());
        }
        device.setStatus(newStatus);
    });
    return deviceManagementService.updateDevice(tenantId, deviceId, device, deviceVersion, span).compose(result -> {
        if (HttpURLConnection.HTTP_NO_CONTENT == result.getStatus()) {
            span.log("successfully marked device's auto-provisioning notification as having been sent");
            LOG.debug("successfully marked device's auto-provisioning notification as having been sent " + "[tenant-id: {}, device-id: {}, device-version: {}]", tenantId, deviceId, deviceVersion.orElse(null));
            return Future.succeededFuture();
        } else {
            LOG.warn("failed to mark device's auto-provisioning notification as having been sent " + "[tenant-id: {}, device-id: {}, device-version: {}, status: {}]", tenantId, deviceId, deviceVersion.orElse(null), result.getStatus());
            Tags.HTTP_STATUS.set(span, result.getStatus());
            deviceVersion.ifPresent(version -> span.setTag("device-registration-version", version));
            TracingHelper.logError(span, "failed to mark device's auto-provisioning notification as having been sent");
            return Future.failedFuture(ServiceInvocationException.create(tenantId, result.getStatus(), "failed to mark device's auto-provisioning notification as having been sent", null));
        }
    });
}
Also used : DeviceStatus(org.eclipse.hono.service.management.device.DeviceStatus)

Example 2 with DeviceStatus

use of org.eclipse.hono.service.management.device.DeviceStatus in project hono by eclipse.

the class AbstractRegistrationService method assertRegistration.

/**
 * {@inheritDoc}
 * <p>
 * Subclasses may override this method in order to implement a more sophisticated approach for asserting
 * registration status, e.g. using cached information etc. This method relies on
 * {@link #getRegistrationInformation(DeviceKey, Span)} to retrieve the information registered for
 * the given device.
 */
@Override
public Future<RegistrationResult> assertRegistration(final String tenantId, final String deviceId, final String gatewayId, final Span span) {
    Objects.requireNonNull(tenantId);
    Objects.requireNonNull(deviceId);
    Objects.requireNonNull(gatewayId);
    Objects.requireNonNull(span);
    return this.tenantInformationService.getTenant(tenantId, span).compose(tenant -> {
        final Future<RegistrationResult> deviceInfoTracker = getRegistrationInformation(DeviceKey.from(tenantId, deviceId), span);
        final Future<RegistrationResult> gatewayInfoTracker = getRegistrationInformation(DeviceKey.from(tenantId, gatewayId), span);
        return CompositeFuture.all(deviceInfoTracker, gatewayInfoTracker).compose(ok -> {
            final RegistrationResult deviceResult = deviceInfoTracker.result();
            final RegistrationResult gatewayResult = gatewayInfoTracker.result();
            if (deviceResult.isNotFound() && !gatewayResult.isNotFound() && isDeviceEnabled(gatewayResult) && hasAuthorityForAutoRegistration(gatewayResult) && supportsEdgeDeviceAutoProvisioning()) {
                final Device device = new Device().setEnabled(true).setVia(Collections.singletonList(gatewayId)).setStatus(new DeviceStatus().setAutoProvisioned(true));
                final JsonArray memberOf = gatewayResult.getPayload().getJsonObject(RegistrationConstants.FIELD_DATA).getJsonArray(RegistryManagementConstants.FIELD_MEMBER_OF);
                Optional.ofNullable(memberOf).ifPresent(array -> device.setViaGroups(array.stream().filter(String.class::isInstance).map(String.class::cast).collect(Collectors.toList())));
                LOG.debug("auto-provisioning device {} for gateway {}", deviceId, gatewayId);
                return edgeDeviceAutoProvisioner.performAutoProvisioning(tenantId, tenant, deviceId, gatewayId, device, span.context()).compose(newDevice -> {
                    final JsonObject deviceData = JsonObject.mapFrom(newDevice);
                    return createSuccessfulRegistrationResult(tenantId, deviceId, deviceData, span);
                }).recover(this::convertToRegistrationResult);
            } else if (!isDeviceEnabled(deviceResult)) {
                if (deviceResult.isNotFound()) {
                    LOG.debug("no such device");
                    TracingHelper.logError(span, "no such device");
                } else {
                    LOG.debug("device not enabled");
                    TracingHelper.logError(span, "device not enabled");
                }
                return Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_NOT_FOUND));
            } else if (!isDeviceEnabled(gatewayResult)) {
                if (gatewayResult.isNotFound()) {
                    LOG.debug("no such gateway");
                    TracingHelper.logError(span, "no such gateway");
                } else {
                    LOG.debug("gateway not enabled");
                    TracingHelper.logError(span, "gateway not enabled");
                }
                return Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_FORBIDDEN));
            } else {
                final JsonObject deviceData = deviceResult.getPayload().getJsonObject(RegistrationConstants.FIELD_DATA, new JsonObject());
                final JsonObject gatewayData = gatewayResult.getPayload().getJsonObject(RegistrationConstants.FIELD_DATA, new JsonObject());
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Device data: {}", deviceData.encodePrettily());
                    LOG.debug("Gateway data: {}", gatewayData.encodePrettily());
                }
                if (isGatewayAuthorized(gatewayId, gatewayData, deviceId, deviceData)) {
                    if (supportsEdgeDeviceAutoProvisioning()) {
                        final Device device = deviceData.mapTo(Device.class);
                        return edgeDeviceAutoProvisioner.sendDelayedAutoProvisioningNotificationIfNeeded(tenantId, tenant, deviceId, gatewayId, device, span).compose(v -> createSuccessfulRegistrationResult(tenantId, deviceId, deviceData, span));
                    } else {
                        return createSuccessfulRegistrationResult(tenantId, deviceId, deviceData, span);
                    }
                } else {
                    LOG.debug("gateway not authorized");
                    TracingHelper.logError(span, "gateway not authorized");
                    return Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_FORBIDDEN));
                }
            }
        });
    }).recover(this::convertToRegistrationResult);
}
Also used : HttpURLConnection(java.net.HttpURLConnection) CacheDirective(org.eclipse.hono.util.CacheDirective) Lifecycle(org.eclipse.hono.util.Lifecycle) LoggerFactory(org.slf4j.LoggerFactory) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) Constants(org.eclipse.hono.util.Constants) CompositeFuture(io.vertx.core.CompositeFuture) RegistrationResult(org.eclipse.hono.util.RegistrationResult) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) TenantInformationService(org.eclipse.hono.deviceregistry.service.tenant.TenantInformationService) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) NoopTenantInformationService(org.eclipse.hono.deviceregistry.service.tenant.NoopTenantInformationService) Device(org.eclipse.hono.service.management.device.Device) Logger(org.slf4j.Logger) Set(java.util.Set) RegistrationConstants(org.eclipse.hono.util.RegistrationConstants) DeviceStatus(org.eclipse.hono.service.management.device.DeviceStatus) Collectors(java.util.stream.Collectors) Future(io.vertx.core.Future) Objects(java.util.Objects) RegistrationService(org.eclipse.hono.service.registration.RegistrationService) JsonArray(io.vertx.core.json.JsonArray) Optional(java.util.Optional) Span(io.opentracing.Span) NoopSpan(io.opentracing.noop.NoopSpan) Collections(java.util.Collections) JsonArray(io.vertx.core.json.JsonArray) Device(org.eclipse.hono.service.management.device.Device) CompositeFuture(io.vertx.core.CompositeFuture) Future(io.vertx.core.Future) JsonObject(io.vertx.core.json.JsonObject) DeviceStatus(org.eclipse.hono.service.management.device.DeviceStatus) RegistrationResult(org.eclipse.hono.util.RegistrationResult)

Example 3 with DeviceStatus

use of org.eclipse.hono.service.management.device.DeviceStatus 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 4 with DeviceStatus

use of org.eclipse.hono.service.management.device.DeviceStatus in project hono by eclipse.

the class DeviceManagementIT method testUpdateDeviceSucceeds.

/**
 * Verifies that the registration information provided when updating
 * a device replaces the existing information.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testUpdateDeviceSucceeds(final VertxTestContext ctx) {
    final JsonObject originalData = new JsonObject().put("ext", new JsonObject().put("key1", "value1").put("key2", "value2")).put(RegistrationConstants.FIELD_ENABLED, Boolean.TRUE);
    final JsonObject updatedData = new JsonObject().put("ext", new JsonObject().put("newKey1", "newValue1")).put(RegistrationConstants.FIELD_ENABLED, Boolean.FALSE);
    final AtomicReference<String> latestVersion = new AtomicReference<>();
    final AtomicReference<Instant> creationTime = new AtomicReference<>();
    registry.registerDevice(tenantId, deviceId, originalData.mapTo(Device.class)).compose(httpResponse -> {
        latestVersion.set(httpResponse.getHeader(HttpHeaders.ETAG.toString()));
        ctx.verify(() -> assertThat(latestVersion.get()).isNotNull());
        return registry.getRegistrationInfo(tenantId, deviceId);
    }).compose(httpResponse -> {
        final String resourceVersion = httpResponse.getHeader(HttpHeaders.ETAG.toString());
        ctx.verify(() -> {
            assertThat(latestVersion.get()).isEqualTo(resourceVersion);
            final var deviceStatus = getDeviceStatus(httpResponse.bodyAsJsonObject());
            assertThat(deviceStatus).isNotNull();
            assertThat(deviceStatus.getCreationTime()).isNotNull();
            assertThat(deviceStatus.getLastUpdate()).isNull();
            creationTime.set(deviceStatus.getCreationTime());
        });
        return registry.updateDevice(tenantId, deviceId, updatedData);
    }).compose(httpResponse -> {
        final String updatedVersion = httpResponse.getHeader(HttpHeaders.ETAG.toString());
        ctx.verify(() -> {
            assertThat(updatedVersion).isNotNull();
            assertThat(updatedVersion).isNotEqualTo(latestVersion.get());
            latestVersion.set(updatedVersion);
        });
        return registry.getRegistrationInfo(tenantId, deviceId);
    }).onComplete(ctx.succeeding(httpResponse -> {
        final String resourceVersion = httpResponse.getHeader(HttpHeaders.ETAG.toString());
        ctx.verify(() -> {
            assertThat(latestVersion.get()).isEqualTo(resourceVersion);
            assertRegistrationInformation(httpResponse, updatedData.mapTo(Device.class), creationTime.get(), true);
        });
        ctx.completeNow();
    }));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) VertxTestContext(io.vertx.junit5.VertxTestContext) BeforeEach(org.junit.jupiter.api.BeforeEach) Arrays(java.util.Arrays) HttpResponse(io.vertx.ext.web.client.HttpResponse) MultiMap(io.vertx.core.MultiMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) Nested(org.junit.jupiter.api.Nested) Timeout(io.vertx.junit5.Timeout) CompositeFuture(io.vertx.core.CompositeFuture) Matcher(java.util.regex.Matcher) IntegrationTestSupport(org.eclipse.hono.tests.IntegrationTestSupport) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) SearchResult(org.eclipse.hono.service.management.SearchResult) Map(java.util.Map) Assertions(org.assertj.core.api.Assertions) JsonObject(io.vertx.core.json.JsonObject) TypeReference(com.fasterxml.jackson.core.type.TypeReference) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) EnabledIf(org.junit.jupiter.api.condition.EnabledIf) Device(org.eclipse.hono.service.management.device.Device) DeviceWithId(org.eclipse.hono.service.management.device.DeviceWithId) Truth.assertWithMessage(com.google.common.truth.Truth.assertWithMessage) JacksonCodec(io.vertx.core.json.jackson.JacksonCodec) HttpHeaders(io.vertx.core.http.HttpHeaders) RegistrationConstants(org.eclipse.hono.util.RegistrationConstants) Truth.assertThat(com.google.common.truth.Truth.assertThat) Instant(java.time.Instant) DeviceStatus(org.eclipse.hono.service.management.device.DeviceStatus) VertxExtension(io.vertx.junit5.VertxExtension) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) List(java.util.List) Buffer(io.vertx.core.buffer.Buffer) CrudHttpClient(org.eclipse.hono.tests.CrudHttpClient) DeviceRegistryHttpClient(org.eclipse.hono.tests.DeviceRegistryHttpClient) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) Device(org.eclipse.hono.service.management.device.Device) Instant(java.time.Instant) JsonObject(io.vertx.core.json.JsonObject) AtomicReference(java.util.concurrent.atomic.AtomicReference) Test(org.junit.jupiter.api.Test)

Aggregations

DeviceStatus (org.eclipse.hono.service.management.device.DeviceStatus)4 JsonObject (io.vertx.core.json.JsonObject)3 HttpURLConnection (java.net.HttpURLConnection)3 Device (org.eclipse.hono.service.management.device.Device)3 RegistryManagementConstants (org.eclipse.hono.util.RegistryManagementConstants)3 Truth.assertThat (com.google.common.truth.Truth.assertThat)2 Truth.assertWithMessage (com.google.common.truth.Truth.assertWithMessage)2 NoopSpan (io.opentracing.noop.NoopSpan)2 CompositeFuture (io.vertx.core.CompositeFuture)2 Timeout (io.vertx.junit5.Timeout)2 VertxTestContext (io.vertx.junit5.VertxTestContext)2 Instant (java.time.Instant)2 Collections (java.util.Collections)2 List (java.util.List)2 Optional (java.util.Optional)2 TimeUnit (java.util.concurrent.TimeUnit)2 Logger (org.slf4j.Logger)2 LoggerFactory (org.slf4j.LoggerFactory)2 TypeReference (com.fasterxml.jackson.core.type.TypeReference)1 Span (io.opentracing.Span)1