OneStream – execute a rule as an Administrator using Powershell


I was on a project where Hyperion Workforce planning was replaced using OneStream’s People Planning specialty application. There was an instance where I found that OneStream’s extra tight grip on security was prohibiting me from executing a business rule with Administrator privileges (this is how Hyperion Planning works).

Most of the parts you don’t want to do this!! All the rules that are executed must run using the current user’s privilege.

However, there are cases where you wish you want that extra privilege.

How is it done

The idea behind the working of this is as follows.

Use the client API and PowerShell to log in as an Administrator. Once logged in execute the rule using a Data Management sequence 🙂

I scrubbed modified the script found here to fit my needs.

As you can see from that blog post that I need the contents of the PowerShell script as a string, add a reference to System.Management.Automation.dll and off you go.

I got help from OneStream support to find out the location of Automation.dll. If you don’t know how to add references to external dlls, please check my blog post on the same.

Reading file contents

This function loops through each line in the file and adds it to a StringBuilder.

' helper method that takes the script path and loads up the script text
' into a variable, and passes the variable to the RunScript method
' that will then execute the contents
Private Function LoadScript(ByVal si As SessionInfo,ByVal filename As String) As String

	Try

		' Create an instance of StreamReader to read from the file.
		Dim sr As New StreamReader(filename)

		' use a string builder to get all the lines from the file
		Dim fileContents As New StringBuilder()

		' string to hold the current line
		Dim curLine As String = ""

		' loop through the file and read each line into the
		' stringbuilder
		Do
			' read each line
			curLine = sr.ReadLine()
			fileContents.Append(curLine + vbCrLf)
		Loop Until curLine Is Nothing

		' close the reader
		sr.Close()

		' call RunScript and pass in the file contents
		' converted to a string
		Return fileContents.ToString()

		
	Catch ex As Exception
		Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
	End Try

End Function

Run PowerShell from VB

NoNow that we have the function to read the PowerShell contents let’s look at the function to execute it.

To run an Automation, you need a runspace and a pipeline (they do sound funny, I know :))

Line 14 is where I’m passing the user information (when the rule is executed by the admin, it is the admin who is running it, not the user who initiated it) to capture some information in the following DM job. I have got a variable in my DM job called InitiatedUserName.

' Takes script text as input and runs it, then converts
' the psResults to a string to return to the user		
Private Function RunScript(ByVal si As SessionInfo, ByVal scriptText As String) As String
	Try
		
		' create Powershell runspace
		Dim psRunSpace As Runspace = RunspaceFactory.CreateRunspace()

		' open it
		psRunSpace.Open()
		
		' create a pipeline and feed it the script text
		Dim psPipeLine As Pipeline = psRunSpace.CreatePipeline()
		Dim newScriptText As String = scriptText.Replace("InitiatedUserName", "InitiatedUserName=" & si.UserName)
		psPipeLine.Commands.AddScript(newScriptText)
		
		' add an extra command to transform the script output
		psPipeLine.Commands.Add("Out-String")

		' execute the script
		Dim psResults As Collection(Of PSObject) = psPipeLine.Invoke()

		' close the runspace
		psRunSpace.Close()

		' convert the script result into a single string
		Dim psOut As New StringBuilder()

		For Each obj As PSObject In psResults
			psOut.AppendLine(obj.ToString())
		Next

		' return the results of the script
		Return psOut.ToString()
		
	Catch ex As Exception
		Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
	End Try
End Function

Lines 26 to 31 are where I’m capturing the text output from the DM job and returning it.

The PowerShell script

In order to invoke OneStream Client API, you need to install OneStream Studio on the server that you are executing this. In my case, these are executed on OS application servers, and by default, Studio is installed on all App servers.

You can encrypt the password using PowerShell by issuing the following commands.

Add-Type -Path "C:\Program Files (x86)\OneStream Software\OneStreamStudio\OneStreamClientApi.dll"
$xfApi = new-object OneStream.Client.Windows.OneStreamClientApi
$xfApi.Authentication.EncryptPassword("password", [OneStream.Shared.Wcf.XFClientAuthenticationType]::EncryptedPW)

You can also use the option EncryptedPWForOneClientPC as well.

Here is the script that you can use if you are not using External Authentication.

Provide your OneStream web URL, username, encrypted password, application name, and sequence name.

Add-Type -Path "C:\Program Files (x86)\OneStream Software\OneStreamStudio\OneStreamClientApi.dll"
$xfApi = new-object OneStream.Client.Windows.OneStreamClientApi

$xfLogonInfo = $xfApi.Authentication.LogonAndOpenApplication("https://yourserver.onestreamcloud.com/OneStreamWeb", "userName", "FvAIwgx8Ff2uXefWJ0OazNym6cub0gRARJTvQyo//Lc=","Application Name", [OneStream.Shared.Wcf.XFClientAuthenticationType]::EncryptedPW)

if ($xfLogonInfo.IsAuthenticated)
{
	# UserName will be replaced from the BR with a real value
	$xfResult = $xfApi.DataManagement.ExecuteSequence("YourSequence", "InitiatedUserName")
    if (-Not ($xfResult.IsOK)){
       $xfResult.Message
    }
	"Data transferrred and processed"
    $xfApi.Authentication.Logoff()
}
Else
{
	"Error logging in user"
    $xfLogonInfo.ErrorMessage
}

Here is the script that you can use for an external authenticated system.

The difference is that you need to generate an SSO token and use that token to log in. Line 6, you’ll see that we are using ClearTextPW; it is because SSOToken is clear text.

Add-Type -Path "C:\Program Files (x86)\OneStream Software\OneStreamStudio\OneStreamClientApi.dll"
$xfApi = new-object OneStream.Client.Windows.OneStreamClientApi

$ssoToken = $xfApi.Authentication.ProcessSSOAuthenticationAndCreateToken("https://centene-dev.onestreamcloud.com/OneStreamWeb", "userName", "FvAIwgx8Ff2uXefWJ0OazNym6cub0gRARJTvQyo//Lc=", [OneStream.Shared.Wcf.XFClientAuthenticationType]::EncryptedPW)

$xfLogonInfo = $xfApi.Authentication.LogonAndOpenApplication("https://yourserver.onestreamcloud.com/OneStreamWeb", $xfApi.Authentication.GetXFUserNameFromSSOToken($ssoToken), "$ssoToken","Application Name", [OneStream.Shared.Wcf.XFClientAuthenticationType]::ClearTextPW)

if ($xfLogonInfo.IsAuthenticated)
{
	# UserName will be replaced from the BR with a real value
	$xfResult = $xfApi.DataManagement.ExecuteSequence("YourSequence", "InitiatedUserName")
    if (-Not ($xfResult.IsOK)){
       $xfResult.Message
    }
	"Data transferrred and processed"
    $xfApi.Authentication.Logoff()
}
Else
{
	"Error logging in user"
    $xfLogonInfo.ErrorMessage
}

All you’ve to do now is to upload the PowerShell to an OS location, create an Extensible rule, add that into a DM sequence, and off you go.

I’ll cover how to do this using REST API in a different post.

Leave a comment

Your email address will not be published. Required fields are marked *