Isilon Rest API using Powershell Part 1: Basics


Looking at the Isilon Platform API introduced with OneFS 7.0.2, which is using REST with JSON for communication, I was struggling how to start. At first I tried to use Perl for scripting but as I’m not very experienced in Perl, I was quickly frustrated. Luckily I stumbled across Powershell for REST scripting.
After searching a little bit I found two great blogs ([1] [2]) which helped me as a good starting point.

Powershell:

Powershell 3.0 introduced a couple of very handy cmdlets for scripting with REST and Json:

ConvertTo-Json
ConvertFrom-Json
Invoke-RestMethod

Powershell 3.0 is available for Windows 7, Windows Server 2008 and its successors.
Powershell 4.0 just recently released and has also some improvements and fixes for the “Invoke-RestMethod” included.

JSON:

The first two cmdlets are great as you don’t need to have any JSON knowledge to generate JSON code. You can simply create a standard Powershell Object and convert it to a JSON Object. This can be done also vice versa.

Here is a simple example to generate the JSON Object for creating a new share. At first we are creating the Powershell object with the required properties “name” and “path”:

$obj = [pscustomobject]@{}
$share = "share1"
$path = "/ifs/data/share1"
Add-Member -InputObject $obj -type NoteProperty -name name -value $share
Add-Member -InputObject $obj -type NoteProperty -name path -value $path
$obj

The last line will output our share as a Powershell Object:

name : share1
path : /ifs/data/share1

Secondly we apply the “ConvertTo-Json” cmdlet to create the corresponding JSON object:

$jobj = ConvertTo-Json $obj
$jobj

And its output:

{
    "name":  "share1",
    "path":  "/ifs/data/share1"
}

With these two cmdlets we are able to work with JSON without knowing the syntax. I personal think this is great.

Invoke-RestMethod:

The next step is to communicate with the Isilon Platform API using the third cmdlet “Invoke-RestMethod”. The Isilon REST implementation is using the HTTP(s) protocol and JSON for the body.

Invoke-RestMethod [-Uri <Uri>] [-Body <Object> ]&nbsp;[-ContentType <String> ]&nbsp;[-Headers <IDictionary> ]&nbsp;[-Method <WebRequestMethod> ] [-SessionVariable <String> ]&nbsp;[-WebSession <WebRequestSession> ]

The list of parameters reflects only the ones we will use and is not complete:

-Uri <Uri>
Specifies the Uniform Resource Identifier (URI) of the Internet resource to which the web request is sent.
In our case this will be the URI to the Isilon resource. For our share example: “https://isilon:8080/platform/1/protocols/smb/shares”

-Body <Object>
Specifies the body of the request. The body is the content of the request that follows the headers.
Here we will enter our JSON Object, for our share example:”$jobj”

-ContentType <String>
Specifies the content type of the web request.
If we are going to sent to the API a body, we have to define the format. This will be “application/json; charset=utf-8”.

-Method <WebRequestMethod>
Specifies the method used for the web request.
Use “GET” for retrieving, “POST” for creating, “PUT” for modifying and “DELETE” for deleting an object.

For authenticating with the Isilon API we can leverage two different methods. On one side we can send with every call a basic authentication header and therefore use the “headers” parameter. On the other hand we can create a session (“SessionVariable”) and successive send only the cookie(“WebSession”).
Using headers is simpler but requires more Isilon resources as every request has to be authenticated. Also you will have to store you username and password somewhere if you are working in the powershell.

-Headers <IDictionary>
Specifies the headers of the web request. Enter a hash table or dictionary.

-SessionVariable <String>
Creates a web request session and saves it in the value of the specified variable.

-WebSession <WebRequestSession>
Specifies a web request session.

Example:

To give you an idea of the cmdlet and its output we are creating the SMB share from the example above, using header authentication, and retrieve the share object afterwards:

# create header
$username = "root"
$password = "a"
$EncodedAuthorization = [System.Text.Encoding]::UTF8.GetBytes($username + ':' + $password)
$EncodedPassword = [System.Convert]::ToBase64String($EncodedAuthorization)
$headers = @{"Authorization"="Basic $($EncodedPassword)"}

# create Uri
$isilonip = "10.0.0.1"
$baseurl = 'https://' + $isilonip +":8080" 
$resourceurl = "/platform/1/protocols/smb/shares"
$uri = $baseurl + $resourceurl

# create share object
$obj = [pscustomobject]@{}
$share = "share1"
$path = "/ifs/data/share1"
Add-Member -InputObject $obj -type NoteProperty -name name -value $share
Add-Member -InputObject $obj -type NoteProperty -name path -value $path
$jobj = ConvertTo-Json $obj

