ONTAP Discussions

powershell invoke-ncsystemapi and CLI differ for the same user

MORAYHOONDERT
4,160 Views

When connecting over an SSH-connection, the user: readonly_cl_user can see the tiering-minimum-cooling-days.

::> set d

 

Warning: These diagnostic commands are for use by NetApp personnel only.

Do you want to continue? {y|n}: y

 

::*> volume show -fields tiering-minimum-cooling-days

vserver  volume   tiering-minimum-cooling-days

-------- -------- ----------------------------

nct_cifs02 sns004_cifs_vol01 30

nct_cifs02 sns004_cifs_vol02 30

nct_cifs02 sns004_cifs_vol03 30

nct_cifs02 sns004_cifs_vol04 30

 

BUT:

When running the command from powershell, with invoke-ncsystemapi. It says:

PS H:\>  Invoke-NcSystemApi -Request $api -ErrorAction Stop

Invoke-NcSystemApi : Insufficient privileges: user 'readonly_cl_user' does not have write access to this

At line:1 char:2

+  Invoke-NcSystemApi -Request $api -ErrorAction Stop

+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (ncu:NcController) [Invoke-NcSystemApi], EAPIPRIVILEGE

    + FullyQualifiedErrorId : ApiException,DataONTAP.C.PowerShell.SDK.Cmdlets.System.InvokeNcSystemApi

 

 

PRIVILEGES IN THE ROLE ARE:

::> security login role show -vserver xxx

readonly_cl DEFAULT readonly
metrocluster check run all
set all
system all

 

 

MY QUESTION IS: WHAT privilege do I need to create for WHICH command on the CLI to make it work in Powershell over the invoke-ncsystemapi-command?

 

thank you in advance !

 

Moray

 

 

1 ACCEPTED SOLUTION

mbeattie
4,028 Views

Hi Moray,

You can view the Swagger UI for ONTAP in a browser using: https://<%cluster%>/docs/api

 

Browse the Swagger UI and look for /storage/volume. Here is an example to query the tiering minimum cooling days for all volumes on a cluster:

 

Param(
   [Parameter(Mandatory = $True, HelpMessage = "The Cluster name or IP Address")]
   [String]$Cluster,
   [Parameter(Mandatory = $True, HelpMessage = "The Credentials to authenticate to the destination cluster")]
   [System.Management.Automation.PSCredential]$Credential
)
#'------------------------------------------------------------------------------
#'Set the certificate policy and TLS version.
#'------------------------------------------------------------------------------
Add-Type @"
   using System.Net;
   using System.Security.Cryptography.X509Certificates;
   public class TrustAllCertsPolicy : ICertificatePolicy {
   public bool CheckValidationResult(
   ServicePoint srvPoint, X509Certificate certificate,
   WebRequest request, int certificateProblem) {
      return true;
   }
}
"@
[System.Net.ServicePointManager]::SecurityProtocol  = [System.Net.SecurityProtocolType]'Tls12'
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
#'------------------------------------------------------------------------------
Function Get-NcAuthorization{
   [Alias("Get-NcAuth")]
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the cluster")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Set the authentication header to connect to the cluster.
   #'---------------------------------------------------------------------------
   $auth    = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName + ':' + $Credential.GetNetworkCredential().Password))
   $headers = @{
      "Authorization" = "Basic $auth"
      "Accept"        = "application/json"
      "Content-Type"  = "application/json"
   }
   Return $headers;
}#'End Function Get-NcAuthorization.
#'------------------------------------------------------------------------------
#'Enumerate the volume tiering minimum cooling days for all volumes on the cluster.
#'------------------------------------------------------------------------------
$headers = Get-NcAuth -Credential $Credential
$url     = "https://$Cluster/api/storage/volumes?fields=tiering.min_cooling_days"
Try{
   $response = Invoke-RestMethod -Method GET -Uri $Url -Headers $headers -ErrorAction Stop
}Catch{
   Write-Warning -Message $("Failed Invoking Private CLI using URL ""$Url"". Error " + $_.Exception.Message)
   Break;
}
If($Null -ne $response){
   $response.records
}Else{
   Write-Host "No records returned"
}
#'------------------------------------------------------------------------------

 

