extract a value from the output of a script and store in a variable winodws? - bash

According to the document Get Azure AD tokens for service principals:
curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token \
-d 'client_id=<client-id>' \
-d 'grant_type=client_credentials' \
-d 'scope=2ff814a6-3304-4ab8-85cb-cd0e6f879c1d%2F.default' \
-d 'client_secret=<client-secret>'
Now, I could get the correct output,like:
The Azure AD access token is in the access_token value within the output of the call.
What I want is that I need the get the value of the access_token and set it to the variable, so that I could use it in next REST API scripts.
But I'm not very familiar with Bash and curl, can anyone offer advice?

use jq to extract access_token from the json, and VAR=$(...) to store it in a variable,
ACCESS_TOKEN=$(curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token \
-d 'client_id=<client-id>' \
-d 'grant_type=client_credentials' \
-d 'scope=2ff814a6-3304-4ab8-85cb-cd0e6f879c1d%2F.default' \
-d 'client_secret=<client-secret>' \
| jq -r .access_token )
then you can use ACCESS_TOKEN like
curl -d access_token="$ACCESS_TOKEN"
but be wary, bash is a shitty scripting language, you should not attempt to use bash for complex logic, you should probably switch to a better scripting language like Python, Perl, or PHP, rather than implementing complex logic in Bash. (same goes for Windows's cmd and PowerShell. all 3 are languages unsuitable, but not incapable, of complex logic)

Related

Multiline GET request using cURL

I want to format a valid GET request in a way it is more human readable. There are many parameters and might be more in the future. So in case of a documentation, how would you format a long URL in a cURL command ? Preferably exhibiting each queryparam in a newline.
curl --header 'header1: XXXXXX' 'https://localhost/api/similar?word=science&target=en&target=fr&target=bg&target=ar&target=fr&source=en&limit=10&score=0.5'
Please note the repeating param target which is valid (and is interpreted as an array depending on the query parser on server side).
Edit: This is what I already tried without success:
curl -XGET -G 'https://localhost/api/similar?' \
-d word=science \
-d target=en \
-d target=fr \
-d target=bg \
-d target=ar \
-d target=fr \
-d source=en \
-d limit=10 \
-d score=0.5
Unfortunately, this is not working
you're very close :) just replace -XGET with --get and it should work
curl --get 'https://localhost/api/similar?' \
-d word=science \
-d target=en \
-d target=fr \
-d target=bg
also note that the \ syntax for multi-line shell invocations is specific to posix shells, meaning it won't work on Microsoft Windows, in Windows's cmd it would be
curl --get 'https://localhost/api/similar?' ^
-d word=science ^
-d target=en ^
-d target=fr ^
-d target=bg
(and again ^ is exclusive to Windows so that won't work on posix shells~)

How Do You Pass a Variable to Curl in Bash Script

How Do You Pass a Variable to Curl in Bash Script
I'm not able to get this curl to work in a bash script using an environment variable. The API key gets misinterpreted somehow when passed in via a variable and I'm getting authentication errors on submit. If I plug in the API key with no surrounding quotes as plaintext, this works just fine. I've tried various forms of escaping quotes and other combinations. Any help would be great.
Code
#!/bin/bash
source .env
curl -X POST https://api.easypost.com/v2/shipments \
-u "$EASYPOST_TEST_API_KEY": \
-d 'shipment[to_address][name]=Dr. Steve Brule' \
-d 'shipment[to_address][street1]=179 N Harbor Dr' \
-d 'shipment[to_address][city]=Redondo Beach' \
-d 'shipment[to_address][state]=CA' \
-d 'shipment[to_address][zip]=90277' \
-d 'shipment[to_address][country]=US' \
-d 'shipment[to_address][phone]=8573875756' \
-d 'shipment[to_address][email]=dr_steve_brule#gmail.com' \
-d 'shipment[from_address][name]=EasyPost' \
-d 'shipment[from_address][street1]=417 Montgomery Street' \
-d 'shipment[from_address][street2]=5th Floor' \
-d 'shipment[from_address][city]=San Francisco' \
-d 'shipment[from_address][state]=CA' \
-d 'shipment[from_address][zip]=94104' \
-d 'shipment[from_address][country]=US' \
-d 'shipment[from_address][phone]=4153334445' \
-d 'shipment[from_address][email]=support#easypost.com' \
-d 'shipment[parcel][length]=20.2' \
-d 'shipment[parcel][width]=10.9' \
-d 'shipment[parcel][height]=5' \
-d 'shipment[parcel][weight]=65.9' \
Per Gordon Davisson's suggestion to break it down into a minimal request, it started sending right. Then I rebuilt it just as in my question above and for whatever reason it worked like a charm. The -x flag was also incredibly helpful in troubleshooting this but come to find out there wasn't anything inherently wrong with it in the first place. Thanks for everyone's responses!

Sending large file as data inside JSON via cURL

I'm trying to send a file as base64-encoded data via POST to the Bugzilla REST API as follows:
curl -X POST https://www.example.com/rest/bug/$id/attachment -H "Content-Type: application/json" \
-d "{\
\"login\" : \"$username\", \
\"password\" : \"$password\", \
\"ids\" : [ $id ], \
\"summary\" : \"...\", \
\"content_type\" : \"application/gzip\", \
\"data\" : \"$data\"\
}"
What I'm getting is an error from cURL that the argument list is too long. Presumably, this is because the file ($data) I'm trying to send is more than the shell maximum (the file is 11M). What I've seen online is that the best way to get around that is to have cURL read the data from a file using --data-binary. But since I need to send a username and password, I'd prefer not to have to save the entire file with them inside.
Is there some way to get around this maximum, or is there another way to send a large amount of data this way? I prefer native Linux tools, as I want this script to be portable.
You can try using a file like this, which is the recommended way.
curl -i \
-H 'Accept:application/json' \
-H 'Authorization:Basic $username:$password' \
-X POST -d #datafile.txt https://www.example.com/rest/bug/$id/attachment

curl PUT using auth token header to mesosphere fails without eval

EDIT:
I have managed to make it work with
response=$(
curl -k -X PUT -d "$marathon_payload" --write-out %{http_code} --silent --output "$tmp"\
-H "Authorization: token=$dcos_token" -H "$header_content_type" $app_id_url
)
The single quotes were causing the problem. It took a few gyrations but all good.
MORAL: quotes inside the value don't matter if the value is properly quoted UNLESS you eval the whole thing, and I should have known that. Occam's wins again.
end edit
I am initiating Mesosphere microservice deployments with curl, but it won't succeed without using eval. Since I recently inherited this code I've been trying to scrub the eval out of it just as a matter of habit, but it's thwarting me.
The script initiates the deployment with
response=$(
eval curl -k -X PUT -d "'$marathon_payload'" --write-out %{http_code} --silent --output $tmp\
-H "'Authorization: token=$dcos_token'" -H "'$header_content_type'" $app_id_url
)
If it gets a 200 or a 201, it loops a curl to effectively screen-scrape the deployments page till the request disappears.
chkDeploy() { rm -f $tmp;
eval curl -k -X GET --silent --write-out %{http_code} --silent --output $tmp\
-H "'Authorization: token=$dcos_token'" -H "'$header_content_type'" $deployments_url
}
response=$( chkDeploy )
$dcos_token is a base64 encoded string.
It then checks the service with another curl loop to the info page so it can verify the version number. This one is working fine with no eval.
chkCode() {
curl -k -X GET --write-out %{http_code} --silent --output $tmp $info_url;
}
response=$( chkCode )
The first two return 401, authentication failure.
I'm guessing the auth token quoting is off.
There's no reason to use eval here; you just need to quote the arguments to -H properly.
response=$(
curl -k -X PUT -d "$marathon_payload" \
--write-out %{http_code} \
--silent --output "$tmp" \
-H "Authorization: token=$dcos_token" \
-H "$header_content_type" "$app_id_url"
)

Nested cURL call

I've one cron task to update my DDNS with my current ip address and do it through a cURL call.
The problem is one of the parameters to pass in the call is the CURRENT IP and in order to discover ir i need to do another cURL call.
I would like to know if is possible to nest two cURL calls in one single script in order to make my cron task avoiding extra scripts
example:
to get my current ip I use
curl ipinfo.io/ip
to update my ddns i need to do:
curl -X PUT "https://api.cloudflare.com/client/v4/zones/2wertyh/dns_records/23ertghj" \
-H "X-Auth-Email: tomatechines#gmail.com" \
-H "X-Auth-Key: 123ertgyh" \
-H "Content-Type: application/json" \
--data '{"type":"A","name":"qwsdfg.com.br","content":"MY-CURRENT-IP","ttl":1800,"proxied":false}'
how can i fit this two calls together in order to make my cron task
Use command substitution, like this:
curl -X PUT "https://api.cloudflare.com/client/v4/zones/2wertyh/dns_records/23ertghj" \
-H "X-Auth-Email: tomatechines#gmail.com" \
-H "X-Auth-Key: 123ertgyh" \
-H "Content-Type: application/json" \
--data '{"type":"A","name":"qwsdfg.com.br","content":"'"$(curl ipinfo.io/ip)"'","ttl":1800,"proxied":false}'
String argument for --data is composed from three concatenated parts, 'beginning' "$(curl ...)" 'ending' (more details see in this answer).

Resources