Exception when creating a Databricks cluster via REST API - powershell

I can successfully create a Databricks cluster via REST API using the following in Postman:
POST /api/2.0/clusters/create HTTP/1.1
Host: adb-xxxxxxxxxxxxxxxx.xx.azuredatabricks.net
Authorization: Bearer eyJ <REMOVED> EJA
Content-Type: application/json
{
"cluster_name": "xxxxxxx-xxxxx-xx-x-xxx-##-xxxxxxx-####",
"spark_version": "5.5.x-scala2.11",
"node_type_id": "Standard_DS3_v2",
"autoscale" : {
"min_workers": 2,
"max_workers": 10
},
"autotermination_minutes": 30
}
When I convert the above for use with PowerShell's Invoke-RestMethod, I get a WebException. When running the script in the Windows PowerShell ISE (running as Administrator) the following results:
The remote server returned an error: (400) Bad Request.
at <ScriptBlock>, <No file>: line 91
System.Net.WebException: The remote server returned an error: (400) Bad Request.
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
The Azure AD token generated in PowerShell is the same token used successfully in Postman. This issue doesn't appear to be related to a bad token.
Here is the PowerShell that results in the exception:
<SCRIPT>
... API calls re: AAD Token omitted ...
Write-Host "Create Databricks Cluster"
$body = #{
cluster_name = "xxxxxxx-xxxxx-xx-x-xxx-##-xxxxxxx-####"
spark_version = "5.5.x-scala2.11"
node_type_id = "Standard_DS3_v2"
autoscale = #{
min_workers = 2
max_workers = 10
}
autotermination_minutes = 30
}
$headers = #{
"Authorization"="Bearer " + "$apiKey";
"Content-Type"="application/json";
}
$uri = "$uriroot/2.0/clusters/create"
Write-Host $uri
Write-Host $headers
try { $response = Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body }
catch {
Write-Host $_
Write-Host $_.ScriptStackTrace
Write-Host $_.Exception
Write-Host $_.ErrorDetails
}
Write-Host $response
</SCRIPT>
What is the PowerShell version missing but present in Postman?

Here's a solution I found. Use ConvertTo-Json on the $body variable passed to the -Body command-line argument.
try { $response = Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body (ConvertTo-Json $body) }

Related

Update sensitivity label to M365 Group with Graph API and PowerShell throws 401 error

UGH!
I'm struggling with 401 error when trying to update M365 groups sensitivity label information with Graph API and PowerShell. With Graph Explorer the beast works just fine, but with PowerShell I receive an error Invoke-RestMethod : The remote server returned an error: (401) Unauthorized. -message. Updating groups description and displayname programatically works without exceptions. Azure app registration is consented with application level grants: Group.ReadWrite.All and Directory.ReadWrite.All as mentioned in the MS documentation. Any ideas?
Code sample:
Connect-PnPOnline -Url $tenantBaseUrl -ClientId $clientId -Tenant $tenantId -Thumbprint $thumbPrint
$body=#"
{
"assignedLabels": [
{
"labelId": "$labelId"
}
]
}
"#
$AccessToken = (Get-PnPGraphAccessToken)
$headers = #{ Authorization=("Bearer " + $AccessToken)}
$uri = "https://graph.microsoft.com/beta/groups/$groupId"
$webRequest = Invoke-RestMethod –Uri $uri -Body $body –Method Patch -Headers $headers -ContentType "application/json"
Reference to MS-documentation:
https://learn.microsoft.com/en-us/graph/api/group-update?view=graph-rest-beta&tabs=http#example-2-apply-sensitivity-label-to-a-microsoft-365-group
It seems that app-only permission is not supported.
Setting of sensitivity labels is not available with app credentials
Token is valid. If I run the same command with same token, but only changing the body to update description and displayname it works.
$body2 = #"
{
"description": "M365 Group new desc",
"displayName": "M365 Group new displayname"
}
"#
$webRequest2 = Invoke-RestMethod –Uri $uri -Body $body2 –Method Patch -Headers $headers -ContentType "application/json"

