Replies

Fabio - does this work if you make changes via Object access as well, or just SQL?

Sven,

I know that customers have set this up before.  Here are some old notes that I found which may point you in the right direction.  NOTE - I have never done this myself so I con't be of much help beyond pointing out this starting point:

Implementation Outline:
1. Configure CSP to accept IIS's authentication headers and pass them to Caché

2. Set up delegated authentication to use existing security model to assign $username and $roles 
based on the user's domain accountname and/or domain groups. (Implement ZAUTHENTICATE.MAC)

3. Enable delegated authentication for any desired services and CSP applications -- in this case 
the system management portal.
·  Configuration (e.g. CSP application definition)
·  Login Page Logic decides based on Gateway Service User, whether to trust REMOTE_USER HTTP 
header, or to prompt for username/password (other fields such as PIN are also an option).

HTH,

Ben

Steve,

Here is some sample code that should help get you going in the right direction.  NOTE - the byRef LD argument is a handle for the connection to the LDAP server and it needs to be cleaned up when you're done if you're going to fetch any attributes.  

(sorry for the messed up indentation)

/// Authenticates against the configured domain, with username/password, passing a resulting a status ByRef and a returning success/failure value
ClassMethod Authenticate(username As %String, password As %String, ByRef Status As %Status, ByRef LD As %Integer) As %Boolean
{
Set Status=$$$OK, ret=0
If ('$data(username))||('$data(password)) 
    Set Status=$$$ERROR($$$GeneralError,"Both fields are required") 
    Quit 0
}

Set sc=$$$OK
Try {
//Connect to the LDAP server
Set LDAPServer="myldapserver.mydomain.com"
Set sc=$$$OK
Set LD=##class(%SYS.LDAP).Init(LDAPServer)
If LD=0 {
        Set LDAPStatus=##class(%SYS.LDAP).GetLastError()
        Set sc=$$$ERROR($$$GeneralError,"LDAP Init Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus))
Else {
    //Authenticate the passed in user by using the Binds command 
    Set Domain=..GetDomain()
    If ($$$isWINDOWS) {
        Set LDAPStatus=##Class(%SYS.LDAP).StartTLSs(LD)
        If LDAPStatus'=$$$LDAPSUCCESS {
        Set sc=$$$ERROR($$$GeneralError,"LDAP StartTLSs Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus))
    Else {
        Set LDAPStatus=##Class(%SYS.LDAP).Binds(LD,"",$lb(username,Domain,password),$$$LDAPAUTHNEGOTIATE)
        If LDAPStatus'=$$$LDAPSUCCESS {
        Set sc=$$$ERROR($$$GeneralError,"LDAP Binds Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus))
    } 
}
ElseIf ($$$isUNIX) {
    Set cert = ..GetCert()
    Set LDAPStatus=##Class(%SYS.LDAP).SetOption(LD,$$$LDAPOPTXTLSCACERTFILE,cert)
    If LDAPStatus'=$$$LDAPSUCCESS {
        Set sc=$$$ERROR($$$GeneralError,"LDAP SetOption Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus))
        Do ..RotateOnFailure(sc)
Else {
        Set LDAPStatus=##Class(%SYS.LDAP).StartTLSs(LD)
        If LDAPStatus'=$$$LDAPSUCCESS {
        Set sc=$$$ERROR($$$GeneralError,"LDAP StartTLSs Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus))
    }
}
If LDAPStatus=$$$LDAPSUCCESS {
    Set LDAPStatus=##Class(%SYS.LDAP).SimpleBinds(LD,username_"@"_Domain,password)
    If LDAPStatus'=$$$LDAPSUCCESS {
        Set sc=$$$ERROR($$$GeneralError,"LDAP SimpleBinds Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus))
    }
}
Else {
    Set LDAPStatus=$$$LDAPAUTHMETHODNOTSUPPORTED
}
If (LDAPStatus'=$$$LDAPSUCCESS)&&($$$ISOK(sc)) {
    Set sc=$$$ERROR($$$GeneralError,"LDAP API Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus))
}
} 
Catch err {
    Set sc = $$$ERROR($$$GeneralError,err.Data) 
}
If $$$ISOK(sc) {
     Set ret = 1
Else {
    Set Status = sc 
}

Quit ret
}

I certainly hope that the mystery parties who have been moderating that site are reaching out to Google in order to get it reinstated.  There was certainly a lot of valuable information on that site!

You can use $system.OBJ.Load() or LoadDIr() to load source from disk.

Personally, I would do this via Source Control and not via Studio.  The approach to this will depend on your source control structures, etc, but the easiest way to handle this for me would be:

1) Make sure that everything in my package was checked into my branch, e.g. /MyApp/cls/MyFirstPackage/...

2) Since my source tree is structured according to package names, I would copy /MyApp/cls/MyFirstPackage/... to /MyApp/cls/MySecondPackage/... 

3) Check in /MyApp/cls/MySecondPackage/... into source control

4) Check out /MyApp/cls/MySecondPackage/... 

5) Do a Find & Replace in /MyApp/cls/MySecondPackage/... to replace all instances of "MyFirstPackage" with "MySecondPackage"

6) Diff /MyApp/cls/MySecondPackage/...  and make sure all replacements are desired

7) Check in /MyApp/cls/MySecondPackage/... 

8) Run my build routine to pull all of /MyApp/cls/MySecondPackage/...  into my namespace and Compile it (or just use $system.OBJ.LoadDir() if you don't already have a build routine)

Voila!  Package is duplicated and all checked into source control ready for further changes :) The above process should only take a couple of minutes.