use of org.eclipse.hono.service.management.credentials.PasswordCredential in project hono by eclipse.
the class CredentialsManagementIT method testUpdateCredentialsSucceeds.
/**
* Verifies that the service accepts an update credentials request for existing credentials.
*
* @param ctx The vert.x test context.
*/
@Test
public void testUpdateCredentialsSucceeds(final VertxTestContext ctx) {
final AtomicReference<PasswordSecret> originalSecret = new AtomicReference<>();
// GIVEN a device with a set of hashed password credentials
registry.addCredentials(tenantId, deviceId, List.of(hashedPasswordCredential)).compose(ok -> registry.getCredentials(tenantId, deviceId)).compose(httpResponse -> {
ctx.verify(() -> assertResourceVersionHasChanged(resourceVersion, httpResponse.headers()));
// WHEN updating the existing password
final JsonArray bodyAsJsonArray = httpResponse.bodyAsJsonArray();
LOG.debug("received original credentials list: {}", bodyAsJsonArray.encodePrettily());
ctx.verify(() -> assertThat(bodyAsJsonArray).hasSize(1));
final PasswordCredential existingCredentials = bodyAsJsonArray.getJsonObject(0).mapTo(PasswordCredential.class);
ctx.verify(() -> {
assertThat(existingCredentials.getSecrets()).hasSize(1);
final PasswordSecret existingSecret = existingCredentials.getSecrets().get(0);
assertThat(existingSecret.getId()).isNotNull();
originalSecret.set(existingSecret);
});
final PasswordSecret changedSecret = new PasswordSecret();
changedSecret.setId(originalSecret.get().getId());
changedSecret.setPasswordPlain("completely-different-password");
changedSecret.setComment("updated");
// and adding a new one
final PasswordSecret newSecret = new PasswordSecret();
newSecret.setPasswordPlain("future-password");
newSecret.setNotBefore(Instant.now().plus(1, ChronoUnit.DAYS));
final PasswordCredential updatedCredentials = new PasswordCredential(existingCredentials.getAuthId(), List.of(changedSecret, newSecret));
return registry.updateCredentialsWithVersion(tenantId, deviceId, List.of(updatedCredentials), resourceVersion.get(), HttpURLConnection.HTTP_NO_CONTENT);
}).compose(httpResponse -> {
ctx.verify(() -> assertResourceVersionHasChanged(resourceVersion, httpResponse.headers()));
return registry.getCredentials(tenantId, deviceId);
}).onComplete(ctx.succeeding(httpResponse -> {
final JsonArray bodyAsJsonArray = httpResponse.bodyAsJsonArray();
LOG.debug("received updated credentials list: {}", bodyAsJsonArray.encodePrettily());
ctx.verify(() -> {
assertThat(bodyAsJsonArray).hasSize(1);
final PasswordCredential updatedCredentials = bodyAsJsonArray.getJsonObject(0).mapTo(PasswordCredential.class);
assertThat(updatedCredentials.getSecrets()).hasSize(2);
// THEN the original secret has been updated
final PasswordSecret updatedSecret = updatedCredentials.getSecrets().stream().filter(s -> originalSecret.get().getId().equals(s.getId())).findAny().orElse(null);
assertThat(updatedSecret).isNotNull();
assertThat(updatedSecret.getComment()).isEqualTo("updated");
});
ctx.completeNow();
}));
}
use of org.eclipse.hono.service.management.credentials.PasswordCredential in project hono by eclipse.
the class MqttConnectionIT method testConnectFailsForDisabledDevice.
/**
* Verifies that the adapter rejects connection attempts from devices for which credentials exist but the device is
* disabled.
*
* @param ctx The test context
*/
@Test
public void testConnectFailsForDisabledDevice(final VertxTestContext ctx) {
final Tenant tenant = new Tenant();
helper.registry.addTenant(tenantId, tenant).compose(ok -> {
final var device = new Device();
device.setEnabled(false);
return helper.registry.registerDevice(tenantId, deviceId, device);
}).compose(ok -> {
final PasswordCredential secret = IntegrationTestSupport.createPasswordCredential(deviceId, password);
return helper.registry.addCredentials(tenantId, deviceId, Collections.singleton(secret));
}).compose(ok -> connectToAdapter(IntegrationTestSupport.getUsername(deviceId, tenantId), password)).onComplete(ctx.failing(t -> {
// THEN the connection is refused with a NOT_AUTHORIZED code
ctx.verify(() -> {
assertThat(t).isInstanceOf(MqttConnectionException.class);
assertThat(((MqttConnectionException) t).code()).isEqualTo(MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED);
});
ctx.completeNow();
}));
}
use of org.eclipse.hono.service.management.credentials.PasswordCredential in project hono by eclipse.
the class MqttConnectionIT method testConnectFailsForDisabledCredentials.
/**
* Verifies that the adapter rejects connection attempts from devices for which credentials exist but are disabled.
*
* @param ctx The test context
*/
@Test
public void testConnectFailsForDisabledCredentials(final VertxTestContext ctx) {
helper.registry.addTenant(tenantId).compose(ok -> {
return helper.registry.registerDevice(tenantId, deviceId);
}).compose(ok -> {
final PasswordCredential secret = IntegrationTestSupport.createPasswordCredential(deviceId, password);
secret.setEnabled(false);
return helper.registry.addCredentials(tenantId, deviceId, Collections.singleton(secret));
}).compose(ok -> connectToAdapter(IntegrationTestSupport.getUsername(deviceId, tenantId), password)).onComplete(ctx.failing(t -> {
// THEN the connection is refused with a NOT_AUTHORIZED code
ctx.verify(() -> {
assertThat(t).isInstanceOf(MqttConnectionException.class);
assertThat(((MqttConnectionException) t).code()).isEqualTo(MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD);
});
ctx.completeNow();
}));
}
use of org.eclipse.hono.service.management.credentials.PasswordCredential in project hono by eclipse.
the class DeviceRegistryUtils method checkCredential.
/**
* Validates the given credentials for consistency.
* <p>
* The following checks are performed
* <ol>
* <li>The credential's <em>checkValidity</em> method is invoked and</li>
* <li>if the given credentials object is of type {@link PasswordCredential}, for
* each of the credential's hashed password secrets the secret's
* {@link PasswordSecret#encode(HonoPasswordEncoder)}, {@link PasswordSecret#checkValidity()}
* and {@link PasswordSecret#verifyHashAlgorithm(Set, int)} methods are invoked.</li>
* </ol>
*
* @param credential The secret to validate.
* @param passwordEncoder The password encoder.
* @param hashAlgorithmsWhitelist The list of supported hashing algorithms for pre-hashed passwords.
* @param maxBcryptCostFactor The maximum cost factor to use for bcrypt password hashes.
* @throws IllegalStateException if any of the checks fail.
* @throws NullPointerException if any of the parameters is {@code null}.
*/
public static void checkCredential(final CommonCredential credential, final HonoPasswordEncoder passwordEncoder, final Set<String> hashAlgorithmsWhitelist, final int maxBcryptCostFactor) {
Objects.requireNonNull(credential);
Objects.requireNonNull(passwordEncoder);
Objects.requireNonNull(hashAlgorithmsWhitelist);
credential.checkValidity();
if (credential instanceof PasswordCredential) {
for (final PasswordSecret passwordSecret : ((PasswordCredential) credential).getSecrets()) {
passwordSecret.encode(passwordEncoder);
passwordSecret.checkValidity();
passwordSecret.verifyHashAlgorithm(hashAlgorithmsWhitelist, maxBcryptCostFactor);
}
}
}
Aggregations