bash (21)


MFA from command line

MFA, 2FA, 2 step validation, etc. are everywhere these days. And it’s a good thing.

Problem with using the phone to get the authentication code is that you need to have it handy at all times (when you want to login at least) and that you have to read the code then type it in (too many steps)

One possible alternative is to use the command line oathtool

Here’s my snippet, I added the following line in my .bashrc

function mfa () { oathtool --base32 --totp "$(cat ~/.mfa/$1.mfa)" | xclip -sel clip ;}

Some preparation work:

sudo apt install oathtool xclip
mkdir ~/.mfa

If you want to use the same account with both a phone based MFA generator and the shell, set them up at the same time. Simply use the generated string for setting up the account in the Google Authenticator (as an example) and the add it to the ~/.mfa/account_name.mfa

The use of xclip automatically copies the 6 digit authentication code to the clipboard. You can go ahead and paste it.

The above setup works in Ubuntu. Didn’t try it on other systems.

Similar Posts:




List IPs from CloudTrail events

A quick command to list the IPs from AWS CloudTrail events.

#!/bin/bash
ACCESS_KEY_ID=AKIASMOETHINGHERE
MAX_ITEMS=100
aws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=${ACCESS_KEY_ID} --max-items ${MAX_ITEMS} \
  | jq -r '.Events[].CloudTrailEvent' \
  | jq '.sourceIPAddress' \
  | sort | uniq

This of course can be extended to include more information, for example:

#!/bin/bash
ACCESS_KEY_ID=AKIASMOETHINGHERE
MAX_ITEMS=100
aws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=${ACCESS_KEY_ID} --max-items ${MAX_ITEMS} \
  | jq -r '.Events[].CloudTrailEvent' \
  | jq '{ User: .userIdentity.userName, IP: .sourceIPAddress, Event: .eventName }'

Similar Posts:




Change profiles automatically in Tilix when connecting to SSH hosts

I use Tilix as my main terminal app on Ubuntu. I like it mainly because it’s easy to use and shows multiple sessions in tiles and tabs, so it’s easy to switch between multiple servers without too much fuss

Tilix is also pretty customizable. I just needed to have the “profile” automatically switch according to the server/machine I switch to. This can be done according to the documentation per https://gnunn1.github.io/tilix-web/manual/profileswitch/ but I wanted something configured locally, not sent to the remote system.

So I just added a function that wraps my ssh command. Here’s how it looks in my .bashrc

ssh() { 
	SSHAPP=`which ssh`;   
	ARGS=$@;   
	echo "switching to $ARGS"; 
	printf "\033]7;file://%s/\007" "$ARGS";   
	$SSHAPP $ARGS; 
}

This sets up the hostname of machine you’re logging into as the title. That’s your trigger. What remains is to create a profile and assign that profile to automatically switch when the trigger (hostname:directory, user can also be added) is set.

Go to Profiles > Edit Profile > Advanced (tab) and under Match add the hostname.


That’s about it. I’m going to add a new profile with a RED background now for my production machines! too much?

Update (Jan 8, 2020)

I noticed that I have also added a Match for my localhost hostname in the Default profile, so that the profile would revert to that once I logged off a remote host.

Another thing I needed was to create a special trigger if I wanted to use a wildcard match for hostnames (ie. if I wanted to switch profile on all my AWS instances via Session Manager). And match that special hostname (aws-instance below for example). Here’s my ssh bash function now:

ssh () {
     SSHAPP=/usr/bin/ssh 
     ARGS=$@ 
     if [[ $ARGS == i-* ]]
     then
         echo "switching to AWS instance"
         printf "\033]7;file://%s/\007" "aws-instance"
     else
         echo "switching to $ARGS"
         printf "\033]7;file://%s/\007" "$ARGS"
     fi
     $SSHAPP $ARGS
 }

Similar Posts:




Check PHP-FPM Status from CLI

It’s good to have the status page, especially if you need to troubleshoot issues that are not showing up in the regular logs, such as high load or memory consumption.

However, looking at that page and refreshing it manually is not always useful. Sometimes you need to log that data, or have a way to pinpoint a single PID causing the load.

First make sure you have the status page accessible. Here’s a tutorial I like: https://easyengine.io/tutorials/php/fpm-status-page/

The create this script on the server. Make sure to change the connect part to your PHP-FPM pool’s correct port or socket

#!/bin/bash
# Requirements: cgi-fcgi
#   on ubuntu: apt-get install libfcgi0ldbl

RESULT=$(SCRIPT_NAME=/status \
SCRIPT_FILENAME='/status' \
QUERY_STRING=full \
REQUEST_METHOD=GET \
/usr/bin/cgi-fcgi -bind -connect 127.0.0.1:9000)

if [ -n "$1" ]; then
echo -e "$RESULT" | grep -A12 "$1"
else
echo -e "$RESULT"
fi

One way I use it is run `top` and check for the suspect process PID, then run ` fpm_status.sh <PID>`

Similar Posts:




Find the owner of an AWS Access Key

This is something you will have to deal with at one time or another after managing AWS IAM users for a while. Basically, it’s straight forward with the following code:

  • Get a list of users
    • for each user get their access key IDs
    • (optional) pipe to grep for checking a specific ID

And here’s the `aws-cli` code

for user in $(aws iam list-users --output text --query 'Users[*].UserName'); do     
  aws iam list-access-keys --user $user --output text; 
done

# or 
Q_ACCESSKEY=AKIA*************
for user in $(aws iam list-users --output text --query 'Users[*].UserName'); do     
  aws iam list-access-keys --user $user --output text | grep $Q_ACCESSKEY 
done

 

Similar Posts:




Change Nickname in Mattermost

