Skip to content

Commit bc2782a

Browse files
committed
Allow the dataset to generate users with a limited number of unique passwords
Closes #1237 Signed-off-by: Ryan Emerson <[email protected]>
1 parent 217d700 commit bc2782a

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

dataset/dataset-import.sh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ set_environment_variables () {
2424
STATUS_TIMEOUT="120"
2525
CREATE_TIMEOUT="3600"
2626
THREADS="-1"
27+
UNIQUE_CREDENTIALS="-1"
2728

28-
while getopts ":a:r:n:c:u:e:o:g:i:p:l:t:C:T:" OPT
29+
while getopts ":a:r:n:c:u:e:o:g:i:p:l:t:C:T:U:" OPT
2930
do
3031
case $OPT in
3132
a)
@@ -70,6 +71,9 @@ set_environment_variables () {
7071
T)
7172
THREADS=$OPTARG
7273
;;
74+
U)
75+
UNIQUE_CREDENTIALS=$OPTARG
76+
;;
7377
?)
7478
echo "Invalid option: $OPT, read the usage carefully -> "
7579
help
@@ -85,7 +89,7 @@ create_clients () {
8589

8690
create_users () {
8791
echo "Creating $1 user/s in realm $2"
88-
execute_command "create-users?count=$1&realm-name=$2"
92+
execute_command "create-users?count=$1&realm-name=$2&unique-credential-count=$3"
8993
}
9094

9195
create_events () {
@@ -201,7 +205,7 @@ main () {
201205
exit 0
202206
;;
203207
create-users)
204-
create_users $USERS_COUNT $REALM_NAME
208+
create_users $USERS_COUNT $REALM_NAME $UNIQUE_CREDENTIALS
205209
exit 0
206210
;;
207211
create-events)

dataset/src/main/java/org/keycloak/benchmark/dataset/DatasetResourceProvider.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.keycloak.benchmark.dataset.config.DatasetException;
3434
import org.keycloak.benchmark.dataset.organization.OrganizationProvisioner;
3535
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
36+
import org.keycloak.credential.hash.PasswordHashProvider;
3637
import org.keycloak.events.Event;
3738
import org.keycloak.events.EventStoreProvider;
3839
import org.keycloak.events.EventType;
@@ -52,6 +53,7 @@
5253
import org.keycloak.models.UserModel;
5354
import org.keycloak.models.UserSessionModel;
5455
import org.keycloak.models.cache.CacheRealmProvider;
56+
import org.keycloak.models.credential.PasswordCredentialModel;
5557
import org.keycloak.models.utils.KeycloakModelUtils;
5658
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
5759
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
@@ -71,6 +73,7 @@
7173
import java.util.concurrent.atomic.AtomicInteger;
7274
import java.util.regex.Pattern;
7375
import java.util.stream.Collectors;
76+
import java.util.stream.IntStream;
7477

7578
import static org.keycloak.benchmark.dataset.config.DatasetOperation.CREATE_CLIENTS;
7679
import static org.keycloak.benchmark.dataset.config.DatasetOperation.CREATE_EVENTS;
@@ -435,6 +438,8 @@ private void createUsersImpl(Task task, DatasetConfig config, RealmModel realm)
435438
}
436439

437440
private void addUserCreationTasks(RealmContext context, Task task, DatasetConfig config, ExecutorHelper executor, int startIndex, int usersCount) {
441+
// Initialize password credentials if unique-credentials-count is configured
442+
List<PasswordCredentialModel> credentials = initializeCredentials(config, context);
438443

439444
for (int i = startIndex; i < (startIndex + usersCount); i += config.getUsersPerTransaction()) {
440445
final int usersStartIndex = i;
@@ -446,7 +451,7 @@ private void addUserCreationTasks(RealmContext context, Task task, DatasetConfig
446451
executor.addTaskRunningInTransaction(session -> {
447452
KeycloakModelUtils.cloneContextRealmClientToSession(baseSession.getContext(), session);
448453

449-
createUsers(context, session, usersStartIndex, endIndex);
454+
createUsers(context, session, usersStartIndex, endIndex, credentials);
450455

451456
task.debug(logger, "Created users in realm %s from %d to %d", context.getRealm().getName(), usersStartIndex, endIndex);
452457

@@ -457,6 +462,17 @@ private void addUserCreationTasks(RealmContext context, Task task, DatasetConfig
457462
}
458463
}
459464

465+
private List<PasswordCredentialModel> initializeCredentials(DatasetConfig config, RealmContext context) {
466+
PasswordPolicy policy = context.getRealm().getPasswordPolicy();
467+
PasswordHashProvider hash = policy.getHashAlgorithm() != null ?
468+
baseSession.getProvider(PasswordHashProvider.class, policy.getHashAlgorithm()) :
469+
baseSession.getProvider(PasswordHashProvider.class);
470+
471+
return IntStream.range(0, config.getUniqueCredentialCount())
472+
.boxed()
473+
.map(i -> hash.encodedCredential("password-" + i, policy.getHashIterations()))
474+
.toList();
475+
}
460476

461477
@GET
462478
@Path("/create-events")
@@ -1130,7 +1146,7 @@ private void createClients(RealmContext context, Task task, KeycloakSession sess
11301146
}
11311147

11321148
// Worker task to be triggered by single executor thread
1133-
private void createUsers(RealmContext context, KeycloakSession session, int startIndex, int endIndex) {
1149+
private void createUsers(RealmContext context, KeycloakSession session, int startIndex, int endIndex, List<PasswordCredentialModel> credentials) {
11341150
// Refresh the realm
11351151
RealmModel realm = session.realms().getRealm(context.getRealm().getId());
11361152
DatasetConfig config = context.getConfig();
@@ -1147,8 +1163,13 @@ private void createUsers(RealmContext context, KeycloakSession session, int star
11471163
user.setLastName(username + "-last");
11481164
user.setEmail(username + String.format("@%s.com", realm.getName()));
11491165

1150-
String password = String.format("%s-password", username);
1151-
user.credentialManager().updateCredential(UserCredentialModel.password(password, false));
1166+
if (credentials.isEmpty()) {
1167+
String password = String.format("%s-password", username);
1168+
user.credentialManager().updateCredential(UserCredentialModel.password(password, false));
1169+
} else {
1170+
PasswordCredentialModel password = credentials.get(i % config.getUniqueCredentialCount());
1171+
user.credentialManager().createStoredCredential(password);
1172+
}
11521173

11531174
// Assign a role to a user if any exist in the realm
11541175
if (!context.getRealmRoles().isEmpty()) {

dataset/src/main/java/org/keycloak/benchmark/dataset/config/DatasetConfig.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ public class DatasetConfig {
226226
@QueryParamIntFill(paramName = "identity-provider-mappers-count", operations = CREATE_ORGS)
227227
private int identityProviderMappersCount;
228228

229+
@QueryParamIntFill(paramName = "unique-credential-count", defaultValue = 0, operations = CREATE_USERS)
230+
private int uniqueCredentialCount;
231+
229232
// String representation of this configuration (cached here to not be computed in runtime)
230233
private String toString = "DatasetConfig []";
231234

@@ -432,4 +435,8 @@ public int getIdentityProvidersCount() {
432435
public int getIdentityProviderMappersCount() {
433436
return identityProviderMappersCount;
434437
}
438+
439+
public int getUniqueCredentialCount() {
440+
return uniqueCredentialCount;
441+
}
435442
}

0 commit comments

Comments
 (0)