I am using the Azure Management Rest API in Powershell , to create an NSG with some rule properties at the creation time. (yes I am aware that there is a PS module that can do that as well)
I have constructed the body of my PUT request as per the Microsoft documentation.
$url = "https://management.azure.com/subscriptions/$subid/resourceGroups/$rg/providers/Microsoft.Network/networkSecurityGroups/$nsg2" "?api-version=2022-05-01"
$body = @{
"name" = "NSG-Test";
"location" = "useast";
"properties"= @{
"securityRules" = @(
@{
"name" = "rule1"
"properties"= @{
"protocol" = "*"
"sourcePortRange"= "*"
"destinationPortRange" = "80"
"sourceAddressPrefix"= "*"
"destinationAddressPrefix"= "*"
"access" = "Allow"
"priority" = 130
"direction"="Inbound"
}
}
)
}
} | ConvertTo-Json
try{
$Result = (Invoke-RestMethod -Uri $url -Headers $Headers -Method PUT -Body $body -Verbose -ContentType "application/json")
Write-Host $Result
}
Unfortunately I am greeted with the following error when executing this code :
{
"error": {
"code": "InvalidRequestFormat",
"message": "Cannot parse the request.",
"details": [
{
"code": "InvalidJson",
"message": "Error converting value \"System.Collections.Hashtable\" to type 'Microsoft.WindowsAzure.Networking.Nrp.Frontend.Contract.Csm.Public.Se
curityRule'. Path 'properties.securityRules[0]', line 4, position 75."
}
]
}
}
So the reason behind this is the nested dictionary @{"name"="rule1"..} inside the securityRules attribute value.
When removing this hashtable, the request executes and the NSG gets created, however without any properties of course.
Is there any way to circumvent this issue and have the REST API accept my JSON body with it's properties?
CodePudding user response:
I tried to reproduce the same in my environment I got the same error as below:
To resolve this issue, Make sure to add -Depth 4 in the ConvertTo-Json
.
When I added ConvertTo-Json -Depth 4 the error was resolved.
Code:
$AppId="<clientID>"
$AppSecret="75X8Q~2RXXXXXX"
$TokenURI="https://login.microsoftonline.com/2f2ebbbc-e970-XXXXXXXX/oauth2/token"
$Resource="https://management.core.windows.net"
#OAUTH
$BodyRequest="grant_type=client_credentials&client_id=$AppId&client_secret=$AppSecret&resource=$Resource"
$AccessToken=Invoke-RestMethod -Method Post -Uri $TokenURI `
-Body $BodyRequest -ContentType 'application/x-www-form-urlencoded'
$subid ="<SubscriptionID>"
$rg="imran"
$nsg2="nsg2"
#$Headers=@{}
#$Headers.Add("Authorization ","Bearer " $AccessToken.access_token)
$RequestURI = "https://management.azure.com/subscriptions/$subid/resourceGroups/$rg/providers/Microsoft.Network/networkSecurityGroups/$nsg2" "?api-version=2022-07-01"
$body=@{
"name" = "nsg2";
"location" = "East us";
"properties"= @{
"securityRules" = @(
@{
"name" = "rule1"
"properties"= @{
"protocol" = "*"
"sourcePortRange"= "*"
"destinationPortRange" = "80"
"sourceAddressPrefix"= "*"
"destinationAddressPrefix"= "*"
"access" = "Allow"
"priority" = 130
"direction"="Inbound"
}
}
)
}
} | ConvertTo-Json -Depth 4
$Headers=@{}
$Headers.Add("Authorization","Bearer " $AccessToken.access_token)
$Result = (Invoke-RestMethod -Uri $RequestURI -Headers $Headers -Method PUT -Body $body -Verbose -ContentType 'application/json' )
Write-Host $Result
Result:
To confirm in portal rule1 is added successfully like below: