Invoke-Restmethod powershell in Azure Devops - strange powershell errors - azure

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

Related

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

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

Unable to retrieve token from Azure API

I am trying to get a token to be able to retrieve Groups information in Azure AD
This is my powershell script against the API:
Invoke-RestMethod -Method POST -Uri 'https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token?api-version=1.6'
-Header #{'Content-type' = 'application/x-www-form-urlencoded'}
-Body '{grant_type=client_credentials&client_id=<clientID>&scope=https://graph.microsoft.com/.default&client_secret=<clientSecret> }'
I keep getting this error: {"error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID:
Your body ia malformed, just do:
$body = #{
Grant_Type = 'client_credentials'
Scope = 'https://graph.microsoft.com/.default'
Client_Id = $ClientID
Client_Secret = $Secret
}
$con = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantid/oauth2/v2.0/token" -Method 'Post' -Body $body
$token = $con.access_token

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

Azure REST API list key vault secrets has maxresults limited to 25

I'm trying to get a list of all the secrets in each of my key vaults and I'm using Microsofts documentation at this URL.
https://learn.microsoft.com/en-us/rest/api/keyvault/getsecrets/getsecrets#secretlistresult
It states that if you do not set maxresults it will default to 25. It does however throw this error in my powershell script when i try to set it higher than 25.
{"error":{"code":"BadParameter","message":"invalid maxresults"}}
From the documentation the endpoint does not appear to contain any pagination or way to get more than 25 random secrets. This seems to make the endpoint pretty useless as there are no ways to filter the listings.
The command I'm using to get the list is this.
$uri = ""https://$($Vault).vault.azure.net/secrets?api-version=7.1&maxresults=26""
Invoke-RestMethod -Method Get -Uri $uri -Headers $headers
As Gaurav said in the comment, you need to use nextLink to get the result of next page.
There is my test code with do-until:
$LoginUrl = "https://login.microsoft.com"
$RresourceUrl = "https://vault.azure.net/.default"
$ClientID = ""
$ClientSecret = ""
$TenantName = ""
# Compose REST request.
$Body = #{ grant_type = "client_credentials"; scope = $RresourceUrl; client_id = $ClientID; client_secret = $ClientSecret }
$OAuth = Invoke-RestMethod -Method Post -Uri $LoginUrl/$TenantName/oauth2/v2.0/token -Body $Body
# Check if authentication was successfull.
if ($OAuth.access_token) {
# Format headers.
$HeaderParams = #{
'Content-Type' = "application\json"
'Authorization' = "Bearer $($OAuth.access_token)"
}
# Create an empty array to store the result.
$QueryResults = #()
$Uri = "https://<your-key-vault-name>.vault.azure.net/secrets?api-version=7.1"
# Invoke REST method and fetch data until there are no pages left.
do {
$Results = Invoke-RestMethod -Headers $HeaderParams -Uri $Uri -UseBasicParsing -Method "GET" -ContentType "application/json"
$Results.nextLink
if ($Results.value) {
$QueryResults += $Results.value
}
else {
$QueryResults += $Results
}
$Uri = $Results.nextLink
} until (!($Uri))
# Return the result.
$QueryResults
}
else {
Write-Error "No Access Token"
}

Storage REST API Returns Remote Name Could Not be Resolve Often

I am calling the storage REST API to get container names using
Invoke-WebRequest -Method GET -Uri $storage_url -Headers $headers
This command often returns 'remote name could not be resolved error', even when the storage account exists and is reachable. Just running the command again gives correct result.
Invoke-WebRequest : The remote name could not be resolved: '<storageAccountName>.blob.core.windows.net'
At line:1 char:1
+ Invoke-WebRequest -Method GET -Uri $storage_url -Headers $headers #In ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
From the information you provided, you use the client credential flow to get the access token, then use the token to call the Storage Rest API - List Containers.
You could use the script below, it works for me.
Make sure the service principal you used has a RBAC role e.g. Contributor/Owner in your storage account -> Access Control, if not, click the Add to add it.
$ClientID = "xxxxxxx"
$ClientSecret = "xxxxxxx"
$tennantid = "xxxxxxx"
$storageaccountname = "joystoragev2"
$TokenEndpoint = {https://login.microsoftonline.com/{0}/oauth2/token} -f $tennantid
$Resource = "https://storage.azure.com/"
$Body = #{
'resource'= $Resource
'client_id' = $ClientID
'grant_type' = 'client_credentials'
'client_secret' = $ClientSecret
}
$params = #{
ContentType = 'application/x-www-form-urlencoded'
Headers = #{'accept'='application/json'}
Body = $Body
Method = 'Post'
URI = $TokenEndpoint
}
$token = Invoke-RestMethod #params
$accesstoken = $token.access_token
$url = {https://{0}.blob.core.windows.net/?comp=list} -f $storageaccountname
$header = #{
'Authorization' = 'Bearer ' + $accesstoken
'x-ms-version' = '2019-02-02'
}
$response = Invoke-WebRequest –Uri $url –Headers $header –Method GET
$response.RawContent

Resources