Life Of Navin

Random Musings, Random Bullshit.


Google Authenticator 2FA on Mac OS with oathtool

Multi-factor authentication (Commonly 2FA) is a security godsend. You really should enable it on every account you have that supports it. I usually use Google Authenticator for time-variant OTP systems. However, I find it irritating to have to reach for my phone to check for the OTP every time I log in to a site. Why do I find it irritating? Because of 2 reasons:
  1. I actually have to get to my physical device, which I usually don't carry around with me. 
    • In office, I usually keep my phone away from me to avoid distraction/unwanted calls/notifications.
  2. Even after I open up Authenticator, I have to type out the digits from screen to screen. 
    • I know there are other alternatives, but Google Authenticator is most widely supported across services I use daily: AWS, Okta, Google Suite, Pager etc. and it's not going away soon.
I always wondered if there is an easier way to get the added security of 2FA, with more flexibility. And the solution was to simply use 2FA from my laptop itself. So I came up with a workflow. This is my current workflow on Mac OS Sierra (but should work on any Mac).

Step 1: Generate 2FA tokens on laptop
This turned out to be simpler than I imagined. I simply needed to use the awesome oath-toolkit, which basically behaves like Google Authenticator for the laptop. It can be used to easily generate time-variant one time passwords, which is what GA does! Setting it up is a breeze:

$ brew install oath-toolkit
$ oathtool --totp -b "your_key_here" | pbcopy

The key you use here is a key generated when you set up OTP (You probably remember scanning a QR code). If you don't have the key saved locally, you will have to do a one-time reset of your 2FA to generate a new key.

We pipe the generated token to pbcopy to copy it to clipboard. This allows us to generate totp tokens and have them ready to be pasted when needed. No need to look for your mobile phone for OTP anymore!

Step 2: Smoother Workflow
Now that we can generate OTP tokens without a phone, let's clean up the process. Currently, we need to go to the terminal every time we want to generate a new token. What if we could bind this to a global key command instead? Mac OS has an awful global keyboard macro system (Yay Linux as always), but it can still be done. This is how I do it:
  • Install ICanHazShortcut, a nifty Mac app for global hotkeys. It's not too fancy, but delivers what it promises!
  • Set up an Automator service to simply paste clipboard contents when called:
    • Go to Applications -> Automator -> New -> Service
    • Service receives "no input" in "any application"
    • Drag the "Run Applescript" action to the right and fill in the following and then save the workflow as paste-from-clipboard. You can save it in your home directory:

  • Finally, bring it all together! Set up keyboard shortcuts in ICanHazShortcut, and set the command to run as:  
/usr/local/bin/oathtool --totp -b "your_key_here" | pbcopy | automator ~/paste-from-clipboard.workflow/
Here I assume that the workflow you created was named paste-from-clipboard and saved in your home directory. You may not need to specify the full path for oathtool, but I had to.

And that's it! Now whenever you're on a page that needs a 2FA token, simply type in your keyboard shortcut, and your token will be filled in!

...And the love kickstarts again ;)

PS: Yes, this is unsafe because if someone get's physical access to your system, then he can access your 2FA key and generate tokens, thereby rendering your 2FA useless. Then again, if he has physical access to your system, then this is just one of a million ways to get access to your data, so the attack vector surface increase is not as prominent. Of course, if you're uber concerned about security, skip this. But if you want a compromise between security and usability then this is a decent solution! :)

Debugging Running JVM Without Restart

Debugging a process actively running on a JVM without restarting the application and setting up flags and attaching a debugger is a a bit of a pain. However, there's quite a bit you can do to debug a running process without needing a JVM restart.

This. But with less enthusiasm. Much less enthusiasm.
Here's a quick walkthrough, with the associated commands. I'm simply compiling the steps to allow a single lookup for everyone else who has to walk down this road.
  • Ensure that it is the JVM which is consuming too many resources. A combination of free and sorting ps output should do the trick.  free tells us current memory consumption, while ps gives us process level statistics
