Blog

Import User Photo from LDAP

If you store user photos in your LDAP database, you can also import them into ServiceNow.

There are a number of forum posts about how to do this, but I wanted to add a little more detailed information to help out.  Here are the steps to import User photos.

User Record with Photo

Step 1: Import Set Table (u_thumbnail)

If you use the import set table, ldap_import, to import users, make sure there is an u_thumbnailphoto (or similar) column with string(14,500).  This column usually gets created by your ldap user import.

To check this field, use this url and replace <yourinstance> with your ServiceNow instance:

https://<yourinstance>.service-now.com/sys_dictionary_list.do?sysparm_query=name%3Dldap_import%5Eelement%3Du_thumbnailphoto

Note: 14,500 is an estimated value. You may need a larger size for your thumbnails

Step 2: LDAP Binary Attributes

Add the value "thumbnailphoto" to the system property "glide.ldap.binary_attributes". 

To check this field, use this url and replace <yourinstance> with your ServiceNow instance:

https://<yourinstance>.service-now.com/sys_properties_list.do?sysparm_query=name%3Dglide.ldap.binary_attributes

Note: The value for the System Property should be something like: 
objectsid,objectguid,thumbnailphoto

If you are using a MID Server to import from ldap, you have to add the property to that mid server.

Restart the MID server afterwards after adding the property. Without restarting the MID server the new setting does not take effect.

 

Step 3: Add Transform Script

Add a Transform Script to your LDAP User Import Transform Map

When: OnAfter
Script: 
//gs.log('User Photo Script: Check for Existing Attachment');
var grPhotoAttachmentExists = new GlideRecord('sys_attachment');
grPhotoAttachmentExists.addQuery('table_name','ZZ_YYsys_user'); 
grPhotoAttachmentExists.addQuery('table_sys_id',target.sys_id); 
grPhotoAttachmentExists.addQuery('file_name','photo');
grPhotoAttachmentExists.query();
if (source.u_thumbnailphoto != '') {
//gs.log('User Photo Script: LDAP Source Photo Exists'); 
if (!grPhotoAttachmentExists.next()) {
//gs.log('User Photo Script: No existing photo attachment, attach new photo'); 
attachPhoto();
}
else {
//gs.log('User Photo Script: Photo Attachment Exists, Compare Attachments'); 
var sysEncodedAttachment = new GlideSysAttachment();
var binData =sysEncodedAttachment.getBytes(grPhotoAttachmentExists);
var EncodedBytes = GlideStringUtil.base64Encode(binData);
if (EncodedBytes != source.u_thumbnailphoto) {
//gs.log('User Photo Script: Photo attachment exists, bytes don't match, delete existing attachment and attach new photo'); 
grPhotoAttachmentExists.deleteRecord();
attachPhoto();
}
}
}
else {
//gs.log('User Photo Script: LDAP Source Photo Does Not Exist'); 
if (grPhotoAttachmentExists.next()) {
//gs.log('User Photo Script: Delete existing photo attachment'); 
grPhotoAttachmentExists.deleteRecord();
}
}

function attachPhoto(){
//gs.log('User Photo Script: Attach Photo'); 
var sysDecodedAttachment = new GlideSysAttachment();
var DecodedBytes = GlideStringUtil.base64DecodeAsBytes(source.u_thumbnailphoto);
var attID = sysDecodedAttachment.write(target, 'photo', 'image/jpeg', DecodedBytes);
var newAttachment = new GlideRecord("sys_attachment");
newAttachment.addQuery("sys_id", attID);
newAttachment.query();
if (newAttachment.next()) {
newAttachment.table_name = "ZZ_YYsys_user";
newAttachment.table_sys_id = target.sys_id;
newAttachment.content_type = 'image/jpeg';
newAttachment.update();
}
} 

Step 4: Limit Import

Limit your LDAP User import to only a few users so you can test.  It is safer and quicker to test one user rather than 10,000.

1. In your LDAP OU Definition for LDAP Users, add a filter.  For example: (sAMAccountName=mike.kaufman).
2. Click Browse on the LDAP OU Definition for LDAP Users
3. Click the plus sign on the LDAP Nodes to verify only the one user is returned.

Step 5:  Add the Photo Field

1. On the User Form, Right click the Header Bar > Go to Personalize Form Layout
2. Add the Photo Field to your Form.

Step 6: Test

1. In Scheduled Imports, open your LDAP User Import
2. Click Execute Now
3. Wait until Import completes.  You can check "All Active Transactions" to see if process is running.
4. Check Imported User
5. Remember to change back LDAP OU Definition to import all users
6. Rerun the Scheduled Import for all users

Step 7: Troubleshooting

  • You may need to increase the u_thumbnail column to a size larger than 13500. If some pictures don't import, you may need to adjust.

  • Watch the Warning and Error logs during import

  • In theTransform Script, I included some gs.log statements you can uncomment out for debugging

  • Some forum posts say to set system property, "com.glide.loader.verify_target_field_size" to true. This is what this property does:

Controls whether import set fields can automatically increase in size during an import (true) or not (false). By default, data that exceeds the import field size is truncated. Set this property to true to allow any import set field to increase the column size to match the length of the data.

In my opinion, property causes more issues than it solves. You are better off manually setting the size of the u_thumbnail column like in Step 1.  Some columns in LDAP that store credentials are very large. If you use this property you may receive this error and not able to import any ldap records:

java.sql.SQLException: java.sql.BatchUpdateException: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs

If you decided to use the "com.glide.loader.verify_target_field_size" property and received this error, here is a way to fix it:

1. Set System Property "com.glide.loader.verify_target_field_size" to false
2. Set the LDAP attributes if needed to limit fields that are imported.
3. Delete the columns in the ldap_import table that are too large.  Might be 2 or 3 large fields.
4. Reimport the ldap users.  The columns will be recreated in smaller sizes.