Pulling information from Credentials using Cache Object Script

Is there a way to pull a user name and password from the Credentials list that is kept in Ensemble? Right now I have a LDAP user that I have hard coded into my ZAUTHENTICATE, which I would like to get away from. I am not to familiar with settings Global, or calling them at least.

Thanks

Scott

  • + 1
  • 0
  • 485
  • 11
  • 1

Answers

Hi

If you want to get the username and password that is stored in the Ensemble credentials list that is accessible via the management portal Ensemble>Credentials, and  if you know the credential id,

then you can get the username and password via the Ens.Config.Credentials class:

SET cr=##class(Ens.Config.Credentials).%OpenId("yourCredentialID")

SET UserName=cr.Username

SET Password=cr.Password

 

see here the class reference:

http://docs.intersystems.com/latest/csp/docbook/%25CSP.Documatic.cls?AGE...

 

I hope it helps

Stelios

 

 

Comments

Passwords are encrypted so no.

Login details are stored in Security.Users table or ^SYS("Security","UsersD") global in %sys namespace. 

Instead of storing it at the Credentials level, I have created a Global to store the LDAP server information. However when I am calling $Get(^OSUMCLDAP(Server)) nothing is being returned. Am I not calling it appropriately? Do I need to add an include statement somewhere to make sure it includes the globals?

#define LDAPServer $Get(^OSUMCLDAP(Server))

 $$$WindowsLDAPServer{
AdminDN=$Get(^OSUMCLDAP(User))
AdminPW=$Get(^OSUMCLDAP(Pass))
 }

Thanks

Scott

Could you please add your code as an example what you already did with ZAUTHENTICATE? 

ZAUTHENTICATE(ServiceName,Namespace,Username,Password,Credentials,Properties) PUBLIC {
#include %occErrors
#include %sySecurity
#include %syLDAP

 
 s LDAPServer="xxxxx.xxxxxx.xxxx"
 s LD=##Class(%SYS.LDAP).Init(LDAPServer)
 i LD=0 {
   s Status=##Class(%SYS.LDAP).GetLastError()
   //g Error
 }
 s LDAPUser = "ensemble.Services"
 s LDAPPass = "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
 
 s Status=##Class(%SYS.LDAP).Binds(LD,"",$lb(LDAPUser,"",LDAPPass),$$$LDAPAUTHNEGOTIATE)
 i Status'=$$$LDAPSUCCESS q $SYSTEM.Status.Error($$$InvalidUsernameOrPassword)
 
  s BaseDN="dc=OSUMC,dc=EDU"
 s Filter="sAMAccountname="_Username
 s Attributes=$lb("sAMAccountname","displayName","mail")
 s Status=##Class(%SYS.LDAP).SearchExts(LD,BaseDN,$$$LDAPSCOPESUBTREE,Filter,Attributes,0,"","",10,1,.SearchResult)
 i Status'=$$$LDAPSUCCESS {
 w !,"SearchExts error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
 g Done
 }
 s CurrentEntry=##Class(%SYS.LDAP).FirstEntry(LD,SearchResult)
 i CurrentEntry=0 {
 s Status=##Class(%SYS.LDAP).GetError(LD)
 w !,"FirstEntry error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status) 
 g Done
 }
 s DN=##Class(%SYS.LDAP).GetDN(LD,CurrentEntry) 
 s Attribute=##Class(%SYS.LDAP).FirstAttribute(LD,CurrentEntry,.Ptr)
 while (Attribute'="") {
   s Values=##Class(%SYS.LDAP).GetValuesLen(LD,CurrentEntry,Attribute)
   //w Values
   s Properties("Attributes",Attribute)=Values
   //w Attributes(Attribute)
  s Attribute=##Class(%SYS.LDAP).NextAttribute(LD,CurrentEntry,.Ptr)
 }
 s Properties("Username")=$li(Properties("Attributes","sAMAccountName"))
 k Properties("Attributes","sAMAccountName")
 s Properties("FullName")=$li(Properties("Attributes","displayName"))
 k Properties("Attributes","displayName")

 s GroupFilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:="_DN_"))"
 s GroupAttributes=""
 s Status=##Class(%SYS.LDAP).SearchExts(LD,BaseDN,$$$LDAPSCOPESUBTREE,GroupFilter,GroupAttributes,0,"","",10,0,.GroupSearchResult)
 i Status'=$$$LDAPSUCCESS {
