use of org.apache.kafka.common.requests.AlterUserScramCredentialsResponse in project kafka by apache.
the class KafkaAdminClient method alterUserScramCredentials.
@Override
public AlterUserScramCredentialsResult alterUserScramCredentials(List<UserScramCredentialAlteration> alterations, AlterUserScramCredentialsOptions options) {
final long now = time.milliseconds();
final Map<String, KafkaFutureImpl<Void>> futures = new HashMap<>();
for (UserScramCredentialAlteration alteration : alterations) {
futures.put(alteration.user(), new KafkaFutureImpl<>());
}
final Map<String, Exception> userIllegalAlterationExceptions = new HashMap<>();
// We need to keep track of users with deletions of an unknown SCRAM mechanism
final String usernameMustNotBeEmptyMsg = "Username must not be empty";
String passwordMustNotBeEmptyMsg = "Password must not be empty";
final String unknownScramMechanismMsg = "Unknown SCRAM mechanism";
alterations.stream().filter(a -> a instanceof UserScramCredentialDeletion).forEach(alteration -> {
final String user = alteration.user();
if (user == null || user.isEmpty()) {
userIllegalAlterationExceptions.put(alteration.user(), new UnacceptableCredentialException(usernameMustNotBeEmptyMsg));
} else {
UserScramCredentialDeletion deletion = (UserScramCredentialDeletion) alteration;
ScramMechanism mechanism = deletion.mechanism();
if (mechanism == null || mechanism == ScramMechanism.UNKNOWN) {
userIllegalAlterationExceptions.put(user, new UnsupportedSaslMechanismException(unknownScramMechanismMsg));
}
}
});
// Creating an upsertion may throw InvalidKeyException or NoSuchAlgorithmException,
// so keep track of which users are affected by such a failure so we can fail all their alterations later
final Map<String, Map<ScramMechanism, AlterUserScramCredentialsRequestData.ScramCredentialUpsertion>> userInsertions = new HashMap<>();
alterations.stream().filter(a -> a instanceof UserScramCredentialUpsertion).filter(alteration -> !userIllegalAlterationExceptions.containsKey(alteration.user())).forEach(alteration -> {
final String user = alteration.user();
if (user == null || user.isEmpty()) {
userIllegalAlterationExceptions.put(alteration.user(), new UnacceptableCredentialException(usernameMustNotBeEmptyMsg));
} else {
UserScramCredentialUpsertion upsertion = (UserScramCredentialUpsertion) alteration;
try {
byte[] password = upsertion.password();
if (password == null || password.length == 0) {
userIllegalAlterationExceptions.put(user, new UnacceptableCredentialException(passwordMustNotBeEmptyMsg));
} else {
ScramMechanism mechanism = upsertion.credentialInfo().mechanism();
if (mechanism == null || mechanism == ScramMechanism.UNKNOWN) {
userIllegalAlterationExceptions.put(user, new UnsupportedSaslMechanismException(unknownScramMechanismMsg));
} else {
userInsertions.putIfAbsent(user, new HashMap<>());
userInsertions.get(user).put(mechanism, getScramCredentialUpsertion(upsertion));
}
}
} catch (NoSuchAlgorithmException e) {
// we might overwrite an exception from a previous alteration, but we don't really care
// since we just need to mark this user as having at least one illegal alteration
// and make an exception instance available for completing the corresponding future exceptionally
userIllegalAlterationExceptions.put(user, new UnsupportedSaslMechanismException(unknownScramMechanismMsg));
} catch (InvalidKeyException e) {
// generally shouldn't happen since we deal with the empty password case above,
// but we still need to catch/handle it
userIllegalAlterationExceptions.put(user, new UnacceptableCredentialException(e.getMessage(), e));
}
}
});
// submit alterations only for users that do not have an illegal alteration as identified above
Call call = new Call("alterUserScramCredentials", calcDeadlineMs(now, options.timeoutMs()), new ControllerNodeProvider()) {
@Override
public AlterUserScramCredentialsRequest.Builder createRequest(int timeoutMs) {
return new AlterUserScramCredentialsRequest.Builder(new AlterUserScramCredentialsRequestData().setUpsertions(alterations.stream().filter(a -> a instanceof UserScramCredentialUpsertion).filter(a -> !userIllegalAlterationExceptions.containsKey(a.user())).map(a -> userInsertions.get(a.user()).get(((UserScramCredentialUpsertion) a).credentialInfo().mechanism())).collect(Collectors.toList())).setDeletions(alterations.stream().filter(a -> a instanceof UserScramCredentialDeletion).filter(a -> !userIllegalAlterationExceptions.containsKey(a.user())).map(d -> getScramCredentialDeletion((UserScramCredentialDeletion) d)).collect(Collectors.toList())));
}
@Override
public void handleResponse(AbstractResponse abstractResponse) {
AlterUserScramCredentialsResponse response = (AlterUserScramCredentialsResponse) abstractResponse;
// Check for controller change
for (Errors error : response.errorCounts().keySet()) {
if (error == Errors.NOT_CONTROLLER) {
handleNotControllerError(error);
}
}
/* Now that we have the results for the ones we sent,
* fail any users that have an illegal alteration as identified above.
* Be sure to do this after the NOT_CONTROLLER error check above
* so that all errors are consistent in that case.
*/
userIllegalAlterationExceptions.entrySet().stream().forEach(entry -> {
futures.get(entry.getKey()).completeExceptionally(entry.getValue());
});
response.data().results().forEach(result -> {
KafkaFutureImpl<Void> future = futures.get(result.user());
if (future == null) {
log.warn("Server response mentioned unknown user {}", result.user());
} else {
Errors error = Errors.forCode(result.errorCode());
if (error != Errors.NONE) {
future.completeExceptionally(error.exception(result.errorMessage()));
} else {
future.complete(null);
}
}
});
completeUnrealizedFutures(futures.entrySet().stream(), user -> "The broker response did not contain a result for user " + user);
}
@Override
void handleFailure(Throwable throwable) {
completeAllExceptionally(futures.values(), throwable);
}
};
runnable.call(call, now);
return new AlterUserScramCredentialsResult(new HashMap<>(futures));
}
use of org.apache.kafka.common.requests.AlterUserScramCredentialsResponse in project kafka by apache.
the class KafkaAdminClientTest method testAlterUserScramCredentialsUnknownMechanism.
@Test
public void testAlterUserScramCredentialsUnknownMechanism() throws Exception {
try (AdminClientUnitTestEnv env = mockClientEnv()) {
env.kafkaClient().setNodeApiVersions(NodeApiVersions.create());
final String user0Name = "user0";
ScramMechanism user0ScramMechanism0 = ScramMechanism.UNKNOWN;
final String user1Name = "user1";
ScramMechanism user1ScramMechanism0 = ScramMechanism.UNKNOWN;
final String user2Name = "user2";
ScramMechanism user2ScramMechanism0 = ScramMechanism.SCRAM_SHA_256;
AlterUserScramCredentialsResponseData responseData = new AlterUserScramCredentialsResponseData();
responseData.setResults(Arrays.asList(new AlterUserScramCredentialsResponseData.AlterUserScramCredentialsResult().setUser(user2Name)));
env.kafkaClient().prepareResponse(new AlterUserScramCredentialsResponse(responseData));
AlterUserScramCredentialsResult result = env.adminClient().alterUserScramCredentials(Arrays.asList(new UserScramCredentialDeletion(user0Name, user0ScramMechanism0), new UserScramCredentialUpsertion(user1Name, new ScramCredentialInfo(user1ScramMechanism0, 8192), "password"), new UserScramCredentialUpsertion(user2Name, new ScramCredentialInfo(user2ScramMechanism0, 4096), "password")));
Map<String, KafkaFuture<Void>> resultData = result.values();
assertEquals(3, resultData.size());
Arrays.asList(user0Name, user1Name).stream().forEach(u -> {
assertTrue(resultData.containsKey(u));
try {
resultData.get(u).get();
fail("Expected request for user " + u + " to complete exceptionally, but it did not");
} catch (Exception expected) {
// ignore
}
});
assertTrue(resultData.containsKey(user2Name));
try {
resultData.get(user2Name).get();
} catch (Exception e) {
fail("Expected request for user " + user2Name + " to NOT complete excdptionally, but it did");
}
try {
result.all().get();
fail("Expected 'result.all().get()' to throw an exception since at least one user failed, but it did not");
} catch (final Exception expected) {
// ignore, expected
}
}
}
use of org.apache.kafka.common.requests.AlterUserScramCredentialsResponse in project kafka by apache.
the class KafkaAdminClientTest method testAlterUserScramCredentials.
@Test
public void testAlterUserScramCredentials() throws Exception {
try (AdminClientUnitTestEnv env = mockClientEnv()) {
env.kafkaClient().setNodeApiVersions(NodeApiVersions.create());
final String user0Name = "user0";
ScramMechanism user0ScramMechanism0 = ScramMechanism.SCRAM_SHA_256;
ScramMechanism user0ScramMechanism1 = ScramMechanism.SCRAM_SHA_512;
final String user1Name = "user1";
ScramMechanism user1ScramMechanism0 = ScramMechanism.SCRAM_SHA_256;
final String user2Name = "user2";
ScramMechanism user2ScramMechanism0 = ScramMechanism.SCRAM_SHA_512;
AlterUserScramCredentialsResponseData responseData = new AlterUserScramCredentialsResponseData();
responseData.setResults(Arrays.asList(user0Name, user1Name, user2Name).stream().map(u -> new AlterUserScramCredentialsResponseData.AlterUserScramCredentialsResult().setUser(u).setErrorCode(Errors.NONE.code())).collect(Collectors.toList()));
env.kafkaClient().prepareResponse(new AlterUserScramCredentialsResponse(responseData));
AlterUserScramCredentialsResult result = env.adminClient().alterUserScramCredentials(Arrays.asList(new UserScramCredentialDeletion(user0Name, user0ScramMechanism0), new UserScramCredentialUpsertion(user0Name, new ScramCredentialInfo(user0ScramMechanism1, 8192), "password"), new UserScramCredentialUpsertion(user1Name, new ScramCredentialInfo(user1ScramMechanism0, 8192), "password"), new UserScramCredentialDeletion(user2Name, user2ScramMechanism0)));
Map<String, KafkaFuture<Void>> resultData = result.values();
assertEquals(3, resultData.size());
Arrays.asList(user0Name, user1Name, user2Name).stream().forEach(u -> {
assertTrue(resultData.containsKey(u));
assertFalse(resultData.get(u).isCompletedExceptionally());
});
}
}
Aggregations