Orchestration: Create AD Object, Reset AD User Password, Enable AD User Account
Hey Awesome Community.
I have Attached this in Word Document, so you can download it for later reading if necessary.
This is going to be a rather long, but instructive post, so i'll try to stay on topic.
First off, If you're like me, you're spending a lot of time on the community these days looking for answers, since the Docs are not very good or helpful. (that's my 2 cents).
So There is this thing called Orchestration, that works wonders, if you can figure out how to do it.There are tons of questions on the community (which the docs do not address), so i'm going to attempt to answer many of those in this post.
This is going to be specifically for the Active Directory Orchestration features.
More Specifically to create a user from a request, and activate them in AD where they can login.
2nd. Lets address the elephant in the room: For a product we spend so much money on, why is the documentation not better? Why do they not give real life examples?
Ok, Off We Go....
First thing is you have have Orchestration Enabled. That is a license cost you must get enabled from your account Representative.
Here is our use case.
We have Clients that use our Active Directory to login to our system. Those clients (who are external to us) may need to add new users in order to have access to our system.
Process:
I have created a Request Item in the service catalog.Service Catalog Item submitted, Gets sent for approval.
This approval will verify the user fields, verify what the user should have access. (Close the Task)
After the task is closed, we will use Orchestration to create the AD User Account.Then We will attemp to activate the AD User Account.
Task to our External User Team to verify user is setup correctly, can login, has all the access needed.
Beyond the scope of this post:
I created 2 virtual Machines on my computer and for my personal dev site to test this.1 VM is a Windows Server 2012 R2 Name: JDCISC2012 Just my Domain Controller In Service Creation 2012 a test server.IP Address on VM: 192.168.60.1321 VM is a Windows 7 Pro x64On the Windows Server, i set the Server as a Domain Controller, DNS Box, and DHCP box. Fully functional of allowing logins to the server.
on the windows 7 box i added it to the domain from the Server above. I added a Mid Server connected to my dev site.
that is where this documentation starts.
So lets get to it already.
Lets Discuss the "Create AD Object" Activity in the workflow.
SN Docs give you very basic example of how to create a user By adding object data:
A JSON object containing Active Directory property names and their corresponding values. For example:
{
"givenName" : "John",
"SN" : "Doe",
"title" : "Sr. Account Specialist",
"allowLogin" : true
}
- This example sets the first name (givenName), last name (SN), and title on the Active Directory user account and allows that user to log in (allowLogin). This field allows expression evaluation via the ${} variable substitution syntax.
Then see at the bottom where it says you can use the ${} but doesn’t give you an example. If you used this example in your workflow activity, then every time you created an activity the first name would be john, and so on.Plus the allowLogin doesn’t work.
So where do we go from here:
Lets go back to the Request that I created. Keep in mind, this is just a test form to demonstrate for you guys.
You can only send values to Active Directory if property already exists there.Ex. First Name, Last Name, Display Name
You cannot send something like Date of Birth, or Last 4 of SSN.
So we have our form set, now what?
Now lets move into the workflow.
First off, I did come across some examples on the community of the Object data to dynamically pull from a field.
Ex. { "givenName" : ${workflow.inputs.first}} that will set the “givenName value in AD the value of the first name field in your request. (based on the field name: First Name, field value is “first” so that would be the workflow.inputs. (field value) first}
Ex2. {"givenName":${workflow.inputs.first},"sn":${workflow.inputs.last}} This sets first and last name
- Active Directory Object always within “ ”
- Colon : will separate the AD object from the SN value
- ServiceNow value
- Comma , Separates the items to let the system know it’s time for the next object
- Active Directory Object always within “ ”
- Colon : will separate the AD object from the SN value
- ServiceNow value
Now, full disclosure. This way DOES WORK, if you’re only needing to set a few fields.I’ve successfully created a user with 3 values, using this method.
However, as soon as I added a 4th value using this method, the workflow failed every single time.
So, how did I get around this?
Creating a script allows me to pass as many variables as necessary.
I used a script and created the object in the script. And passed the object value to the activity.
So, lets begin with the script.
We have a very specific criteria for the UserID. So I’m creating that via Script as well.Ex. Martin Luther King + Year + letter.His User ID would be mlk18a
If there is already a mlk18a then the second one created would be mlk18b or mlk18c and so on.
SCRIPT:
generateScratchpad();
function generateScratchpad() {
//Get First, Middle, Last name fields. Make sure they are String Fields
var first = current.variables.first.toString();
var middle = current.variables.middle.toString();
var last = current.variables.last.toString();
//Get the first character from the First, Middle, Last names
var f = first.substring(0,1);
var m = middle.substring(0,1);
var l = last.substring(0,1);
//get the current glidedate time and then get the year.
var gdt = new GlideDateTime();
var year = gdt.getYear();
var yearString = year.toString();
//create userID (first itial, middle initial, last initial, last 2 digits of year, letter a)
var ID = f+m+l + yearString.substring(2,4) + "a";
//set the ID tolowerCase() to ensure they are all uniform
var IDlow = ID.toLowerCase();
//Set the scratchpad for all needed items.
workflow.scratchpad.dN = current.variables.first + " " + current.variables.middle + " " + current.variables.last; //Display Name (first, middle, last)
workflow.scratchpad.first = current.variables.first; //First Name
workflow.scratchpad.middle = current.variables.middle; //Middle Name
workflow.scratchpad.last = current.variables.last; // Last Name
workflow.scratchpad.dob = current.variables.dob.getDisplayValue(); //Date of Birth not used in the Create AD Object
workflow.scratchpad.ssn = current.variables.ssn; //SSN not used in the Create AD Object
workflow.scratchpad.address = current.variables.address; //Street Address
workflow.scratchpad.city = current.variables.city; //City
workflow.scratchpad.state = current.variables.state; //State
workflow.scratchpad.zip = current.variables.zip; //Zip
workflow.scratchpad.phone = current.variables.phone; //phone
workflow.scratchpad.start = current.variables.start_date.getDisplayValue(); //Users Start Date Not used in Create AD Object
workflow.scratchpad.email = current.variables.email.getDisplayValue(); //email Address
workflow.scratchpad.id = IDlow;
//Generate Random Password and Set AD password.
//set AD Password activity must have "Password2" type field which is an encrypted password.
//Create an Encrypted password to use in Activity, and Create a plain text to send to user for login.
var encr = new GlideEncrypter();
var clearString = new PwdCryptoSecureAutoGenPassword().generatePassword();
var encrString = encr.encrypt(clearString); //Encrypted password for use in the Set AD Password Activity.
workflow.scratchpad.pass = encrString; //Set scratchpad password variable to the encrypted password string.
var decrString = workflow.scratchpad.clearpass = encr.decrypt(encrString); //Can be used as the clear text password
/****************************************************************************************/
/****************************************************************************************/
/****************************************************************************************/
//being to create the object for sending to the create AD Object activity
//Needs to start with a {
var object = "{ ";
//set the First name in AD
object += '"givenName" : "' + workflow.scratchpad.first + '" , ';
//set the last name in AD
object += '"sn" : "' + workflow.scratchpad.last + '" , ';
//set the display name in AD
object += '"displayName" : "' + workflow.scratchpad.dN + '" , ';
//if Email is not Blank, set the Email in AD
//email may not be mandatory, and we dont want to send anything if the email is not filled in.
if(!current.variables.email.nil()){
object += '"mail" : "' + workflow.scratchpad.email + '" , ';
}
//set the login id and the domain in AD.
object += '"userPrincipalName" : "' + IDlow + '@JOKERSTEST.ORG" , ';
//set the user password in AD.
object += '"userPassword" : "' + decrString + '" , ';
if(current.variables.address != ""){
object += '"streetAddress" : "' + workflow.scratchpad.address + '" , ';
}
if(current.variables.city != ""){
object += '"l" : "' + workflow.scratchpad.city + '" , ';
}
if(current.variables.state != ""){
object += '"st" : "' + workflow.scratchpad.state + '" , ';
}
if(current.variables.zip != ""){
object += '"postalCode" : "' + workflow.scratchpad.zip + '" , ';
}
if(current.variables.phone != ""){
object += '"telephoneNumber" : "' + workflow.scratchpad.phone + '" , ';
}
//set the Initials field in AD
object += '"initials" : "' + m.toUpperCase() + '"';
//end the object with a }
object += "}";
/****************************************************************************************/
/****************************************************************************************/
/****************************************************************************************/
//for Information purposed and possible troubleshooting, add the whole object string to the work_notes field
current.work_notes = object;
//Set the object to the scratchpad.
workflow.scratchpad.object = object;
}
Next:
Remember, I’m generating the USER ID in the Object Name via the script. You don’t have to generate via script.
Then notice I’m only calling 1 item in the object data.
Here is an example of the entire object that is created via script:
If it successfully Creates the AD Object, we get a work note that it was successful.
current.work_notes = "Successfully Created User's Acitve Directory Account";
If it fails to create the AD Object, We are going to get some notes for troubleshooting.
The red box is what is returned from AD.
Script for the Run Script Box:
update();
function update() {
var currentID = "RITM's sys_id = " +current.sys_id;
var contextID;
var errorMSG;
var created;
var context = new GlideRecord("wf_context");
context.addQuery('id', current.sys_id);
context.query();
if(context.next()){
contextID = "Workflow Context sys_id = " + context.sys_id;
var error = new GlideRecord("wf_log");
error.addEncodedQuery("context=" + context.sys_id);
error.addEncodedQuery("level=2");
error.orderByDesc('sys_created_on');
error.query();
if(error.next()){
errorMSG = error.message.getDisplayValue();
created = error.sys_created_on.getDisplayValue();
}
}
var log = '';
log += "Failed to Create User's Active Directory Account";
log += "\n";
log += currentID;
log += "\n";
log += contextID;
log += "\n";
log += errorMSG;
log += "\n";
log += created;
current.work_notes = log;
}
We are only working on the successful path in this Post, so after it successfully Creates the object, it’s not much good until it’s activated/enabled in AD, right?
Well, this took the most time. No matter what I tried, the Enable AD Object activity always failed. Said that the Server was unwilling to process request.
So before we can enable the account, you have to process the password reset request first.
Keep in mind that I set the user ID on the scratchpad, and also the password on the scratchpad.
The Reset AD User Password activity must have the password come in as a Password2 type field. So where exactly is the documentation on Password2 fields? When you find it let me know, cuz the docs suck.
So after some testing and struggling, I finally just encrypted the password in the script and sent it to the activity and it works. It just needs an encrypted value sent to the field..
And lastly,
The Enable AD Account.
So a full test, my ticket Activity would look like this:
https://www.servicenow.com/community/now-platform-articles/orchestration-create-ad-object-reset-ad-user-password-enable-ad/ta-p/2323886
