Using cURL to send JSON within a BASH script - bash

Alright, here's what I'm trying to do. I'm attempting to write a quick build script in bash that will check out a private repository from GitHub on a remote server. To do this a "hands off" as possible, I want to generate a local RSA key set on the remote server and add the public key as a Deploy Key for that particular repository. I know how to do this using GitHub's API, but I'm having trouble building the JSON payload using Bash.
So far, I have this particular process included below:
#!/bin/bash
ssh-keygen -t rsa -N '' -f ~/.ssh/keyname -q
public_key=`cat ~/.ssh/keyname.pub`
curl -u 'username:password' -d '{"title":"Test Deploy Key", "key":"'$public_key'"}' -i https://api.github.com/repos/username/repository/keys
It's just not properly building the payload. I'm not an expert when it comes to string manipulation in Bash, so I could seriously use some assistance. Thanks!

It's not certain, but it may help to quote where you use public_key, i.e.
curl -u 'username:password' \
-d '{"title":"Test Deploy Key", "key":"'"$public_key"'"}' \
-i https://api.github.com/repos/username/repository/keys
Otherwise it will be much easier to debug if you use the shell's debugging options set -vx near the top of your bash script.
You'll see each line of code (or block (for, while, etc) as it is in your file. Then you see each line of code with the variables expanded to their values.
If you're still stuck, edit your post to show the expanded values of variables for the problem line in your script. What you have looks reasonable at first glance.

Related

Starting bootcamp - MacTerminal and Github SSH fingerprint don't match

I have been following the steps of the courses pre-work, including:
checking for, generating, copy/paste, and
saving the SSH keys to GitHub.
But when I am instructed to check the matching fingerprints using "ssh -T git#github.com", the prints don't match.
I've even started from the beginning clear through, but they still don't match.
Thought I'd reach out here before using my 1 tutoring.
Hopefully the screenshot showing what I see helps(link).
EDIT- I understand there's some stuff in there that shouldn't be, I was just trying things for diff results. I would just like to know where I went wrong and how to avoid it.
What you ssh is the remote site SSH key fingerprint, not you registered SSH key fingerprint.
You see (or should see if you are contacting the correct github.com) the fingerprints exposed with api.github.com/meta as explained here.
Using jq, you can add them to your ~/.ssh/known_hosts with:
curl --silent https://api.github.com/meta \
| jq --raw-output '"github.com "+.ssh_keys[]' >> ~/.ssh/known_hosts
From there, you can test your connection with ssh -Tv github.com, and check if you see a welcome message:
Hi username!
You've successfully authenticated, but GitHub does not provide shell access

Here document is cutting off commands

I'm trying to connect to my server via SSH and issue some commands to it. For some reason it seems like the commands are getting cut "off".
Here is the code that does the putty connection as well as issuing the SSH commands:
./plink.exe ${USER}#${HOSTNAME} -pw ${PASS}<<SSH
cd /some/foo/bar
deploy_artifact.sh --instance development1 some_artifact.ear
APP_development1.sh restart
exit
SSH
For me it works, but on the machine of my colleague the issued SSH commands are getting cut off and thus are not interpreted correctly. For example deploy_artifact.sh is getting turned into ploy_artifact.sh (See the following the screenshot).
How can i prevent this? And what is causing this?
Thanks in advance for any help!
It appears the problem is with the plink and how it is used. The given example sends commands as a standard input, however I did not find in the plink manual any mention that it reads commands from the STDIN. It is better to avoid undocumented features, since they may not work correctly or the author may remove them without any notice. Instead, if you want to pass commands inline you should provide them as an argument, ie you either have to use a quoted text, or you can wrap heredoc in the "$(cat *heredoc* )" code, eg:
./plink.exe ${USER}#${HOSTNAME} -pw ${PASS} "$(cat <<SSH
cd /some/foo/bar
deploy_artifact.sh --instance development1 some_artifact.ear
APP_development1.sh restart
exit
SSH
)"
Or, you can keep the commands in a file and run the plink with the -m commands_file option.