w !,"SearchExts error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
g Done
 }
 s GroupNumEntries=##Class(%SYS.LDAP).CountEntries(LD,GroupSearchResult)
 i GroupNumEntries=-1 {
s Status=##Class(%SYS.LDAP).GetError(LD)
//w !,"CountEntries Group error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
g Done
 }

 w !
 i GroupNumEntries=0 {
w !,"No nested groups for "_Username_" found"
g Done
 }
 i GroupNumEntries>0 {
//w !,"Found "_GroupNumEntries_" nested groups for user "_Username
 }

#;Get the dn of the first entry returned.
 s GroupCurrentEntry=##Class(%SYS.LDAP).FirstEntry(LD,GroupSearchResult)
 i GroupCurrentEntry=0 {
s Status=##Class(%SYS.LDAP).GetError(LD)
w !,"FirstEntry error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
g Done
 }
 s Groups=""
 While (GroupCurrentEntry'=0) {
s GroupDN=##Class(%SYS.LDAP).GetDN(LD,GroupCurrentEntry)
i GroupDN="" {
s Status=##Class(%SYS.LDAP).GetError(LD)
w !,"GetDN Group error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
q
}
s CN=$p(GroupDN,",",1)
s AD=$p(CN,"=",2)
s AD=$zcvt(AD,"L") 
set exists=''$d(^|"%SYS"|SYS("Security","RolesD",AD))
if exists{
s Properties("Roles") = AD
w Properties("Roles")
}
#;Save for later display
//w !,AD
  s GroupCurrentEntry=##Class(%SYS.LDAP).NextEntry(LD,GroupCurrentEntry)
 }
Done
 i $d(SearchResult) d ##Class(%SYS.LDAP).MsgFree(SearchResult)
 i $d(GroupSearchResult) d ##Class(%SYS.LDAP).MsgFree(GroupSearchResult)
#;Close the connection and free the LDAP in memory structures.
 i $d(LD) d ##Class(%SYS.LDAP).UnBinds(LD)
 q $SYSTEM.Status.OK()
Error s $zt=""
 w !,"Cache error: "_$ze
 g Done
}

ZAUTHENTICATE used to authenticate users with their login and password, so, if you already have user's password you can connect to LDAP/AD server with this credentials.

Ensemble Credentials are normally used to satisfy security for an Ensemble Business host.  This separates the maintenance of security from the maintenance of the actual interfaces.   The application of the security is handled completely by Ensemble in that scenario.   This does not appear to be how you are attempting to utilize this.  It would help to better understand your use case here.   What is the entry path/service  that is utilizing delegated authentication?  

  • To verify against LDAP we needed a separate user other than the user trying to log into the system.
  • Also to make it easier on all parties involved instead of using new Attributes in LDAP, I had a group created that I could match up against a role of the same name in Ensemble.

So if I have an additional user I need to use to verify as the LDAP search user, how would I store the user name and password in this scenario?

First, you can access Ensemble Credentials using the Ens.Config.Credentials class.  To be clear this is NOT User definitions from the Security module.  These are defined via the Ensemble Management portal options under Ensemble -> Configure ->Credentials.

That should work for you.  I would still like to better understand what is going on in the application here that drives this.  You seem to be indicating that this is a user logging into Ensemble.   If you could detail out the workflow that is happening and how it related to Ensemble Services we might be able to better advise you.

Finally,  I want to make you aware that the LDAP interface in InterSystems technologies has a method for using groups to define everything the security model needs.   In fact that is the default method in recent versions.

The best path forward is to get your Sales Engineer (SE) involved in what you are trying to achieve.  That person would be best suited to dig into your requirements and advise you.  If, for some reason, you cannot contact your SE or don't know who that is send me a private message.  I'd be happy to help out more directly.

Sorry I am learning AD/LDAP as I go. I talked with the "powers that be" and they did confirm that I do not see a separate username and password to BIND to LDAP, and that I can use the UserName. So I will make that switch in the code above.

Thanks everyone.