InvalidOperation in PowerShell RestMethod API Call using Bearer sending Body as HASHTABLE - powershell

In PowerShell using Invoke-RestMetjhod to call different API´s I am stuck getting an InvalidOperation error when trying to pass both header and body information to the POST call.
My script is:
Set-StrictMode -Version Latest
$ApiToken = Get-Content ‘C:\APIEnergiNet\api_token.txt’
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer $ApiToken")
$response = Invoke-RestMethod 'https://api.eloverblik.dk/customerapi/api/token' -Method 'GET' -Headers $headers
$GetMetringPointID = Invoke-RestMethod 'https://api.eloverblik.dk/customerapi/api/meteringpoints/meteringpoints?includeAll=true' -Headers #{ Authorization = "Bearer " + $response.result }
foreach($result in $GetMetringPointID){
$CurrentMeteringID = $GetMetringPointID.result.meteringPointId
foreach($Currentresult in $CurrentMeteringID){
$MeterID = $Currentresult
$GetCharges = Invoke-RestMethod 'https://api.eloverblik.dk/customerapi/api/MeteringPoints/MeteringPoint/GetCharges' -Method 'POST' -Headers #{ Authorization = "Bearer " + $response.result } -Body #{ meteringPoints = #( #{meteringPoint = "$Currentresult" } ) }
$GetCharges
}
}
The API needs the following sent in the body :
{
"meteringPoints": {
"meteringPoint": [
"string"
]
}
}
if I create variable $postParams containing the data like this:
$postParams = #{
meteringPoints = #(
#{meteringPoint = "$MeterID" }
)
}
$postParams
it returns:
meteringPoints {System.Collections.Hashtable}
The API has a swagger here https://api.eloverblik.dk/customerapi/index.html
Can anyone help me why I get this error and how to fix it?
Best Regards
Stig :-)
UPDATE WITH LATEST CODE BELOW:
Set-StrictMode -Version Latest
$ApiToken = Get-Content ‘C:\APIEnergiNet\api_token.txt’
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer $ApiToken")
$response = Invoke-RestMethod 'https://api.eloverblik.dk/customerapi/api/token' -Method 'GET' -Headers $headers
$GetMetringPointID = Invoke-RestMethod 'https://api.eloverblik.dk/customerapi/api/meteringpoints/meteringpoints?includeAll=true' -Headers #{ Authorization = "Bearer " + $response.result }
foreach ($result in $GetMetringPointID)
{
$CurrentMeteringID = $GetMetringPointID.result.meteringPointId
foreach ($Currentresult in $CurrentMeteringID)
{
$MeterID = $Currentresult
$postParams = #{
meteringPoints = #(
#{ meteringPoint = "$MeterID" }
)
} | ConvertTo-Json
$resultlist = Invoke-RestMethod 'https://api.eloverblik.dk/customerapi/api/MeteringPoints/MeteringPoint/GetCharges' -Method 'POST' -ContentType 'application/json' -Headers #{ Authorization = "Bearer " + $response.result } -Body #{ $postParams }
$resultlist
}
}
ERROR I NOW GET:
ParserError: C:\APIEnergiNet\api.ps1:31:245
Line |
31 | … Authorization = "Bearer " + $response.result } -Body #{ $postParams }
| ~
| Missing '=' operator after key in hash literal.

I've made this little PS for you based on yours
$Path = "C:\EnergiNet\"
$TokenFile = $Path + "token.txt"
$JSON_ResponseFile = $Path + "Response.json"
$XML_ResponseFile = $Path + "Response.xml"
$ApiToken = Get-Content $TokenFile
# Get Auth token #
$response = Invoke-RestMethod 'https://api.eloverblik.dk/customerapi/api/token' -Method 'GET' -Headers #{ Authorization = "Bearer " + $ApiToken }
$Auth_Token = $response.result
$body = '{ "meteringPoints": {"meteringPoint": ["571313174xxxxxxxxxxx","571313174xxxxxxxxxxx","571313174xxxxxxxxxxx"] }}'
$headers = #{
'Authorization' = "Bearer " + $response.result
'Accept' = 'application/json'
}
Invoke-RestMethod 'https://api.eloverblik.dk/customerapi/api/meterdata/gettimeseries/2023-01-01/2023-02-01/Quarter' -Method 'POST' -ContentType 'application/json' -Headers $headers -Body $body | ConvertTo-Json -Depth 100 | out-file $JSON_ResponseFile
$headers = #{
'Authorization' = "Bearer " + $response.result
'Accept' = 'application/xml'
}
(Invoke-RestMethod 'https://api.eloverblik.dk/customerapi/api/meterdata/gettimeseries/2023-01-01/2023-02-01/Quarter' -Method 'POST' -ContentType 'application/json' -Headers $headers -Body $body).outerXml | out-file $XML_ResponseFile

