Goal:
I'm using a bash CURL script to connect to the Cloudflare APIv4. The goal is to update an A-record. My script:
# Get current public IP
current_ip=curl --silent ipecho.net/plain; echo
# Update A record
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONEIDHERE/dns_records/DNSRECORDHERE" \
-H "X-Auth-Email: EMAILHERE" \
-H "X-Auth-Key: AUTHKEYHERE" \
-H "Content-Type: application/json" \
--data '{"id":"ZONEIDHERE","type":"A","name":"example.com","content":"'"${current_ip}"'","zone_name":"example.com"}'
Problem:
The current_ip variable is not printed when I call it in my script. The output will be "content" : "" and not "content" : "1.2.3.4".
I used other stackoverflow posts and I'm trying to follow their examples but I think I'm still doing something wrong, just can't figure out what. :(
Using jq for this, as Charles Duffy's answer suggests, is a very good idea. However, if you can't or do not want to install jq here is what you can do with plain POSIX shell.
#!/bin/sh
set -e
current_ip="$(curl --silent --show-error --fail ipecho.net/plain)"
echo "IP: $current_ip"
# Update A record
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONEIDHERE/dns_records/DNSRECORDHERE" \
-H "X-Auth-Email: EMAILHERE" \
-H "X-Auth-Key: AUTHKEYHERE" \
-H "Content-Type: application/json" \
--data #- <<END;
{
"id": "ZONEIDHERE",
"type": "A",
"name": "example.com",
"content": "$current_ip",
"zone_name": "example.com"
}
END
The reliable way to edit JSON from shell scripts is to use jq:
# set shell variables with your contents
email="yourEmail"
authKey="yourAuthKey"
zoneid="yourZoneId"
dnsrecord="yourDnsRecord"
# make sure we show errors; --silent without --show-error can mask problems.
current_ip=$(curl --fail -sS ipecho.net/plain) || exit
# optional: template w/ JSON content that won't change
json_template='{"type": "A", "name": "example.com"}'
# build JSON with content that *can* change with jq
json_data=$(jq --arg zoneid "$zoneid" \
--arg current_ip "$current_ip" \
'.id=$zoneid | .content=$current_ip' \
<<<"$json_template")
# ...and submit
curl -X PUT "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records/$dnsrecord" \
-H "X-Auth-Email: $email" \
-H "X-Auth-Key: $authKey" \
-H "Content-Type: application/json" \
--data "$json_data"
Related
This question already has answers here:
Escaping characters in bash (for JSON)
(13 answers)
Parsing JSON with Unix tools
(45 answers)
Closed 10 days ago.
I have the following GET CURL from which I get an xml.
curl -X 'GET' \
'http://local/something/something2' \
-H 'accept: application/json' \
-H 'authorization: auth'
Now I want to use the previous xml received above within this POST CURL:
curl -X 'POST' \
'http://something/something2' \
-H 'accept: application/json' \
-H 'authorization: auth' \
-H 'Content-Type: application/json' \
-d '{
"components": [
{
"locator": "sample",
"config": xml file from above
}
]
}'
How can I make the second CURL with POST?
See this post to see how to capture the output of the first command into a variable. Use it like this:
output=$(curl -X 'GET' \
'http://local/something/something2' \
-H 'accept: application/json' \
-H 'authorization: auth')
# Assuming the $output variable is a JSON object, with a property
# called 'result', use 'jq' to extract the value of that property
result=$(jq -r '.result' <<< "$output")
# As noted above, escape the double quotes with backslashes
curl -X 'POST' \
'http://something/something2' \
-H 'accept: application/json' \
-H 'authorization: auth' \
-H 'Content-Type: application/json' \
-d "{
\"components\": [
{
\"locator\": \"sample\",
\"config\": \"$result\"
}
]
}"
Note the double quotes - double quotes must be there so $output variable can be used. As a result, the double quotes in the JSON need to be escaped.
I have command I am running with works for one enviornment in a bash script e.g.
so for example
ZONE_ID=prod
#!/bin/bash
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
-H "X-Auth-Email: EMAIL" \
-H "X-Auth-Key: AUTH_KEY" \
-H "Content-Type: application/json" \
--data '{"purge_everything":true}'
What i would like to do is change the data item if possible for a different environment depending on the zone_id
ZONE_ID=prod
ZONE_ID=UAT
for example UAT would be
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
-H "X-Auth-Email: EMAIL" \
-H "X-Auth-Key: AUTH_KEY" \
-H "Content-Type: application/json" \
--data '{"files":["http://www.example.com/css/styles.css",{"url":"http://www.example.com/cat_picture.jpg","headers":{"Origin":"https://www.cloudflare.com","CF-IPCountry":"US","CF-Device-Type":"desktop"}}]}'
So what I kind of want to do is the following, but this doesnt work
#!/bin/bash
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
-H "X-Auth-Email: EMAIL" \
-H "X-Auth-Key: AUTH_KEY" \
-H "Content-Type: application/json" \
if [$ZONE_ID -q prod]; then
--data '{"purge_everything":true}'
else
--data '{"files":["http://www.example.com/css/styles.css",{"url":"http://www.example.com/cat_picture.jpg","headers":{"Origin":"https://www.cloudflare.com","CF-IPCountry":"US","CF-Device-Type":"desktop"}}]}'
One possible way to do it is:
#! /bin/bash
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
-H "X-Auth-Email: EMAIL" \
-H "X-Auth-Key: AUTH_KEY" \
-H "Content-Type: application/json" \
--data "$(if [[ $ZONE_ID == prod ]]; then
echo '{"purge_everything":true}'
else
echo '{"files":["http://www.example.com/css/styles.css",{"url":"http://www.example.com/cat_picture.jpg","headers":{"Origin":"https://www.cloudflare.com","CF-IPCountry":"US","CF-Device-Type":"desktop"}}]}'
fi)"
However, a much better option (for clarity and maintainability) is to put the --data argument in a variable.
I would recommend set variable before use it in curl command
example as follow
DATA=""
if [ "$ZONE_ID" = "prod" ]; then
DATA='{"purge_everything":true}'
else
DATA='{"files":["http://www.example.com/css/styles.css",{"url":"http://www.examp
le.com/cat_picture.jpg","headers":{"Origin":"https://www.cloudflare.com","CF-IPC
ountry":"US","CF-Device-Type":"desktop"}}]}'
fi
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache"
\
-H "X-Auth-Email: EMAIL" \
-H "X-Auth-Key: AUTH_KEY" \
-H "Content-Type: application/json" \
--data $DATA
This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 4 years ago.
I am curling Azure Log Analytics for some info, but first I need to grab an OAuth token from 1 command and pass it into the next. I have the following Curl commands which I have tested fine on their own (copying pasting the output for the next input), however I want to pass the OAuth token output as a variable for an automation task, but for some reason it is not able to read the variable into the next command.
token=$(curl -X POST \
https://login.microsoftonline.com/{{subscriptionID}}/oauth2/token \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&client_id={{clientID}}&client_secret={{clientSECRET}}&resource=https%3A%2F%2Fapi.loganalytics.io' \
| jq .access_token)
curl -X POST \
https://api.loganalytics.io/v1/workspaces/{{workspaceID}}/query \
-H 'Authorization: Bearer $token' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{ "query": "AzureActivity | summarize count() by Category" }'
Unfortunately when I run this command it responds back that a token is needed.
{"error":{"message":"Valid authentication was not provided","code":"AuthorizationRequiredError"}}
However, if I were to echo the $token variable it shows that it was saved
beefcake#ubuntu:~$ echo $token
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1...."
As I said, the commands work fine if I remove the token=$(..) and just copy/paste the output into the next input. Any ideas why this won't work for automation?
#Aserre had the right mindset. Turns out that jq copies the inverted commas " " from the string, whereas the bearer token requires none. Thus my first command should have looked like this:
token=$(curl -X POST \
https://login.microsoftonline.com/{{subscriptionID}}/oauth2/token \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&client_id={{clientID}}&client_secret={{clientSECRET}}&resource=https%3A%2F%2Fapi.loganalytics.io' \
| jq -r .access_token)
Note the last line that has the -r command for removing the double quotes. Which showed an echo of:
beefcake#ubuntu:~$ echo $token
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs....
Note the " " removed from the echo. In addition to that, I had to alter the next command where I replaced 'Authorization: Bearer $token' with "Authorization: Bearer $token":
curl -X POST \
https://api.loganalytics.io/v1/workspaces/{{workspaceID}}/query \
-H "Authorization: Bearer $token" \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{ "query": "AzureActivity | summarize count() by Category" }'
Goal:
I'm using a bash CURL script to connect to the Cloudflare APIv4. The goal is to update an A-record. My script:
# Get current public IP
current_ip=curl --silent ipecho.net/plain; echo
# Update A record
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONEIDHERE/dns_records/DNSRECORDHERE" \
-H "X-Auth-Email: EMAILHERE" \
-H "X-Auth-Key: AUTHKEYHERE" \
-H "Content-Type: application/json" \
--data '{"id":"ZONEIDHERE","type":"A","name":"example.com","content":"'"${current_ip}"'","zone_name":"example.com"}'
Problem:
The current_ip variable is not printed when I call it in my script. The output will be "content" : "" and not "content" : "1.2.3.4".
I used other stackoverflow posts and I'm trying to follow their examples but I think I'm still doing something wrong, just can't figure out what. :(
Using jq for this, as Charles Duffy's answer suggests, is a very good idea. However, if you can't or do not want to install jq here is what you can do with plain POSIX shell.
#!/bin/sh
set -e
current_ip="$(curl --silent --show-error --fail ipecho.net/plain)"
echo "IP: $current_ip"
# Update A record
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONEIDHERE/dns_records/DNSRECORDHERE" \
-H "X-Auth-Email: EMAILHERE" \
-H "X-Auth-Key: AUTHKEYHERE" \
-H "Content-Type: application/json" \
--data #- <<END;
{
"id": "ZONEIDHERE",
"type": "A",
"name": "example.com",
"content": "$current_ip",
"zone_name": "example.com"
}
END
The reliable way to edit JSON from shell scripts is to use jq:
# set shell variables with your contents
email="yourEmail"
authKey="yourAuthKey"
zoneid="yourZoneId"
dnsrecord="yourDnsRecord"
# make sure we show errors; --silent without --show-error can mask problems.
current_ip=$(curl --fail -sS ipecho.net/plain) || exit
# optional: template w/ JSON content that won't change
json_template='{"type": "A", "name": "example.com"}'
# build JSON with content that *can* change with jq
json_data=$(jq --arg zoneid "$zoneid" \
--arg current_ip "$current_ip" \
'.id=$zoneid | .content=$current_ip' \
<<<"$json_template")
# ...and submit
curl -X PUT "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records/$dnsrecord" \
-H "X-Auth-Email: $email" \
-H "X-Auth-Key: $authKey" \
-H "Content-Type: application/json" \
--data "$json_data"
I'm trying to get both the HTTP code and the output of a curl command as part of a shell script, but in turn I'm trying to set both of them as variables. My code (which uses the pushbullet API) looks like this:
CURL_OUTPUT="$(exec 3>&1; \
HTTP_CODE="$(curl -s -S \
-w "%{http_code}" -o >(cat >&3) \
--header 'Authorization: Bearer '"$ACCT_TOKEN" \
-X POST https://api.pushbullet.com/v2/pushes \
--header 'Content-Type: application/json' \
--data-binary "$JSON")" \
)"
which should theoretically set $CURL_OUTPUT to the JSON returned by curl and $HTTP_CODE to the status code I get. Instead, I get only $CURL_OUTPUT; $HTTP_CODE is empty.
However, if I don't do the outer nest, like so:
exec 3>&1; \
HTTP_CODE="$(curl -s -S \
-w "%{http_code}" -o >(cat >&3) \
--header 'Authorization: Bearer '"$ACCT_TOKEN" \
-X POST https://api.pushbullet.com/v2/pushes \
--header 'Content-Type: application/json' \
--data-binary "$JSON")" \
The command works as expected; I get the JSON redirected to stdout, and the status code ends up in $HTTP_CODE.
So is it possible to get both outputs? Can I assign variables within a command substitution line?