FreshAgent Get Asset Data - powershell

I am trying to fetch asset data from the Fresh client with Powershell. I am able to get any asset by typing it's name but I want to save some of the variables it returns so I can use it further.
$naam = Read-Host "Voer product naam in"
# Set global variables
$APIKey = 'Myapikey'
$EncodedCredentials = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $APIKey,$null)))
$HTTPHeaders = #{ "X-ApiKey" = $APIKey}
$HTTPHeaders.Add('Authorization', ("Basic {0}" -f $EncodedCredentials))
$HTTPHeaders.Add('Content-Type', 'application/json')
$URL = 'https://helpdesk.company.nl/cmdb/items/list.json?field=name&q='+$naam
(Invoke-WebRequest -Method Get -Uri $URL -Headers $HTTPHeaders ).content
The following are some of the values that return after I run the above
{"config_items":[{"id":25000477949,"name":"SYS-MB1334","description":null,"ci_type_id":25000015988,"impact":1,"created_at":"2020-03-12T10:14:40+01:00","updated_at":"2020-04-24T16:42:42+02:00"
I would like to save the name and id variable for example

Unfortunately, the JSON you show is invalid.
Suppose the json returned from
$output = (Invoke-WebRequest -Method Get -Uri $URL -Headers $HTTPHeaders ).Content
looks like:
{"config_items":
[{"id":25000477949,"name":"SYS-MB1334","description":null,"ci_type_id":25000015988,"impact":1,"created_at":"2020-03-12T10:14:40+01:00","updated_at":"2020-04-24T16:42:42+02:00"},
{"id":12345678901,"name":"SYS-MB9876","description":null,"ci_type_id":12358745896,"impact":1,"created_at":"2020-03-12T10:14:40+01:00","updated_at":"2020-04-24T16:42:42+02:00"}]
}
Then you can collect the properties you need from the config_items using:
$result = ($output | ConvertFrom-Json).config_items |
Select-Object #{Name = 'Id'; Expression = {$_.id}},
#{Name = 'Name'; Expression = {$_.name}}
# output on screen
$result
# output to CSV file
$result | Export-Csv -Path 'X:\TheOutput.csv' -NoTypeInformation
Output on screen would look like
Id Name
-- ----
25000477949 SYS-MB1334
12345678901 SYS-MB9876
Hope that helps

Related

How to modify data in a format-table result?

Trying to make a powershell script that tracks link clicks.
I have three goals:
change destination to name
Filter out destinations that are not a file type
Only display name of file, not the URL or extension
# Set the API key and endpoint
$apiKey = "API-KEY"
$endpoint = "https://api.rebrandly.com/v1/links?&limit=100"
# Make the API call and store the response
$response = Invoke-RestMethod -Method GET -Uri $endpoint -Headers #{ "apikey" = $apiKey } | Format-Table -Property clicks, destination
$response
clicks destination
------ -----------
11 https://github.com/file1.ps1
4 https://github.com/file2.ps1
2 https://github.com/main.zip
1 https://www.instagram.com
Desired Result
clicks destination
------ -----------
11 file1
4 file2
2 main
Format-Table doesn't perform collection filtering hence is not the right cmdlet for this use case. Also, for 2 property objects, it is not needed at all since default formatting output will be a table by default for objects with 4 properties or less.
Invoke-RestMethod -Method GET -Uri $endpoint -Headers #{ "apikey" = $apiKey } | ForEach-Object {
$lastSegment = ($_.destination -as [uri]).Segments | Select-Object -Last 1
if([System.IO.Path]::GetExtension($lastSegment)) {
[pscustomobject]#{
Clicks = $_.Clicks
Name = [System.IO.Path]::GetFileNameWithoutExtension($lastSegment)
}
}
}
This is a modification of Santiagos answer.
I couldn't quite get his to work.
I'm sure this can be optimized however.
$apiKey = "API-KEY"
$endpoint = "https://api.rebrandly.com/v1/links?&limit=100"
$r = Invoke-RestMethod -Method GET -Uri $endpoint -Headers #{ "apikey" = $apiKey }
ForEach($l in $r){$s = ($l.destination -as [uri]).Segments[-1]
if([System.IO.Path]::GetExtension($s)) {
[pscustomobject]#{
Clicks = $l.Clicks
Name = [System.IO.Path]::GetFileNameWithoutExtension($s)
}
}
}

