Yes I was. That would explain the syntax issue. I have verified that the SimpleBinds without StartTLSs works fine. I have added some additional print statements to see where the issue might lie. The code gets past the Init, and SetOption, but then dies on the StartTLSs.

LD=1
SetOption=Success
-11,ldap_StartTLSs(Certificate) - Connect error

I went ahead and opened a ticket up with WRC to see if they could help. Thanks everyone.

I am still struggling to get this to work. If I go through %SYS and manually try to start a TLS connection in AIX to my LDAP server I am getting...

s Status=##Class(%SYS.LDAP).SetOption(LD,$$$LDAPOPTXTLSCACERTFILE,"/ensemble/TestClin/mgr/LDAPKeyStore/OSUWMC_CA.pem") - Error <SYNTAX>

Does the certificate need to be in a certain directory for this to work as the examples suggested " /usr/share/ssl/certs/...."?

Thanks.

I am now to the point where I am getting Error message: LDAP error: 0 - Success. How can a Success be a Failure?

ZAUTHENTICATE(ServiceName,Namespace,Username,Password,Credentials,Properties) PUBLIC {

#include %occErrors
#include %sySecurity
#include %sySite
#include %syLDAP
#define LDAPServer $Get(^OSUMCLDAP("Server"))

#define WindowsLDAPServer 1

#define WindowsCacheClient 0
#define UseSecureConnection 1
#define UnixCertificateFile $Get(^OSUMCLDAP("LDAPKey"))_"certnew.pem"
#define WindowsBaseDN "dc="_$Get(^OSUMCLDAP("Domain"))_",dc=edu"

#define WindowsFilter "sAMAccountname"
#define WindowsAttributeList $lb("displayName","department","mail")
$zt="Error"
 
 Status = 0

 Password="" {
Status= $SYSTEM.Status.Error($$$InvalidUsernameOrPassword)
Error
 }
 $$$WindowsLDAPServer{
AdminDN=$Get(^OSUMCLDAP("User"))
AdminPW=$Get(^OSUMCLDAP("Pass"))
 }

 #;The following line sets up the internal LDAP structures.
 $$$ISWINDOWS,$$$UseSecureConnection {
LD=##Class(%SYS.LDAP).Init($$$LDAPServer,636)
 else {
LD=##Class(%SYS.LDAP).Init($$$LDAPServer)
 }
 LD=0 {
Status=##Class(%SYS.LDAP).GetLastError()
Status="Init error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }
 Status=##Class(%SYS.LDAP).SetOption(LD,$$$LDAPOPTXTLSCACERTFILE,$$$UnixCertificateFile)
 Status'=$$$LDAPSUCCESS{
Status ="SetOption error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 
 Status=##class(%SYS.LDAP).StartTLSs(LD)
 Status'=$$$LDAPSUCCESS{
Status=Status_",ldap_setoption(Certificate) - "_##class(%SYS.LDAP).Err2String(Status)
Error
  }
 
 Status=##Class(%SYS.LDAP).SimpleBinds(LD,AdminDN,AdminPW)
 Status'=$$$LDAPSUCCESS 
  {
Status = Status_", ldap_Simple_Bind(AdminDN) - "_##Class(%SYS.LDAP).Err2String(Status)
#;w !,Status
Error
  }

 $$$WindowsLDAPServer {
Filter=$$$WindowsFilter_"="_Username
 }
 $$$WindowsLDAPServer {
AttributeList=$$$WindowsAttributeList

 
 $$$WindowsLDAPServer {
BaseDN=$$$WindowsBaseDN

 
 
 SearchScope=$$$LDAPSCOPESUBTREE
 Timeout=30
 
 SizeLimit=1
 
 Status=##Class(%SYS.LDAP).SearchExts(LD,BaseDN,SearchScope,Filter,AttributeList,0,"","",Timeout,"",.SearchResult)
 Status'=$$$LDAPSUCCESS {

Status=$$$XLDAPFILTERERROR {
Status="1,User "_Username_" does not exist"
!,Status
else {
Status=Status_",ldap_Search_Ext - "_##Class(%SYS.LDAP).Err2String(Status)
}
Error
 }

 NumEntries=##Class(%SYS.LDAP).CountEntries(LD,SearchResult)
 NumEntries=-1 {
 Status=##Class(%SYS.LDAP).GetError(LD)
 Status=Status_",ldap_Count_Entries - "_##Class(%SYS.LDAP).Err2String(Status)
 Error
 }
NumEntries=0 {
Status="1,User "_Username_" does not exist"
  Error
 }
 
 NumEntries>1 {
Status="1,LDAP Filter is not unique"
  Error
 }
 
 CurrentEntry=##Class(%SYS.LDAP).FirstEntry(LD,SearchResult)
 CurrentEntry=0 {
Status=##Class(%SYS.LDAP).GetError(LD)
Status=Status_",ldap_FirstEntry - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }
 
 DN=##Class(%SYS.LDAP).GetDN(LD,CurrentEntry
 Password="" {
Status="1,ldap_Simple_Bind("_DN_") - password cannot be null"
Error
 }
 
 Status=##Class(%SYS.LDAP).SimpleBinds(LD,DN,Password)
 Status'=$$$LDAPSUCCESS {
Status=Status_",ldap_Simple_Bind("_DN_") - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }

 Attribute=##Class(%SYS.LDAP).FirstAttribute(LD,CurrentEntry,.Ptr)

 while (Attribute'="") {
   Values=##Class(%SYS.LDAP).GetValuesLen(LD,CurrentEntry,Attribute)
   #;Values:"_Values
   Properties("Attributes",Attribute)=Values
  Attribute=##Class(%SYS.LDAP).NextAttribute(LD,CurrentEntry,.Ptr)
 }
 Properties("Username")=Username
 Properties("FullName")=$li(Properties("Attributes","displayName"))
 Properties("Attributes","displayName")
 Properties("Comment")=$li(Properties("Attributes","department"))
 Properties("Attributes","department")
 Properties("EmailAddress")=$li(Properties("Attributes","mail"))
 Properties("Attributes","mail")
 
 $d(SearchResult) ##Class(%SYS.LDAP).MsgFree(SearchResult)
 
 GroupFilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:="_DN_"))"
 GroupAttributes=""
 Status=##Class(%SYS.LDAP).SearchExts(LD,BaseDN,$$$LDAPSCOPESUBTREE,GroupFilter,GroupAttributes,0,"","",10,0,.GroupSearchResult)
 #;GroupSearch Status: "_Status
 Status'=$$$LDAPSUCCESS {
!,"SearchExts error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }
 GroupNumEntries=##Class(%SYS.LDAP).CountEntries(LD,GroupSearchResult)
 GroupNumEntries=-1 {
Status=##Class(%SYS.LDAP).GetError(LD)
Status=##Class(%SYS.LDAP).Err2String(Status)
Error
 }
!
 GroupNumEntries=0 {
!,"No nested groups for "_Username_" found"
Done
 }
 GroupNumEntries>0 {
 }
 
 GroupCurrentEntry=##Class(%SYS.LDAP).FirstEntry(LD,GroupSearchResult)
 GroupCurrentEntry=0 {
Status=##Class(%SYS.LDAP).GetError(LD)
!,"FirstEntry error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }
 Groups=""
 While (GroupCurrentEntry'=0) {
GroupDN=##Class(%SYS.LDAP).GetDN(LD,GroupCurrentEntry)
GroupDN="" {
Status=##Class(%SYS.LDAP).GetError(LD)
!,"GetDN Group error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
}
CN=$p(GroupDN,",",1)
AD=$p(CN,"=",2)
AD=$zcvt(AD,"L")
exists=''$d(^|"%SYS"|SYS("Security","RolesD",AD))
exists{
Properties("Roles") = AD

}


  GroupCurrentEntry=##Class(%SYS.LDAP).NextEntry(LD,GroupCurrentEntry)
 }
Done
+$d(LD) ##Class(%SYS.LDAP).UnBinds(LD)
 #;w !,"SystemOK "_$SYSTEM.Status.OK()
 $SYSTEM.Status.OK()
Error $zt=""
 $d(SearchResult) ##Class(%SYS.LDAP).MsgFree(SearchResult)
 $d(GroupSearchResult) ##Class(%SYS.LDAP).MsgFree(GroupSearchResult)
 +$d(LD) Status=##class(%SYS.LDAP).UnBinds(LD)
 $ze'=""{
 $SYSTEM.Status.Error($$$CacheError,$ze)
 else{  
  $SYSTEM.Status.Error($$$GeneralError,"LDAP error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status))
 }
}
 

Using the Ensemble Scheduler we ran into issues when we had multiple schedules running at the same time, and notice it pausing the whole environment just to refresh. That's why we went down this route.

It looks like this particular Inbound.SQL.Adapter service that caused the issue had a data lock on the database which caused more issues. So I am wondering if the data lock caused EnsConfigItem() to get in a hung status.

I have always called it the other way around with the outbound before the I in the Execute Procedure Parm Array.

Method InsertProviderDivisionSp(pRequest As osuwmc.CPD.DataStructures.InsertProviderDivision, Output pResponse As Ens.Response) As %Status
{
set SPQuery = "{ ?= call usp_Interfaces_Insert_ProviderDivision_Ens(?,?,?,?) }"
set par = 4
set par(1) = pRequest.DoctorNumber
set par(2) = pRequest.Division
set par(3) = pRequest.UpdatedBy
set par(4) = pRequest.OrderBy

set tSC = ..Adapter.ExecuteProcedureParmArray(.InsertDivision,.outputs,SPQuery,"oiiii",.par)

if 'tSC write " failed ",tSC 
quit tSC
}
 


or you can call it like...

Method InsertProviderPreference(pRequest As osuwmc.CPD.DataStructures.InsertPreferences, Output pResponse As Ens.Response) As %Status
{
set SPQuery = "{ ?= call usp_Interfaces_Insert_ProviderPreference(?,?,?,?,?) }"

set parm = 6
set parm(1,"SqlType")=$$$SQLVARCHAR
set parm(1,"IOTypes")=$$$SQLPARAMOUTPUT

set parm(2) = pRequest.DoctorNumber
set parm(2,"SqlType")=$$$SQLVARCHAR
set parm(2,"IOTypes")=$$$SQLPARAMINPUT

set parm(3) = pRequest.Preference
set parm(3,"SqlType")=$$$SQLNUMERIC
set parm(3,"IOTypes")=$$$SQLPARAMINPUT

set parm(4) = pRequest.PreferenceValue
set parm(4,"SqlType")=$$$SQLNUMERIC
set parm(4,"IOTypes")=$$$SQLPARAMINPUT

set parm(5) = pRequest.PreferenceDesc
set parm(5,"SqlType")=$$$SQLVARCHAR
set parm(5,"IOTypes")=$$$SQLPARAMINPUT

set parm(6) = pRequest.UpdatedBy
set parm(6,"SqlType")=$$$SQLVARCHAR
set parm(6,"IOTypes")=$$$SQLPARAMINPUT

set tSC = ..Adapter.ExecuteProcedureParmArray(.InsertPreference,.outputs,SPQuery,"oiiiii",.parm)

if 'tSC write "Failed",tSC
quit tSC
}

What does your... ##class(SamsReq).%New() look like? Here is what my Request and code look like as a whole. I have used this many times across many services in different fashions. I am using JDBC vs ODBC which maybe a difference, not sure.


Class osuwmc.CPD.DataStructures.StartJobRequest Extends (%Library.Persistent, %XML.Adaptor) [ Not ProcedureBlock, SqlRowIdPrivate ]
{

Property StartJobStatus As %Integer;

Storage Default
{
<Data name="StartJobRequestDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>StartJobStatus</Value>
</Value>
</Data>
<DataLocation>^osuwmc.CPD59D.StartJobReqE986D</DataLocation>
<DefaultData>StartJobRequestDefaultData</DefaultData>
<IdLocation>^osuwmc.CPD59D.StartJobReqE986D</IdLocation>
<IndexLocation>^osuwmc.CPD59D.StartJobReqE986I</IndexLocation>
<StreamLocation>^osuwmc.CPD59D.StartJobReqE986S</StreamLocation>
<Type>%Library.CacheStorage</Type>
}

}


Class osuwmc.CPD.UpdateClarityAddressesFromCPDService Extends Ens.BusinessService [ ClassType = "", ProcedureBlock ]
{

Parameter ADAPTER = "EnsLib.SQL.InboundAdapter";

Parameter REQUESTCLASSES As %String = "EnsLib.SQL.Snapshot";

Property InitDSN As %String;

Method OnInit() As %Status
{
Set ..InitDSN = ..Adapter.DSN
//Set ..Adapter.ConnectAttrs = "QueryTimeout:45" ; try this too just in case...
Quit $$$OK
}

Method OnProcessInput(pInput As EnsLib.SQL.Snapshot, pOutput As %RegisteredObject) As %Status
{
set req=##class(osuwmc.CPD.DataStructures.StartJobRequest).%New()
set req.StartJobStatus = pInput.Get("1")
set sc = ..SendRequestSync("CPDClarityAddressUpdateBPL",req,.pOutput)
    Quit sc
}

}