# send request to create share
$ISIObject = Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -Body $jobj -ContentType "application/json; charset=utf-8"

After creating the share we are retreaving the object and printing the Powershell object:

# get share and print
$uri = $baseurl + $resourceurl + '/' + $share
$ISIObject = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
$ISIObject.shares

Output:

access_based_enumeration           : False
access_based_enumeration_root_only : False
allow_delete_readonly              : False
allow_execute_always               : False
allow_variable_expansion           : False
auto_create_directory              : False
browsable                          : True
change_notify                      : norecurse
create_permissions                 : default acl
csc_policy                         : manual
description                        :
directory_create_mask              : 448
directory_create_mode              : 0
file_create_mask                   : 448
file_create_mode                   : 64
hide_dot_files                     : False
host_acl                           : {}
id                                 : share1
impersonate_guest                  : never
impersonate_user                   :
inheritable_path_acl               : False
mangle_byte_start                  : 60672
mangle_map                         : {0x01-0x1F:-1, 0x22:-1, 0x2A:-1, 0x3A:-1...}
name                               : share1
ntfs_acl_support                   : True
oplocks                            : True
path                               : /ifs/data/share1
permissions                        : {@{permission=read; permission_type=allow; trustee=}}
run_as_root                        : {}
strict_flush                       : True
strict_locking                     : False

SSL Validation:

If you are using the default self signed certificate of the Isilon your code will probably fail with the following error:
Invoke-RestMethod : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.

This happens because the Isilon generates by default a self signed certificate. To alleviate this you can disable the certificate validation for the current Powershell session with following code:

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

Update:

Curiously this does not work with Session Authentication (explained in Part2) and fails with following error:
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.

To reliably disable SSL validation please you following code, written by Matt Graeber, which can also be found on PoshCode:

function Disable-SSLValidation{
<#
.SYNOPSIS
    Disables SSL certificate validation
.DESCRIPTION
    Disable-SSLValidation disables SSL certificate validation by using reflection to implement the System.Net.ICertificatePolicy class.

    Author: Matthew Graeber (@mattifestation)
    License: BSD 3-Clause
.NOTES
    Reflection is ideal in situations when a script executes in an environment in which you cannot call csc.ese to compile source code. If compiling code is an option, then implementing System.Net.ICertificatePolicy in C# and Add-Type is trivial.
.LINK
    http://www.exploit-monday.com
#>

    Set-StrictMode -Version 2

    # You have already run this function
    if ([System.Net.ServicePointManager]::CertificatePolicy.ToString() -eq 'IgnoreCerts') { Return }

    $Domain = [AppDomain]::CurrentDomain
    $DynAssembly = New-Object System.Reflection.AssemblyName('IgnoreCerts')
    $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
    $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('IgnoreCerts', $false)
    $TypeBuilder = $ModuleBuilder.DefineType('IgnoreCerts', 'AutoLayout, AnsiClass, Class, Public, BeforeFieldInit', [System.Object], [System.Net.ICertificatePolicy])
    $TypeBuilder.DefineDefaultConstructor('PrivateScope, Public, HideBySig, SpecialName, RTSpecialName') | Out-Null
    $MethodInfo = [System.Net.ICertificatePolicy].GetMethod('CheckValidationResult')
    $MethodBuilder = $TypeBuilder.DefineMethod($MethodInfo.Name, 'PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask', $MethodInfo.CallingConvention, $MethodInfo.ReturnType, ([Type[]] ($MethodInfo.GetParameters() | % {$_.ParameterType})))
    $ILGen = $MethodBuilder.GetILGenerator()
    $ILGen.Emit([Reflection.Emit.Opcodes]::Ldc_I4_1)
    $ILGen.Emit([Reflection.Emit.Opcodes]::Ret)
    $TypeBuilder.CreateType() | Out-Null

    # Disable SSL certificate validation
    [System.Net.ServicePointManager]::CertificatePolicy = New-Object IgnoreCerts
}

Conclusion:

Powershell v3+ offers you a great platform for scripting with the Isilon PAPI. You can write rich scripts without the need to learn JSON and/or write your own methods for communication.
I will discuss authentication and the usage of “Invoke-RestMethod” with Isilon in Part 2 in more depth.

[1] http://muegge.com/blog/?p=251
[2] https://community.emc.com/community/connect/isilon/blog/2013/09/25/using-powershell-with-the-papi-and-ran–the-basics

Leave a comment

Your email address will not be published.

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