How do I format a variable inside the broken double quotes of a curl command?

I am trying to test the Sumo Logic API by updating the information of my collector. The second curl command is the one that is causing the issue 'curl: (55) Failed sending PUT request'. It works in my terminal but not in the bash script.
#!/bin/bash
readonly etag=$(curl -u '<accessId>:<accessKey>' -I -X GET https://api.sumologic.com/api/v1/collectors/<id> | grep -Fi etag | awk '{print $2}' | tr -d \''"\')
echo ${etag}
curl -vvv -u '<accessId>:<accessKey>' -X PUT -H "Content-Type: application/json" -H "If-Match: \"${etag}\"" -T updated_collector.json https://api.sumologic.com/api/v1/collectors/<id>
set -x
The first curl command is assigned to the variable called 'etag' which stores the necessary etag. The etag is used in the second curl command to make a request to update the information stored in the 'updated_collector.json'. The updated_collector.json file is not the issue as I have successfully updated the information via the terminal with it. I suspect the content-type is not being sent in the header because someone ran the script on their end and it was not showing that information with the -vvv tag.
Here you can find the Sumo Logic Collector API Methods and Examples from which I got the curl commands to test the API: https://help.sumologic.com/APIs/Collector-Management-API/Collector-API-Methods-and-Examples
Update: I retieved the etag and then ran the second command in a bash script. I manually inserted the etag into the ${etag} portion of the second curl command. I then ran the script and it worked. Therefore, the etag variable isn't correctly formatted inside the second curl command. I do not know how to fix this.
The issue was partially the syntax but after fixing that, I was still getting an error. "If-Match: \"${etag}\" in my command should be "If-Match: ${etag}" instead. I had to add the --http1.1 flag for it to work. I'm sure this is a sumo logic issue. I am able to execute GET requests no problem using http2.0.

Bash script set Coordinate Universal Time on remote system using ssh and date

I have a bash script that attempts to synchronize the time on another machine. It is not my source code, but as I am refactoring bash script, I am trying to get it to pass ShellCheck.
The source code for it looks something like this:
d=$(date -u +%m%d%H%M%Y.%S)
ssh decs#host-zc1 "sudo date -u ${d}"
The ShellCheck warning is SC2029 and states "Note that, unescaped, this expands on the client side.". In fact I don't want to escape this.
Is there another way to get rid of this warning and yet perform this step?
When you've determined that a warning does not apply to you, you can ignore it with a # shellcheck disable comment:
d=$(date -u +%m%d%H%M%Y.%S)
# shellcheck disable=SC2029
ssh decs#host-zc1 "sudo date -u ${d#Q}"
Though you should really be using ${d#Q} or printf %q to ensure the name will be properly escaped.

cURL to call REST Api

So I want to call a REST API from Bamboo after a deployment has completed.
This API needs a username and password but it can't be stored in Bamboo as it seems it can be viewed in the Bash History of the Build agent.
I intended to use a script task and execute something like
curl -f -v -k --user "${bamboo.user}":"${bamboo.password}" -X POST https://bamboo.url/builds/rest/api/latest/queue/project_name"/
This would make the REST call. But the username and password is a problem.
I do have the option, however of using a PEM file. It can be provided so does anyone know if this can be used in conjunction with the cURL?
--OR--
One other thought- could I encrypt a password within a file in my source control, and somehow decrypt it on the build agent, and then have curl use the file instead of reading the password from the command line? How would this look in cURL?
Any ideas how this could be achieved?
Your command seems to have an extra quote at the end of your command
Using a pem file to authenticate with curl:
curl -E /path/to/user-cert.pem -X POST https://bamboo.url/builds/rest/api/latest/queue/project_name
The file should have both private key and public key inside.

Resources