while using arraylist how to display objects in powershell

$result = New-Object System.Collections.ArrayList
ForEach ($repoElement in $Repo.value)
{
$repoId = $repoElement.id
$BranchCreatorUrl = "https://dev.azure.com/xyz/_apis/git/repositories/$repoId/refs?api-version=6.1-preview.1"
$CreateorInfo = (Invoke-RestMethod -Uri $BranchCreatorUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$url1= "https://dev.azure.com/xyz/_apis/policy/configurations?api-version=4.1"
$response = (Invoke-RestMethod -Uri $url1 -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$obj=[pscustomobject]#{
RepositoryName = $repoElement.name
RepositoryId = $repoId
BranchName = $CreateorInfo.value.name
PolicyName = $response.value.type.displayname
}
$result += $obj
}
Write-Output $result
The above code gives an output
I want to show all the branch name as string and not in the form of object ie this way {..,...,...,..}
If this is just about for-display formatting, i.e. what is shown in the implicitly table-formatted display output, you can call Format-Table explicitly and use a calculated column to apply custom formatting to the BranchName column:
# Sample result.
$result = [pscustomobject]#{
RepositoryName = 'name'
RepositoryId = 'id'
BranchName = 'branch1', 'branch2', 'branch3'
PolicyName = 'policy'
}
# Use explicit Format-Table formatting with custom formatting of the
# 'BranchName' column.
$result | Format-Table RepositoryName,
RepositoryId,
#{ n='BranchName'; e={ $_.BranchName -join ', ' } },
PolicyName
The above yields a tabular display whose BranchName column doesn't have the enclosing { ... }, which PowerShell uses to indicate that the column value is an array (perhaps confusingly, because it looks like a script block):
RepositoryName RepositoryId BranchName PolicyName
-------------- ------------ ---------- ----------
name id branch1, branch2, branch3 policy

Iterating through Invoke-WebRequest JSON result

I am trying to iterate the result of a webrequest call through powershell
$response = Invoke-WebRequest -URI $apiUri -Method Get -UseBasicParsing
$response
Result:
StatusCode : 200
StatusDescription : OK
Content : {"tenants":[{"name":"default","active":true},{"name":"tenant1","active":true}]}
RawContent : HTTP/1.1 200 OK
...
Using ConvertFromJson
$parsed = $response.Content | ConvertFrom-Json
$parsed
Result:
tenants : {#{name=default; active=True}, #{name=tenant1; active=True}}
Now, I want to list all the "name" value like this
Name
--------
default
tenant1
I've tried iterating it using this script but can't get the result:
$parsed | Select-Object -Property name | ForEach-Object {
Write-Host $_.name
}
The code below will output a table of names:
$json = '{"tenants":[{"name":"default","active":true},{"name":"tenant1","active":true}]}'
$data = $json | ConvertFrom-Json
$data.tenants | ft name
#name
#----
#default
#tenant1
If you want to capture them into a variable as an array you can use a feature called Member Enumeration:
$names = $data.tenants.name;
$names
#default
#tenant1

Get-content not producing an array that Invoke-restmethod can process

As a follow-up to this question, instead of using a long array in the script I wanted to draw from a text file. So I replaced this:
$URLs = 'http://websiteone.com','http://websitetwo.com','http://websitethree.com'
with this
$URLs = Get-Content ./urlfile.txt
or (functionally the same as far I know) this
$URLs = #(Get-Content ./urlfile.txt)
But I end up with Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
Incorporating the great response form my last question, my foreach loop looks like this:
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","EXECUTABLE","THREAT_ENTRY_TYPE_UNSPECIFIED"; "threatEntries" = #{"url" = $URL}}})
$JSONBODY = $BODY | ConvertTo-Json
$Result = Invoke-RestMethod -Method 'POST' -Uri $Uri -Body $JSONBODY -Headers $HEADERS
if ( ([string]::IsNullOrEmpty($Result)) ) {} else {write-host $URL "ALERT: Safe browsing match!"}
}
... but this doesn't work if I create the array with the Get-Content cmdlet. If I run the script either way, then type $URLs, I get the exact same data returned. What am I doing wrong with get-content?
The Invoke-RestMethod cmdlet is there to make one Rest request at a time and can't take an array.
You will need to add a forEach loop to step through your $urls one at a time, something like this:
foreach($url in $urls){
$result = Invoke-RestMethod -Uri $url
#do something with $result
}
So to integrate into your sample from the previous question, you should have a urls.txt file which looks like this:
http://google.com
http://small.com
https://fast.com/
And then your code would look like this:
$URLs = get-content .\urls.txt
$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
$result = Invoke-RestMethod -Method 'POST' -Uri $Uri -Body $JSONBODY -Headers $HEADERS
[pscustomObject]#{SiteName=$url;ThreatInfo=$result.Matches}
}
This would load up the list of $urls from your text file, then run a Rest Request on each, storing the result in $result. Finally, it will make a new PowerShell Object with the site name and show you if there are any matches from the Google SafeBrowsing API.
You'll need to run the command interactively and see which properties from $result are meaningful to you, but you can see all of the expected properties in the Google API Docs.
Edit
Found the bug. It turns out when we use Get-Content the object returned back retains some of the document formatting information from the original file! We can see this by inspecting $JSONBODY. We also see that the conversion to Json from [PSCustomObject is leaving a lot of cruft behind too.
To fix this, we should cast $URL into a string using the ToString() method and also ditch casting to [psCustomObject] too as shown below.
$BODY = #{
"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.ToString()
}
}
}
$JSONBODY = $BODY | ConvertTo-Json