Related

Pass JSON in powershell script

I want to tag a commit in azure devops git repo using the below POST call (in PowerShell script). API documentation here:
https://learn.microsoft.com/en-us/rest/api/azure/devops/git/annotated-tags/create?view=azure-devops-rest-6.0
{
"name": "v0.1-beta",
"taggedObject": {
"objectId": "c60be62ebf0e86b5aa01dbb98657b4b7e5905234"
},
"message": "First beta release"
}
So far I have written the below PowerShell script:
$Azuretoken = "xxxxxxxxxxxxxxxxxxxxxxxx"
$OrganizationName = "myorg"
$ProjectName = "myproj"
$AuthenicationHeader = #{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($Azuretoken)")) }
$uri_tag = "https://dev.azure.com/$($OrganizationName)/$($ProjectName)/_apis/git/repositories/b27ea2df-a72f-45gdf/annotatedtags?api-version=6.0-preview.1"
$body = #(
"name"= "v0.1-beta",
"taggedObject" #{
"objectId" = "2fa9486683e3d3003fd58dbb9345aae3cdd21013"
},
"message" = "First beta release"
)
$uri = Invoke-RestMethod -Uri $uri_tag -Method POST -ContentType "application/json" -Body $body -Headers $AuthenicationHeader
Getting errors due to the format of the JSON. Please help.
Looks like $body isn't formatted correctly. Check out about_Hash_Tables.
$Azuretoken = "xxxxxxxxxxxxxxxxxxxxxxxx"
$OrganizationName = "myorg"
$ProjectName = "myproj"
$AuthenicationHeader = #{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($Azuretoken)")) }
$uri_tag = "https://dev.azure.com/$($OrganizationName)/$($ProjectName)/_apis/git/repositories/b27ea2df-a72f-45gdf/annotatedtags?api-version=6.0-preview.1"
$body = #{
"name" = "v0.1-beta";
"taggedObject" = #{
"objectId" = "2fa9486683e3d3003fd58dbb9345aae3cdd21013"
};
"message" = "First beta release";
}
$uri = Invoke-RestMethod -Uri $uri_tag -Method POST -ContentType "application/json" -Body $body -Headers $AuthenicationHeader

How can I query multiple URL's with Google Safe Browsing API using Powershell?

The script below works fine to check a single URL, but what is the simplest way to check a list of URL's in one query? Turning $URL into an array doesn't work (only the first entry is checked).
$HEADERS = #{ 'Content-Type' = "application/json" }
$GOOGLE_API_KEY='[API Key]'
$Uri = 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key='+ $GOOGLE_API_KEY
$URL = 'http://www.sitetocheck.com'
$BODY = #()
$BODY +=[pscustomobject]#{"client" = #{"clientId" = "company"; "clientVersion" = "1.0"}; "threatInfo" = #{"threatTypes" = "MALWARE","SOCIAL_ENGINEERING","THREAT_TYPE_UNSPECIFIED","UNWANTED_SOFTWARE","POTENTIALLY_HARMFUL_APPLICATION"; "platformTypes" = "ANY_PLATFORM"; "threatEntryTypes" = "URL"; "threatEntries" = #{"url" = $URL}}}
$JSONBODY = $BODY | ConvertTo-Json
Invoke-RestMethod -Method 'POST' -Uri $Uri -Body $JSONBODY -Headers $HEADERS
If you look at your existing code, you'll find that the only thing deriving it's value from the target URL is the request body.
Prepare your URL values as an array, then take the code that creates the request body and calls Invoke-RestMethod, and put that inside a loop (or ForEach-Object):
$URLs = 'http://www.sitetocheck.com','http://www.othersitetocheck.com','http://somethingelse.com'
$HEADERS = #{ 'Content-Type' = "application/json" }
$GOOGLE_API_KEY='[API Key]'
$Uri = 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key='+ $GOOGLE_API_KEY
foreach($URL in $URLs) {
$BODY = #([pscustomobject]#{"client" = #{"clientId" = "company"; "clientVersion" = "1.0"}; "threatInfo" = #{"threatTypes" = "MALWARE","SOCIAL_ENGINEERING","THREAT_TYPE_UNSPECIFIED","UNWANTED_SOFTWARE","POTENTIALLY_HARMFUL_APPLICATION"; "platformTypes" = "ANY_PLATFORM"; "threatEntryTypes" = "URL"; "threatEntries" = #{"url" = $URL}}})
$JSONBODY = $BODY | ConvertTo-Json
Invoke-RestMethod -Method 'POST' -Uri $Uri -Body $JSONBODY -Headers $HEADERS
}

