Need to get a value in single quotes in the body section while calling a restapi through powershell - azure

I'm using below script to call a RestAPi using powershell:
$cd = 12000
$Url = 'https://exampleSet/Set'
$Body = #{
OperationType = 'new'
Number = "'$($cd)'"
CdAspId = 'Z_CK_BUGFIX'
CdType = 'CA_106_4'
} | ConvertTo-Json
$headers = #{
'ContentType' = 'application/json'
'Accept' = 'application/json'
'APIKey' = 'abcdef'
}
Invoke-RestMethod -contentType "application/json" -Uri $url -Method Post -body $Body -Headers $headers
While execution, powershell task in Azure is showing me internal server error.
I need help in passing the value in the body as:
Number = '12000'
How can I get the values in body in single quotes. Please help in this.

As mentioned in the comments, JSON exclusively uses double-quoted string literals, so trying to create a JSON document with a property entry Number = '12000' doesn't make any sense - it wouldn't be valid JSON.
To force string encoding rather than a numerical value, simply surround the value with double-quotes in PowerShell:
$Body = #{
OperationType = 'new'
Number = "$cd"
CdAspId = 'Z_CK_BUGFIX'
CdType = 'CA_106_4'
} | ConvertTo-Json

Related

Azure devops REST API | Build Number extract to txt file

I am trying to extract a build number via POWERSHELL to a TXT FILE, I have the GET request and the URI is arranged.
I have a format with PAT TOKEN, but I can't do it, how do I do OutFile to a TXT file?
# Build Auth header
$MyPat = "XXXX"
$B64Pat = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$MyPat"))
$h = #{'Authorization' = 'Basic ' + $B64Pat}
$BuildNumberInfo = Invoke-WebRequest -Uri "https://dev.azure.com/$($Company)/$($Project)/_apis/build/builds/$($BuildID)?api-version=6.0-preview.6" -Method 'GET'
Use Invoke-RestMethod instead of Invoke-WebRequest:
# Build Auth header
$MyPat = "XXX"
$B64Pat = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$MyPat"))
$h = #{'Authorization' = 'Basic ' + $B64Pat}
$BuildNumberInfo = Invoke-RestMethod -Uri "https://dev.azure.com/$($Company)/$($Project)/_apis/build/builds/$($BuildID)?api-version=6.0-preview.6" -Method 'GET' -Headers $h
$BuildNumberInfo.buildNumber | Out-File buildnumber.txt

Invoke-Restmethod powershell in Azure Devops - strange powershell errors

I am using this invoke-restmethod so I can get a token so I can do some sql work. the variables come from Azure Key Vault. I have tried to write the variables as
$($SPNAppid)
$SPNAppid
${$SPNAppid} etc
Here is the code :
$request = Invoke-RestMethod -Method POST -Uri
"https://login.microsoftonline.com/${$TenantId}"/oauth2/token" -Body
#{ resource="https://database.windows.net/";
grant_type="client_credentials"; client_id=${$SPNAppid};
client_secret=${$SPNValue} } -ContentType
"application/x-www-form-urlencoded"
Getting this error below. What is the best way to do this - whatever i do i am getting the errors below.
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to
delimit the name.
At C:\agent01_2\_work\_temp\b3f54d23-b7b6-4cc3-96ec-8b4b534be571.ps1:20 char:319
+ ... ervicePrincipalKey } -ContentType "application/x-www-form-urlencoded"
+ ~
The string is missing the terminator: ".
The code you posted, has an extra " and given the ambiguity of the long line I would suggest to use splatting like this :
$header = #{
"Content-type" = "application/x-www-form-urlencoded"
"Authorization" = "Bearer $token"
}
$body = #{
resource = "https://database.windows.net/"
grant_type = "client_credentials"
client_id = $SPNAppid
client_secret = $SPNValue
}
$params = #{
Method = 'Post'
Uri = "https://login.microsoftonline.com/$($TenantId)/oauth2/token"
Body = $body
ContentType = $header
}
$request = Invoke-RestMethod #params
I do not think the API call would work this way, usually clientId etc. are part of the URL, you can read more about it here - https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow

