使用數據庫統一管理ssh登陸用戶密鑰信息

使用數據庫統一管理ssh登陸用戶密鑰信息

    需求是由一個開發部門提出的,他們需要在他們的測試服務器上開放root權限給所有的開發人員,同時要給每個開發人員配置無密碼登錄,由於使用ssh默認的認證文件存儲公鑰不方便人員信息的管理(例如一個人離職後不方便在大量的key中找到他的key,且需要在大量的服務器上全部刪除)。

    基於上述需求,我們決定將所有人員的key和其對應的fingerprint保存在數據庫中,而且每個fingerprint都對應一個真實用戶名,在用戶登錄的時候,雖然都是使用root用戶登錄,但是,其登錄的時候不會再到autherized_keys文件中查找key,而是根據用戶傳遞的fingerprint去數據庫中查找對應的公鑰。

    爲了實現上述的需求,我們需要用戶在使用ssh登錄的時候首先去執行一個取公鑰的腳本,然後再根據腳本取回的key來驗證用戶。這裏需要用到兩個ssh的配置參數AuthorizedKeysCommand和AuthorizedKeysCommandUser,第一個參數用來指定登錄時執行的腳本文件,第二個參數用來指定這個腳本的用戶,這裏要注意,這個腳本權限必須是700且屬組屬主必須是root。這兩個配置參數在低版本的openssh中無法使用,需要首先升級openssh的版本,而且在升級時需要我們修改一部分openssh的源碼,本文中升級到了ssh 6.6p1這個版本。

    一、升級openssh

    準備升級openssh的源碼包,在官網上找到6.6版本的源碼包並下載:

[root@localhost ~]# wget http://ftp.jaist.ac.jp/pub/OpenBSD/OpenSSH/portable/openssh-6.6p1.tar.gz
[root@localhost ~]# tar -zxf openssh-6.6p1.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/openssh-6.6p1

    解包完成後,我們要更改一下其源碼,更改解壓後目錄下的auth2-pubkey.c文件

//512行左右
 struct passwd *pw;
        struct stat st;
        int status, devnull, p[2], i;
        pid_t pid;
        //char *username, errmsg[512];    註釋掉此行代碼
        char *username, *fp, errmsg[512];    添加此行代碼

        if (options.authorized_keys_command == NULL ||
            options.authorized_keys_command[0] != '/')
                return 0;
//552行左右

        if (pipe(p) != 0) {
                error("%s: pipe: %s", __func__, strerror(errno));
                goto out;
        }

//      debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",    註釋掉這行
//          options.authorized_keys_command, user_pw->pw_name, pw->pw_name);  註釋掉這行
        fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);    添加這行
        debug3("Running AuthorizedKeysCommand: \"%s %s %s\" as \"%s\"",
            options.authorized_keys_command, user_pw->pw_name, fp, pw->pw_name);
        /*
         * Don't want to call this in the child, where it can fatal() and
         * run cleanup_exit() code.
         */
        restore_uid();

        switch ((pid = fork())) {
        case -1: /* error */
//602行左右
/* stdin is pointed to /dev/null at this point */
           if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
                    error("%s: dup2: %s", __func__, strerror(errno));
                    _exit(1);
            }

            execl(options.authorized_keys_command,
            //    options.authorized_keys_command, user_pw->pw_name, NULL); 註釋掉此行  
                  options.authorized_keys_command, user_pw->pw_name, fp, NULL); 添加此行

             error("AuthorizedKeysCommand %s exec failed: %s",
                 options.authorized_keys_command, strerror(errno));
             _exit(127);
        default: /* parent */
                break;
        }

        free(fp);    添加此行
        temporarily_use_uid(pw);

    改完上述源碼後,我們將更改後的源碼打成rpm包來升級:

[root@localhost ~]# cd /usr/src/openssh-6.6p1/contrib/redhat    #本文系統爲CentOS 6.5
[root@localhost ~]# vim openssh.spec    #更改spec文檔,關閉一些用不到的參數
# Do we want to disable building of x11-askpass? (1=yes 0=no)
%define no_x11_askpass 1        #此處設置爲1,不構建x11-askpass

# Do we want to disable building of gnome-askpass? (1=yes 0=no)
%define no_gnome_askpass 1      #此處設置爲1,不構建gnome-askpass
[root@localhost ~]# cd /usr/src/
[root@localhost ~]# tar -zcf openssh-6.6p1.tar.gz openssh-6.6p1/
注意:此處必須在/usr/src/目錄下打包,否則製作rpm包時會報錯,且文件名必須如上所示
[root@localhost ~]# cd /usr/src/openssh-6.6p1/contrib/redhat
[root@localhost ~]# rpmbuild -bb openssh.spec    #開始製作rpm包
注意:製作rpm包的時候可能會遇到依賴包不全的問題,常見的有pam pam-devel glibc glibc-devel tcp_wrappers-devel openssl098e gcc等,此處不再一一贅述。

    打包完成後,在/usr/src/redhat/RPMS/x86_64目錄下有打好的rpm包。用rpm方式升級安裝。我在安裝的時候遇到了版本衝突的問題,然後直接強制安裝。

    安裝完成後,修改/etc/ssh/sshd_config配置文件:

#AuthorizedKeysFile	.ssh/authorized_keys        //註釋掉這一行

#AuthorizedPrincipalsFile none

AuthorizedKeysCommand /bin/ssh-zhy.sh            //添加這一行,指定查找ssh-key的腳本
AuthorizedKeysCommandUser root                       //添加這一行,指定運行腳本的用戶,必須是root

     AuthorizedKeysCommand迴向ssh-key腳本傳遞兩個位置參數,$1是登陸用戶名,$2是登陸用戶的fingerprint,在腳本中可以直接用$2來獲取fingerprint。

     準備取ssh-key的腳本,該腳本可以是shell腳本,也可以是其他腳本,只要能從數據庫中取到對應的key就可以了,此處我使用的是shell腳本。數據庫中保存各用戶的key和fingerprint,根據fingerprint來取對應的key值,這樣就保證所有用戶即使都使用root登陸,也可以根據其fingerprint值來對應查找到對應的登陸人員從而完成人員記錄。

    準備好腳本後,放到配置文件中配置的位置,改腳本文件屬主和屬組爲root,腳本權限爲700,這兩步是必須設置的。配置完成後準備好存儲key的數據庫,然後重啓sshd服務。此時再登陸的時候就會去數據庫中查找key信息,如果在數據庫中找不到對應的key,依然會去authorized_keys文件中找。

    配置好後,我們只需要通過管理數據庫,就可以很方便的管理所有人的key。也可以方便後期的管理界面的開發。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章