To enumerate values not available via the REST API you can also use the private CLI via the REST API to invoke a CLI command.

 

Param(
   [Parameter(Mandatory = $True, HelpMessage = "The URL of the private CLI to invoke")]
   [String]$Url,
   [Parameter(Mandatory = $True, HelpMessage = "The destination cluster name or IP Address")]
   [ValidateSet("GET","PATCH","POST","DELETE")]
   [String]$Method,
   [Parameter(Mandatory = $True, HelpMessage = "The Credentials to authenticate to the destination cluster")]
   [System.Management.Automation.PSCredential]$Credential
)
#'------------------------------------------------------------------------------
#'Set the certificate policy and TLS version.
#'------------------------------------------------------------------------------
Add-Type @"
   using System.Net;
   using System.Security.Cryptography.X509Certificates;
   public class TrustAllCertsPolicy : ICertificatePolicy {
   public bool CheckValidationResult(
   ServicePoint srvPoint, X509Certificate certificate,
   WebRequest request, int certificateProblem) {
      return true;
   }
}
"@
[System.Net.ServicePointManager]::SecurityProtocol  = [System.Net.SecurityProtocolType]'Tls12'
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
#'------------------------------------------------------------------------------
Function Get-NcAuthorization{
   [Alias("Get-NcAuth")]
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the cluster")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Set the authentication header to connect to the cluster.
   #'---------------------------------------------------------------------------
   $auth    = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName + ':' + $Credential.GetNetworkCredential().Password))
   $headers = @{
      "Authorization" = "Basic $auth"
      "Accept"        = "application/json"
      "Content-Type"  = "application/json"
   }
   Return $headers;
}#'End Function Get-NcAuthorization.
#'------------------------------------------------------------------------------
Function Invoke-OntapCommand{
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The URL of private CLI to invoke")]
      [String]$Url,
      [Parameter(Mandatory = $True, HelpMessage = "The destination cluster name or IP Address")]
      [ValidateSet("GET","PATCH","POST","DELETE")]
      [String]$Method,
      [Parameter(Mandatory = $True, HelpMessage = "The Credentials to authenticate to the destination cluster")]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Invoke the Private CLI command.
   #'---------------------------------------------------------------------------
   $headers = Get-NcAuth -Credential $Credential
   Try{
      $response = Invoke-RestMethod -Method GET -Uri $Url -Headers $headers -ErrorAction Stop
   }Catch{
      Write-Warning -Message $("Failed Invoking Private CLI using URL ""$Url"". Error " + $_.Exception.Message)
      Return $Null;
   }
   Return $response
}
#'End Function Invoke-OntapCommand.
#'------------------------------------------------------------------------------
#'Display the response.
#'------------------------------------------------------------------------------
$response = Invoke-OntapCommand -Url $Url -Method $Method -Credential $credential
If($Null -ne $response){
   $response.records
}Else{
   Write-Host "No records returned"
}
#'------------------------------------------------------------------------------

 

EG:

 

PS C:\Scripts\PowerShell\Projects\InvokeOntapCommand> .\InvokeOntapCommand.ps1 -Url "https://192.168.100.200/api/private/cli/volume?fields=tiering-minimum-cooling-days" -Method GET -Credential $credential

I suspect you will have similar issues enumerating the information from the REST API though as your issue appears to be related to roles\permissions

 

/Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

View solution in original post

8 REPLIES 8

mbeattie
4,089 Views

Hi Moray,

 

You can set the diag privilege level in the command. Have a look at this example (browse down)

EG something like this ...

