Powershell access property stored in JSON object - json

$primaryEndpoints = az storage account show --resource-group rg --name sto --query 'primaryEndpoints'
The above command returns
{
"blob": "https://sto.blob.core.windows.net/",
"dfs": null,
"file": "https://sto.file.core.windows.net/",
"internetEndpoints": null,
"microsoftEndpoints": null,
"queue": "https://sto.queue.core.windows.net/",
"table": "https://sto.table.core.windows.net/",
"web": null
}
But his command below returns nothing :
echo $primaryEndpoints["blob"]
I've also tried
echo $primaryEndpoints.blob
How do I access the json property ?

It seems to me that you are getting a JSON string as a return value. To access the properties by name, you need to first convert the JSON string to a PSObject.
$primaryEndpoints = az storage account show --resource-group rg --name sto --query 'primaryEndpoints'
$primaryEndpointObjects = $primaryEndpoints | ConvertFrom-Json
$primaryEndpointObjects.blob

Related

Using Azure CLI Get the 'principalId' value of an Azure Application Gateway

PS /home/ian> az network application-gateway identity show --gateway-name "xxx-inf-abc-wag" --resource-group "network-xxx"
{
"principalId": null,
"tenantId": null,
"type": "userAssigned",
"userAssignedIdentities": {
"/subscriptions/XXXXXXXXX-80b8-4447-b2a6-XXXXXXXXXX/resourcegroups/network-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/dev-gpp-wag-mi": {
"clientId": "DDDDDDDDD-eb2e-4836-898a-DDDDDDDDD",
"principalId": "UUUUUUUUUU-b7c8-43d2-80a2-UUUUUUUUUU"
}
}
}
I just want to retrieve the value of the field 'principalId' from the above json returned from running 'az network application-gateway identity show'.
I think I need to add "--query ...something". I tried "--query .principalId" but this doesn't work. I know there's something wrong with my syntax for "--query" but don't know how to solve it ?
Solved it by using another az command...
$id = $(az ad sp list --display-name "XXX-abc-wag-mi" --query [0].id --output tsv)
The az network application-gateway identity show works with the following query expression
$id=$(az network application-gateway identity show -g MyResourceGroup --gateway ag1 --query 'userAssignedIdentities."/subscriptions/XXXXXXXXX-80b8-4447-b2a6-XXXXXXXXXX/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id1".principalId' -o tsv)
Explanation
The az network application-gateway identity show -g MyResourceGroup --gateway-name ag1 gives the below output:
{
"principalId": null,
"tenantId": null,
"type": "userAssigned",
"userAssignedIdentities": {
"/subscriptions/XXXXXXXXX-80b8-4447-b2a6-XXXXXXXXXX/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id1": {
"clientId": "DDDDDDDDD-eb2e-4836-898a-DDDDDDDDD",
"principalId": "UUUUUUUUUU-b7c8-43d2-80a2-UUUUUUUUUU"
}
}
}
Since the key /subscriptions/XXXXXXXXX-80b8-4447-b2a6-XXXXXXXXXX/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id1 contains forward slashes and a dot character (which are special characters), it has to be escaped.
Hence, the key should be quoted with double quotes

ws ec2 create-launch-template-version passing variables into json array

I have 4 environment variables on my laptop, ami_id, instance_type, key_name and security_group_ids. I am trying to create a launch template version using these variables but I do not know how to pass them into the JSON array properly
aws ec2 create-launch-template-version --launch-template-id lt-xxx --launch-template-data '{"ImageId":"$ami_id", "InstanceType": "$instance_type", "KeyName": "$key_name", "SecurityGroupIds": ["$security_group_ids"]}'
An error occurred (InvalidAMIID.Malformed) when calling the CreateLaunchTemplateVersion operation: The image ID '$ami_id' is not valid. The expected format is ami-xxxxxxxx or ami-xxxxxxxxxxxxxxxxx.
Using a here-document allows you to feed some readable text into a variable while expanding the shell variables, like this:
#!/bin/sh
ami_id=ami1234
instance_type=t3.nano
key_name=key1
security_group_ids=sg123,sg456
template_data=$(cat <<EOF
{
"ImageId":"$ami_id",
"InstanceType": "$instance_type",
"KeyName": "$key_name",
"SecurityGroupIds": ["$security_group_ids"]
}
EOF
)
echo "$template_data"
You can then test the JSON syntax with jq:
./template.sh | jq -c
{"ImageId":"ami1234","InstanceType":"t3.nano","KeyName":"key1","SecurityGroupIds":["sg123,sg456"]}