VSTS - Test -> Runs -> Query endpoint is not filtering based on parameters

I'm attempting to use the Test -> Runs -> Query endpoint to return a list of test runs for a particular release, as detailed here
Unfortunately whatever I put in as a query parameter (with the exception of $top which does appear to filter), I appear to get every test run returned against the project.
For example, I know there are 14 test runs against a particular release.
I can get my release id with the following query...
https://smartassessor.vsrm.visualstudio.com/Smart End Point Assessment/_apis/release/releases?searchText=Release-103
If I then try to use that id in the test run query like this...
https://smartassessor.visualstudio.com/Smart End Point Assessment/_apis/test/runs?releaseIds=1678&api-version=5.0-preview.2
I get 529 results, which looks like most of the test runs agains the project.
Are the filters working against this endpoint? If so, how should I tweak my request to utilize the releaseIds parameter.
Thanks
I can reproduce this issue. Seems the APIs are not available for now.
There is an issue submitted here for tracking this. You can also track the updates on it.
As a workaround, you can use below PowerShell script to filter the test runs by Release ID: (Alternately you can export the result to a *.CSV file)
Param(
[string]$collectionurl = "https://{account}.visualstudio.com",
[string]$project = "ProjectName",
[string]$releaseid = "1",
[string]$user = "username",
[string]$token = "password"
)
#Set the path and name for the output csv file
$path = "D:\temp"
$filename = "ReleaseTestRun" + "-" + $releaseid
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$baseUrl = "$collectionurl/$project/_apis/test/runs"
$response = Invoke-RestMethod -Uri $baseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$testruns = $response.value
Write-Host $results
$Releaseruns = #()
foreach ($testrun in $testruns)
{
$testrunID = $testrun.id
$runbaseUrl = "$collectionurl/$project/_apis/test/runs/$testrunID"
$runresponse = Invoke-RestMethod -Uri $runbaseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} | Where {$_.release.id -eq $releaseid} #| Filter the test run by Release ID
$customObject = new-object PSObject -property #{
"id" = $runresponse.id
"name" = $runresponse.name
"url" = $runresponse.url
"isAutomated" = $runresponse.isAutomated
"state" = $runresponse.state
"totalTests" = $runresponse.totalTests
"incompleteTests" = $runresponse.incompleteTests
"notApplicableTests" = $runresponse.notApplicableTests
"passedTests" = $runresponse.passedTests
"unanalyzedTests" = $runresponse.unanalyzedTests
"revision" = $runresponse.revision
"webAccessUrl" = $runresponse.webAccessUrl
}
$Releaseruns += $customObject
}
$Releaseruns | Select `
id,
name,
url,
isAutomated,
state,
totalTests,
incompleteTests,
notApplicableTests,
passedTests,
unanalyzedTests,
revision,
webAccessUrl | where {$_.id -ne $Null} #|export-csv -Path $path\$filename.csv -NoTypeInformation # Filter non-empty values and export to csv file.