Azure DevOps how to edit Wiki page via REST API

I want to edit a Azure DevOps wiki page over the REST API (Azure DevOps Server 2019.0.1).
When I run this PowerShell script:
#VARIABLES
$api = "api-version=5.0"
$root = "http://136.202.18.216:8070/Samples"
$personalToken = "uwawlzqp6j7i1nd5dasspwkwp63tr2w2sxb5563zrla2bivynbza"
#AUTHORIZATION
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalToken)"))
$headers = #{
"Authorization" = ('Basic {0}' -f $token)
"If-Match" = '*'
}
#PROJECT VARIABLES
$project = "Framework%20A"
$pageToUpdate = "/Seite2"
#BODY
$body = #"
{
"content": "Hello"
}
"#
#GET
$url = "$root/$project/_apis/wiki/wikis/2e887fde-ce76-4180-aa8d-f26ed4799eb3/pages?version=wikiMaster&path=$pageToUpdate&includeContent=True&$api"
$content = Invoke-RestMethod -Uri $url -Method Get -ContentType "application/json" -Headers $headers
Write-Host "$($content.path) = $($content.content)" -ForegroundColor Yellow
#PUT
$url = "$root/$project/_apis/wiki/wikis/2e887fde-ce76-4180-aa8d-f26ed4799eb3/pages?version=wikiMaster&path=$pageToUpdate&$api"
$update = Invoke-RestMethod -Uri $url -Method Put -ContentType "application/json" -Headers $header -Body $body -Verbose
Write-Host $update.content -ForegroundColor Yellow
exit(0)
The consolen output is:
/Seite2 = Seite 2 Content
AUSFÜHRLICH: PUT http://136.202.18.216:8070/Samples/Framework A/_apis/wiki/wikis/2e887fde-ce76-4180-aa8d-f26ed4799eb3/pages?version=wikiMaster&path=/Seite2&api-version=5.0 with -1-byte payload
Invoke-RestMethod: {"$ id": "1", "innerException": null, "message": "The required \" IfMatch \ "header specified in the request is an invalid page version Version of the
Wiki page as \ "IfMatch \" header for the request. \ R \ nParameterName: IfMatch "," typeName ":" Microsoft.TeamFoundation.SourceControl.WebServer.InvalidArgumentValueException,
Microsoft.TeamFoundation.SourceControl.WebServer "," TypeKey ":" InvalidArgumentValueException "," error code ": 0," eventId ": 0}
In C:\Users\mkober\Desktop\Azure DevOps Skripte (Bearbeitung)\WikiAPI.ps1:34 Zeichen:11
+ $update = Invoke-RestMethod -Uri $url -Method Put -ContentType "appli ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
The first line /Seite2 = Seite 2 Content is the result of a successful get request from the page I want to edit. The put request occures the error. What am I doing wrong here?
UPDATE: (Working Example)
#VARIABLES
$api = "api-version=5.0"
$root = "http://136.202.18.216:8070/Samples"
$personalToken = "uwawlzqp6j7i1nd5dasspwkwp63tr2w2sxb5563zrla2bivynbza"
#AUTHORIZATION
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalToken)"))
$headers = #{
"Authorization" = ('Basic {0}' -f $token)
"If-Match" = '{0}'
}
#PROJECT VARIABLES
$project = "Framework%20A"
$pageToUpdate = "/Seite2"
#BODY
$body = #"
{
"content": "Hello"
}
"#
#---------------------------------------------------------------------------------------------------------------------------
#GET
$url = "$root/$project/_apis/wiki/wikis/2e887fde-ce76-4180-aa8d-f26ed4799eb3/pages?version=wikiMaster&path=$pageToUpdate&includeContent=True&$api"
$content = Invoke-WebRequest -Uri $url -Method Get -ContentType "application/json" -Headers $headers
$etag = $content.Headers.ETag
$headers.'If-Match' = $headers.'If-Match' -f $etag
Write-Host "$($content.path) = $($content.content)" -ForegroundColor Yellow
#PUT
$url = "$root/$project/_apis/wiki/wikis/2e887fde-ce76-4180-aa8d-f26ed4799eb3/pages?version=wikiMaster&path=$pageToUpdate&$api"
$update = Invoke-RestMethod -Uri $url -Method Put -ContentType "application/json" -Headers $headers -Body $body -Verbose
Write-Host $update.content -ForegroundColor Yellow
exit(0)
#---------------------------------------------------------------------------------------------------------------------------
In the If-Match header you can't just put '*', you need to put there the ETag of the page.
How do you get it? in your first GET call use Invoke-WebRequest (instaed of Invoke-RestMethod), now in the response you will get also headers response and there the ETag exist:
$page = Invoke-WebRequest -Uri $url ...........
$etag = $page.Headers.ETag
$headers = #{
"Authorizaion = ....."
"If-Match" = $etag
}
Now the second Invoke-RestMethod will work to update the page.