$ free -m
                            total        used   free   shared   buffers   cached
  Mem:               15040    13956  1083      0          84         890
  -/+ buffers/cache: 12980 2059
  Swap:                  0            0        0

$ ps -eo pmem,pcpu,vsize,pid,cmd | sort -k 1 -nr | head -5 

69.8  67.5 8180544 24204 java -Duser.dir=[...]
  7.5   5.6 1550956 4866 python /mnt/ run_gunicorn -c /mnt/
  7.4   6.3 1542356 4848 python /mnt/ run_gunicorn -c /mnt/
  7.4   6.0 1548132 4863 python /mnt/ run_gunicorn -c /mnt/
  7.4   5.8 1537104 4869 python /mnt/ run_gunicorn -c /mnt/

Wow, so we seem to have barely a GB of memory free and a resource hog java process and a bunch of gunicorn processes. Let's take a look at the Java process shall we? The pid is 24204 (highlighted in previous command)
  • Let's find thread utilization of resources. ps to the rescue again!
$ ps -mo 'pid lwp stime time pcpu' -p 24204
        PID   LWP   STIME   TIME   %CPU
    24204       -      16:12   00:32:41   17.4
          -   24204   16:12   00:00:00   0.0
          -   24255   16:12   00:00:03   0.0
          -   24256   16:12   00:01:11   0.6
          -   24257   16:12   00:01:11   0.6
          -   24258   16:12   00:01:11   0.6
          -   24259   16:12   00:01:11   0.6
          -   24260   16:12   00:06:34  33.5
          -   24261   16:12   00:00:11   0.0
          -   24262   16:12   00:00:00   0.0
          -   24263   16:12   00:00:00   0.0
          -   24264   16:12   00:00:00   0.0
          -   24265   16:12   00:00:00   0.0
          -   24266   16:12   00:00:43   0.3
Interesting. It looks like a single issue here. How do we trace this? Why, we take a couple of thread dumps of course! We use jstack for this. jstack simply produces a thread dump of the given process.

jstack 24204 > 1.dump
jstack 24204 > 2.dump
jstack 24204 > 3.dump

I usually take multiple jstacks just for further analysis. You may also need to run jstack as sudo as sudo -u user jstack <pid>

  • Now we have the thread dump and the misbehaving thread, so we can check what that thread is doing. Since thread id in the previous command (24260) is a decimal, we first convert it into hex because thread dumps use hex ids. To do this we simply use bc to convert the number, and then tr to transform the uppercase into lowercase. 
$ echo "obase=16; 24260" | bc | tr '[:upper:]' '[:lower:]'
5ec4  # this is the thread id in hex

$ vim 1.dump # Now search for the thread hex in the dump file
"Concurrent Mark-Sweep GC Thread" os_prio=0 tid=0x00007fea2c083000 nid=0x5ec4 runnable
So it turns out in this specific case that the GC is taking up a massive number of CPU cycles. The solutions for this are numerous, and may vary depending on what your constraints are. The other issues may be related to database access, I/O access, or, quite frankly, a million other reasons relating to badly written code.

To be honest, this method of debugging does have it's constraints, but can be a godsend when you need to quickly validate your thinking when it comes to resource hog bugs. And of course, you can celebrate by posting memes on slack!

At Bloomreach, we prefer :patre: #insidejoke
Hope this is helpful! Until the next b̶u̶g̶ feature...  :D

PS: Yes, I know the first couple of steps can be done using htop as well, using htop in thread view. I just find ps so much more convenient

The Best Teacher.

I am .
I .
I .
I will win!
This page generates a new set of typos every time someone visits the page. It has enough variation that you can (almost) safely claim that every person on this site sees a personalized set of mistakes, never seen before by anyone and never to seen again by anyone. Eternally looking for perfection, just like you and me.

Thank You Mario. Your Quest is Over!

