HOWTO: Import Public Keys to SSH authorized_keys

Saturday, July 29, 2017

A little while back I was looking for a way to add a handful of users to the authorized_keys file on some test servers.

This server necessarily required the existence of only one account that when troubleshooting was required, would be used to login/troubleshoot. These servers would be rebuilt every morning and it would have probably been fine to share a password and just login with shared credentials, but the security guy in me is allergic to enabling Challenge/Response authentication. The alternative – sharing a public/private keypair among users – is also a huge no-no0.

Unfortunately, where public/private keys were in use, they were generally generated by the users themselves – one of the perks of being at a dev shop with a bunch of folks who seriously know what they’re doing is that they have generally done this ‘correctly’, however, we didn’t have a central server that stored a record of the public keys for easy distribution.

Another side-effect of being at a dev shop is that many of the users were Keybase users. Unfortunately, Keybase keys are PGP keys, not SSH keys and the two key formats are not inter-changeable. Worse, still, is that they’re really not designed for the same purpose. In the GnuPG world, a key used for authentication would almost always have a sub-key for that purpose. Having been using my keybase key for login to SSH for a while, I’ve had a script (albiet, one that only works with gpg v1) to automate exporting the public/private keypair, making it easy to get the public key to the server with a simple ssh-copy-id, but what about when I have a few users I want to provision without ever handling their private key? I couldn’t find a good reference for doing that so I figured it out on my own.

Importing a GPG public key without the private key and without installing the keybase client

I wrote a shell script, located here, if you want to skip the details and just run it.

Simply login as the user you wish to add an authorized key to and:

chmod 770 ./ # only needed the first time
./ <id> # where ID is the keybase ID

It requires GnuPG 2 to execute (at least version 2.1.11) because it relies on a feature added in that version.

The script works by grabbing the public key via’s public API (beta) and calling GnuPG 2 with the --export-ssh-key (forced with the “!”) to convert the key from GnuPG public key format to SSH public key format.

Because various distributions’ packagers install gpg in different ways, there’s a few checks to figure out which gpg binary is version 2 (often it’s gpg2) and a check to ensure the v2 binary is at the right minor/patch versions to successfully run the script. I also discovered some odd differences in the way that GnuPG 2 behaves between a few distributions – sometimes returning the 32-bit fingerprint rather than the 64-bit fingerprint, so I take an extra step to get the 64-bit fingerprint with some awk parsing.

Currently, this only handles grabbing the public key and it does so without touching the private key (which is something that requires a lot more delicate handling). I’m working on a script to download/import the private key (as well as password protect both the ssh private key and protect it in the GnuPG database). I’ll post that as soon as I’m comfortable that it’s somewhere resembling “safe”, but for the time being, there are several scripts out there that allow you to do this and I’ve tested a few of them against the method I’m using here. They all have worked.

0 I sort of hope I don’t have to explain why, but one big reason is that if one of those employees leaves the company, the shared credential has to be destroyed and removed from every host and a new one has to be issued to all of those users. If one uses

Resetting the Visual Studio Experimental Instance Visual Studio 2010-2017 via PowerShell

Wednesday, July 5, 2017

There’s a handful of things that you have to do frequently enough when debugging a Visual Studio extension that it becomes almost routine, but not frequently enough for you to actually remember the exact shape of the command you need to run.

Since I got horribly tired of having to hit up Bing every time I needed to remember the specific command, I decided to document some of them here.

The TL;DR; - Use PowerShell to Reset the Visual Studio Experimental Instance

I’ve created a simple script to reset the Visual Studio instance, available here. It takes two parameters, -Version and -InstanceName (which matches the “RootSuffix” parameter used … most of the time). You needn’t run it from a Developer Command Prompt, it grabs the install locations from the registry.

Some Useful Bits to Remember

Visual Studio Version Mapping and .Net Framework

Marketing Version Actual Version Framework Versions
2010 10.0 4.0
2012 11.0 4.5.2
2013 12.0 4.5.2
2015 14.0 4.6
2017 15.0 4.6.2

Default Visual Studio Paths

For these defaults, I’m assuming you’re on a 64-bit operating system. If you’re still stuck banging rocks together on a 32-bit OS, just knock out the (x86) where you see it.

Visual Studio 2010 - 2015

The paths for these versions have been pretty predictable. They start in %ProgramFiles(x86)%, which usually maps toC:\Program Files (x86) and are stored in Microsoft Visual Studio 1x.x where x corresponds to one of version numbers in the Actual column.

Install Root:

"${env:ProgramFiles(x86)}\Microsoft Visual Studio 1x.x"

… or if you prefer cmd.exe:

"%ProgramFiles(x86)%\Microsoft Visual Studio 1x.x"

Visual Studio 2017

Things were reorganized a little bit with Visual Studio 2017. The install root is now located at:

"${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\<Edition>"

Where <Edition> is going to correspond to the edition, Community, Professional or Enterprise.

In addition, the RootSuffix, at least on my machine, is only part of the suffix name. This is a fact that Visual Studio understands, but the tool for creating/managing the experimental instances from the command prompt does not.

The PowerShell script provided above will provide you with experimental instance names if you attempt to reset one that doesn’t exist (as would happen if you provided Exp but the name was actually _70a4f204Exp

Refresh the Experimental Instance with the Script

Basic help can be found by typing Get-Help ResetExperimentalInstance.ps1 -Full, but here’s how you use it:

.\ResetExperimentalInstance.ps1 [-InstanceName] <InstanceName> [-Version <Version>]

Version - Optional - If you have only one version of Visual Studio installed. Note that this includes applications that use other versions of Visual Studio, like SQL Management Studio and System Center Configuration Manager’s management tools. If you have more than one version installed, the script will exit but will print the versions that are available.

InstanceName - Required - Usually the same as what is provided as the /RootSuffix parameter in the Debug panel within Visual Studio for your extension. However, it may actually be _[some 32-bit Hex][RootSuffix], i.e. _71af83c4Exp for the Exp instance. If a corresponding folder for that instance is not found, you’ll be given a list of all of the instances that are found for the provided version and prompted as to whether or not you want to create a new experimental instance.

The _ in the long name is required for the Visual Studio provided tool, CreateExpInstance.exe, which the script uses. However, the script will look for a folder that only differs by the starting _ and will correct your InstanceName if that’s the only difference.