Scott Roth · Feb 16, 2018

User Role Lookup from ZAUTHENTICATE

I am working on an ZAUTHENTICATE.mac to move us from local cache users to Delegated Authentication against LDAP. 

I have created a user role within my instance of Ensemble that matches the AD Group that I will be assigning everyone in my group to.  Is there a way to query the list of available Roles within Ensemble, and if one of my AD groups matches that role, set the role for that user?

How would I compare the AD Group against the Role listing?



2 0 10 406


provided you have sufficient access rights you may get defined roles in Caché / Ensbele like this:

 set role=""
 for   {
     set role=$ORDER(^|"%SYS"|SYS("Security","RolesD",role)) quit:role=""  
     write role,!    ;; or do whatever you need

This currently works, but breaks the class abstraction, so it might stop working without warning if the implementation of the class changes.  If you can use the documented queries or methods in the Security.Roles class, I would recommend that instead.  

I believe it is either a String for a Fixed Sequence. I cut and pasted that from a document given to me to show me the LDAP/AD Attributes. I believe the structure is {CN=  ,OU=,  DC=, DC= , CN=,OSU=,DC=,DC=.....}  so every time we see a CN its a new group which is what I want to key off of.

so with a little change you get the content of CN= as starting string 

set list2=$lfs(input,"CN=")
; ignore trailer
for i=2:1:$LL(list2) write !,i,?5,$p($li(list2,i),",")
2    Access.Ensemble.Developer.User
3    [CPD Admin]
4    [MUSE_Access]
5    [IT eMaterials]

When I run...

 i=2:1:$LL(list2) write !,i,"",$p($li(list2,i),",")

I am getting the output of


How can I remove the 2 from the beginning and ending of the string, then compare it to the %SYS Roles?




for i=2:1:$LL(list2) {
  set CN=$p($li(list2,i),",") ;get 1st piece 
  set CN=$zcvt(CN,"L")        ;lower case required..v 
  write !,i,"  ",exists," ",CN
  if exists write " role found"

what is this ?  a String or a JSON object ,  or a fixed sequence of (CN=  ,OU=,  DC=, DC= )
there is no obvious groupIng by a separator visible.
You may start by

set list=$lfs($p($p(input,"{",2),"}"))
zw list
list=$lb("CN=Access.Ensemble.Developer.User","OU=Access Groups","DC=OSUMC","DC=EDU"," CN=[CPD Admin]","OU=Distribution Lists","DC=OSUMC","DC=EDU"," CN=[MUSE_Access]","OU=Distribution Lists","DC=OSUMC","DC=EDU"," CN=[IT eMaterials]","OU=Distribution Lists","DC=OSUMC","DC=EDU...")


But instead of an unstructured string you have an unstructured list  

In general I would agree:
Though in order to use the class query you have the change  to namespace "%SYS" and  back.
As the query is predefined you finally build your own lookup list which is a copy of the original global.

Anyhow this would provide the required result:

     kill roles
    set roles=""
    new $namespace
    zn "%SYS"
    set rs=##class(%ResultSet).%New("Security.Roles:ListAll1")
    set tSC=rs.Execute()
    if tSC
        while rs.Next() {
            set role=rs.Get("Name")
            write ">",role,! ;; just for display
            set roles($zcvt(role,"L"))=""
     set rs=""                       ;; for save return from "%SYS"
     zw roles                        ;; for demo
     set list2=$lfs(input,"CN=")
     for i=2:1:$LL(list2) {
        set CN=$p($li(list2,i),",") ;; get 1st piece
        set CN=$zcvt(CN,"L") ;; lower case required..v
        set exists=''$d(roles(CN))
        write !,i," ",exists," ",CN ;; for debugging and demo
        if exists write " role found"
     quit                            ;; get back to original namespace

Object approach:

Set sc = ##class(Security.Users).AddRoles("User", "Role1,Role2")


So I am trying to take a list of....

managedObjects                       : {CN=Access.Ensemble.Developer.User,OU=Access Groups,DC=OSUMC,DC=EDU, CN=[CPD Admin],OU=Distribution Lists,DC=OSUMC,DC=EDU, CN=[MUSE_Access],OU=Distribution Lists,DC=OSUMC,DC=EDU, CN=[IT eMaterials],OU=Distribution Lists,DC=OSUMC,DC=EDU...}

How can I put this into a list and properly filter out the values I need. For Example Access.Ensemble.Developer.User is my end target that corresponds to a role of that same name.

I am struggling with how to appropriately pull this information out so I can do the IF statements below.