For as long as I can remember, I've been addicted to technology. And I can happily credit a childhood spent interacting with technology as the reason for that. The first time I was blown away by technology was when I was lucky enough to own a Nintendo NES console (a FamiCom rather).

I spent hours and hours saving the princess in Super Mario Bros, and shooting up ducks in Duck Hunt, and building mazes in Battle City, or simply running around shooting people as Mega Man.

Ah Childhood!
So when Nintendo announced the Mini NES Classic just before Christmas, I was possessed by a near Gollum-like need to possess one of these beauties. Alas, Nintendo really underestimated the nostalgia quotient of the NES, and for over a month, the NES Classic supply chain seemed nearly non-existent. I had a (sort of) planned visit to Mountain View starting the first week of Feb, and decided that I simply could not return without getting my hands on a NES Classic.

My Precious!
So this is where my story starts:

From the day I got to MV, I started lurking around message boards on Reddit which discussed the Mini NES. /r/MiniNES was the best forum, with a lot of likeminded, nostalgia-fuelled gamers looking to get a late Christmas present. This is where I read about this amazing site called BrickSeek. The concept of Brickseek itself is so amazing. Basically, they collate data from Target/Walmart/CVS etc. using their own inventory IDs (or SKUs as they call them) and allows people to query to find product availability in different stores. While they do not claim to be 100% accurate, they are nonetheless a godsend when looking for hard to find products. I had a BestBuy a block away from my hotel, a Target a couple of blocks away, and a Walmart about 2-3 miles away. So I assumed I had a good chance. Oh boy, was I wrong!

The NES Classic turned out to be so much harder to find than I expected it to be. Nintendo even put out a press release apologizing for the delay in restocking, and BrickSeek just kept showing a total count of 0 in all stores in a 100 mile radius from me. I read 1-2 posts a day on Reddit of people who somehow managed to get one, and that mostly included people who saw an update on Brickseek and camped outside a Target from 4:30 AM!

And then it happened. This post came up on Reddit:

Moist_Cookies for President!
I clicked on the link 9 minutes after it was posted. Was it too late? Load you damn page, load! And almost unbelievably, it was still "In Stock". Buy Now. Buy Now. Buy Now. Typed out my card details faster than I ever have and pressed Buy. Credit card debited $$$. OMG THIS IS REALLY HAPPENING. There's an email confirmation as well! Doo-doo Do-doo-do Doo doo!

But wait, what's this? Another email from BestBuy?

NOOOOOOOO! I quickly visited the page again to reorder but by now, it's gone back to it's dormant state of "Out of Stock". Y U NO GIVE ME NES CLASSIC BESTBUY?

This event really felt sad. More so, because almost everyone else on the MiniNES reddit seemed to have gotten their order placed successfully. Stupid international credit cards. Either way, the wait continued.

The next few days I almost gave up on the idea of getting a MiniNES. People on forums got more and more cynical about the stock being replenished in physical stores, and even when they were, stories of store employees themselves buying them to sell later at hyper inflated prices (3-4x the MSRP) became common place. These grapes are sour anyway, I though to myself at a point.

One fine evening around 9PM, after a day spent tinkering with code, I remember the quest I had left incomplete, so I open up BrickSeek. Target, as with every other time I have checked, shows zero stock. Walmart, as with every time I've che... WAIT WHAAAT? The Milpitas Walmart, which is about 12 miles away from my hotel shows a stock of 6. Not 1 or 2.... but 6! How can this even be true? The most ANY store has shown has been in the range of 1-2. Six is too good to be true, but I need to get this. I google the store timings, and it says it's a 24 hours Walmart. I know everything I need to know. I pull on a hoodie, and I jump into my car to drive down to Milpitas.

Is this the real life?
It's about 10PM by the time I get there. And I practically run to the electronics section. No one at the counter, though I see a couple other people waiting, and I already know what they're waiting for! I do a quick count, and there's 7 other people there already. Gulp!

