How to store 1 output from one script to another? - powershell

Suppose I have script1.ps1 with the following code:
Function Renew_Token($token) {
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("X-Vault-Token", $token)
$response = Invoke-RestMethod -method POST -uri "https://vault.com:8243/v1/auth/token/renew-self" -ContentType 'application/json' -headers $headers
$response| ConvertTo-Json -depth 100
}
Function getValues($token) {
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("X-Vault-Token", $token)
$response = Invoke-RestMethod -method GET -uri "https://vault.com:8243/v1/secret/vault/development" -ContentType 'application/json' -headers $headers
$response.data| ConvertTo-Json -depth 100
}
Renew_Token $token
write-host "token renewed!"
write-host "Vault Values:"
getValues $token
This gives me back a response like this:
{
"request_id": "ghgdf5-yuhgt886-gfd76trfd",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": null,
"wrap_info": null,
"warnings": null,
"auth": {
"client_token": "i657ih4rbg68934576y",
"accessor": "t543qyt54y64y654y",
"policies": [
"default",
"vault"
],
"token_policies": [
"default",
"vault"
],
"metadata": null,
"lease_duration": 2000,
"renewable": true,
"entity_id": ""
}
}
token renewed!
Vault Values:
{
"abc": "1234",
"def": "897",
"klm": "something12"
}
Now consider in a Script2.ps1, I call script1
$second_response = & ".\Script1.ps1"
of course, $second_response will store the 2 responses above as output.
How can i store JUST the second response as keys/values say in a table in Script2? i.e. this part:
{
"abc": "1234",
"def": "897",
"klm": "something12"
}
$HashTable = #{ }
$HashTable.Add($second_response.key, $second_response.value)
in other words, somehow the $second_response variable should only store this output:
{
"abc": "1234",
"def": "897",
"klm": "something12"
}
Note: that second response is considerably dynamic. meaning there could be different values on different environments. therefore, i want to be able to DYNAMICALLY store whatever is in this response, not hardcode the values
Also, I need the 2 responses in script 1 because i use script1 for other purposes, such as say i want to only view the vault content. script2 will have operations on the response from script1, so i have them separated for this convenience and flexibility
UPDATE: Following #kuzimoto suggestion, i removed the output and converting the response back from JSON, i get this output from Script2:
abc: 1234
def: 897
klm: something12

I can't comment yet, but here's a couple possibilities:
Edit script1.ps1
You don't mention if you need the first set of results. If you don't, just simply delete or comment out this line $response| ConvertTo-Json -depth 100 from the Renew_Token function.
Parse the output of script1.ps1 as json
You're passing the output of script1 to script2 as plain text. Simply change $second_response = & ".\Script1.ps1" to $second_response = & ".\Script1.ps1" | ConvertFrom-Json. Then when you want to access the second response, use $second_response[1] as both sets of JSON get added to a custom PS Object and can be accessed individually like you would an array.

Related

Looping through PSObject from JSON response