how to translate curl command in powershell

I've this command:
curl -s -L --header "PRIVATE-TOKEN:XXXX" https://myuri/"
And I need to convert to PowerShell
I've tried this, but doesn't works:
Invoke-RestMethod -Method Get -Headers #{"AUTHORIZATION"="XXXXXX"} -Uri https://myUri
I've also tried this:
PS > $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
PS > $headers.Add("Authorization","XXXXXX")
PS > $headers.Add("Accept","application/json")
PS > $headers.Add("Content-Type","application/json")
PS> $uri = "https://myUri"
PS> $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get -ContentType "application/json"
PS> $response
PS>
but the $response is empty.
Any help ?
Here is one that I used to authenticate to Teamcity
function Connect-to-Teamcity ($userName, $password, $tcServer, $uri)
{
$auth = $username + ':' + $password
$Encoded = [System.Text.Encoding]::UTF8.GetBytes($auth)
$EncodedPassword = [System.Convert]::ToBase64String($Encoded)
$headers = #{"Authorization"="Basic $($EncodedPassword)"}
$url = "http://$tcServer/httpAuth/app/rest"
$result = Invoke-RestMethod -Uri "$url/$uri" -Header $headers -Method Get
return $result
}
Here is another example if you have more than one header Item:
$resourceAppIdURI = "https://graph.windows.net"
# Login to Azure and get a token valid for accessing the graph API
$authority = "https://login.windows.net/$adTenant"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId, $redirectUri, "Auto")
# Add the token to the header of all future calls to the graph API
$headers = #{"Authorization"=$authResult.CreateAuthorizationHeader();"Content-Type"="application/json"}
$uri = [string]::Format("https://graph.windows.net/{0}/groups/{1}/appRoleAssignments?api-version=1.5", $adTenant, $groupId)
$body = #"
{
"id": $appRoleId,
"principalId": $groupId,
"principalType": "Group",
"resourceId": $appObjectId
}
"#
$result = Invoke-RestMethod -Method "POST" -Uri $uri -Headers $headers -Body $Body

Getting Unauthorised error while triggering TFS build from release definition

I need to trigger a build after successful deployment of a release. I have tried using below code in Powershell in the release definition.
After executing, I get this error - Access is denied due to invalid credentials
$url = "http://abc:8080/tfs/GlobalCollection/Project/_apis/build/builds?
api-version=2.0"
$body = "{ 'definition' : { 'id' : 1} }"
$type = "application/json"
$headers = #{
Authorization = "Basic d3JlblxzcsampleTIzNA=="
}
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Body $body -ContentType $type -
Method Post -Headers $headers
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 1000)"`
Based on my test, you can use -UseDefaultCredentials :
$type = "application/json"
$url = "http://abc:8080/tfs/GlobalCollection/Project/_apis/build/builds?api-version=2.0"
$body = "{ 'definition' : { 'id' : 56} }"
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Body $body -ContentType $type -Method Post -UseDefaultCredentials
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 1000)"
Alternatively provide the specific Credential:
$user = "username"
$password = "password"
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$password)))
$headers = #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$type = "application/json"
$url = "http://abc:8080/tfs/GlobalCollection/Project/_apis/build/builds?api-version=2.0"
$body = "{ 'definition' : { 'id' : 56} }"
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Body $body -ContentType $type -Method Post -Headers $headers
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 1000)"