use of org.eclipse.hono.util.CredentialsObject in project hono by eclipse.
the class BaseCredentialsServiceTest method testGetFailsForMissingAuthId.
/**
* Verifies that the base service fails a request for getting credentials
* with a 400 error code if the authentication identifier is missing.
*
* @param ctx The vert.x test context.
*/
@Test
public void testGetFailsForMissingAuthId(final TestContext ctx) {
// GIVEN a request for getting credentials that does not specify an auth ID
final CredentialsObject malformedPayload = new CredentialsObject().setType("my-type").addSecret(CredentialsObject.emptySecret(null, null));
final EventBusMessage request = createRequestForPayload(CredentialsConstants.CredentialsAction.get, JsonObject.mapFrom(malformedPayload));
// WHEN processing the request
service.processRequest(request).setHandler(ctx.asyncAssertFailure(t -> {
// THEN the response contains a 400 error code
ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode());
}));
}
use of org.eclipse.hono.util.CredentialsObject in project hono by eclipse.
the class ProtonBasedCredentialsClientTest method testGetCredentialsWithClientContextReturnsValueFromCache.
/**
* Verifies that Credentials are taken from cache, if cache is configured and the cache contains an entry for
* the given criteria.
*
* @param ctx The vert.x test context.
*/
@Test
public void testGetCredentialsWithClientContextReturnsValueFromCache(final VertxTestContext ctx) {
// GIVEN a client with a cache containing an entry
givenAClient(cache);
final String authId = "test-auth";
final String credentialsType = CredentialsConstants.SECRETS_TYPE_HASHED_PASSWORD;
final var bytes = new byte[] { 0x01, 0x02 };
final JsonObject credentialsObject = newCredentialsResult("device", authId);
final CredentialsResult<CredentialsObject> credentialsResult = client.getResult(HttpURLConnection.HTTP_OK, RequestResponseApiConstants.CONTENT_TYPE_APPLICATION_JSON, credentialsObject.toBuffer(), null, null);
when(cache.getIfPresent(any())).thenReturn(credentialsResult);
final var cacheKey = ArgumentCaptor.forClass(AnnotatedCacheKey.class);
// WHEN getting credentials with a client context that contains a raw byte array
final var contextWithByteArray = new JsonObject().put("bytes", bytes);
client.get("tenant", credentialsType, authId, contextWithByteArray, span.context()).onFailure(ctx::failNow).compose(result -> {
ctx.verify(() -> {
// THEN the credentials are read from the cache
verify(cache).getIfPresent(cacheKey.capture());
assertThat(result).isEqualTo(credentialsResult.getPayload());
verify(sender, never()).send(any(Message.class), VertxMockSupport.anyHandler());
// and the span is finished
verify(span).finish();
});
// and WHEN getting the same credentials with a client context that contains
// the Base64 encoding of the byte array
final var contextWithBase64String = new JsonObject().put("bytes", contextWithByteArray.getValue("bytes"));
return client.get("tenant", credentialsType, authId, contextWithBase64String, span.context());
}).onComplete(ctx.succeeding(result -> {
ctx.verify(() -> {
// THEN same credentials are read from the cache using the same key as before
verify(cache, times(2)).getIfPresent(cacheKey.getValue());
assertThat(result).isEqualTo(credentialsResult.getPayload());
verify(sender, never()).send(any(Message.class), VertxMockSupport.anyHandler());
// and the span is finished
verify(span, times(2)).finish();
});
ctx.completeNow();
}));
}
use of org.eclipse.hono.util.CredentialsObject in project hono by eclipse.
the class ProtonBasedCredentialsClientTest method testGetCredentialsReturnsValueFromCache.
/**
* Verifies that Credentials are taken from cache, if cache is configured and the cache has this credentials cached.
*
* @param ctx The vert.x test context.
*/
@Test
public void testGetCredentialsReturnsValueFromCache(final VertxTestContext ctx) {
// GIVEN a client with a cache containing a credentials
givenAClient(cache);
final String authId = "test-auth";
final String credentialsType = CredentialsConstants.SECRETS_TYPE_HASHED_PASSWORD;
final JsonObject credentialsObject = newCredentialsResult("device", authId);
final CredentialsResult<CredentialsObject> credentialsResult = client.getResult(HttpURLConnection.HTTP_OK, RequestResponseApiConstants.CONTENT_TYPE_APPLICATION_JSON, credentialsObject.toBuffer(), null, null);
when(cache.getIfPresent(any())).thenReturn(credentialsResult);
// WHEN getting credentials
client.get("tenant", credentialsType, authId, span.context()).onComplete(ctx.succeeding(result -> {
ctx.verify(() -> {
// THEN the credentials are read from the cache
verify(cache).getIfPresent(any());
assertThat(result).isEqualTo(credentialsResult.getPayload());
verify(sender, never()).send(any(Message.class), VertxMockSupport.anyHandler());
// and the span is finished
verify(span).finish();
});
ctx.completeNow();
}));
}
use of org.eclipse.hono.util.CredentialsObject in project hono by eclipse.
the class ProtonBasedCredentialsClientTest method testGetCredentialsAddsResponseToCacheOnCacheMiss.
/**
* Verifies that on a cache miss the adapter retrieves credentials information from the
* Credentials service and puts it to the cache.
*
* @param ctx The vert.x test context.
*/
@SuppressWarnings("unchecked")
@Test
public void testGetCredentialsAddsResponseToCacheOnCacheMiss(final VertxTestContext ctx) {
// GIVEN an adapter with an empty cache
givenAClient(cache);
final String authId = "test-auth";
final String credentialsType = CredentialsConstants.SECRETS_TYPE_HASHED_PASSWORD;
final JsonObject credentialsObject = newCredentialsResult("device", authId);
final JsonObject clientContext = new JsonObject();
// WHEN getting credentials information
client.get("tenant", credentialsType, authId, clientContext, span.context()).onComplete(ctx.succeeding(credentials -> {
ctx.verify(() -> {
final var responseCacheKey = ArgumentCaptor.forClass(AnnotatedCacheKey.class);
verify(cache).getIfPresent(responseCacheKey.capture());
assertThat(credentials.getDeviceId()).isEqualTo("device");
// THEN the credentials result has been added to the cache.
verify(cache).put(eq(responseCacheKey.getValue()), any(CredentialsResult.class));
// and the span is finished
verify(span).finish();
});
ctx.completeNow();
}));
final Message request = AmqpClientUnitTestHelper.assertMessageHasBeenSent(sender);
final Message response = ProtonHelper.message();
response.setCorrelationId(request.getMessageId());
MessageHelper.addProperty(response, MessageHelper.APP_PROPERTY_STATUS, HttpURLConnection.HTTP_OK);
MessageHelper.addCacheDirective(response, CacheDirective.maxAgeDirective(60));
MessageHelper.setPayload(response, MessageHelper.CONTENT_TYPE_APPLICATION_JSON, credentialsObject.toBuffer());
final ProtonDelivery delivery = mock(ProtonDelivery.class);
AmqpClientUnitTestHelper.assertReceiverLinkCreated(connection).handle(delivery, response);
}
use of org.eclipse.hono.util.CredentialsObject in project hono by eclipse.
the class ProtonBasedCredentialsClient method get.
@Override
public Future<CredentialsObject> get(final String tenantId, final String type, final String authId, final JsonObject clientContext, final SpanContext spanContext) {
Objects.requireNonNull(tenantId);
Objects.requireNonNull(type);
Objects.requireNonNull(authId);
Objects.requireNonNull(clientContext);
final int clientContextHashCode;
if (clientContext.isEmpty()) {
clientContextHashCode = clientContext.hashCode();
} else {
// "normalize" JSON so that binary valued properties always
// contain the value's Base64 encoding instead of the raw byte array
// and thus always result in the same hash code
clientContextHashCode = new JsonObject(clientContext.encode()).hashCode();
}
final AnnotatedCacheKey<CacheKey> responseCacheKey = new AnnotatedCacheKey<>(new CacheKey(tenantId, type, authId, clientContextHashCode));
final Span span = newChildSpan(spanContext, "get Credentials");
span.setTag(MessageHelper.APP_PROPERTY_TENANT_ID, tenantId);
span.setTag(TAG_CREDENTIALS_TYPE, type);
span.setTag(TAG_AUTH_ID, authId);
final Future<CredentialsResult<CredentialsObject>> resultTracker = getResponseFromCache(responseCacheKey, span).recover(cacheMiss -> getOrCreateClient(tenantId).compose(client -> {
final JsonObject specification = CredentialsConstants.getSearchCriteria(type, authId).mergeIn(clientContext);
if (LOG.isTraceEnabled()) {
LOG.trace("getting credentials using spec:{}{}", System.lineSeparator(), specification.encodePrettily());
}
return client.createAndSendRequest(CredentialsConstants.CredentialsAction.get.toString(), null, specification.toBuffer(), RequestResponseApiConstants.CONTENT_TYPE_APPLICATION_JSON, this::getRequestResponseResult, span);
}).map(credentialsResult -> {
addResultToCache(responseCacheKey, credentialsResult);
return credentialsResult;
}));
return mapResultAndFinishSpan(resultTracker, result -> {
switch(result.getStatus()) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_CREATED:
return result.getPayload();
case HttpURLConnection.HTTP_NOT_FOUND:
throw new ClientErrorException(result.getStatus(), "no such credentials");
default:
throw StatusCodeMapper.from(result);
}
}, span);
}
Aggregations