Skip to main content

NEEDED: SOAP API call/method to "Initialize a Server Sync" to Cerberus Servers in Highly Available VM Set.

Comments

8 comments

  • Official comment
    Permanently deleted user
    Development

    Hi Phil,

    Glad you're enjoying the SOAP API. We have a lot of room to improve, of course, and your feedback is really valuable to us. So thank you!

    Have you considered storing your Cerberus users in AD or LDAP? While the setup and maintenance are non-zero costs, they are robust and handle exactly this situation, where password changes must be replicated across instances. Cerberus has good (and improving) integration with these servers and might be a good long-term solution.

    That being said, it is definitely possible to implement what you describe through SOAP API. After all, the SOAP API is how Cerberus FTP implement its Sync functionality.

    In broad strokes, you could use `GetProfiles` and `SetProfiles` between the two cerberus instances to do a replication of users between servers. A finer-grained solution might be to use `GetUserInformation` and `AddUser` to replicate only the exact user who's changed their password during the event. Be sure to set `saveToDisk` during the call to `AddUser` to ensure the change gets flushed to the filesystem.

    There are pitfalls to be careful of if you choose this path. One could easily write event loops that would infinitely replicate users between the two Cerberus instances!

    I will file an enhancement request for what you ask for (a way to trigger replication through SOAP API) as well as one that (I think) gets to the root of what you're after (fine-grained replication between sync servers).

  • Phil Grant

    Vincent, 

    Thank you so much for you reply. 

    We had considered an AD/LDAPS implementation, but ran into many design issues for external Customer company accounts, which is our primary use case. Another issue we had was merging accounts previously created on 2 other obsolete SFTP systems, migrating the data, and keeping the naming conventions the same for compatibility of External Customers deployed machine configurations that exclusively access our SFTP(could be thousands of machines that someone would have to manually update the changes). The good news is most of the migration is done and Cerberus will be our only SFTP system moving forward.

    I have used the GetUserInformation and AddUser Methods, but was unaware of the "Savetodisk" property on the .net object for building the AddUserRequest. I will begin testing that call. If I submit a AddUserRequest with no "password" property defined, IIRC, that would respond with failed user creation due to "password" is $Null. Is that a correct statement?

    Your last statement hit the nail on the head, a way to get the Sync trigger in the wsdl and/or fine grained replication for a specific user object.

     Again, Vincent, Thank you So much.

    We really like the Cerberus SFTP Product, and it is miles ahead of other SFTP products we have used.

    0
  • Permanently deleted user
    Development

    > If I submit a AddUserRequest with no "password" property defined, IIRC, that would respond with failed user creation due to "password" is $Null. Is that a correct statement?

    You'll get some kind of error, yes. In my test environment an empty password fails the password policy test.

    For the replication use-case you're describing, the password should already be hashed in the User object returned by `GetUserInformation`. If the User object already has a hashed password, AddUser will update the user object as such. The user on the source Cerberus instance and the destination instance should have the same password at this point.

    `AddUser` will detect if the User object's password is plain-text and do password policy evaluation before hashing and saving the user.

    0
  • Phil Grant

    Vincent, 

    I have been testing the GetUserInformation Approach you mentioned and had some questions to further understand your guidance.

    If I perform a GetUserInformation from the source Cerberus instance where the password change was performed by a user, then if I call the Savetodisk method on the source Cerberus instance, would that trigger the rehashing on the Cerberus destination instance as well? I read above and thought "it can't be that easy." 

    So I have been testing a Local Powershell Scriptblock to perform the GetUserInformation, save the User object as JSON, so I can pass the user object to a RemoteScriptblock with PSRemoting to ensure i can access "localhost" on the Cerberus destination instance, since the API is only listening on loopback of Cerberus destination instance. Once connected to the Cerberus destination API instance, build an AddUser request, bind the Imported user Object to the request as the User object class, add SaveToDisk method to the Request, then submit to Cerberus destination instance. The reason I opted to try a json object to pass, I found in earlier testing, PSremoting doesn't support custom types or classes(especially namespace objects I created with New-WebserviceProxy on the Cerberus source instance).

    I still haven't gotten this approach to work in testing, any ideas? I have posted scrubbed testing functions below.

    $Script:ErrorLogPath = "C:\Temp\LogCollection\SyncTest.log"
    $AccountUserName="sftp.test5"
    If($Env:COMPUTERNAME -eq "cerb-01"){
    $LocalServerIpAddress="10.0.103.106"
    $RemoteServerIpAddress="10.0.103.107"
    $RemoteServerComputerName="cerb-01"
    }
    If($Env:COMPUTERNAME -eq "cerb-02"){
    $LocalServerIpAddress="10.0.103.107"
    $RemoteServerIpAddress="10.0.103.106"
    $RemoteServerComputerName="cerb-02"
    }

    #Order of operations
    #Get-LocalServerUserObject
    #Start PSSessiontoRemote Server
    #Pass UserObject to Remote Scriptblock
    #Set-RemoteServerUserObject

     

    #Local Server ScriptBlock
    Function Get-LocalServerUserObject{
    Param(
    [String]$AccountUserName,
    [String]$LocalServerIpAddress
    )


    Function Connect-CerberusSOAPService{
    [CmdletBinding()]
    Param(
    [String]$Environment,
    [String]$ServerIpAddress
    )
    ####################################################
    $VerbosePreference="Continue"
    $ErrorActionPreference="Stop"
    $Error.Clear()
    ####################################################
    $CerberusFTPCredentialfile=$null
    $CerberusSOAPService=$null
    $Script:CerberusSOAPService=$null
    $Script:CerberusSOAPRequestCredentials=$null
    ####################################################
    # Environment Switch
    ####################################################
    switch ($Environment) {
    "InternalDev" {
    $wsdlFile="https://$($ServerIpAddress):8808/wsdl/Cerberus.wsdl"
    $SoapRequestURL="https://localhost:10001/service/CerberusSOAPService"
    $CerberusFTPCredentialFile="C:\Users\pgrant\Documents\DEVCerberusSOAP.cred"
    }
    "InternalPROD" {
    $wsdlFile="https://$($ServerIpAddress):8808/wsdl/Cerberus.wsdl"
    $SoapRequestURL="https://localhost:10001/service/CerberusSOAPService"
    $CerberusFTPCredentialFile="C:\Users\pgrant\Documents\PRODCerberusSOAP.cred"
    }
    }#end of Environment Switch Statement
    ####################################################
    #Prepare TLS v1.2 and Credentials
    ####################################################
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    ####################################################
    #Create Web Service Object to SOAP Connection
    ####################################################
    $CerberusSOAPService=New-WebServiceProxy -Uri $wsdlFile -Class CerberusFTP -Namespace CerberusSOAPService -Credential (Import-Clixml -Path $CerberusFTPCredentialFile)
    ####################################################
    If($CerberusSOAPService){
    $CerberusSOAPService.Url=$SoapRequestURL
    $CerberusSOAPService.PreAuthenticate = $true;
    $Script:CerberusSOAPService = $CerberusSOAPService
    ####################################################
    #Create Request Credential Object
    ####################################################
    $Script:CerberusSOAPRequestCredentials = New-Object -TypeName CerberusSOAPService.Credentials
    $Script:CerberusSOAPRequestCredentials.user = (Import-Clixml -Path $CerberusFTPCredentialFile).UserName
    $Script:CerberusSOAPRequestCredentials.password = (Import-Clixml -Path $CerberusFTPCredentialFile).GetNetworkCredential().Password
    $Script:CerberusFTPCredentialObject=(Import-Clixml -Path $CerberusFTPCredentialFile)
    ####################################################
    }
    Else{
    Return
    }
    }#End of Function Connect-CerberusSOAPService

    Connect-CerberusSOAPService -Environment "InternalPROD" -ServerIpAddress $LocalServerIpAddress -Verbose
    $getuserrequest=$null
    $getuserresponse=$null
    ####################################################
    #Create Get User Information Request Object
    ####################################################
    [CerberusSOAPService.GetUserInformationRequest] $getuserrequest = New-Object -TypeName CerberusSOAPService.GetUserInformationRequest
    $getuserrequest.credentials = $Script:CerberusSOAPRequestCredentials
    $getuserrequest.userName = $AccountUserName
    ####################################################
    # Create Get User Information Response Object
    ####################################################
    [CerberusSOAPService.GetUserInformationResponse] $getuserresponse = $Script:CerberusSOAPService.GetUserInformation($getuserrequest)
    ####################################################
    $getuserresponse.result
    $getuserresponse.message
    $Script:UserObject=$getuserresponse.UserInformation
    $Script:CerberusSOAPService.Dispose()
    }#End of Function Get-LocalServerUserObject

    Function Set-RemoteServerUserObject{
    Param(
    $UserObject,
    [String]$RemoteServerIpAddress,
    [String]$RemoteServerComputerName,
    [System.Management.Automation.PSCredential]$RemoteCerberusFTPCredential
    )
    $PSSession=$null
    $PSSessionCredential=$null
    $PSSessionCredential= Import-CLIXML "C:\Users\pgrant\Documents\PRODCerberusService.cred"
    $PSSession=New-PSSession -ComputerName $RemoteServerComputerName -Credential $PSSessionCredential


    #Remote Server ScriptBlock
    $RemoteServerScriptBlock={
    Param(
    $UserObject,
    [String]$RemoteServerIpAddress,
    [System.Management.Automation.PSCredential]$RemoteCerberusFTPCredentialFile
    )
    Function Connect-RemoteCerberusSOAPService{
    #Converted for Remote Use
    [CmdletBinding()]
    Param(
    [String]$RemoteServerIpAddress,
    [System.Management.Automation.PSCredential]$RemoteCerberusFTPCredentialObject
    )
    ####################################################
    $VerbosePreference="Continue"
    $ErrorActionPreference="Stop"
    $Error.Clear()
    ####################################################
    $RemotewsdlFile="https://$($RemoteServerIpAddress):8808/wsdl/Cerberus.wsdl"
    $RemoteSoapRequestURL="https://localhost:10001/service/CerberusSOAPService"
    ####################################################
    #Prepare TLS v1.2 and Credentials
    ####################################################
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    ####################################################
    #Create Web Service Object to SOAP Connection
    ####################################################
    $RemoteCerberusSOAPService=New-WebServiceProxy -Uri $RemotewsdlFile -Class CerberusFTP -Namespace CerberusSOAPService -Credential $RemoteCerberusFTPCredentialObject
    ####################################################
    If($RemoteCerberusSOAPService){
    $RemoteCerberusSOAPService.Url=$RemoteSoapRequestURL
    $RemoteCerberusSOAPService.PreAuthenticate = $true;
    $Script:RemoteCerberusSOAPService = $RemoteCerberusSOAPService
    ####################################################
    #Create Request Credential Object
    ####################################################
    $Script:RemoteCerberusSOAPRequestCredentials = New-Object -TypeName CerberusSOAPService.Credentials
    $Script:RemoteSOAPRequestCredentials.user = $($RemoteCerberusFTPCredentialObject).UserName
    $Script:RemoteSOAPRequestCredentials.password = $($RemoteCerberusFTPCredentialObject).GetNetworkCredential().Password
    ####################################################
    }
    Else{
    Write-output "Cannot Connect to SOAP API"
    Return
    }
    }#End of Function Connect-RemoteCerberusSOAPService

    Connect-RemoteCerberusSOAPService -RemoteServerIpAddress $RemoteServerIpAddress -RemoteCerberusFTPCredentialObject $RemoteCerberusFTPCredentialFile
    $ImportedUserObject=$UserObject |ConvertFrom-Json
    Write-output $ImportedUserObject
    $UpdateUserRequest=$null
    $UpdateUserResponse=$null

    ####################################################
    # Create new $UpdateUserRequest object
    ####################################################
    [CerberusSOAPService.AddUserRequest] $UpdateUserRequest = New-Object -TypeName CerberusSOAPService.AddUserRequest
    $UpdateUserRequest.credentials = $Script:RemoteCerberusSOAPRequestCredentials
    ####################################################
    # Populate request object with new user object
    ####################################################
    $RemoteCerberusUserObject= New-Object -TypeName CerberusSOAPService.User -ArgumentList $ImportedUserObject
    $UpdateUserRequest.User = $RemoteCerberusUserObject
    $UpdateUserRequest.saveToDisk
    $UpdateUserRequest.saveToDiskSpecified = $true
    ####################################################
    # Create new $UpdateUserResponse object
    ####################################################
    [CerberusSOAPService.AddUserResponse] $UpdateUserResponse = $Script:RemoteCerberusSOAPService.AddUser($UpdateUserRequest)

    Write-Output $UpdateUserResponse.Result
    Write-Output $UpdateUserResponse.Message

    $Script:RemoteCerberusSOAPService.Dispose()
    }#End of Remote ScriptBlock

    Invoke-Command -Session $PSSession -ScriptBlock $RemoteServerScriptBlock -ArgumentList $UserObject,$RemoteServerIpAddress,$RemoteCerberusFTPCredentialFile
    Remove-PSSession -Session $PSSession
    }#End of Function Set-RemoteServerUserObject


    Get-LocalServerUserObject -AccountUserName $AccountUserName -LocalServerIpAddress $LocalServerIpAddress
    $Script:UserObject=$Script:UserObject |ConvertTo-Json
    Set-RemoteServerUserObject -UserObject $Script:UserObject -RemoteServerComputerName $RemoteServerComputerName -RemoteServerIpAddress $RemoteServerIpAddress -RemoteCerberusFTPCredential $Script:CerberusFTPCredentialObject

     

    0
  • Permanently deleted user
    Development

    Hi PGrant,

     

    > If I perform a GetUserInformation from the source Cerberus instance where the password change was performed by a user, then if I call the Savetodisk method on the source Cerberus instance,

    I think you mean destination here, right?

    > would that trigger the rehashing on the Cerberus destination instance as well? I read above and thought "it can't be that easy." 

    No rehashing would take place here. You would be transferring the hashed password from one Cerberus instance to the other. This is a detail, though, that your code shouldn't need to be aware of.

    It looks like converting to JSON and back again is losing information. This error appears when I do this conversion:

    Cannot create object of type "CerberusFtp.VirtualDirectory". Cannot convert the "CerberusFtp.DirectoryPermissions" value of type "System.String" to type "CerberusFtp.DirectoryPermissions"

    I suspect the JSON conversion is using a non-reversible toString conversion.

    I suggest you side-step all of this by avoiding the remote powershell session. The SOAP ports should be open between these two instances of Cerberus, as this is required for the regular Sync operation.

    You should be able create two service objects, $LocalCerberusSoapService and $RemoteCerberusSoapSerivice and never have to pass the object between powershell sessions. (I *think* you could also just change $CerberusSOAPService.Url depending on which Cerberus instance your script needs to communicate with).

    0
  • Phil Grant

    Vincent, 

    I wanted to give an update, I finally figured this out and got it working in testing.

    The trick was using the LOCAL WSDL for the remote call to the Remote SOAP URL and I had to get around a PowerShell WebserviceProxy bug that affects types when casting ("[CerberusFTPService.GetUserInformationResponse]") methods to methods that are used in many of the API tutorials. The exception error for this specific bug coming from System.Management.Automation is something along the lines of "Cannot convert type "CerberusFTPService.GetUserInformationResponse" to type CerberusFTPService.GetUserInformationResponse". To get around the bug use $LocalCerberusSOAPServiceType=$LocalCerberusSOAPService.GetType().Namespace after creating the webserviceproxy object. When creating Objects you would normally Cast to, use New-Object ($LocalCerberusSOAPServiceType + '.GetUserInformationRequest') to pass the correct type.

    For Reference and others who follow looking for the solution,see below. This has been scrubbed for security, so use the Private IP of your listeners in the VariablesMapping Section. Also note the SOAP IP in the URL is not localhost or loopback (127.0.0.1), again use the Private IP. This script was setup to be part of a Scheduled Task on each server and is designed to be idempotent.

    ####################################################
    #Inputs
    ####################################################
    $AccountUserName="sftp.test5"

    ####################################################
    $VerbosePreference="Continue"
    $ErrorActionPreference="Stop"
    $Error.Clear()
    ####################################################
    $CerberusFTPCredentialfile=$null

    $Script:CerberusSOAPRequestCredentials=$null
    ####################################################
    #Variables Mapping
    ####################################################
    $Script:ErrorLogPath = "C:\Temp\SyncTest.log"
    $CerberusFTPCredentialFile="C:\Temp\CerberusSOAP.cred"
    If($Env:COMPUTERNAME -eq "cerb01"){
    $LocalServerWSDL="https://yourserverlistenerPrivateIP:8808/wsdl/Cerberus.wsdl"
    $LocalServerSOAP="https://yourserverlistenerPrivateIP:10001/service/CerberusSOAPService"
    $RemoteServerSOAP="https://yourserverlistenerPrivateIP:10001/service/CerberusSOAPService"
    }
    If($Env:COMPUTERNAME -eq "cerb02"){
    $LocalServerWSDL="https://yourserverlistenerPrivateIP:8808/wsdl/Cerberus.wsdl"
    $LocalServerSOAP="https://yourserverlistenerPrivateIP:10001/service/CerberusSOAPService"
    $RemoteServerSOAP="https://yourserverlistenerPrivateIP:10001/service/CerberusSOAPService"
    }
    ####################################################
    #Local Server ScriptBlock
    ####################################################
    Write-Output "Starting Call to Local SOAP Service"
    ####################################################
    #Prepare TLS v1.2 and Credentials
    ####################################################
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    ####################################################
    #Create Web Service Object to SOAP Connection
    ####################################################
    $LocalCerberusSOAPService=New-WebServiceProxy -Uri $LocalServerWSDL -Credential (Import-Clixml -Path $CerberusFTPCredentialFile)
    $LocalCerberusSOAPServiceType=$null
    $LocalCerberusSOAPServiceType=$LocalCerberusSOAPService.GetType().Namespace
    ####################################################
    If($LocalCerberusSOAPService){
    $LocalCerberusSOAPService.Url=$LocalServerSOAP
    $LocalCerberusSOAPService.PreAuthenticate = $true;
    ####################################################
    #Create Request Credential Object
    ####################################################
    $Script:CerberusSOAPRequestCredentials = New-Object ($LocalCerberusSOAPServiceType + '.Credentials')
    $Script:CerberusSOAPRequestCredentials.user = (Import-Clixml -Path $CerberusFTPCredentialFile).UserName
    $Script:CerberusSOAPRequestCredentials.password = (Import-Clixml -Path $CerberusFTPCredentialFile).GetNetworkCredential().Password
    ####################################################
    Write-Output "Connected Successfully with WebserviceProxy to Local SOAP Service"
    ####################################################
    }
    Else{
    Write-output "Cannot Connect to Local SOAP API"
    Return
    }
    $GetLocalUserObjectRequest=$null
    $GetLocalUserObjectRequestResponse=$null
    ####################################################
    #Create Get User Information Request Object
    ####################################################
    #[CerberusSOAPService.GetUserInformationRequest]
    $GetLocalUserObjectRequest = New-Object ($LocalCerberusSOAPServiceType + '.GetUserInformationRequest')
    $GetLocalUserObjectRequest.credentials = $Script:CerberusSOAPRequestCredentials
    $GetLocalUserObjectRequest.userName = $AccountUserName
    ####################################################
    # Create Get User Information Response Object
    ####################################################
    #[CerberusSOAPService.GetUserInformationResponse]
    #$GetLocalUserObjectRequestResponse = New-Object ($LocalCerberusSOAPServiceType + '.GetUserInformationResponse')
    $GetLocalUserObjectRequestResponse =$LocalCerberusSOAPService.GetUserInformation($GetLocalUserObjectRequest)
    ####################################################
    Write-Output "Local SOAP Service Response"
    $GetLocalUserObjectRequestResponse.result
    $GetLocalUserObjectRequestResponse.message
    $Script:UserObject=$GetLocalUserObjectRequestResponse.UserInformation
    ####################################################

    ####################################################
    #Remote Server ScriptBlock
    ####################################################
    Write-Output "Starting Call to Remote SOAP Service"
    #Prepare TLS v1.2 and Credentials
    ####################################################
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    ####################################################
    #Create Web Service Object to SOAP Connection
    ####################################################
    $RemoteCerberusSOAPService=New-WebServiceProxy -Uri $LocalServerWSDL -Credential (Import-Clixml -Path $CerberusFTPCredentialFile)
    $RemoteCerberusSOAPServiceType=$null
    $RemoteCerberusSOAPServiceType=$RemoteCerberusSOAPService.GetType().Namespace
    ####################################################
    If($RemoteCerberusSOAPService){
    $RemoteCerberusSOAPService.Url=$RemoteServerSOAP
    $RemoteCerberusSOAPService.PreAuthenticate = $true;
    ####################################################
    #Create Request Credential Object
    ####################################################
    $Script:CerberusSOAPRequestCredentials = New-Object ($RemoteCerberusSOAPServiceType + '.Credentials')
    $Script:CerberusSOAPRequestCredentials.user = (Import-Clixml -Path $CerberusFTPCredentialFile).UserName
    $Script:CerberusSOAPRequestCredentials.password = (Import-Clixml -Path $CerberusFTPCredentialFile).GetNetworkCredential().Password
    ####################################################
    Write-Output "Connected Successfully with WebserviceProxy to Remote SOAP Service"
    ####################################################
    }
    Else{
    Write-output "Cannot Connect to Remote SOAP API"
    Return
    }

    $UpdateRemoteUserObjectRequest=$null
    $UpdateRemoteUserObjectResponse=$null
    ####################################################
    # Create new $UpdateUserRequest object
    ####################################################
    #[CerberusSOAPService.AddUserRequest]
    $UpdateRemoteUserObjectRequest = New-Object ($RemoteCerberusSOAPServiceType +'.AddUserRequest')
    $UpdateRemoteUserObjectRequest.credentials = $Script:CerberusSOAPRequestCredentials
    ####################################################
    # Populate request object with Updated user object
    ####################################################
    $UpdateRemoteUserObjectRequest.User = $Script:UserObject
    $UpdateRemoteUserObjectRequest.saveToDisk
    $UpdateRemoteUserObjectRequest.saveToDiskSpecified = $true
    ####################################################
    # Create new $UpdateUserResponse object
    ####################################################
    #[CerberusSOAPService.AddUserResponse]
    $UpdateRemoteUserObjectResponse = $RemoteCerberusSOAPService.AddUser($UpdateRemoteUserObjectRequest)
    Write-Output "Remote SOAP Service Response"
    Write-Output $UpdateRemoteUserObjectResponse.Result
    Write-Output $UpdateRemoteUserObjectResponse.Message
    ####################################################
    #Cleanup Connections
    ####################################################
    Write-Output "Cleaning Up WebserviceProxy Objects"
    ####################################################
    $LocalCerberusSOAPService.Dispose()
    $RemoteCerberusSOAPService.Dispose()

     

    0
  • Permanently deleted user
    Development

    Brilliant!

     

    > The trick was using the LOCAL WSDL for the remote call to the Remote SOAP URL 

    I could see this being required if the your remote Cerberus instance does not have an accessible HTTPS Admin listener. It's not uncommon to restrict the admin port to local connections only.

    > and I had to get around a PowerShell WebserviceProxy bug that affects types when casting ... The exception error for this specific bug coming from System.Management.Automation is something along the lines of "Cannot convert type "CerberusFTPService.GetUserInformationResponse" to type CerberusFTPService.GetUserInformationResponse".

    I've seen this before, usually when I call New-WebServiceProxy multiple times in the same powershell session. I haven't delved too deeply, but I get this impression:

    New-WebServiceProxy creates a collection of .NET types to manipulate Cerberus' SOAP interface. Calling New-WebServiceProxy a second time recreates the types. Since both calls populate the same namespace, the types are re-generated.

    The script has objects created with the first set of types, then create a new set of types and tries to pass them to the new proxy object. Despite identical WSDL between the first and second calls to New-WebServiceProxy, .NET's type system treats them as unique and will not automatically convert between them.

    I get the feeling that a second call to New-WebServiceProxy shouldn't be necessary. It seems like the same instance of $CerberusSvc should be usable for both the remote and local server. I'll have to experiment with this.

     

    Great work. Thank you for contributing the code sample!

    0
  • Permanently deleted user
    Development

    PGrant,

     

    I've taken the liberty of creating a support ticket for you. I can't promise any timeline on the two issues you've identified, but the support ticket will ensure you get notified as progress is made.

    * Method of triggering sync from SOAP API

    * Fine-grained Sync for User password changes

     

    Thanks!

    0

Please sign in to leave a comment.