PowerShell & BlackBerry 10 Web Services (Part 2 – Coding)

In my first post, I explained how to get started with the BlackBerry 10 Web Services. Mostly it revolves around downloading and compiling a DLL that contains all the BlackBerry Web Service objects.

In this post, I’ll be going over the PowerShell code that I wrote to leverage this DLL.

We’re going to start with the most basic setup where I clear out all of the previous run information, and declare the variables that are needed for the sample.

#region Reset Everything
Get-Variable | Remove-Variable -ErrorAction SilentlyContinue
$Error.Clear()
Clear-Host
#endregion Reset Everything

# Trust all Web Clients
. "D:\Scripts\WebServices\New-TrustAllWebClient.ps1"

# Build the BlackBerry Web Proxy Classes
$BesProxy = Add-Type -Path "D:\Scripts\WebServices\Bes10Proxy.dll" -PassThru

#region Variable Definition
$BasFqdn                  = "basconsole.domain.local"
$BasTimeout               = 60      # seconds
$BasClientVersion         = "6.2.0" # <-- version of the web services, not the software
$BasLocale                = "en_US" # <-- this changed from en(dash)US to en(underscore)US
$BasOrgId                 = 0
# BlackBerry Administrative Services Credentials
$BasAuthType              = "Blackberry Administration Service"
$BasUsername              = "BesAdmin"
$BasPassword              = "BesPassword"
# Active Directory Credentials
$BasAdAuthType            = "Active Directory"
$BasAdAuthUsername        = "BesAdAdmin"
$BasAdAuthPassword        = "BesAdPassword"
$BasAdAuthDomain          = "Domain"
$BasUserResultSize        = 100
#endregion Variable Definition

#region Build Metadata Object
$Metadata                 = New-Object -TypeName BWS.RequestMetadata
$Metadata.clientVersion   = $BasClientVersion
$Metadata.locale          = $BasLocale
$Metadata.organizationUid = $BasOrgId
#endregion Build Metadata Object

#region Build BWS Service
$BwsService         = New-Object -TypeName BWS.BWSService
$BwsService.Url     = ( "https://" + $BasFqdn + "/enterprise/admin/ws?wsdl" )
$BwsService.Timeout = ( $BasTimeout * 1000 )
#endregion Build BWS Service

#region Build BWS Util Service
$BwsUtilService         = New-Object -TypeName BWS.BWSUtilService
$BwsUtilService.Url     = ( "https://" + $BasFqdn + "/enterprise/admin/util/ws?wsdl" )
$BwsUtilService.Timeout = ( $BasTimeout * 1000 )
#endregion Build BWS Util Service

Next, I’ll try and build the authenticator for use with BWS

