Random Password in catalog item run script

Brendan Hallida
Kilo Guru

Hi all,

So I got some assistance from a consultant on this script.  Our requirements are to generate a random password, and the password needed to have the following:

  • 8 characters
  • At least 1 Uppercase
  • At least 1 Lowercase
  • At least 1 Number

The password is then passed over to our custom powershell activities.

We came up with the below:

var randomNum;
lowerUpperNum = false;
while(!lowerUpperNum) {
    randomNum = GlideSecureRandomUtil.getSecureRandomString(8);
    if(hasLowerUpperNumCase(randomNum)) {
        lowerUpperNum = true;
    }
}

current.variables.password = randomNum; //passes string to request item variable

function hasLowerUpperNumCase(_randomNum) {
    return (/[a-zA-Z0-9]/.test(_randomNum));
}

It seemed to be working, however, i just got a result without a lowercase: ie this was it 38B9U485.

Anyone know what could be happening, or if there was a better way to meet our requirements?

 

Cheers,

Brendan

 

1 ACCEPTED SOLUTION

Try running it with the print enclosed inside of an evaluation of lowerUpperNum. As you've written it, the password is always printed, even if lowerUpperNum evaluates as false.

I just tested the following and got 1,000 matches exactly.

 

for (i=0; i<1000; ){
	var lowerUpperNum = false;
	while(!lowerUpperNum) {

		var password = GlideSecureRandomUtil.getSecureRandomString(8);	
		lowerUpperNum = !!((password).match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/));
		
		if(lowerUpperNum) {
			gs.print(password);
			i++;
		}

		//current.variables.password = GlideSecureRandomUtil.getSecureRandomString(8);	
		//lowerUpperNum = !!((current.variables.password).match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/));
	}
}

 

You could take it a step further and modify it for your application by the following, which guarantees that lowerUpperNum needs to be truthy before password is assigned.

 

var lowerUpperNum = false;
while(!lowerUpperNum) {

	var password = GlideSecureRandomUtil.getSecureRandomString(8);	
	lowerUpperNum = !!((password).match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/));
	
	if(lowerUpperNum) {
		current.variables.password = password;	
	}
	
}

View solution in original post

11 REPLIES 11

Hi, I slightly update and this worked for me. Can you try it out

var randomNum;
for (i=0; i<10; ){
lowerUpperNum = false;
while(!lowerUpperNum) {
    randomNum = GlideSecureRandomUtil.getSecureRandomString(8);
    if(hasLowerUpperNumCase(randomNum)) {
        lowerUpperNum = true;
	gs.print(randomNum);
        i++;
    }
}
}
function hasLowerUpperNumCase(_randomNum) {
var a = (/[a-z][A-Z][0-9]/.test(_randomNum));
//gs.log("a is ---- "+a);
return a;

}

Cheers mate,

This did work perfectly, however, I chose Ben's answer as correct as I believe it is the most efficient code.

 

i appreciate your assistance 🙂

benjamin_alldri
Mega Expert

You're almost there with your original code. But, for the sake of scope security, I personally prefer to handle everything inside of the loop itself. I also find that using String.prototype.match(...) is easier to work with than RegExp.prototype.test(...), especially when you're ensuring it as a boolean by prepending a double-bang.

 

var lowerUpperNum = false;

while(!lowerUpperNum) {

    current.variables.password = GlideSecureRandomUtil.getSecureRandomString(8);	
    lowerUpperNum = !!((current.variables.password).match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/));
}

 

It's all personal preference of course, but that should achieve what you are chasing.

Thanks for your reply 🙂

 

I tried it and add it to a loop to test 1000 times, and it is failing also.  Am I missing something?  I do like this as it is a smaller script 🙂

 

for (i=0; i<1000; ){
var lowerUpperNum = false;
while(!lowerUpperNum) {

		var password = GlideSecureRandomUtil.getSecureRandomString(8);	
		lowerUpperNum = !!((password).match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/));
		
		gs.print(password);
			i++;

    //current.variables.password = GlideSecureRandomUtil.getSecureRandomString(8);	
    //lowerUpperNum = !!((current.variables.password).match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/));
}
}

Try running it with the print enclosed inside of an evaluation of lowerUpperNum. As you've written it, the password is always printed, even if lowerUpperNum evaluates as false.

I just tested the following and got 1,000 matches exactly.

 

for (i=0; i<1000; ){
	var lowerUpperNum = false;
	while(!lowerUpperNum) {

		var password = GlideSecureRandomUtil.getSecureRandomString(8);	
		lowerUpperNum = !!((password).match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/));
		
		if(lowerUpperNum) {
			gs.print(password);
			i++;
		}

		//current.variables.password = GlideSecureRandomUtil.getSecureRandomString(8);	
		//lowerUpperNum = !!((current.variables.password).match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/));
	}
}

 

You could take it a step further and modify it for your application by the following, which guarantees that lowerUpperNum needs to be truthy before password is assigned.

 

var lowerUpperNum = false;
while(!lowerUpperNum) {

	var password = GlideSecureRandomUtil.getSecureRandomString(8);	
	lowerUpperNum = !!((password).match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/));
	
	if(lowerUpperNum) {
		current.variables.password = password;	
	}
	
}