Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added: Random Passwords #48

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public enum CliOptions {
EMAIL("m", "mail", true, "account email address"),
SINGLE_USERNAME("u", "username", true, "account username/login"),
PASSWORD("p", "password", true, "account password"),
PASSWORD_LENGTH("pl", "passwordLength", true, "random account password length"),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Options key should not overlap each other one should not start like the other.
"p" is contained in "pl"


SEQ_ACCOUNTS_COUNT("c", "count", true, "number of accounts to generate"),
SEQ_ACCOUNTS_START("s", "startnum", true, "number of the first one"),
Expand Down
32 changes: 25 additions & 7 deletions KinanCity-core/src/main/java/com/kinancity/core/KinanCityCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
import org.slf4j.LoggerFactory;

import com.kinancity.api.model.AccountData;
import com.kinancity.core.generator.PasswordGenerator;
import com.kinancity.core.generator.account.CsvReaderAccountGenerator;
import com.kinancity.core.generator.account.SequenceAccountGenerator;
import com.kinancity.core.generator.account.SingleAccountGenerator;
import com.kinancity.core.generator.password.RandomPasswordGenerator;
import com.kinancity.core.generator.password.SinglePasswordGenerator;
import com.kinancity.core.proxy.bottleneck.ProxyNoBottleneck;
import com.kinancity.core.proxy.policies.UnlimitedUsePolicy;

Expand Down Expand Up @@ -106,22 +109,36 @@ private static Configuration updateConfiguration(Configuration config, Options o

// 3 types of generation : unique, csv and sequence
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Password generator could also be used with csv input, if the password header is not added in file.

This could be part of another PR.


if (cmd.hasOption(CliOptions.SEQ_ACCOUNTS_FORMAT.shortName) && cmd.hasOption(CliOptions.SEQ_ACCOUNTS_COUNT.shortName) && cmd.hasOption(CliOptions.EMAIL.shortName) && cmd.hasOption(CliOptions.PASSWORD.shortName)) {
if (cmd.hasOption(CliOptions.SEQ_ACCOUNTS_FORMAT.shortName) && cmd.hasOption(CliOptions.SEQ_ACCOUNTS_COUNT.shortName) && cmd.hasOption(CliOptions.EMAIL.shortName)) {
LOGGER.info("Use a Sequence Account Generator");
SequenceAccountGenerator sequenceGenerator = new SequenceAccountGenerator();
sequenceGenerator.setBaseEmail(cmd.getOptionValue(CliOptions.EMAIL.shortName));
sequenceGenerator.setStaticPassword(cmd.getOptionValue(CliOptions.PASSWORD.shortName));
sequenceGenerator.setUsernamePattern(cmd.getOptionValue(CliOptions.SEQ_ACCOUNTS_FORMAT.shortName));
sequenceGenerator.setNbAccounts(Integer.parseInt(cmd.getOptionValue(CliOptions.SEQ_ACCOUNTS_COUNT.shortName)));
sequenceGenerator.setStartFrom(Integer.parseInt(cmd.getOptionValue(CliOptions.SEQ_ACCOUNTS_START.shortName, "0")));
if (cmd.hasOption(CliOptions.PASSWORD.shortName)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate code should be joined as one.

PasswordGenerator definition could be done before the "3 types of generation" fork

sequenceGenerator.setPasswordGenerator(new SinglePasswordGenerator(cmd.getOptionValue(CliOptions.PASSWORD.shortName)));
}
else {
Integer length = Integer.valueOf(cmd.getOptionValue(CliOptions.PASSWORD_LENGTH.shortName, "-1"));
sequenceGenerator.setPasswordGenerator(new RandomPasswordGenerator(length));
}
config.setAccountGenerator(sequenceGenerator);

} else if (cmd.hasOption(CliOptions.EMAIL.shortName) && cmd.hasOption(CliOptions.SINGLE_USERNAME.shortName) && cmd.hasOption(CliOptions.PASSWORD.shortName)) {
}
else if (cmd.hasOption(CliOptions.EMAIL.shortName) && cmd.hasOption(CliOptions.SINGLE_USERNAME.shortName)) {
LOGGER.info("Create a single account");
AccountData account = new AccountData();
account.setEmail(cmd.getOptionValue(CliOptions.EMAIL.shortName));
account.setUsername(cmd.getOptionValue(CliOptions.SINGLE_USERNAME.shortName));
account.setPassword(cmd.getOptionValue(CliOptions.PASSWORD.shortName));
PasswordGenerator pwGen;
if (cmd.hasOption(CliOptions.PASSWORD.shortName)) {
pwGen = new SinglePasswordGenerator(cmd.getOptionValue(CliOptions.PASSWORD.shortName));
}
else {
Integer length = Integer.valueOf(cmd.getOptionValue(CliOptions.PASSWORD_LENGTH.shortName, "-1"));
pwGen = new RandomPasswordGenerator(length);
}
account.setPassword(pwGen.generatePassword());
config.setAccountGenerator(new SingleAccountGenerator(account));

// No need to use multiple thread for 1 account only
Expand All @@ -134,9 +151,9 @@ private static Configuration updateConfiguration(Configuration config, Options o

HelpFormatter formatter = new HelpFormatter();
String cmdLineSyntax = " one of \n"
+ " -m <email> -u <username> -p <password> \n"
+ " -m <email> -u <username> (-p <password> -pl <passwordLength>) \n"
+ " -a <accounts.csv> \n"
+ " -m <email> -c <#ofAccounts> -f <format**> -p <password> (-s <first#>)\n"
+ " -m <email> -c <#ofAccounts> -f <format**> (-p <password> -pl <passwordLength> -s <first#>)\n"
+ " and optional : -ck <captchakey> \n\n";
formatter.setWidth(180);
formatter.printHelp(cmdLineSyntax, options);
Expand All @@ -157,6 +174,7 @@ private static Options setupCliOptions() {
options.addOption(CliOptions.EMAIL.asOption());
options.addOption(CliOptions.SINGLE_USERNAME.asOption());
options.addOption(CliOptions.PASSWORD.asOption());
options.addOption(CliOptions.PASSWORD_LENGTH.asOption());

// Create Multiple accounts
options.addOption(CliOptions.CSV_ACCOUNTS.asOption());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.kinancity.core.generator.PasswordGenerator;
import com.kinancity.core.generator.UsernameGenerator;
import com.kinancity.core.generator.email.PlusTrickEmailGenerator;
import com.kinancity.core.generator.password.SinglePasswordGenerator;
import com.kinancity.core.generator.username.SequenceUsernameGenerator;

import lombok.Setter;
Expand All @@ -23,9 +22,6 @@ public class SequenceAccountGenerator implements AccountGenerator {
// Format with prefix and suffix. use * instead of the number sequence
private String usernamePattern;

@Setter
private String staticPassword;

@Setter
private String baseEmail;

Expand Down Expand Up @@ -59,9 +55,6 @@ public void init() {
throw new IllegalArgumentException("Sequence would overflow format, use more *");
}
usernameGenerator = seqUsernameGenerator;

passwordGenerator = new SinglePasswordGenerator(staticPassword);

initDone = true;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.kinancity.core.generator.password;

import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.kinancity.core.KinanCityCli;
import com.kinancity.core.generator.PasswordGenerator;

/**
* Random Password generator
* @author 0815Flo0815
*
*/
public class RandomPasswordGenerator implements PasswordGenerator {

private static final char[][] CHAR_POOL = {
{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'},
{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'},
{'1','2','3','4','5','6','7','8','9','0'},
{'#','?','!','@','$','%','%','^','&','>','<','+','`','*','(',')','-',']'}
};
private static final int MIN_LENGTH = 8;
private static final int MAX_LENGTH = 50;

private static Logger LOGGER = LoggerFactory.getLogger(KinanCityCli.class);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On other classes I currently use instance loggers :
private Logger logger = LoggerFactory.getLogger(getClass());


private int length;

public RandomPasswordGenerator(Integer length) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to take an Integer as paramter, primitive int would be better to avoid null checks

super();
if (length == null) {
LOGGER.warn("Password length must be a number! Using a random length!");
this.length = -1;
}
else if (length < 0) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style : else if should be on the same line then the closing bracket of previous if

this.length = -1;
}
else if (length < MIN_LENGTH) {
LOGGER.warn("The minimum password length is " + MIN_LENGTH + "! Using " + MIN_LENGTH + "!");
this.length = MIN_LENGTH;
}
else if (length > MAX_LENGTH) {
LOGGER.warn("The maximum password length is " + MAX_LENGTH + "! Using " + MAX_LENGTH + "!");
this.length = MAX_LENGTH;
}
else {
this.length = length;
}
}

@Override
public String generatePassword() {
int length;
if (this.length == -1) {
length = ThreadLocalRandom.current().nextInt(MIN_LENGTH, MAX_LENGTH + 1);
}
else {
length = this.length;
}

ArrayList<Character> passwordPool = new ArrayList<Character>();
for (int i = 0; i < length; i++) {
char[] currentPool = CHAR_POOL[i % CHAR_POOL.length];
int randomIndexPool = ThreadLocalRandom.current().nextInt(currentPool.length);
int randomIndexPosition = ThreadLocalRandom.current().nextInt(passwordPool.size() + 1);
passwordPool.add(randomIndexPosition, currentPool[randomIndexPool]);
}
Collections.shuffle(passwordPool);
return String.valueOf(passwordPool.stream().map(e->e.toString()).collect(Collectors.joining()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import com.kinancity.api.model.AccountData;
import com.kinancity.core.generator.account.SequenceAccountGenerator;
import com.kinancity.core.generator.password.RandomPasswordGenerator;
import com.kinancity.core.generator.password.SinglePasswordGenerator;

public class SequenceAccountGeneratorTest {

Expand All @@ -16,21 +18,37 @@ public void sequenceTest() {
generator.setBaseEmail("[email protected]");
generator.setUsernamePattern("pref*****suf");
generator.setStartFrom(1234);
generator.setNbAccounts(3);
generator.setNbAccounts(4);

AccountData data;

generator.setPasswordGenerator(new SinglePasswordGenerator("Test"));

data = generator.next();
assertThat(data).isNotNull();
assertThat(data.getUsername()).isEqualTo("pref01234suf");
assertThat(data.getPassword()).isEqualTo("Test");

generator.setPasswordGenerator(new RandomPasswordGenerator(-1));

data = generator.next();
assertThat(data).isNotNull();
assertThat(data.getUsername()).isEqualTo("pref01235suf");
assertThat(data.getPassword().length()).isBetween(8, 50);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the same regexp or calling directly isAccountValid would be better.

https://github.com/drallieiv/KinanCity/blob/develop/ptc-api/src/main/java/com/kinancity/api/PtcSession.java


generator.setPasswordGenerator(new RandomPasswordGenerator(5));

data = generator.next();
assertThat(data).isNotNull();
assertThat(data.getUsername()).isEqualTo("pref01236suf");
assertThat(data.getPassword().length()).isEqualTo(8);

generator.setPasswordGenerator(new RandomPasswordGenerator(100));

data = generator.next();
assertThat(data).isNotNull();
assertThat(data.getUsername()).isEqualTo("pref01237suf");
assertThat(data.getPassword().length()).isEqualTo(50);

data = generator.next();
assertThat(data).isNull();
Expand Down