ONTAP Discussions
ONTAP Discussions
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
Solved! See The Solution
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
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
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
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
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
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
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
PS H:\> $output.results
status cli-output cli-result-value
------ ---------- ----------------
passed 0