Using $filter through Microsoft graph API request

I'm trying to use MS graph API via a small Powershell script as described here https://learn.microsoft.com/en-us/graph/api/riskyusers-list?view=graph-rest-beta&tabs=http
this filter doesn't give any result and if I remove it it works but do not give the complete list (only few results)
$ApplicationID = "45xxxxxxxx"
$TenatDomainName = "2a3xxxxx"
$AccessSecret = Read-Host "Enter Secret"
$Body = #{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
client_Id = $ApplicationID
Client_Secret = $AccessSecret
}
$ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenatDomainName/oauth2/v2.0/token" -Method POST -Body $Body
$token = $ConnectGraph.access_token
#$GrapRisk = "https://graph.microsoft.com/v1.0/identityProtection/riskyUsers"
$GrapRisk = "https://graph.microsoft.com/beta/identityProtection/riskyUsers?$filter=riskLevel eq microsoft.graph.riskLevel'medium'"
$riskyList= (Invoke-RestMethod -Headers #{Authorization = "Bearer $($token)"} -Uri $GrapRisk -Method Get).value |select userPrincipalName, riskState, riskLastUpdatedDateTime, riskLevel
$riskyList
I execute this script through Powershell ISE but even with curl and terminal I cannot use the filter parameter.
Thanks
Whenever a string literal uses double-quotes ("'s), PowerShell interprets it as expandable, meaning PowerShell will attempt to resolve and expand variable expressions (like $filter) when evaluating the string.
Use a backtick (`) to escape the $, and it should work:
$GrapRisk = "https://graph.microsoft.com/beta/identityProtection/riskyUsers?`$filter=riskLevel eq microsoft.graph.riskLevel'medium'"
For more details about the semantics of different types of string literals in PowerShell, read the about_Quoting_Rules help topic

Powershell invoke-restmethod variable in url

I am new to powershell, and I am trying to create a simple script that will allow me to turn on several Azure VMs using the invoke-restmethod.
My code works when instead of using a variable I directly write the VM name into the url, but I want to use a variable, since eventually this must work for more than one VM.
Relevant part of code:
$body = #{
"$virtualMachines" = "VM1"
} | ConvertTo=Json
$url= "https://management.azure.com/subscriptions/mySubscriptionId/resourceGroups/myResourceGroupName/providers/Microsoft.DevTestLab/labs/myLabName/virtualmachines/" + $virtualMachines + "/start?api-version=2018-09-15"
$response = Invoke-RestMethod -uri $url -Method 'POST' -Headers $headers -Body $body
$response | ConvertTo-Json
If you had a number of VMs, you could put them all into a PowerShell variable like this, an array of strings.
$VMs = "myVm1", "myVm2", "myVm3"
PowerShell has a number of flow control statements, the one you want to use is ForEach, which will step through an array one at a time. We just modify the way you're setting up the URL to be friendlier and easier to read and this should work just fine.
$baseUrl = "https://management.azure.com/subscriptions/mySubscriptionId/resourceGroups/myResourceGroupName/providers/Microsoft.DevTestLab/labs/myLabName/virtualmachines/"
ForEach ($vm in $VMs){
$url = $baseurl + $vm + "/start?api-version=2018-09-15"
Write-host "About to start [$Vm]"
$response = Invoke-RestMethod -uri $url -Method 'POST' -Headers $headers
$response | ConvertTo-Json
}
I checked the API documentation for the start? REST API endpoint, and it doesn't look like you need the -Body parameter for this endpoint.

How to make Invoke-RestMethod GET and PUT requests to Azure table storage using SAS key

This is a two-part question. I am in the process of automating tasks that a) require information from my Azure table and b) need to update specific entities in my Azure table. I've currently been able to accomplish this by using either of the 2 provided access keys but think this is an unsafe practice and want to define individual policies for different groups and so want to transition into using generated SAS keys.
a) I can currently use SAS policies to retrieve the whole table and find the information I need but I think a better method is to perform an individual query that only pulls the single entity that matches a specific property I'm looking for (e.g. pull all properties of an entity that matches a customer ID: "000000001"). How can I change my code to accomplish this?
$tableName = "accountTD"
$sasReadToken = '<SAS token here>'
$tableUri = "https://$storageAccount.table.core.windows.net/$tableName$sasReadToken"
$GMTTime = (Get-Date).ToUniversalTime().toString('R')
$header = #{
'x-ms-date' = $GMTTime;
Accept = 'application/json;odata=nometadata'
}
$finalResult = Invoke-WebRequest -Uri $tableUri -Headers $header -UseBasicParsing
$finalResult = $finalResult.Content | ConvertFrom-Json
$finalResult.value
b) I also need to update the same entity in the table and can't seem to figure out how to authorize it with my generated SAS key. I'm not sure whether to use Invoke-WebRequest or Invoke-RestMethod or how to go about either of them. Here's what I have so far based on my research.
function addUpdateEntity ($tableName, $PartitionKey, $RowKey, $entity){
$sasReadToken = '<SAS token here>'
$resource = "$tableName(PartitionKey='$PartitionKey',RowKey='$Rowkey')"
$tableUri = "https://$storageAccount.table.core.windows.net/$tableName$sasReadToken"
$GMTTime = (Get-Date).ToUniversalTime().toString('R')
$header = #{
'x-ms-date' = $GMTTime;
Accept = 'application/json;odata=nometadata'
}
$body = $entity | ConvertTo-Json
$item = Invoke-RestMethod -Method PUT -Uri $tableUri -Headers $headers -Body $body -ContentType application/json
}
$mBody = #{
PartitionKey = "MPS02000"
RowKey = "2019-000101"
appUpdateMode = "1"
m_CustID = "000000001"
}
addUpdateEntity -TableName "atdMachines" -PartitionKey $mBody.PartitionKey -RowKey $mBody.RowKey -entity $mBody
Q1. Pull all properties of an entity that matches a customer ID
Answer: You can use $filter query expression. For example, I have 2 entities in my testTable:
I can get the entity whose Id equals to 00001 by making a request as following:
GET https://storagetest789.table.core.windows.net/testTable?{sastoken}&$filter=(Id eq '00001')
$storageAccount = "storagetest789"
$tableName = "testTable"
$sasReadToken = "?sv=2019-02-02&ss=t&sr***************D"
$filter = "`$filter=(Id eq '00001')"
$tableUri = "https://$storageAccount.table.core.windows.net/$tableName$sasReadToken&$filter"
$GMTTime = (Get-Date).ToUniversalTime().toString('R')
$header = #{
'x-ms-date' = $GMTTime;
Accept = 'application/json;odata=nometadata'
}
$finalResult = Invoke-WebRequest -Uri $tableUri -Headers $header -UseBasicParsing
$finalResult = $finalResult.Content | ConvertFrom-Json
$finalResult.value
Result:
Q2. Update the same entity in the table
Answer: Both Invoke-WebRequest and Invoke-RestMethod are suitable for making a HTTP request here. I find some mistakes in your scripts, here is the fixed one:
function addUpdateEntity ($tableName, $PartitionKey, $RowKey, $entity){
$storageAccount = "storagetest789"
$tableName = "testTable"
# Need write access
$sasWriteToken = "?sv=2019-02-02&ss=t&s*****************************D"
$resource = "$tableName(PartitionKey='$PartitionKey',RowKey='$Rowkey')"
# should use $resource, not $tableNmae
$tableUri = "https://$storageAccount.table.core.windows.net/$resource$sasWriteToken"
# should be headers, because you use headers in Invoke-RestMethod
$headers = #{
Accept = 'application/json;odata=nometadata'
}
$body = $entity | ConvertTo-Json
$item = Invoke-RestMethod -Method PUT -Uri $tableUri -Headers $headers -Body $body -ContentType application/json
}
$mBody = #{
PartitionKey = "p1"
RowKey = "r1"
Id = "00001"
Value = "new value"
}
addUpdateEntity -TableName "atdMachines" -PartitionKey $mBody.PartitionKey -RowKey $mBody.RowKey -entity $mBody
Result:

Resources