Making a call to a Flask Restful API with invoke-restmethod and JWT auth

I have this API that I made with Flask (Python) and I am unable to get powershell to successfully make an API request to it. The problem is not the API because I tested it with postman and everything works as it should. More precisely it's when I add JWT token auth that it's not working with powershell, in my api the Create, Update and delete functions are protected with JWT token auth and the basic Read function have no auth at all. Below is the powershell code i am using:
Here is the function that generate my token (that part is working, note that I removed username and password from the function for security purposes):
function get-token {
param (
[Parameter(Position=0, Mandatory=$false)]
[string]$user,
[Parameter(Position=1, Mandatory=$false)]
[string]$password
)
$body = #{
username="$user"
password="$password"
}
$jsonbody = $body | ConvertTo-Json
$uri = "https://codegenius.live/api/auth"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Accept","application/json")
$headers.Add("Content-Type","application/json")
$response = Invoke-RestMethod -Uri $uri -Method Post -Body $jsonbody -Headers $headers
$response.access_token
}
This function will generate a token like this:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1ODIyMzA2OTUsImlhdCI6MTU4MjIzMDM5NSwibmJmIjoxNTgyMjMwMzk1LCJpZGVudGl0eSI6MX0.8wZZJEGxV7P4ZzN23eZ3d5-MGJ00N5zKHuCZXn9XRuw
Here is the call i am trying to make that doesn't work:
$body = #{
tpl_name="my template name"
tpl_subject="my template subject"
tpl_plaintext_content="bla bla bla"
tpl_html_content="bla bla bla"
}
$authheader = "JWT " + (get-token)
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Accept","application/json")
$headers.Add("Content-Type","application/json")
$headers.Add("Authorization",$authheader)
$jsonbody = $body | ConvertTo-Json
$uri = "https://codegenius.live/api/add-email"
$response = Invoke-RestMethod -Uri $uri -Method Post -Body $jsonbody -Headers $headers
The request response message is this one:
Invoke-RestMethod :
500 Internal Server Error
Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server
is overloaded or
there is an error in the application.
Au caractère Ligne:25 : 17
+ ... $response = Invoke-RestMethod -Uri $uri -Method Post -Body $jsonbody ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-
RestMethod], WebEx
ception
+ FullyQualifiedErrorId :
WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
This is very strange because as I said it is working with Postman (see below images), I have tried googling the issue but I found no clue on how to actually solve this.
EDIT: the images show that in postman i used http instead of https, this is not the issue. In powershell http or https nothing works!
Change your line to this,
$authheader = "JWT $(get-token)"

Powershell Neo4j connectivity Invoke-RestMethod

I am trying to connect to a Neo4j via Invoke-RestMethod (PowerShell versions 3,4,5).
Based on web recommendations, I am setting URI:
$Uri = "http://localhost:7474/db/data/cypher"
... followed by a call to invoke rest method (POST or GET, does not matter)
Invoke-RestMethod -Uri $Uri -Method Post -Body $Body -ContentType 'application/json'
Message I get is:
System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
I tried putting in http://userId/pwd#localhost:7474....
but the error is the same.
Is there another way to pass authentication information to Neo4j?
Disabling security is not an option.
Thank you!
--Alex
The authetication havs to bee the http standard authentication. You can do this in powershell for example with the following code.
$user = 'user'
$pass = 'pass'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = #{
Authorization = $basicAuthValue
}
Invoke-RestMethod -Uri $Uri -Method Post -Body $Body -ContentType 'application/json' -Headers $Headers
Background
The error code 401 says that the authentication is not correct on the server.
I found this information in the documentation.
https://neo4j.com/docs/developer-manual/3.4/http-api/authentication/

Powershell Invoke-RestMethod Internal Server Error