[Array]$command = @("set diag;volume", "show", "-fields", "tiering-minimum-cooling-days")
Try{
   $api = $("<system-cli><args><arg>" + ($command -join "</arg><arg>") + "</arg></args></system-cli>")
   Write-Host $("Executed Command`: " + $([String]::Join(" ", $command)))
   $output = Invoke-NcSystemApi -Request $api -ErrorAction Stop
}Catch{
   Write-Warning -Message $("Failed Executing Command`: " + $([String]::Join(" ", $command))
   Break;
}

Hope that helps

 

/Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

MORAYHOONDERT
4,084 Views

Hello Matt,

 

Thank you for your reply, I already tried this but the result is empty. I try the invoke-command as the Powershell Toolkit does not show the minimum-cooling-days field. No luck until now. If I enter your code:

 

Executed Command: set diag;volume show -fields tiering-minimum-cooling-days

PS H:\>

PS H:\> $output.results.'cli-output'

.....EMPTY

 

 

What do I oversee or do wrong.... 

 

running on 9.11.1P5

 

with regards, Moray

mbeattie
4,065 Views

Hi Moray,

It seems like a permission issue as the output returned results for me when i ran it on a cluster using admin credentials. I'm guessing you are trying to implement some type of health check as a read-only user? Perhaps the volume REST API might be an alternative option?

 

/Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

MORAYHOONDERT
4,063 Views
Hi Matt,

Never thought of the REST API, is there a way to learn this quick, as I did not find any clear and simple manual for this, I even do not know how to start.

And yes, I am already running a script that collects daily data and I want the tiering-minumum-cooling-days in it as well. The script runs over the readonly_cl_user with minimal privileges.

Thanks again!

Moray

mbeattie
4,029 Views

Hi Moray,

You can view the Swagger UI for ONTAP in a browser using: https://<%cluster%>/docs/api

 

Browse the Swagger UI and look for /storage/volume. Here is an example to query the tiering minimum cooling days for all volumes on a cluster:

 

Param(
   [Parameter(Mandatory = $True, HelpMessage = "The Cluster name or IP Address")]
   [String]$Cluster,
   [Parameter(Mandatory = $True, HelpMessage = "The Credentials to authenticate to the destination cluster")]
   [System.Management.Automation.PSCredential]$Credential
)
#'------------------------------------------------------------------------------
#'Set the certificate policy and TLS version.
#'------------------------------------------------------------------------------
Add-Type @"
   using System.Net;
   using System.Security.Cryptography.X509Certificates;
   public class TrustAllCertsPolicy : ICertificatePolicy {
   public bool CheckValidationResult(
   ServicePoint srvPoint, X509Certificate certificate,
   WebRequest request, int certificateProblem) {
      return true;
   }
}
"@
[System.Net.ServicePointManager]::SecurityProtocol  = [System.Net.SecurityProtocolType]'Tls12'
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
#'------------------------------------------------------------------------------
Function Get-NcAuthorization{
   [Alias("Get-NcAuth")]
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the cluster")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Set the authentication header to connect to the cluster.
   #'---------------------------------------------------------------------------
   $auth    = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName + ':' + $Credential.GetNetworkCredential().Password))
   $headers = @{
      "Authorization" = "Basic $auth"
      "Accept"        = "application/json"
      "Content-Type"  = "application/json"
   }
   Return $headers;
}#'End Function Get-NcAuthorization.
#'------------------------------------------------------------------------------
#'Enumerate the volume tiering minimum cooling days for all volumes on the cluster.
#'------------------------------------------------------------------------------
$headers = Get-NcAuth -Credential $Credential
$url     = "https://$Cluster/api/storage/volumes?fields=tiering.min_cooling_days"
Try{
   $response = Invoke-RestMethod -Method GET -Uri $Url -Headers $headers -ErrorAction Stop
}Catch{
   Write-Warning -Message $("Failed Invoking Private CLI using URL ""$Url"". Error " + $_.Exception.Message)
   Break;
}
If($Null -ne $response){
   $response.records
}Else{
   Write-Host "No records returned"
}
#'------------------------------------------------------------------------------

 

To enumerate values not available via the REST API you can also use the private CLI via the REST API to invoke a CLI command.

 

