How to get SSH public keys for any user from GitHub

How to get SSH public keys for any user from GitHub

If you use GitHub regularly, you most likely have uploaded your SSH Public Key(s) to connect with GitHub.

It is helpful when you want to interact with GitHub with Git via SSH. For example, you do not need additional authentication when cloning private repositories or pulling and pushing changes to them.

But there are other uses for uploading your SSH Public Key to GitHub. You can use GitHub as your public key server. For example, if you need SSH access to a remote server, you can ask the sysadmin to import your SSH Public Key by pointing them to a URL.

The URL looks like this and is available for every user who has uploaded their SSH Public Keys to GitHub:

https://github.com/USERNAME.keys

Here's mine, for example: https://github.com/raisedadead.keys.

You can copy the SSH public keys for any user and add them to the authorized_keys file on the servers you need access via SSH.

Use ssh-import-id to quickly import keys

You can import SSH Public Keys very quickly using a CLI tool called ssh-import-id on your machine:

ssh-import-id gh:raiseadead

Quick reference:

'gh:' for Github
'lp:' for Launchpad

Full reference: https://launchpad.net/ssh-import-id

Use GitHub's API for getting SSH Public Keys

But there is even more; GitHub has an API to fetch them programmatically. So, you can script your way into automatically adding your (and your friends') keys from GitHub.

The API documentation is available here: docs.github.com/en/rest/users#list-public-k...

Neat—let's try it out!

Getting SSH Public keys from the GitHub API with GitHub CLI:

Working locally (or when scripting in an environment like bash, etc.) you can use GitHub CLI to get the SSH Public key for any user with a simple command:

gh api \
  -H "Accept: application/vnd.github.v3+json" \
  /users/USERNAME/keys

Learn more about this feature in GitHub CLI here: cli.github.com/manual/gh_api

Getting SSH Public keys from the GitHub API with Code (TypeScript example):

Next, let's see a demo with TypeScript, but you should be able to replicate the same in any language.

Note in the below example, I am using the @octokit/core package to interact with the GitHub API, but you should be able to use something like node-fetch as well.

import { Octokit } from '@octokit/core';

const octokit = new Octokit({
  auth: process.env.GITHUB_PA_TOKEN
});

interface keyMap {
  username: string;
  publicKeys: string[];
}

export const getSSHKeysForUser = async (user: string): Promise<keyMap> => {
  const data = await octokit
    .request(`GET /users/${user}/keys`, { username: user })
    .then((res) => {
      return res.data;
    })
    .catch((err) => {
      console.log(
        `Error getting public SSH keys for user ${user}. Got status: ${err.status}`
      );
      return [];
    });

  return Promise.resolve({
    username: user,
    publicKeys: data.map(({ key }: { key: string }) => key)
  });
};

export const getSSHKeys = async (users: string[]) => {
  return await Promise.all(users.map(getSSHKeysForUser));
};

(async () => {
  // Get keys for a single user
  console.log(await getSSHKeysForUser('ghost'));

  // Get keys for multiple users
  console.log(await getSSHKeys(['ghost', 'raisedadead']));
})();

For the complete code, you can check out this repository.

I hope you liked this story, until the next one.

Did you find this article valuable?

Support Mrugesh Mohapatra by becoming a sponsor. Any amount is appreciated!