function Get-Authenticator ( [string] $AuthenticatorType )
{
	$Authenticator = New-Object -TypeName BWS.Authenticator
	$Request = New-Object -TypeName BWS.GetAuthenticatorsRequest
	$Request.metadata = $Metadata
	$Response = $BwsUtilService.getAuthenticators($Request)

	if ( $Response.returnStatus.code -eq "SUCCESS" )
	{
		if ( $Response.Authenticators.count -gt 0 )
		{
			ForEach ( $AuthType in $Response.Authenticators )
			{
				if ( $AuthType.name -eq $AuthenticatorType )
				{
					$Authenticator = $AuthType
					Write-Verbose "Authenticator of Type `"$AuthenticatorType`" found!"
					break
				}
			}
		}
		else
		{
			Write-Error "No authentication types returned by getAuthenticators"
		}
	}
	else
	{
		Write-Error "Unable to obtain authenticators with message $( $Response.returnStatus.message )"
	}

	# Return the Authenitcator Type
	$AuthType
}

Part of what we’ll need going forward is the Encoded Username – don’t ask my why this is done this way, it just is.

function Get-EncodedUsername ( [string] $Username, [BWS.Authenticator] $Authenticator, [string] $Domain = $null )
{
	$Request                 = New-Object -TypeName BWS.GetEncodedUsernameRequest
	$Request.metadata        = $Metadata
	$Request.username        = $Username
	$Request.orgUid          = $Metadata.organizationUid
	$Request.authenticator   = $Authenticator
	if ( $BasAuthenticator.name -eq "Active Directory" )
	{
		# For Active Directory require the Domain, otherwise ignore it
		$Request.domain = $Domain
	}
	
	$Response = $BwsUtilService.getEncodedUsername($Request)

	if ( $Response.returnStatus.code -eq "SUCCESS" )
	{
	    Write-Verbose "Got Encoded Username!"
	    $BasEncodedUsername = $Response.encodedUsername
		$BasEncodedUsername
	}
	else
	{
	    Write-Error "Failed to Get Encoded Username"
	}
}

Next we’ll assembly the credentials for the BlackBerry Web Service in a super simple function

function New-BasCredential ( [string] $BasEncodedUsername, [string] $Password)
{
	$BasCreds = New-Object -TypeName System.Net.NetworkCredential
	$BasCreds.UserName = $BasEncodedUsername
	$BasCreds.Password = $Password
	$BasCreds
}

Next is sending the authentication to the BlackBerry Web Service

function Get-BwsAuthentication ( [System.Net.NetworkCredential] $Credential )
{
	$BwsService.Credentials     = $Credential
	$BwsService.PreAuthenticate = $true
	$BwsService
}

Next, I really did follow the example almost to the letter and created the “echo” function

function Get-BwsEcho ()
{
	$Request = New-Object -TypeName Bws.EchoRequest
	
	try
	{
		$Request.metadata = $Metadata
		$Request.text = ( "Hello World! (" + ( Get-Date -Format s ) + ")" )
		$Response = $BwsService.echo($Request)
	}
	catch
	{
		Write-Error "BlackBerry Web Services are unauthorized"
	}
	
	( $Response -ne $null )
}

Last Function: Build the Get-BesUser function

function Get-BesUser ( [string]$Criteria )
{
	$UserRequest                            = New-Object -TypeName BWS.GetUsersRequest
	$UserRequest.Metadata                   = $Metadata
	$UserRequest.PageSize                   = 100
	$UserRequest.sortBy                     = New-Object -TypeName BWS.GetUsersSortBy
	$UserRequest.sortBy.DISPLAY_NAME        = $true
	$UserRequest.sortBy.value               = "DISPLAY_NAME"
	$UserRequest.searchCriteria             = New-Object -TypeName BWS.GetUsersSearchCriteria
	$UserRequest.searchCriteria.displayName = $Criteria

	$UserResponse = $BwsService.getUsers($UserRequest)
	if ( $UserResponse.users.Count -gt 0 )
	{
		$Users = @()
		ForEach ( $User in $UserResponse.users )
		{
			$Users += $User
		}
		$Users
	}
	else
	{
		Write-Error ( "No users Returned from search" )
	}
}

And finally, the main “program” that calls all of these functions using both BlackBerry Administration and Active Directory Authentication…

############################################################
# Main Function
############################################################

# Native BAS Authentication
$BasAuthenticator = Get-Authenticator -AuthenticatorType $BasAuthType
$BasEncodedUsername = Get-EncodedUsername -Username $BasUsername -Authenticator $BasAuthenticator

# Active Directory Authentication
$BasAuthenticator = Get-Authenticator -AuthenticatorType $BasAdAuthType
$BasEncodedUsername = Get-EncodedUsername -Username $BasAdAuthUsername -Authenticator $BasAuthenticator -Domain $BasAdAuthDomain

$BwsService = Get-BwsAuthentication -Credential ( New-BasCredential -BasEncodedUsername $BasEncodedUsername -Password $BasPassword )

$BesUsers = Get-BesUser -Criteria "michael"
$BesUsers | Out-GridView -Title "BES Users"

The last thing that I really need to do is adapt the Get-BesUser function so that I can request a search based on other criteria.  This is just the first rough draft of this, so keep the postings flagged so that I can provide more scripts as I develop them.

Trust Web Certificate Script

<#
.Synopsis
   Allows insecure HTTPS communications
.DESCRIPTION
   Changes any web call (Invoke-RestMethod or Invoke-WebRequest) to allow insecure HTTPS communications (like self-signed certificates)
.EXAMPLE
   Trust-AllWebCertificates
.NOTES
   Heavily incluenced by code From http://poshcode.org/624
#>
function Trust-AllWebCertificates
{
    ## Create a compilation environment
    $Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
    $Compiler=$Provider.CreateCompiler()
    $Params=New-Object System.CodeDom.Compiler.CompilerParameters
    $Params.GenerateExecutable=$False
    $Params.GenerateInMemory=$True
    $Params.IncludeDebugInformation=$False
    $Params.ReferencedAssemblies.Add("System.DLL") | Out-Null

$TASource=@'
  namespace Local.ToolkitExtensions.Net.CertificatePolicy{
    public class TrustAll : System.Net.ICertificatePolicy {
      public TrustAll() { 
      }
      public bool CheckValidationResult(System.Net.ServicePoint sp,
        System.Security.Cryptography.X509Certificates.X509Certificate cert, 
        System.Net.WebRequest req, int problem) {
        return true;
      }
    }
  }
'@ 
    $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
    $TAAssembly=$TAResults.CompiledAssembly

    ## We now create an instance of the TrustAll and attach it to the ServicePointManager
    $TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
    [System.Net.ServicePointManager]::CertificatePolicy=$TrustAll
}

 

3 thoughts on “PowerShell & BlackBerry 10 Web Services (Part 2 – Coding)”

  1. Thanks for sharing, very useful blog post !
    I’ve a question about the authentication : all BWS documentations and blog posts use plain text login and password.
    In a Active Directory context, is there any way to use currently logged user’s credentials ?

    Reply
  2. Hello Kevin
    Thanks for great write up!
    you are referncing 2 powershell scrips in the doc(specifically referencing . “D:ScriptsWebServicesNew-TrustAllWebClient.ps1” in the copde); “New-TrustAllWebClient.ps1” and “Bes10WebServices.ps1” can you advise if those files are downloadable?(url does not have any results). Or if the code you explained is to be broken up into two scrips can you advise how to break it up?

    thanks in advance.

    M

    Reply
    • Sorry – I just realized that my attached scripts didn’t upload when I moved my website. I’ve added the New-TrustAllWebClient.ps1 script to the body. The other script is just the embedded parts stitched together. Let me know if you need any additional help.

      Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.