Param(
   [Parameter(Mandatory = $True, HelpMessage = "The URL of the private CLI to invoke")]
   [String]$Url,
   [Parameter(Mandatory = $True, HelpMessage = "The destination cluster name or IP Address")]
   [ValidateSet("GET","PATCH","POST","DELETE")]
   [String]$Method,
   [Parameter(Mandatory = $True, HelpMessage = "The Credentials to authenticate to the destination cluster")]
   [System.Management.Automation.PSCredential]$Credential
)
#'------------------------------------------------------------------------------
#'Set the certificate policy and TLS version.
#'------------------------------------------------------------------------------
Add-Type @"
   using System.Net;
   using System.Security.Cryptography.X509Certificates;
   public class TrustAllCertsPolicy : ICertificatePolicy {
   public bool CheckValidationResult(
   ServicePoint srvPoint, X509Certificate certificate,
   WebRequest request, int certificateProblem) {
      return true;
   }
}
"@
[System.Net.ServicePointManager]::SecurityProtocol  = [System.Net.SecurityProtocolType]'Tls12'
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
#'------------------------------------------------------------------------------
Function Get-NcAuthorization{
   [Alias("Get-NcAuth")]
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the cluster")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Set the authentication header to connect to the cluster.
   #'---------------------------------------------------------------------------
   $auth    = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName + ':' + $Credential.GetNetworkCredential().Password))
   $headers = @{
      "Authorization" = "Basic $auth"
      "Accept"        = "application/json"
      "Content-Type"  = "application/json"
   }
   Return $headers;
}#'End Function Get-NcAuthorization.
#'------------------------------------------------------------------------------
Function Invoke-OntapCommand{
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The URL of private CLI to invoke")]
      [String]$Url,
      [Parameter(Mandatory = $True, HelpMessage = "The destination cluster name or IP Address")]
      [ValidateSet("GET","PATCH","POST","DELETE")]
      [String]$Method,
      [Parameter(Mandatory = $True, HelpMessage = "The Credentials to authenticate to the destination cluster")]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Invoke the Private CLI command.
   #'---------------------------------------------------------------------------
   $headers = Get-NcAuth -Credential $Credential
   Try{
      $response = Invoke-RestMethod -Method GET -Uri $Url -Headers $headers -ErrorAction Stop
   }Catch{
      Write-Warning -Message $("Failed Invoking Private CLI using URL ""$Url"". Error " + $_.Exception.Message)
      Return $Null;
   }
   Return $response
}
#'End Function Invoke-OntapCommand.
#'------------------------------------------------------------------------------
#'Display the response.
#'------------------------------------------------------------------------------
$response = Invoke-OntapCommand -Url $Url -Method $Method -Credential $credential
If($Null -ne $response){
   $response.records
}Else{
   Write-Host "No records returned"
}
#'------------------------------------------------------------------------------

 

EG:

 

PS C:\Scripts\PowerShell\Projects\InvokeOntapCommand> .\InvokeOntapCommand.ps1 -Url "https://192.168.100.200/api/private/cli/volume?fields=tiering-minimum-cooling-days" -Method GET -Credential $credential

I suspect you will have similar issues enumerating the information from the REST API though as your issue appears to be related to roles\permissions

 

/Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

MORAYHOONDERT
4,017 Views

Hello Matt,

 

Thank you for your fast response and scripts. Your suspicion was right:

 

Using my admin account it works for the first script, so the swagger UI.

Using my admin account in the second script, so using the private CLI via the REST API to invoke a CLI command, it gives me the volume back but not the tiering-minimum-cooling-days.

 

Using the readonly_cl_user account gives me only the volume names for both scripts.

 

Is there documentation for what I can enter in the CLI for privileges? 

So I can play around with these privileges?

 

Somewhere under the hood must be the right parameter .....

 

security login role create -role readonly_cl -cmddirname volume -access all -vserver xxx  did not do the trick for me......

 

Thanks again, Moray

mbeattie
3,892 Views

Hi Moray,

Have you tried creating a read-only REST role? Is this just for one vserver or for all vservers? If you just want to target volumes on a single SVM then use: -query "-vserver <%svm%>" at the end of the first command below

security login role create -role volumeread -cmddirname "volume" -access readonly
vserver services web access create -name rest -role volumeread -vserver cluster1
security login create volumeread -application http -authentication-method password -role volumeread 

curl -X GET "https://<%cluster%>/api/storage/volumes?&fields=tiering.min_cooling_days" -H  "accept: application/json" -H  "authorization: Basic <%base64_encoded_credentials%>"

 /Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

MORAYHOONDERT
3,867 Views

PS H:\> $output.results

status cli-output cli-result-value
------ ---------- ----------------
passed 0

Public