├── .gitattributes ├── .gitignore ├── IsilonPlatform ├── Functions │ ├── IsilonPlatformAddOn.ps1 │ ├── IsilonPlatformGet.ps1 │ ├── IsilonPlatformNew.ps1 │ ├── IsilonPlatformRemove.ps1 │ └── IsilonPlatformSet.ps1 ├── IsilonPlatform.psd1 └── IsilonPlatform.psm1 ├── LICENSE ├── README.md └── SSLValidation ├── SSLValidation.psd1 └── SSLValidation.psm1 /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vchrisb/Isilon-POSH/77860e4f4e9cbcde96bc52ee1b37cf39706e238e/.gitignore -------------------------------------------------------------------------------- /IsilonPlatform/Functions/IsilonPlatformAddOn.ps1: -------------------------------------------------------------------------------- 1 | # The MIT License 2 | # 3 | # Copyright (c) 2016 Christopher Banck. 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | Set-StrictMode -Version Latest 24 | $ErrorActionPreference = "Stop" 25 | 26 | Function Get-isiSmbOpenfilesNode{ 27 | 28 | <# 29 | .SYNOPSIS 30 | Get Smb Openfiles from a specific Node 31 | 32 | .DESCRIPTION 33 | List open files from a specific Node 34 | 35 | .PARAMETER Cluster 36 | Name of Isilon Node 37 | 38 | .NOTES 39 | 40 | #> 41 | [CmdletBinding()] 42 | param ( 43 | [Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$True,ValueFromPipeline=$True,Position=0)][ValidateNotNullOrEmpty()][string]$Cluster=(Get-isiSessionDefault) 44 | ) 45 | Begin{ 46 | } 47 | Process{ 48 | 49 | $token = '' 50 | # Isilon API limits returned Openfiles to 1000 by default 51 | $openfiles_node, $token = Get-isiSmbOpenfiles -Cluster $Cluster -limit 1000 52 | while($token){ 53 | $openfiles_node_resume, $token = Get-isiSmbOpenfiles -resume $token -Cluster $Cluster 54 | $openfiles_node += $openfiles_node_resume 55 | } 56 | $openfiles_node | Add-Member -NotePropertyName Cluster -NotePropertyValue $Cluster 57 | return $openfiles_node 58 | 59 | } 60 | End { 61 | } 62 | } 63 | 64 | Export-ModuleMember -Function Get-isiSmbOpenfilesNode 65 | 66 | Function Get-isiSmbSessionsNode{ 67 | 68 | <# 69 | .SYNOPSIS 70 | Get Smb Sessions from a specific Node 71 | 72 | .DESCRIPTION 73 | List sessions from a specific Node 74 | 75 | .PARAMETER Cluster 76 | Name of Isilon Node 77 | 78 | .NOTES 79 | 80 | #> 81 | [CmdletBinding()] 82 | param ( 83 | [Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$True,ValueFromPipeline=$True,Position=0)][ValidateNotNullOrEmpty()][string]$Cluster=(Get-isiSessionDefault) 84 | ) 85 | Begin{ 86 | } 87 | Process{ 88 | 89 | $token = '' 90 | # Isilon API limits returned Openfiles to 1000 by default 91 | $opensessions_node, $token = Get-isiSmbSessions -Cluster $Cluster -limit 1000 92 | while($token){ 93 | $opensessions_node_resume, $token = Get-isiSmbSessions -resume $token -Cluster $Cluster 94 | $opensessions_node += $opensessions_node_resume 95 | } 96 | $opensessions_node | Add-Member -NotePropertyName Cluster -NotePropertyValue $Cluster 97 | return $opensessions_node 98 | 99 | } 100 | End { 101 | } 102 | } 103 | 104 | Export-ModuleMember -Function Get-isiSmbSessionsNode 105 | 106 | 107 | 108 | function SanitizeBoundParameters { 109 | <# 110 | .SYNOPSIS 111 | Sanitize Bound Parameters 112 | 113 | .DESCRIPTION 114 | Sanitize Bound Parameters 115 | 116 | .NOTES 117 | 118 | #> 119 | [cmdletbinding()] 120 | param( 121 | [parameter(Mandatory=$True, ValueFromPipeline=$True)][hashtable]$Parameters 122 | ) 123 | 124 | $commonParameters = @('Cluster', 'Verbose', 'Debug', 'ErrorAction', 'ErrorVariable', 'WarningAction', 'WarningVariable', 'InformationAction', 'InformationVariable', 'OutBuffer', 'PipelineVariable', 'OutVariable', 'Force') 125 | 126 | $commonParameters | % { 127 | $Parameters.Remove($_) 128 | } 129 | return $Parameters 130 | } 131 | 132 | Export-ModuleMember -Function SanitizeBoundParameters -------------------------------------------------------------------------------- /IsilonPlatform/IsilonPlatform.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'IsilonPlatform' 3 | # 4 | # 5 | # The MIT License 6 | # 7 | # Copyright (c) 2016 Christopher Banck. 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy 10 | # of this software and associated documentation files (the "Software"), to deal 11 | # in the Software without restriction, including without limitation the rights 12 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the Software is 14 | # furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in 17 | # all copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | # THE SOFTWARE. 26 | 27 | @{ 28 | 29 | # Script module or binary module file associated with this manifest. 30 | RootModule = 'IsilonPlatform.psm1' 31 | 32 | # Version number of this module. 33 | ModuleVersion = '8.0.6' 34 | 35 | # ID used to uniquely identify this module 36 | GUID = '0bcb10cf-1d7e-4bad-8239-f725dcf1808f' 37 | 38 | # Author of this module 39 | Author = 'Christopher Banck' 40 | 41 | # Company or vendor of this module 42 | CompanyName = '' 43 | 44 | # Copyright statement for this module 45 | Copyright = '(c) 2017 Christopher Banck. All rights reserved.' 46 | 47 | # Description of the functionality provided by this module 48 | Description = 'EMC Isilon Platform API implementation in PowerShell' 49 | 50 | # Minimum version of the Windows PowerShell engine required by this module 51 | PowerShellVersion = '3.0' 52 | 53 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 54 | NestedModules = @('Functions/IsilonPlatformGet.ps1', 'Functions/IsilonPlatformSet.ps1', 'Functions/IsilonPlatformNew.ps1', 'Functions/IsilonPlatformRemove.ps1', 'Functions/IsilonPlatformAddOn.ps1') 55 | 56 | # Functions to export from this module 57 | FunctionsToExport = '*' 58 | 59 | # Cmdlets to export from this module 60 | #CmdletsToExport = '*' 61 | 62 | # Variables to export from this module 63 | #VariablesToExport = '*' 64 | 65 | # Aliases to export from this module 66 | AliasesToExport = '*' 67 | 68 | # HelpInfo URI of this module 69 | HelpInfoURI = 'https://banck.net' 70 | 71 | } 72 | 73 | -------------------------------------------------------------------------------- /IsilonPlatform/IsilonPlatform.psm1: -------------------------------------------------------------------------------- 1 | # IsilonPlatform.psm1 2 | # 3 | # The MIT License 4 | # 5 | # Copyright (c) 2016 Christopher Banck. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | 25 | Set-StrictMode -Version Latest 26 | $ErrorActionPreference = "Stop" 27 | 28 | function New-isiSession{ 29 | 30 | <# 31 | .SYNOPSIS 32 | New Isilon Sessison 33 | 34 | .DESCRIPTION 35 | Establishes a new Session with an Isilon Cluster 36 | 37 | .PARAMETER ComputerName 38 | IP or FQDN of an Isilon node or SmartConnect address 39 | 40 | .PARAMETER Credential 41 | A PSCredential to authenticate against the Isilon 42 | 43 | .PARAMETER Cluster 44 | This variable will default to the ComputerName if not set. 45 | 46 | .PARAMETER default 47 | 48 | .EXAMPLE 49 | New-isiSession -ComputerName 172.19.20.21 -Cluster Isilon1 50 | 51 | .EXAMPLE 52 | $Credential = Get-Credential 53 | New-isiSession -ComputerName isilon.domain.com -Credential $Credential -Cluster Isilon2 -default 54 | 55 | .EXAMPLE 56 | $Credential = Get-Credential 57 | "isilon1.domain.com","isilon2.domain.com" | New-isiSession -Credential $Credential 58 | 59 | #> 60 | [CmdletBinding()] 61 | Param( 62 | [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true,Position=0)][ValidateNotNullOrEmpty()][string] $ComputerName, 63 | [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,Position=1)][PSCredential]$Credential = (Get-Credential -Message "Isilon Credential"), 64 | [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,Position=2)][ValidateNotNullOrEmpty()][string]$Cluster, 65 | [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,Position=3)][ValidateNotNullOrEmpty()][string]$Port='8080', 66 | [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,Position=4)][switch]$default) 67 | 68 | Begin{ 69 | 70 | # test if the isi_session variables already exists 71 | if(!(Test-Path variable:isi_sessions) ){ 72 | $script:isi_sessions = @() 73 | } 74 | if(!(Test-Path variable:isi_sessiondefault) ){ 75 | $script:isi_sessiondefault = '' 76 | } 77 | 78 | } 79 | Process { 80 | 81 | if (!(Test-Path variable:Cluster) -or !$Cluster) { 82 | $Cluster = $ComputerName 83 | } 84 | 85 | $baseurl = "https://$ComputerName`:$Port" 86 | 87 | #create Jason Object for Input Values 88 | $jobj = convertto-json @{username= $Credential.UserName; password = $Credential.GetNetworkCredential().Password; services = ('platform','namespace')} 89 | 90 | #create session 91 | $ISIObject = Invoke-RestMethod -Uri "$baseurl/session/1/session" -Body $jobj -ContentType "application/json" -Method POST -SessionVariable session -TimeoutSec 180 92 | 93 | #remove cluster if entry exists 94 | Clear-isiSession -Cluster $Cluster 95 | 96 | #add new cluster 97 | $script:isi_sessions += New-Object -TypeName psObject -Property @{Cluster = $Cluster; url=$baseurl; session= $session; timeout_absolute=(Get-Date).AddSeconds($ISIObject.timeout_absolute); timeout=(Get-Date).AddSeconds($ISIObject.timeout_inactive); timeout_inactive=$ISIObject.timeout_inactive;username=$ISIObject.username} 98 | 99 | # Add CSRF and Referer headers (if cookie present) 100 | # https://emcservice.force.com/CustomersPartners/kA5f10000004Jn3CAE 101 | $cookies = $session.cookies.GetCookies($baseurl) 102 | try { 103 | $csrfcookie = [string]$cookies['isicsrf'] 104 | $csrftoken = $csrfcookie.split('=')[1] 105 | $session.Headers.Add('X-CSRF-Token', $csrftoken) 106 | $session.Headers.Add('Referer', $baseurl) 107 | Write-Verbose 'CSRF protection detected.' 108 | } catch { 109 | Write-Verbose 'No CSRF protection detected.' 110 | } 111 | 112 | #if default $true or default cluster not present set current cluster 113 | if ($default -or (@($isi_sessions | where { $_.cluster -eq $isi_sessiondefault} ).count -eq 0)){ 114 | $script:isi_sessiondefault = $Cluster 115 | } 116 | 117 | Remove-Variable Cluster 118 | 119 | } 120 | 121 | End { 122 | 123 | 124 | } 125 | } 126 | 127 | function Get-isiSessionInfo { 128 | 129 | <# 130 | .SYNOPSIS 131 | Get Isilon Sessison Info 132 | 133 | .DESCRIPTION 134 | 135 | .PARAMETER Cluster 136 | 137 | .EXAMPLE 138 | Get-isiSessionInfo 139 | 140 | .EXAMPLE 141 | Get-isiSessionInfo -Cluster Isilon1 142 | 143 | .EXAMPLE 144 | "isilon1.domain.com","isilon2.domain.com" | Get-isiSessionInfo 145 | 146 | .NOTES 147 | 148 | 149 | #> 150 | [CmdletBinding()] 151 | Param([Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true,Position=0)][ValidateNotNullOrEmpty()][string]$Cluster) 152 | 153 | Begin{ 154 | if(!(Test-Path variable:isi_sessions) -or !(Test-Path variable:isi_sessiondefault)){ 155 | Write-Verbose "No Isilon Cluster connected" 156 | break 157 | } 158 | if ( !$psBoundParameters.ContainsKey('Cluster') ) { 159 | Write-Verbose "No Cluster specified. Selecting session default: $isi_sessiondefault" 160 | $Cluster = $isi_sessiondefault 161 | } 162 | } 163 | Process{ 164 | Send-isiAPI -Method 'GET' -Resource "/session/1/session" -Cluster $Cluster 165 | } 166 | 167 | End{ 168 | 169 | } 170 | } 171 | 172 | function Get-isiSession { 173 | 174 | <# 175 | .SYNOPSIS 176 | Display Isilon Sessisons 177 | 178 | .DESCRIPTION 179 | 180 | .PARAMETER Cluster 181 | 182 | .EXAMPLE 183 | Get-isiSession 184 | 185 | .EXAMPLE 186 | Get-isiSession -Cluster Isilon1 187 | 188 | .NOTES 189 | 190 | 191 | #> 192 | [CmdletBinding()] 193 | Param([Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true,Position=0)][ValidateNotNullOrEmpty()][string]$Cluster) 194 | 195 | if(!(Test-Path variable:isi_sessions) -or !(Test-Path variable:isi_sessiondefault)){ 196 | Write-Verbose "No Isilon Cluster connected!" 197 | return 198 | } 199 | 200 | if($isi_sessions){ 201 | if($Cluster){ 202 | $isi_sessions | where { $_.cluster -eq $Cluster } 203 | }else{ 204 | $isi_sessions 205 | } 206 | } 207 | } 208 | 209 | function Clear-isiSession { 210 | 211 | <# 212 | .SYNOPSIS 213 | Clear Isilon Sessison 214 | 215 | .DESCRIPTION 216 | 217 | .PARAMETER Cluster 218 | 219 | .EXAMPLE 220 | Clear-isiSession 221 | 222 | .EXAMPLE 223 | Clear-isiSession -Cluster Isilon1 224 | 225 | .NOTES 226 | 227 | 228 | #> 229 | [CmdletBinding()] 230 | param ([Parameter(Mandatory=$False,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Position=0)][ValidateNotNullOrEmpty()][string]$Cluster) 231 | 232 | if(!(Test-Path variable:isi_sessions) -or !(Test-Path variable:isi_sessiondefault)){ 233 | Write-Error "No Isilon Cluster connected!" 234 | } 235 | 236 | if($Cluster){ 237 | 238 | foreach($clust in $Cluster){ 239 | $script:isi_sessions = @($isi_sessions | where { $_.cluster -ne $clust }) 240 | } 241 | 242 | } Else { 243 | remove-variable -scope script isi_sessions 244 | remove-variable -scope script isi_sessiondefault 245 | } 246 | } 247 | 248 | function Remove-isiSession { 249 | 250 | <# 251 | .SYNOPSIS 252 | Removes Isilon Sessison 253 | 254 | .DESCRIPTION 255 | 256 | .PARAMETER Cluster 257 | 258 | .EXAMPLE 259 | Remove-isiSession 260 | 261 | .EXAMPLE 262 | Remove-isiSession -Cluster Isilon1 263 | 264 | .EXAMPLE 265 | "isilon1.domain.com","isilon2.domain.com" | Remove-isiSession 266 | 267 | .NOTES 268 | 269 | 270 | #> 271 | [CmdletBinding()] 272 | Param([Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true,Position=0)][ValidateNotNullOrEmpty()][string]$Cluster) 273 | 274 | Begin{ 275 | if(!(Test-Path variable:isi_sessions) -or !(Test-Path variable:isi_sessiondefault)){ 276 | Write-Error "No Isilon Cluster connected" 277 | break 278 | } 279 | if ( !$psBoundParameters.ContainsKey('Cluster') ) { 280 | Write-Verbose "No Cluster specified. Selecting session default: $isi_sessiondefault" 281 | $Cluster = $isi_sessiondefault 282 | } 283 | } 284 | 285 | Process{ 286 | 287 | if (@($isi_sessions | where { $_.cluster -eq $Cluster} ).count -eq 1){ 288 | 289 | #remove session on the isilon cluster 290 | Send-isiAPI -Resource "/session/1/session" -Cluster $Cluster -Method 'delete' 291 | #remove entry if exists 292 | Clear-isiSession -Cluster $Cluster 293 | 294 | } 295 | 296 | if (@($isi_sessions | where { $_.cluster -eq $isi_sessiondefault} ).count -eq 0){ 297 | if ($isi_sessions) { 298 | $script:isi_sessiondefault = $isi_sessions[0].cluster 299 | } else { 300 | Remove-Variable -scope script isi_sessiondefault 301 | } 302 | } 303 | 304 | 305 | } 306 | 307 | End{ 308 | } 309 | 310 | } 311 | 312 | function Get-isiSessionDefault { 313 | 314 | <# 315 | .SYNOPSIS 316 | Display Default Isilon Sessisons 317 | 318 | .DESCRIPTION 319 | 320 | .EXAMPLE 321 | Get-isiSession 322 | 323 | .NOTES 324 | 325 | 326 | #> 327 | 328 | if(!(Test-Path variable:isi_sessions) -or !(Test-Path variable:isi_sessiondefault)){ 329 | Write-Error "No Isilon Cluster connected!" 330 | } 331 | 332 | $script:isi_sessiondefault 333 | } 334 | 335 | function Set-isiSessionDefault { 336 | 337 | <# 338 | .SYNOPSIS 339 | Isilon Sessison 340 | 341 | .DESCRIPTION 342 | 343 | 344 | .EXAMPLE 345 | Set-isiSessionDefault -Cluster Isilon1 346 | 347 | .NOTES 348 | 349 | 350 | #> 351 | [CmdletBinding()] 352 | Param([Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$True,ValueFromPipeline=$True,Position=0)][string]$Cluster) 353 | 354 | Begin{ 355 | if(!(Test-Path variable:isi_sessions) -or !(Test-Path variable:isi_sessiondefault)){ 356 | Write-Error "No Isilon Cluster connected!" 357 | } 358 | } 359 | 360 | Process{ 361 | 362 | if (@($isi_sessions | where { $_.cluster -eq $Cluster} ).count -eq 1){ 363 | $script:isi_sessiondefault = $Cluster 364 | 365 | } 366 | else{ 367 | Write-Error "Session for Cluster `"$Cluster`" not found" 368 | 369 | } 370 | 371 | } 372 | 373 | End{ 374 | } 375 | 376 | } 377 | 378 | function Send-isiAPI{ 379 | 380 | <# 381 | .SYNOPSIS 382 | sends Rest Command to Ision API 383 | 384 | .DESCRIPTION 385 | 386 | .PARAMETER Cluster 387 | 388 | .PARAMETER Resource 389 | 390 | .PARAMETER body 391 | 392 | .PARAMETER Method 393 | 394 | .EXAMPLE 395 | Send-isiAPI -Resource "/platform/1/protocols/smb/shares" -Cluster IsilonC1 -Method GET 396 | 397 | .NOTES 398 | 399 | #> 400 | [CmdletBinding()] 401 | Param( 402 | [Parameter(Mandatory=$True,ValueFromPipelineByPropertyName=$False,ValueFromPipeline=$false,Position=0)][string]$Resource, 403 | [Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$False,ValueFromPipeline=$false,Position=1)][ValidateSet('GET_JSON','GET','POST','PUT','DELETE','POST')][string]$Method="GET", 404 | [Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$False,ValueFromPipeline=$false,Position=2)][string]$body, 405 | [Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$False,ValueFromPipeline=$false,Position=3)][string]$Cluster) 406 | 407 | if(!(Test-Path variable:isi_sessions) -or !(Test-Path variable:isi_sessiondefault)){ 408 | Write-Error "No Isilon Cluster connected" 409 | break 410 | } 411 | if ( !$psBoundParameters.ContainsKey('Cluster') -or !$Cluster) { 412 | Write-Verbose "No Cluster specified. Selecting session default: $isi_sessiondefault" 413 | $Cluster = $isi_sessiondefault 414 | } 415 | 416 | $isi_session = Get-isiSession -Cluster $Cluster 417 | $url = $isi_session.url + $Resource 418 | $session = $isi_session.session 419 | $Method = $Method.ToUpper() 420 | $timeout = 180 421 | 422 | if (!$Cluster){ 423 | Write-Error "No Cluster connected!" 424 | 425 | }elseif (@($isi_sessions | where { $_.cluster -eq $Cluster }).count -eq 0){ 426 | Write-Error "Cluster $Cluster not connected!" 427 | 428 | 429 | }elseif (((Get-Date) -gt $isi_session.timeout) -or ((Get-Date) -gt $isi_session.timeout_absolute)){ 430 | Write-Error "Session timeout for $Cluster!" 431 | 432 | 433 | }else{ 434 | try{ 435 | if ($Method -eq 'GET_JSON') { 436 | $ISIObject = (Invoke-WebRequest -Uri $url -Method GET -WebSession $session -TimeoutSec $timeout -UseBasicParsing).content 437 | 438 | } elseif ( ($Method -eq 'GET') -or ($Method -eq 'DELETE') ) { 439 | $ISIObject = (Invoke-WebRequest -Uri $url -Method $Method -WebSession $session -TimeoutSec $timeout -UseBasicParsing).content | ConvertFrom-Json 440 | 441 | } elseif ( ($Method -eq 'PUT') -or ($Method -eq 'POST') ) { 442 | $ISIObject = (Invoke-WebRequest -Uri $url -Method $Method -WebSession $session -TimeoutSec $timeout -Body $body -ContentType "application/json" -UseBasicParsing).content | ConvertFrom-Json 443 | 444 | } 445 | } 446 | catch { 447 | # if it is an Isilon error, extract the error response from http body 448 | if($_.Exception.PSObject.Properties['Response']){ 449 | $result = $_.Exception.Response.GetResponseStream() 450 | $reader = New-Object System.IO.StreamReader($result) 451 | $responseBody = $reader.ReadToEnd() | ConvertFrom-Json 452 | if ($responseBody.PSObject.Properties.name -contains "errors") { 453 | $errorResponse = $_.Exception.Message + " " + $responseBody.errors.message 454 | } elseif ($responseBody.PSObject.Properties.name -contains "message") { 455 | $errorResponse = $_.Exception.Message + " " + $responseBody.message 456 | } else { 457 | $errorResponse = $_.Exception.Message 458 | } 459 | Write-Error $errorResponse 460 | } else { 461 | Write-Error $_.Exception 462 | } 463 | } 464 | $isi_session.timeout = (Get-Date).AddSeconds($isi_session.timeout_inactive) 465 | $ISIObject 466 | } 467 | } 468 | 469 | Export-ModuleMember -Function New-isiSession 470 | Export-ModuleMember -Function Get-isiSession 471 | Export-ModuleMember -Function Get-isiSessionInfo 472 | Export-ModuleMember -Function Get-isiSessionDefault 473 | Export-ModuleMember -Function Set-isiSessionDefault 474 | Export-ModuleMember -Function Remove-isiSession 475 | Export-ModuleMember -Function Send-isiAPI 476 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Christopher Banck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Isilon-POSH 2 | 3 | EMC Isilon Platform API implementation in Powershell 4 | 5 | ===== 6 | 7 | This is an inofficial (not by EMC) Powershell module that allows you to manage your EMC Isilon Scale-Out NAS systems by Powershell. 8 | 9 | More Information clould be found in these blog posts: 10 | * https://banck.net/2013/12/isilon-rest-api-using-powershell-part-1.html 11 | * https://banck.net/2014/01/isilon-rest-api-using-powershell-part-2.html 12 | * https://banck.net/2014/08/tcp-connection-hanging-in-close_wait-when-using-invoke-restmethod-with-put-or-delete/ 13 | 14 | Most of the cmdlets are generated using [Isilon-POSH-Generator](https://github.com/vchrisb/Isilon-POSH-Generator). Please see [Contribution](#contribution) for more information. 15 | 16 | ### Requirements 17 | * Powershell 3.0 and newer 18 | * Isilon OneFS 7.1.0.0 and newer 19 | 20 | ### Features 21 | * Websession support, no need to store password 22 | * PowerShell pipeline support 23 | * concurrently connecting to multiple Isilon clusters 24 | * 99% of the Platform API for OneFS v8.0 covered 25 | * confirmation and error handling 26 | 27 | ### Installation 28 | 29 | #### Windows 30 | 31 | Copy the folder `IsilonPlatform` and `SSLValidation` to the desired module path. 32 | You can find the configured Powershell module paths in the variable 33 | ```PowerShell 34 | $env:PSModulePath 35 | ``` 36 | 37 | With PowerShell 5.0 you can simply use following command: 38 | `Install-Module IsilonPlatform` 39 | 40 | #### Linux 41 | 42 | [Linux PowerShell installation instructions](https://github.com/PowerShell/PowerShell/blob/master/docs/installation/linux.md#paths) can be found in the PowerShell GitHub Repo. 43 | Make sure that you have `libcurl3` (for Ubuntu 16.04) or equivalent installed. 44 | 45 | Copy the folder `IsilonPlatform` to one of the [supported module paths](https://github.com/PowerShell/PowerShell/blob/master/docs/installation/linux.md#paths). 46 | For example the shared modules path: `/usr/local/share/powershell/Modules/` 47 | 48 | ##### SSL certificate 49 | 50 | The `SSLValidation` module does not work on linux. To be able to connect to the Isilon cluster, you will have to trust the SSL certificate on the linux client. 51 | Make sure that the `ComputerName` is identical to the `common name` in the SSL certificate, when connecting to the cluster. 52 | If you are using a self-signed certificate, you will need to replace it with the `common name` configured to match the hostname, used to connect to the Isilon. This should be a DNS Record pointing to the SmartConnect service IP address or the IP itself. A procedure can be found in the [Web Administration Guide](http://www.emc.com/collateral/TechnicalDocument/docu65068.pdf) 53 | 54 | Retrieving and installing the certificate can be accomplished on Ubuntu 16.04 as followed: 55 | ```sh 56 | echo -n | openssl s_client -connect :8080 -showcerts 2>/dev/null | openssl x509 -outform PEM > isilon.crt 57 | sudo cp isilon.crt /usr/share/ca-certificates/ 58 | echo "isilon.crt" | sudo tee --append /etc/ca-certificates.conf 59 | sudo update-ca-certificates 60 | ``` 61 | 62 | `curl https://:8080/session/1/session` shouldn't print any error if successful. 63 | 64 | #### macOS 65 | 66 | tbd 67 | 68 | ### Examples 69 | ```PowerShell 70 | Import-Module IsilonPlatform 71 | 72 | # connect Isilon using FQDN 73 | New-isiSession -ComputerName isilonc1.emc.lab 74 | 75 | # connect Isilon using IP address and configure a Cluster name 76 | New-isiSession -ComputerName 192.168.10.100 -Cluster isilonc2 77 | 78 | # Get all SMB shares for default cluster 79 | Get-isiSmbShares 80 | 81 | # Get all SMB shares for cluster isilonc2.emc.lab 82 | Get-isiSmbShares -Cluster isilonc2 83 | 84 | # Get all SMB shares for all connected cluster 85 | Get-isiSession | Get-isiSmbShares 86 | 87 | # Backup all SMB shares to json file for default session 88 | Get-isiSmbShares | ConvertTo-Json | Out-File shares.json 89 | 90 | # create new SMB share 91 | New-isiSmbShare -name HR -path '/ifs/data/HR' 92 | 93 | # add a describtion to all SMB shares that have 'test' in there share name 94 | Get-isiSmbShares | where name -like '*test*' | Set-isiSmbShare -description 'This is a Test Share' 95 | 96 | # limit Get-isiSmbShares to only receive 1000 shares 97 | $shares, $token = Get-isiSmbShares -limit 1000 98 | # pass the saved token and receive the next 1000 shares, repeat until $token is empty 99 | $next_shares, $token = Get-isiSmbShares -resume $token 100 | $shares += $next_shares 101 | 102 | # print help for function New-isiSmbShares 103 | Get-Help -Detailed New-isiSmbShares 104 | 105 | # permission repair job 106 | New-isiJobs -type permissionrepair -paths /ifs/data/path -prepair_params @{mode="inherit";template="/path"} 107 | ``` 108 | 109 | ### Known Issues 110 | 111 | **receiving large amount of data fails** 112 | You may get following error: 113 | `Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.` 114 | This is due to `ConvertFrom-Json` only supports `JSON` smallen than 2 MB and it couldn't be raised for that Cmdlet. 115 | To overcome this limitation you can use the `limit` and corresponding `resume`flag. See example above. 116 | 117 | **Cmdlet `get-isiSmbOpenfiles` does return 1000 objects at max** 118 | The resource `/platform/1/protocols/smb/openfiles` does return at maximum `1000` openfiles by default 119 | To overcome this limitation you can use the `limit` and corresponding `resume`flag. See example above. 120 | 121 | ### SSL Validation 122 | If you are using self signed certificates on your Isilon you need to disable SSL validation in powershell. 123 | This could be accomplished by code from Matthew Graeber. (http://poshcode.org/3606) 124 | The code could also be found in this repository. 125 | 126 | ```PowerShell 127 | Import-Module SSLValidation 128 | Disable-SSLValidation 129 | ``` 130 | 131 | ### Things to do 132 | * Add support for API endpoints with three parameters (e.g. `/3/network/groupnets//subnets//pools/`) 133 | * testing 134 | * testing 135 | 136 | ### Contribution 137 | 138 | Happy to get PRs! 139 | Please open an issue before sending a PR and for each fix only one PR. 140 | 141 | Following files are are automatically generated via [Isilon-POSH-Generator](https://github.com/vchrisb/Isilon-POSH-Generator): 142 | 143 | * IsilonPlatformGet.ps1 144 | * IsilonPlatformNew.ps1 145 | * IsilonPlatformRemove.ps1 146 | * IsilonPlatformSet.ps1 147 | 148 | To discuss enhancements and bugs open an issue in this repo and PRs for these files will have to go to the [Isilon-POSH-Generator](https://github.com/vchrisb/Isilon-POSH-Generator) repo. 149 | 150 | ### DISCLAIMER 151 | This Powershell Module is not supported. Use at your own risk! 152 | -------------------------------------------------------------------------------- /SSLValidation/SSLValidation.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vchrisb/Isilon-POSH/77860e4f4e9cbcde96bc52ee1b37cf39706e238e/SSLValidation/SSLValidation.psd1 -------------------------------------------------------------------------------- /SSLValidation/SSLValidation.psm1: -------------------------------------------------------------------------------- 1 | function Disable-SSLValidation{ 2 | <# 3 | .SYNOPSIS 4 | Disables SSL certificate validation 5 | .DESCRIPTION 6 | Disable-SSLValidation disables SSL certificate validation by using reflection to implement the System.Net.ICertificatePolicy class. 7 | 8 | Author: Matthew Graeber (@mattifestation) 9 | License: BSD 3-Clause 10 | .NOTES 11 | 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. 12 | .LINK 13 | http://www.exploit-monday.com 14 | #> 15 | 16 | Set-StrictMode -Version 2 17 | 18 | # You have already run this function 19 | if ([System.Net.ServicePointManager]::CertificatePolicy.ToString() -eq 'IgnoreCerts') { Return } 20 | 21 | $Domain = [AppDomain]::CurrentDomain 22 | $DynAssembly = New-Object System.Reflection.AssemblyName('IgnoreCerts') 23 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 24 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('IgnoreCerts', $false) 25 | $TypeBuilder = $ModuleBuilder.DefineType('IgnoreCerts', 'AutoLayout, AnsiClass, Class, Public, BeforeFieldInit', [System.Object], [System.Net.ICertificatePolicy]) 26 | $TypeBuilder.DefineDefaultConstructor('PrivateScope, Public, HideBySig, SpecialName, RTSpecialName') | Out-Null 27 | $MethodInfo = [System.Net.ICertificatePolicy].GetMethod('CheckValidationResult') 28 | $MethodBuilder = $TypeBuilder.DefineMethod($MethodInfo.Name, 'PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask', $MethodInfo.CallingConvention, $MethodInfo.ReturnType, ([Type[]] ($MethodInfo.GetParameters() | % {$_.ParameterType}))) 29 | $ILGen = $MethodBuilder.GetILGenerator() 30 | $ILGen.Emit([Reflection.Emit.Opcodes]::Ldc_I4_1) 31 | $ILGen.Emit([Reflection.Emit.Opcodes]::Ret) 32 | $TypeBuilder.CreateType() | Out-Null 33 | 34 | # Disable SSL certificate validation 35 | [System.Net.ServicePointManager]::CertificatePolicy = New-Object IgnoreCerts 36 | } 37 | 38 | Export-ModuleMember -Function Disable-SSLValidation --------------------------------------------------------------------------------