When I run this (parameters and body that worked from Postman):
$Url = "http://${IPADDR}:8080/api/v1/topology/query"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add('Access-Token', 'token')
$headers.Add('Content-Type', 'application/json')
$headers.Add('Accept', 'application/json')
$json =
'{
"includes":[{"ids":["264690t5te74hy4y"],"observationName":"page_life_expectancy"}],
"startTime":1528718400000,
"endTime":1528768800000,
"granularity":3600000,
"numberOfValue":1,
"retrievalType":"RAW"
}'
$response = Invoke-RestMethod -Method 'Post' -Uri $url -Headers $headers -Body $json
$ple = $response | select -ExpandProperty data | select max
in Powershell ISE, I get this:
An error occurred while calling REST method at: http://${IPADDR}:8080/api/v1/topology/query. Error: The remote server returned an
error: (500) Internal Server Error.. Response body: Apache Tomcat/7.0.82 - Error report
Any expert in Powershell, JSON, and REST API that can help me with this issue?
The content of the Body parameter of Invoke-RestMethod should be an object serialized in JSon. In your example, you have 3 levels of serialization.
You should remove 2 levels of serialization:
$jsonBody = '{
"includes":[{"ids":
["264690t5te74hy4y"],"observationName":"page_life_expectancy"}],
"startTime":1528718400000,
"endTime":1528768800000,
"granularity":3600000,
"numberOfValue":1,
"retrievalType":"RAW"
}'
$response = Invoke-RestMethod -Method 'Post' -Uri $url -Headers $headers -Body $jsonBody
But it's not guaranteed that the error 500 disappear.
You may have more details about the error with the Exception content. You can try that:
try {
$response = Invoke-RestMethod -Method 'Post' -Uri $url -Headers $headers -Body $jsonBody
}
catch {
$errorMessage = $_.Exception.Message
if (Get-Member -InputObject $_.Exception -Name 'Response') {
try {
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$responseBody = $reader.ReadToEnd();
} catch {
Throw "An error occurred while calling REST method at: $url. Error: $errorMessage. Cannot get more information."
}
}
Throw "An error occurred while calling REST method at: $url. Error: $errorMessage. Response body: $responseBody"
}
Error handling from post: How to get Powershell Invoke-Restmethod to return body of http 500 code response
From PowerShell since you serialize the content to JSON, specify -ContentType "application/json". Also, if you think the content might contain unicode strings, include the -ContentType "application/json; charset=utf-8".

PowerShell 403 HTTP Request With Parameters Containing Square Brackets

I'm trying to make a PATCH request using the following lines in PowerShell but it is returning a 403:
Try{
$Body = #{
'api_key' = 'myapikey'
'item[status]' = 'unavailable'
} | ConvertTo-Json
$response = Invoke-WebRequest -Method PATCH -Uri "https://api.example.com/store/apikey.json" -Body $Body -ContentType "application/json"
$response.StatusCode
}
Catch [System.Net.WebException]{
$code = [int]$_.Exception.Response.StatusCode
}
Fiddler is returning a 403 with the following message: "{"error":"Parameter item is required"}". Also, the query string in Fiddler is empty. However, a successful request is made when everything is hard-coded into the Uri:
$statusUpdate = Invoke-WebRequest -Method PATCH -Uri "https://api.example.com/store/apikey.json?api_key=myapikey&item[status]=unavailable" -ContentType "application/json"
If that's the code you're actually using to hit the API, your problem appears to simply be due to piping your json body to out-host, thus sending an empty $Body to the API, so you should edit it to do this:
try
{
$Body = #{
'api_key' = 'myapikey'
'item[status]' = 'unavailable'
} | ConvertTo-Json
$response = Invoke-WebRequest -Method PATCH -Uri "https://api.example.com/store/apikey.json" -Body $Body -ContentType "application/json"
$response.StatusCode
}
catch [System.Net.WebException]
{
$code = [int]$_.Exception.Response.StatusCode
}