A colleague asked me today for a quick way to set the nickname in Mattermost. He needed to do that to provide more information about his status than what the actual “Status” in shows, which is limited to “Online”, “Away”, “Do Not Disturn” and “Offline”

So if you want to tell people you’re away for a couple of hours, or sick, walking the dog, etc. then you need to go IRC style and put the additional information in your nickname. Not too bad actually, just inconvenient.

I checked the Mattermost API docs and wrote a small bash script to get things going

#!/bin/bash
# Requirements:
#  - get the token from Mattermost > Account Settings > Security > Personal Access Tokens > Create New Token
#    make sure to save the Token itself, not the ID!
#  - install jq
TOKEN=GETYOUROWNTOKEN
NICKNAME=${1:-NickNack}
STATUS=${2:-online}
CHANNEL_ID="my_hello_channel_ID"

user_id=$(curl -sH "Authorization: Bearer $TOKEN" \
  https://chat.example.com/api/v4/users/me | jq -r .id)
curl -XPUT -d '{"nickname":"'$NICKNAME'"}' \
  -sH "Authorization: Bearer $TOKEN" \
  "https://chat.example.com/api/v4/users/$user_id/patch"
curl -XPUT -d '{"status":"'$STATUS'"}' \
  -sH "Authorization: Bearer $TOKEN" \
  "https://chat.example.com/api/v4/users/$user_id/status"
if [ -n "$3" ]; then
  curl -XPOST -d '{"channel_id":"'"$CHANNEL_ID"'", "message":"'"$3"'"}' \
  -sH "Authorization: Bearer $TOKEN" "https://chat.example.com/api/v4/posts"
fi

A couple of things to watch out there:

  • You need to save the TOKEN, not the TOKEN ID. Once created and saved the actual TOKEN is no longer showing in the UI. So save that somewhere safe and use it in the script
  • The user needs to be able to create their own token. Follow the procedure per the docs here to allow them to do that. Yes, you need to do all that 🙂
  • The Channel ID can be copied from the channel drop-down menu > View info. In the bottom left, in grey you will see: `ID: xxxxxxxxxx` that’s the one you need!

 

For convenience, I added a few aliases in my bashrc:

alias lunch="mmstatus.sh 'abdallah|lunch' 'dnd' 'going to lunch break'"
alias back="mmstatus.sh 'abdallah|work' 'online' 'back!'"
alias goodmorning="mmstatus.sh 'abdallah|work' online 'Good morning :)'"

I know it’s better to add a slash-command for that. Something like ‘/nick …’ or ‘/status …’. I’ll check out those docs later.

Similar Posts:




Stop un-tagged instances

After setting up a bastion and getting GitLab runner to autoscale on EC2 spot instances, I noticed that some instances are being started but left un-tagged and probably unused. Those seem to slip through the cracks somehow .. I’m still investigating why that’s happening.
Meanwhile, to avoid paying for those instances, I set up a cron to check for non tagged instances on EC2 and terminate them.

Here’s my bash code using aws-cli

#!/bin/bash
INSTANCES=$(aws ec2 describe-instances \
  --filters "Name=key-name,Values=runner-*" \
            "Name=instance-state-name,Values=running" \
  --query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)] | [].[InstanceId]' \
  --output text)
if [ -n "$INSTANCES" ]; then 
  aws ec2 terminate-instances --instance-ids $INSTANCES 
fi

This looks for running instances, with the Key Name runner-* and where the tag Name is not not_null (so null!)

It’s working so far. Will keep on looking for a more permanent solution.

Similar Posts:




How NOT to ban Googlebot

Google do not provide a list of IPs to identify their bots, so you can’t simply add that to fail2ban’s ‘ignoreip =’ line.

Instead, according to their answer per https://support.google.com/webmasters/answer/80553?hl=en you can only verify the bot’s provenance by checking the DNS for the bot’s IP. In fact, they ask you to run 2 queries (1 reverse and 1 forward lookup) to make sure that the IP is not spoofed.

My simple 1 reverse lookup script is:

#!/bin/bash
IP="$1"
HOSTRESULT="$(host -W ${IP})" # updated thanks to comment from Martin
REGEX='.*(googlebot\.com\.|google\.com\.)

And add that to /etc/fail2ban/jail.local

ignorecommand = /usr/local/bin/ignore_ip_check.sh 

This needs more testing, and I should add the second forward lookup, for for now it seems to do the trick

if [[ "$HOSTRESULT" =~ $REGEX ]]; then exit 0; else exit 1; fi

And add that to /etc/fail2ban/jail.local


This needs more testing, and I should add the second forward lookup, for for now it seems to do the trick

Similar Posts:




Install same packages for different PHP version

This is one of the things I should have thought of a long time ago.
More times than I can count I needed to install the same (or similar) list of PHP packages for a different version (ie. installing 7.0 while keeping 5.6) So instead of manually copying over the list or guessing as to what will be installed via dependencies here’s a quick one liner. Again, it’s a “facepalm” moment here for me:

# this installs 7.1 packages from a 7.0 list
dpkg -l | grep php7 | awk '{gsub(/7\.0/,"7.1",$2); print $2}' | xargs apt install

Also on my mind: instead of a sit/stand desk, can I install a shower desk. This way I can work and take showers at the same time!

Similar Posts:




Update PIP on Ubuntu

From SO answer

Your pip may be outdated. Even in Ubuntu 14.04 LTS, the pip version it installed using apt-get install python-pip was 1.5.4. Try updating pip manually, and possibly the new packages again as well.

pip --version # 1.5.4
curl -O https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
hash -r # reset bash cache
pip --version # 6.0.8

The hash -r line is essential!

reference: https://pip.pypa.io/en/latest/installing.html

Similar Posts: