ssh keys管理工具

原文地址:https://rtyan.github.io/%E5%B7%A5%E5%85%B7/2017/09/12/ssh-keys-manager.htmlhtml

引言

我有兩個github帳戶,一個是平時正常使用的,另一個是用來專門作博客用的,
由於以前經常使用的那個作博客名字很差看o(╯□╰)o。git

這就引起了一個問題,我想在博客帳戶中添加ssh keys的時候,github會提示
我下面的信息github

原來,同一個公鑰只能在github系統中添加一次,重複添加的話會報這個錯誤,就算
是不一樣的帳戶也不能將同一個公鑰添加屢次。shell

這個問題要怎麼解決呢?bash

暴力法——從新生成

最簡單的方法,也就是直接生成一套新的公鑰密鑰對,而後添加到個人博客帳戶中,
等下次再用經常使用的帳號時候再從新生成一套,再替換經常使用帳號中的ssh keys就能夠
了,事實上我第一次就是這麼幹的,沒徹底弄清楚怎麼回事,只能按照流程從新生成
一遍了,並且確實生效了。ssh

但用了幾回以後我發現不用從新生成、只要在本地生成兩份ssh keys,而後每次講要
使用的ssh keys命名爲id_rsaid_rsa.pub就能夠了,不用每次替換帳號中的配置了。工具

但用了一段時間,發現仍是很麻煩,是在太難受了,因而就想着寫一個半
自動化的建立、切換ssh keys的工具。優化

半自動化法

沿着上面的思路,我能夠生成多套ssh keys,而後將他們管理起來,每次使用的時候
只須要將他們替換到id_rsaid_rsa.pub就能夠了,省略了人工去切換。就像下面
這樣:this

➜  rtyan.github.io git:(master) git push origin master
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
➜  rtyan.github.io git:(master) sshkeys change rtyan
切換ssh keys對,從[aizuyan]到[rtyan]...
複製/Users/ritoyan/.ssh-keys-pair/rtyan到/Users/ritoyan/.ssh/id_rsa成功
複製/Users/ritoyan/.ssh-keys-pair/rtyan.pub到/Users/ritoyan/.ssh/id_rsa.pub成功
切換到rtyan成功
➜  rtyan.github.io git:(master) git push origin master
Counting objects: 8, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 77.54 KiB | 0 bytes/s, done.
Total 8 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), completed with 5 local objects.
To github.com:rtyan/rtyan.github.io.git
   a05e55f..50b54a7  master -> master

目前已經開發完成,用shell完成的,最後面會將代碼貼出來。code

工具生成的全部ssh keys pairs都保存在~/.ssh-keys-pair/目錄下,就下下面
這樣:

-rw-------  1 ritoyan  staff  3243  9 12 21:15 backup
-rw-r--r--  1 ritoyan  staff   741  9 12 21:15 backup.pub
-rw-r--r--  1 ritoyan  staff     6  9 12 21:16 nowRecord
-rw-------  1 ritoyan  staff  3243  9 12 21:15 rtyan
-rw-r--r--  1 ritoyan  staff   741  9 12 21:15 rtyan.pub

其中backupbackup.pub記錄了軟件安裝以前的ssh keys信息(若是有的話)。

nowRecord記錄了當前使用的是哪一個ssh keys,裏面的內容等同於~/.ssh-keys-pair/
目錄下的密鑰名稱。

其餘文件的話就是公鑰密鑰對了,密鑰是 <生成時候的名稱> ,公鑰是 <生成時候的名稱> .pub

列出全部ssh keys列表的時候就是經過匹配~/.ssh-keys-pair/文件夾下面的.pub
後綴來的,匹配上了就算是一個公鑰密鑰對。

安裝

安裝的話直接把最下面的shell代碼複製到/usr/local/bin/sshkeys中(或其餘$PATH
目錄中),而後執行chmod +x /usr/local/bin/sshkeys給腳本加上可執行權限,而後
就能夠看命令使用了。

命令

這個工具一共5個命令,功能分別以下(也能夠直接看代碼):

sshkeys init

初始化環境,備份原來的ssh keysbackup,設置當前使用的ssh keys名稱爲backup

sshkeys list

列出當前全部的ssh keys名稱,當前使用的前面有星號:

➜  GIT sshkeys list
  aizuyan
  backup
* rtyan

sshkeys create <name> [<email>]

上面的命令是建立一個名稱爲<name>ssh keys,後面的<email>是可選項:

➜  GIT sshkeys create aizuyan ritoyan@163.com
開始建立密鑰公鑰對...
執行命令[ssh-keygen -t rsa -b 4096 -f /Users/ritoyan/.ssh-keys-pair/aizuyan -q -N "" -C "ritoyan@163.com"]
建立成功

sshkeys showpub [<name>]

上面的命令是展現公鑰,後面的<name>是可選的,默認展現當前正在使用的,加了參數顯示
對應<name>的公鑰:

➜  GIT sshkeys showpub aizuyan
ssh-rsa AA.........Vw== ritoyan@163.com

sshkeys change <name>

切換到對應<name>ssh keys

➜  GIT sshkeys change aizuyan
切換ssh keys對,從[rtyan]到[aizuyan]...
複製/Users/ritoyan/.ssh-keys-pair/aizuyan到/Users/ritoyan/.ssh/id_rsa成功
複製/Users/ritoyan/.ssh-keys-pair/aizuyan.pub到/Users/ritoyan/.ssh/id_rsa.pub成功
切換到aizuyan成功

代碼

代碼又長又臭,能夠忽略過了,想看的看下。
還有不少地方要優化,不過如今我用是夠了,哈哈。

#/bin/bash

# 存放數據的根目錄
softBase="${HOME}/.ssh-keys-pair/"
sshBase="${HOME}/.ssh/"
sshIdRsaPath="${sshBase}id_rsa"
sshIdRsaPubPath="${sshBase}id_rsa.pub"
nowSshPairRecordPath="${softBase}nowRecord"

action=$1

function init()
{
    # 判斷根目錄是否存在,不存在建立
    if [ -d $softBase ];then
        return 1
    fi
    echo "初始化..."

    #[1] 建立目錄
    echo "[1]建立必要的目錄..."
    mkdir -p -m 700 $softBase
    if [ $? != 0 ];then
        echo "[1-1]建立目錄${softBase}失敗"
    else
        echo "[1-1]建立目錄${softBase}成功"
    fi

    #[2] 備份如今的sshkey
    echo "[2]備份當前的ssh key pair"
    if [ -f "${sshIdRsaPath}" ];then
        cp $sshIdRsaPath "${softBase}backup"
        if [ $? != 0 ];then
            echo "[2-1]備份${sshIdRsaPath}到${softBase}backup"
        else
            echo "[2-1]備份${sshIdRsaPath}到${softBase}backup"
        fi
    else
        echo "${sshIdRsaPath}文件不存在,不須要備份"
    fi
    if [ -f "${sshIdRsaPubPath}" ];then
        cp $sshIdRsaPubPath "${softBase}backup.pub"
        if [ $? != 0 ];then
            echo "[2-2]備份${sshIdRsaPubPath}到${softBase}backup.pub失敗"
        else
            echo "[2-2]備份${sshIdRsaPubPath}到${softBase}backup.pub成功"
        fi
    else
        echo "${sshIdRsaPubPath}文件不存在,不須要備份"
    fi

    #[3] 設置當前sshkeys
    echo "[3]設置當前sshkeys記錄"
    if [ -f "${sshIdRsaPubPath}" ];then
        echo "backup" > $nowSshPairRecordPath
        if [ $? != 0 ];then
            echo "[3-1]設置當前sshkeys記錄爲[backup],寫入${nowSshPairRecordPath}失敗"
        else
            echo "[3-1]設置當前sshkeys記錄爲[backup],寫入${nowSshPairRecordPath}成功"
        fi
    fi

    echo "初始化成功\n"
    return 0
}

function nowRecord()
{
    local nowRecord=`cat ${nowSshPairRecordPath}`
    echo $nowRecord
    return 0
}

# 列出全部的公鑰名稱
function list()
{
    local files=`ls $softBase | grep "\.pub\$"`
    local file
    local nowRecord=`nowRecord`
    for file in ${files}
    do
        sshKeysName=${file%%.pub}
        if [[ $nowRecord == $sshKeysName ]]; then
            echo "* "$sshKeysName
        else
            echo "  "$sshKeysName
        fi
    done
}

# 建立一對新的密鑰
# $1 密鑰名稱  必選
# $2 郵件 可選
function create()
{
    keyPairName=$1
    maybeEmail=$2
    createPath="${softBase}${keyPairName}"
    cmd="ssh-keygen -t rsa -b 4096 -f ${createPath} -q -N \"\""
    if [[ $maybeEmail ]]; then
        cmd="${cmd} -C \"${maybeEmail}\""
    fi
    echo "開始建立密鑰公鑰對..."
    echo "執行命令[${cmd}]"
    eval $cmd
    if [ $? != 0 ];then
        echo "建立失敗"
    else
        echo "建立成功"
    fi
}

# 切換ssh keys
function change()
{
    local keyPairName=$1
    local rsaPath="${softBase}${keyPairName}"
    local rsaPubPath="${rsaPath}.pub"
    local preSshPairRecord=`nowRecord`
    echo "切換ssh keys對,從[${preSshPairRecord}]到[${keyPairName}]..."
    cp $rsaPath $sshIdRsaPath
    if [ $? != 0 ];then
        echo "複製${rsaPath}到${sshIdRsaPath}失敗"
    else
        echo "複製${rsaPath}到${sshIdRsaPath}成功"
    fi
    cp $rsaPubPath $sshIdRsaPubPath
    if [ $? != 0 ];then
        echo "複製${rsaPubPath}到${sshIdRsaPubPath}失敗"
    else
        echo "複製${rsaPubPath}到${sshIdRsaPubPath}成功"
    fi
    echo "${keyPairName}" > $nowSshPairRecordPath
    if [ $? != 0 ];then
        echo "切換到${keyPairName}失敗"
    else
        echo "切換到${keyPairName}成功"
    fi
}

function showpub()
{
    local keyPairName=$1
    if [ -z "${keyPairName}" ]; then
        keyPairName=`nowRecord`
    fi
    local keyPubPath="${softBase}${keyPairName}.pub"
    cat $keyPubPath
}

case "${action}" in
    "init" )
        init
        ;;
    "list" )
        list
        ;;
    "create" )
        keyPairName=$2
        maybeEmail=$3
        create "${keyPairName}" "${maybeEmail}"
        ;;
    "change" )
        keyPairName=$2
        change "${keyPairName}"
        ;;
    "showpub" )
        keyPairName=$2
        showpub "${keyPairName}"
        ;;
    * )
        echo "this is action none"
        ;;
esac
相關文章
相關標籤/搜索