The guy manning the counter comes up. He's a senior Korean gentleman, who fits every Korean stereotype you can think of. "Hey, I am looking to get a NES Classic for my son" says a distinctly Indian gentleman ahead in line, pointing to the kid next to him. Oh, so they'll just buy one. So there's 6 other people there. But wait, a huge american guy is also here with what looks to be his partner. And maybe they'll also buy just one. Just 5 people! "Are you all waiting for the NES Classic?" asks the Korean Gentleman. "Yes". "Yes". "Yup".  "Yeah". "No, I'm waiting for the PS3 controller". OMG! Just 4 people. But Korean guy has vanished now, and no one knows what to do but wait for him to return.

As people start walking around looking at us, the Indian dad comes up with an idea to make chits, just to ensure sanity. Everyone agrees, and he takes up a brochure lying on a table and makes 6 chits, expecting more people to join the waiting line. Huge American Guy gets #1, Desi Dad gets #2, Solo Gamer Chick (I'll tell you about her soon) gets #3 and I get #4. All Fair and square so far. Korean guy comes back and says that he's paged a manager but no one seems to be responding because it's late. We ask if he can at least check inventory. He says Walmart uses internal skus. Literally all 4 of us offer the internal skuid for him to track, but he mumbles something and goes away again. Will this night end in glory or despair?

It takes literally 20 minutes of us just standing there before a manager comes. "Hey, what you guys here for?". "Thee YenEeEss Classic konsowl" offers the Korean gentleman.  "Oh yes, we have them in the back..." says the manager. Phew, I think. "... but we have just 2 with us right now." What? No, What? How many? What? "Not again" squeals the Solo gamer chick, who's holding the #3 chit. Turns out the same thing has happened to her at a Target a couple weeks back and at another Walmart a week ago! Damn. Damn. Damn.

Sigh. I guess it's just bad luck. Maybe it's not meant to be after all. Maybe I'll just get a PS4 instead. Maybe I'll not tell anyone I came to Walmart at 10PM to look for a gaming console. All these random thoughts going on in my mind, and a good 5 minutes have passed since the manager went into the back to get the NES for the lucky two. I at least want to see what the box looks like. And apparently so does Solo gamer chick, who has also not moved an inch for over 5 minutes at this point.

Out comes the manager with a box, and puts it on the counter proclaiming "Turns out we have 4! Do you know who all are getting them?" "Eep" squeaks the Solo gamer chick (or maybe it was me and her both... or maybe just me....  but it's my blog and I want to sound Macho). In a way, even the Huge American Guy and Desi Dad are happy because everyone there gets an MiniNES! As they say, "Fortune favors the brave".

After three consecutive "Would you like replacement guarantee?" "No thanks" "It's $64.xx" "Thanks" conversations, I'm up. I don't want any replacement guarentee. Just shut up and take my money I think, channeling my inner 9Gag. And that's it! The beauty was mine!

I've played around with this only a couple of times since I got it, but I must admit, it really is as awesome as I expected. I'm not really going to get into a full review because many people have already done that and the Pros almost always outweigh the Cons in most reviews. Be it simply for Nostalgia (the CRT Filter mode is especially nostalgia inducing), or for paying homage to a company that led the gaming revolution, the NES Classic is everything it promised to be. I actually spent a little more to get a second controller to allow multiplayer mode and can't wait to get home and play with my little sister!

Mario, the princess is in another castle!
At some point, I'll also probably use the now famous hack/mod to add more games to the NES Classic, but that'll happen only after I've run through everything on this device right now! :)

All in all, My quest well played and memories to last for a long time to come.

up - down - up - down - left - right - left - right - b - a
up - down - up - down - left - right - left - right - b - a
up - down - up - down - left - right - left - right - b - a 



Finally after all these years, here's to the beginning of what was there, what is there and hopefully what will remain!! So here are my thoughts & words -Online!!