Powershell Nested Json doesn't look like a Json

I am currently trying to prepare a JSON body for an API call, which should look something like this
curl -XPOST -H 'Authorization: Bearer ***API*KEY***' -H 'Content-Type: application/json' http://127.0.0.1:9000/api/alert -d '{
"title": "Other alert",
"description": "alert description",
"type": "external",
"source": "instance1",
"sourceRef": "alert-ref",
"severity": 3,
"tlp": 3,
"artifacts": [
{ "dataType": "ip", "data": "127.0.0.1", "message": "localhost" },
{ "dataType": "domain", "data": "thehive-project.org", "tags": ["home", "TheHive"] },
],
"caseTemplate": "external-alert"
}'
The problem however is that my json body which I create with powershell has weird characters and don't see where the problem is. This is my JSON Body
{
"tlp": 1,
"source": "Test",
"title": "Test Alert1",
"artifacts": "{\r\n \"dataType\": \"ip\",\r\n \"data\": \"127.0.0.1\"\r\n}",
"type": "external",
"sourceRef": "1",
"description": "Test",
"severity": 1
}
I create this JSON body as follows. I have already tried CustomObjects and Hashtables, but always get the same output
$body = #{
title = "$title"
description = "$Alert_Description"
type ="external"
source ="$Source"
sourceRef ="$SourceRef"
severity = $Severity
tlp = $tlp
$artifacts = [PSCustomObject]#{
dataType=ip
data=127.0.0.1}
}| ConvertTo-Json
$JsonBody = $body | ConvertTo-Json
Can somebody give me a hint? I have no clue anymore
First, fix your hashtable so that it creates the intended JSON representation, and only apply ConvertTo-Json once:
$body = [ordered] #{
title = $title
description = $Alert_Description
type = 'external'
source = $Source
sourceRef = $SourceRef
severity = $Severity
tlp = $tlp
artifacts = , [pscustomobject] #{
dataType = 'ip'
data = '127.0.0.1'
}
} | ConvertTo-Json
Variables don't need enclosing in "..." unless you explicitly want to convert their values to strings.
Literal textual information such as ip does require quoting ('...', i.e. a verbatim string literal, is best).
The artifacts property is an array in your sample JSON, so the unary form of ,, the array constructor operator is used to wrap the [pscustomobject] instance in a single-element array.
If you have multiple objects, place , between them; if the array was constructed previously and stored in a variable named, say, $arr, use artifacts = $arr.
Use of [ordered], i.e. the creation of an ordered hashtable isn't strictly necessary, but makes it easier to compare the resulting JSON representation to the input hashtable.
Generally keep in mind that explicit use of a -Depth argument with ConvertTo-Json is situationally required in order to ensure that properties aren't truncated - see this post for more information. However, with the hashtable in your question this happens not to be a problem.
Second, since you're sending the json to an external program, curl (note that in Windows PowerShell you'd have to use curl.exe in order to bypass the built-in curl alias for Invoke-WebRequest, an additional escaping step is - unfortunately - required up to at least v7.1 - though that may change in v7.2: The " instances embedded in the value of $body must manually be escaped as \", due to a long-standing bug in PowerShell:
curl -XPOST -H 'Authorization: Bearer ***API*KEY***' -H 'Content-Type: application/json' `
http://127.0.0.1:9000/api/alert -d ($body -replace '([\\]*)"', '$1$1\"')
Note: With your particular sample JSON, -replace '"', '\"' would do.
See this answer for more information.
Slap a "-Depth 50" on your ConvertTo-Json, that should solve your issue.
Like here: ConvertTo-Json flattens arrays over 3 levels deep

passing json array with spaces to bash script for az cli tagging

I have a bash script that looks like the following and correctly passes tags to the az cli that includes spaces.
RESOURCE_GROUP_NAME=$1
LOCATION=$2
TAGS_INPUT_ARGUMENT=$3 # This TAGS_INPUT_ARGUMENT needs to finally look like the TAGS below.
echo 'TAGS_INPUT_ARGUMENT:' $TAGS_INPUT_ARGUMENT
# HARD CODED TAGS that Work
TAGS=("owner=Firstname Lastname" "application=cool-name")
echo 'TAGS:' "${TAGS[#]}"
az group create \
--name $RESOURCE_GROUP_NAME \
--location $LOCATION \
--tags "${TAGS[#]}"
I am having problems passing the TAGS into the script.
i.e.
export TAGS='["owner=Firstname Lastname","application=cool-name"]'
bash ./entrypoint.sh rg-lionking eastus2 "${TAGS}"
Output:
TAGS_INPUT_ARGUMENT: ["owner=Firstname Lastname","application=cool-name"]
TAGS: owner=Firstname Lastname application=cool-name
{
"id": "/subscriptions/**REDACTED**/resourceGroups/rg-lionking",
"location": "eastus2",
"managedBy": null,
"name": "rg-lionking",
"properties": {
"provisioningState": "Succeeded"
},
"tags": {
"application": "cool-name",
"owner": "Firstname Lastname"
},
"type": "Microsoft.Resources/resourceGroups"
}
Given that I can get TAGS in a good state, what do I need to do to pass in the same thing in json format and get it working as the final argument to the az group create cli?
My jp knowledge is practically zero, so I am guessing that the answer lies in there somewhere.
The equivalent to expanding an array is on the command line is passing multiple separate arguments
./entrypoint rg-lionking eastus2 "owner=Firstname Lastname" "application=cool-name"
...and then, in entrypoint:
#!/usr/bin/env bash
resource_group_name=$1; shift
location=$1; shift
tags=( "$#" )
az group create \
--name "$resource_group_name" \
--location "$location" \
--tags "${tags[#]}"

Filter on nested array with jmespath (using az cli)

I would like to know if a value in a TXT record is already available in the DNS:
az network dns record-set txt show -g myresourcegroup -z 'mydomain' -n 'mytxtvalues'
This is the part of the json result where it's all about:
"txtRecords": [
{
"value": [
"abc"
]
},
{
"value": [
"def"
]
}
]
I tried many queries. These are 2 which I expected to work.
az network dns record-set txt show -g myresourcegroup -z 'mydomain.com' -n 'mytxtvalues' --query txtRecords[?value[?starts_with(#, 'abc')]]
az network dns record-set txt show -g myresourcegroup -z 'mydomain.com' -n 'mytxtvalues' --query txtRecords[*].value[?starts_with(#, 'abc')]]
The result is:
At line:1 char:123
+ ... 'mytxtvalues' --query txtRecords[?value[?starts_with(#, 'abc') ...
+ ~ Unrecognized token in source text. At line:1 char:124
+ ... 'mytxtvalues' --query txtRecords[?value[?starts_with(#, 'abc')] ...
+ ~ Missing argument in parameter list.
It looks like the # used to filter the array is not recognized. But I don't know how to query otherwise.
What would be a correct query to know if value abc is already in the list?
You need to use the command like this:
az network dns record-set txt show -g myresourcegroup -z 'mydomain.com' -n 'mytxtvalues' --query "txtRecords[*].value[?starts_with(#, 'abc')]"
And if you just need to output the string you can append the parameter -o tsv. Hope this will help you.