I am running Invoke-RestMethod to get a response from an API. That response is in JSON format and I am trying to figure out how to get access to the individual properties in my Powershell code.
Given these two lines:
$response = Invoke-RestMethod -Uri $paymentJournalUri -Method 'GET' -Headers $headers | ConvertTo-Json
Write-Host $response
my output looks like this:
{
"#odata.context": "https://api....yments",
"value": [
{
"#odata.etag": "W/\"JzI....Dsn\"",
"id": "b86ac....8fab",
"journalId": "59....b3ca",
"journalDisplayName": "EFT",
"lineNumber": 30000,
"vendorId": "a4c...552",
...
So how can I loop over the 'value' array and get access to each of those properties?
I have tried something like this:
$PSObj = $response | ConvertTo-Json
#Write-Host $PSObj
$PSObj.value | ForEach-Object {
Write-Host $_.journalDisplayName
}

Why can't I pass this Json string into an Invoke-RestMethod in Powershell?

I'm trying to make a PUT request to an API. I am passing a Json string into the -Body of the request.
$StudentId = 1234
$Body = { "name": "John Doe", "active": "no", "id": [$StudentId], "filters": [{"field":"major", "comparator":"==", "value":"cs"}, {"field":"minor", "comparator":"==", "value":"math"}]}
I then input $Body into an Invoke-RestMethod:
$response = Invoke-RestMethod -Uri $Url -Method Put -Body $Body -ContentType "application/json" -Headers #{'Authorization' = '**********'; 'environment' = '*******'; 'token' = $Token}
When I run this in Powershell, I am getting many errors like these (can't paste exact code because its on a separate computer):
Unexpected token ':' in expression or statement, Missing argument in parameter list, ParseError (:) [], ParentContainsErrorRecordException
I am fairly new to Powershell and have not had any luck figuring out why it is having problems taking this Json as the -Body of the request. What am I doing wrong with this Json?
Thanks for any help!
The $body you declare is not a string.
The easiest is to declare it inside a Here-String:
$StudentId = 1234
$Body = #"
{ "name": "John Doe", "active": "no", "id": "$StudentId", "filters": [{"field":"major", "comparator":"==", "value":"cs"}, {"field":"minor", "comparator":"==", "value":"math"}]}
"#
and feed that to the Invoke-RestMethod call
P.S. if the StudentID is always numeric, you can leave out the quotes around it ("id": $StudentId)
If you have the input values as PSObjects, just use ConvertTo-Json like in the example below:
$StudentId = 1234
$Body = [PsCustomObject]#{
"name" = "John Doe"
"active" = "no"
"id" = "$StudentId" # surround with quotes if this is meant to be a string
"filters" = [PsCustomObject]#{"field" = "major"; "comparator" = "=="; "value" = "cs"},
[PsCustomObject]#{"field" = "minor"; "comparator" = "=="; "value" = "math"}
} | ConvertTo-Json

Powershell Invoke-RestMethod POST has issues with json

I am trying to use a REST API to configure some alerts in RecoverPoint for Virtual Machines (RP4VM). I am trying to enter multiple filters at the same using json. The json file looks like this:
[
{
"JsonSubType": "SystemEventLogsFilter",
"level": "WARNING",
"scope": "NORMAL",
"eventsIDs": [],
"filterUID": {
"id": 1570417688566256135
},
"name": "RPA_issue",
"topic": "RPA",
"groupsToInclude": null
},
{
"JsonSubType": "SystemEventLogsFilter",
"level": "WARNING",
"scope": "ADVANCED",
"eventsIDs": [],
"filterUID": {
"id": -1728986321682574312
},
"name": "cluster_events",
"topic": "CLUSTER",
"groupsToInclude": null
}
]
When I try to run the script I get an error:
Unexpected token (START_ARRAY), expected START_OBJECT: need JSON Object to contain As.PROPERTY type information (for class com.emc.fapi.version5_2.commons.SystemEventLogsFilter)
at [Source: org.apache.catalina.connector.CoyoteInputStream#75b592c2; line: 1, column: 1]
If I remove the square brackets it does the first value but not the second. Is this an issue with my code or an issue with theirs?
The script:
$rp4vmcl = import-csv -Path .\test_clusters.csv
$credential = Get-Credential
$username = $credential.GetNetworkCredential().UserName
$password = $credential.GetNetworkCredential().password
$credPair = "$($username):$($password)"
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))
$headers = #{
Authorization = "Basic $encodedCredentials";
"Accept" = "application/json";
"Content-Type" = "application/json"
}
$comp = "/system/event_logs_filters"
$json = Get-Content .\event_log_filter.json -Raw
foreach ($s in $rp4vmcl) {
$cluster = $s.cluster_name
$uid = $s.cluster_uid
$curl = $s.cluster_url
$url = "$curl$comp"
$cluster
$results = Invoke-RestMethod -Method POST -uri $url -SkipCertificateCheck -Headers $headers -Body $json
}
If the recipient expect one Call per Json Object it will not be able to handle arrays. It's totally dependant from the implementation of the webservice. Btw, better change the body:
$results = Invoke-RestMethod -Method POST -uri $url -SkipCertificateCheck -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($json))
Try this first, and if this is doesnt help, loop through the elemnts and call the webservice individual:
$jsonObject = $json | ConvertFrom-Json
$results = #()
$jsonObject | foreach {
$json = $_ | ConvertTo-Json -Depth 99
$results += Invoke-RestMethod -Method POST -uri $url -SkipCertificateCheck -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($json))
}
Btw, the invoke-restmethod is buggy in powershell < 6 Version, so if youre will with the standard V5 Windows Version, check the response headers via invoke-webservice, and if the response header is:
"application/json"
and not
"application/json; charset=utf-8"
powershell will misinterpret this as a windows encoding. So if youree experiencing encoding issues, you have four options:
1.) if you can modify the webservice, change the response header
2.) switch to a newer powershell version (v7 is recommended)
3.) build your own webservice call directly via the .net cmdlets
4.) use the invoke-webservice, write the answer directly into a file with the OutFile Paramater
see also:
Powershell Invoke-RestMethod incorrect character

Invoke-RestMethod convert hashtable to json array

I'm trying to send a request to an API that requires the body to be a json array. How can I convert the parameters hash table into a json array?
$parameters =#{
"sn" = "CND3210W9M"
"pn" = "D5H49AV"
}
$post = Invoke-RestMethod -Uri "https://blah.com/queries" -Method Post -Body ($parameters | ConvertTo-Json) -Headers $headers -ContentType 'application/json'
The API example shows the array below as a valid body
[
{
"sn": "CND3210W9M",
"pn": "D5H49AV"
}
]
If your request is expecting valid json, it might look something like this:
$body = #{
parameters =
#( # Make this an array
#{ # of hashtables
"sn" = "CND3210W9M"
"pn" = "D5H49AV"
} ) }
$body | ConvertTo-Json
Output:
{
"parameters": [
{
"pn": "D5H49AV",
"sn": "CND3210W9M"
}
]
}
#Eris, I tried using your code but it returned an extra {} which the API didn't like.
In the end I ended up just using a here string and moving on. It's not very elegant but couldn't get the API to respond properly otherwise.
$body = #"
[
{
"sn": "$sn",
"pn": "$pn"
}
]
"#

Post JSON data into another domain - Rest API

I am trying to POST a data to receive an input using powershell but it's throwing error.
Url: https://www.example.com/api/login
JSON data = {"username": "emailid", "password": "password"}
Once the post is successful, i will receive an output in JSON format something like:
{"account": "some-guid", "Token": "xxx", "selflink": "https://www.example.com/api/me", "username": "emailid"}
When I am posting the JSON data, I'm getting syntax error.
I'm using the below code to invoke
$url = "https://somedomain.com/api/login"
$params = #{"username"="abcd#pqr.com";
"password"="123456";
}
$response = Invoke-WebRequest -Uri $url -Method POST -Body $params -ContentType "application/json"
I changed the $param to | ConvertTo-Json
$JSON = #{
"username" = "abcd#xyz.com"
"password" = "123456"
} | ConvertTo-Json
and it worked fine.