private ResourceIdentifier getResourceIdentifier(final String tenant) { return ResourceIdentifier.from(TenantConstants.TENANT_ENDPOINT, tenant, null); }
private static ResourceIdentifier getResourceIdentifier(final String tenant, final String device) { return ResourceIdentifier.from(RegistrationConstants.REGISTRATION_ENDPOINT, tenant, device); }
/** * {@inheritDoc} */ @Override public Future<CommandClient> getOrCreateCommandClient(final String tenantId, final String deviceId, final String replyId) { Objects.requireNonNull(tenantId); Objects.requireNonNull(deviceId); Objects.requireNonNull(replyId); log.debug("get or create command client for [tenantId: {}, deviceId: {}, replyId: {}]", tenantId, deviceId, replyId); return getOrCreateRequestResponseClient( ResourceIdentifier.from(CommandConstants.COMMAND_ENDPOINT, tenantId, deviceId).toString(), () -> newCommandClient(tenantId, deviceId, replyId)).map(c -> (CommandClient) c); }
/** * Sets up the fixture. */ @Before public void setUp() { target = ResourceIdentifier.from(CredentialsConstants.CREDENTIALS_ENDPOINT, Constants.DEFAULT_TENANT, null); }
private boolean hasPermissionForTenant(final String subject, final ResourceIdentifier resource, final Permission permission) { if (resource.getResourceId() != null) { final ResourceIdentifier tenantResource = ResourceIdentifier.from(resource.getEndpoint(), resource.getTenantId(), null); return hasPermissionInternal(subject, tenantResource, permission); } return false; }
} else { final ResourceIdentifier resourceId = ResourceIdentifier.from(TenantConstants.TENANT_ENDPOINT, response.getTenant(), null); return getAuthorizationService().isAuthorized(clientPrincipal, resourceId, response.getOperation()) .map(isAuthorized -> {
} else { final ResourceIdentifier resourceId = ResourceIdentifier.from(TenantConstants.TENANT_ENDPOINT, response.getTenant(), null); return getAuthorizationService().isAuthorized(clientPrincipal, resourceId, response.getOperation()) .map(isAuthorized -> {
final String cacheDirective = response.getCacheDirective(); final JsonObject payload = response.getJsonPayload(); final ResourceIdentifier address = ResourceIdentifier.from(endpoint, tenantId, deviceId);
final String cacheDirective = response.getCacheDirective(); final JsonObject payload = response.getJsonPayload(); final ResourceIdentifier address = ResourceIdentifier.from(endpoint, tenantId, deviceId);
"message's address must not contain tenant ID only")); } else if (address.getTenantId() == null && address.getResourceId() == null) { final ResourceIdentifier resource = ResourceIdentifier.from(address.getEndpoint(), authenticatedDevice.getTenantId(), authenticatedDevice.getDeviceId()); result.complete(resource);
Future<ResourceIdentifier> checkAddress(final MqttContext ctx, final ResourceIdentifier address) { final Future<ResourceIdentifier> result = Future.future(); if (ctx.authenticatedDevice() == null) { if (address.getTenantId() == null || address.getResourceId() == null) { result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "topic of unauthenticated message must contain tenant and device ID")); } else { result.complete(address); } } else { if (address.getTenantId() != null && address.getResourceId() == null) { result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "topic of authenticated message must not contain tenant ID only")); } else if (address.getTenantId() == null && address.getResourceId() == null) { // use authenticated device's tenant to fill in missing information final ResourceIdentifier downstreamAddress = ResourceIdentifier.from(address, ctx.authenticatedDevice().getTenantId(), ctx.authenticatedDevice().getDeviceId()); result.complete(downstreamAddress); } else { result.complete(address); } } return result; } }
Future<ResourceIdentifier> checkAddress(final MqttContext ctx, final ResourceIdentifier address) { final Future<ResourceIdentifier> result = Future.future(); if (ctx.authenticatedDevice() == null) { if (address.getTenantId() == null || address.getResourceId() == null) { result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "topic of unauthenticated message must contain tenant and device ID")); } else { result.complete(address); } } else { if (address.getTenantId() != null && address.getResourceId() == null) { result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "topic of authenticated message must not contain tenant ID only")); } else if (address.getTenantId() == null && address.getResourceId() == null) { // use authenticated device's tenant to fill in missing information final ResourceIdentifier downstreamAddress = ResourceIdentifier.from(address, ctx.authenticatedDevice().getTenantId(), ctx.authenticatedDevice().getDeviceId()); result.complete(downstreamAddress); } else { result.complete(address); } } return result; } }
/** * Verifies that the service notifies a registered endpoint about a client * that has established a link. */ @Test public void testHandleReceiverOpenForwardsToEndpoint() { // GIVEN a server with an endpoint final ResourceIdentifier targetAddress = ResourceIdentifier.from(ENDPOINT, Constants.DEFAULT_TENANT, null); final AmqpEndpoint endpoint = mock(AmqpEndpoint.class); when(endpoint.getName()).thenReturn(ENDPOINT); final AuthorizationService authService = mock(AuthorizationService.class); when(authService.isAuthorized(Constants.PRINCIPAL_ANONYMOUS, targetAddress, Activity.WRITE)) .thenReturn(Future.succeededFuture(Boolean.TRUE)); final AmqpServiceBase<ServiceConfigProperties> server = createServer(endpoint); server.setAuthorizationService(authService); // WHEN a client connects to the server using this endpoint final Target target = getTarget(targetAddress); final ProtonReceiver receiver = mock(ProtonReceiver.class); when(receiver.getRemoteTarget()).thenReturn(target); when(receiver.attachments()).thenReturn(mock(Record.class)); server.handleReceiverOpen(newConnection(Constants.PRINCIPAL_ANONYMOUS), receiver); // THEN the server delegates link establishment to the endpoint verify(endpoint).onLinkAttach(any(ProtonConnection.class), eq(receiver), eq(targetAddress)); }
/** * Checks whether an AMQP message contains required standard properties. * <p> * This method checks if the message contains a valid device identifier using * the {@link #hasValidDeviceId(ResourceIdentifier, Message)} method. * <p> * After successful verification the following properties are added to the message's <em>annotations</em>: * <ul> * <li>{@link MessageHelper#APP_PROPERTY_DEVICE_ID} - the ID of the device that reported the data.</li> * <li>{@link MessageHelper#APP_PROPERTY_TENANT_ID} - the ID of the tenant as indicated by the link target's second segment.</li> * <li>{@link MessageHelper#APP_PROPERTY_RESOURCE} - the full resource path including the endpoint, the tenant and the device ID.</li> * </ul> * * @param linkTarget The resource path to check the message's properties against for consistency. * @param msg The AMQP 1.0 message to perform the checks on. * @return {@code true} if the message passes all checks. */ protected static final boolean verifyStandardProperties(final ResourceIdentifier linkTarget, final Message msg) { if (!hasValidDeviceId(linkTarget, msg)) { return false; } else { final ResourceIdentifier targetResource = ResourceIdentifier .from(linkTarget.getEndpoint(), linkTarget.getTenantId(), MessageHelper.getDeviceId(msg)); MessageHelper.annotate(msg, targetResource); return true; } }
/** * Checks whether an AMQP message contains required standard properties. * <p> * This method checks if the message contains a valid device identifier using * the {@link #hasValidDeviceId(ResourceIdentifier, Message)} method. * <p> * After successful verification the following properties are added to the message's <em>annotations</em>: * <ul> * <li>{@link MessageHelper#APP_PROPERTY_DEVICE_ID} - the ID of the device that reported the data.</li> * <li>{@link MessageHelper#APP_PROPERTY_TENANT_ID} - the ID of the tenant as indicated by the link target's second segment.</li> * <li>{@link MessageHelper#APP_PROPERTY_RESOURCE} - the full resource path including the endpoint, the tenant and the device ID.</li> * </ul> * * @param linkTarget The resource path to check the message's properties against for consistency. * @param msg The AMQP 1.0 message to perform the checks on. * @return {@code true} if the message passes all checks. */ protected static final boolean verifyStandardProperties(final ResourceIdentifier linkTarget, final Message msg) { if (!hasValidDeviceId(linkTarget, msg)) { return false; } else { final ResourceIdentifier targetResource = ResourceIdentifier .from(linkTarget.getEndpoint(), linkTarget.getTenantId(), MessageHelper.getDeviceId(msg)); MessageHelper.annotate(msg, targetResource); return true; } }
/** * Verifies that the service rejects sender links on resources that * the client is not authorized to write to. */ @Test public void testHandleReceiverOpenRejectsUnauthorizedClient() { // GIVEN a server with a endpoint final ResourceIdentifier restrictedTargetAddress = ResourceIdentifier.from(ENDPOINT, "RESTRICTED_TENANT", null); final AmqpEndpoint endpoint = mock(AmqpEndpoint.class); when(endpoint.getName()).thenReturn(ENDPOINT); final AuthorizationService authService = mock(AuthorizationService.class); when(authService.isAuthorized(Constants.PRINCIPAL_ANONYMOUS, restrictedTargetAddress, Activity.WRITE)) .thenReturn(Future.succeededFuture(Boolean.FALSE)); final AmqpServiceBase<ServiceConfigProperties> server = createServer(endpoint); server.setAuthorizationService(authService); // WHEN a client connects to the server using a address for a tenant it is not authorized to write to final Target target = getTarget(restrictedTargetAddress); final ProtonReceiver receiver = mock(ProtonReceiver.class); when(receiver.getRemoteTarget()).thenReturn(target); when(receiver.setCondition(any())).thenReturn(receiver); server.handleReceiverOpen(newConnection(Constants.PRINCIPAL_ANONYMOUS), receiver); // THEN the server closes the link with the client verify(receiver).close(); }
final MessageSender sender = senderTracker.result(); final Message msg = newMessage( ResourceIdentifier.from(EventConstants.EVENT_ENDPOINT, tenant, deviceId), senderTracker.result().isRegistrationAssertionRequired(), EventConstants.EVENT_ENDPOINT,
final MessageSender sender = senderTracker.result(); final Message msg = newMessage( ResourceIdentifier.from(EventConstants.EVENT_ENDPOINT, tenant, deviceId), senderTracker.result().isRegistrationAssertionRequired(), EventConstants.EVENT_ENDPOINT,
ResourceIdentifier.from(endpointName, tenant, deviceId), sender.isRegistrationAssertionRequired(), ctx.message().topicName(),
ResourceIdentifier.from(endpointName, tenant, deviceId), sender.isRegistrationAssertionRequired(), ctx.message().topicName(),