堡壘跳板機實現——架構實現

總述

這是關於堡壘機實現的第二篇文章,主要闡述三層架構分別如何實現,包括第一層&第二層的設計與實現,即用戶登陸堡壘機的入口 & 受權驗證, 第三層,如何經過ldap來統一管理服務器帳號權限。linux

關於堡壘機三層架構能夠參見前一篇blog:堡壘跳板機實現——總體架構shell

登陸入口

先說第一層,這層的主要功能爲檢測用戶是否有使用堡壘機的權限。
這個很好理解,總不能來個匿名用戶就可讓他隨意使用堡壘機,雖然說在二層受權驗證這裏能夠有效的抵擋,可是,既然能夠在第一層有效的對無效用戶作快捷的攔截,爲何要放後呢?segmentfault

驗證的方式能夠有不少種,好比,若是用linux用做第一層架構中的服務器,那麼能夠自然的使用linux的user auth做爲檢驗機制,單純爲有使用權限的用戶在服務器上adduser,單首創建一個惟一的32位的密碼。api

服務器定製

咱們在這層的作法是 將用戶驗證與咱們內部的動態Token服務相結合(相似google authenticator),同時還要提供友好的登陸shell界面,這樣的話單純的使用user auth就不太可以達到咱們的目的,這裏,咱們對一層服務器作了ssh登陸all permit定製,修改/etc/pam.d/sshd:bash

auth     required       pam_permit.so
account  required       pam_permit.so
password required       pam_permit.so
session  required       pam_permit.so

開啓sshd的pam認證,修改sshd_config:服務器

UsePAM yes

而後重啓sshd:session

/etc/ini.d/sshd restart

同時將用戶對應的默認login shell改成咱們自定義的。架構

代碼結構

放上咱們的代碼結構,主要結構以下:ssh

├── gateway-shell
├── login-shell
├── mshell
└── sdshell

功能描述

接下來對上述文件作下功能描述:post

  • login-shell: 用戶的login shell,調用sdshell驗證用戶的login passwd,初始化用戶的監控日誌路徑,並開啓監控。

  • sdshell:讀取用戶的login passwd並判斷驗證結果,以exit code來對錶示驗證結果,0表示驗證成功,1表示驗證失敗,2表示root用戶登陸而且驗證成功。

  • mshell:驗證用戶passwd成功能,循環調用gateway-shell來讀取用戶的action操做選擇,並執行。

  • gateway-shell:提供給用戶操做cli界面,供用戶選擇操做。

調用順序爲:

login_shell(入口) -> sdshell(判斷PIN+TOKEN) -> mshell -> gateway-shell(判斷/獲取 用戶選項)

代碼解讀

login_shell:

當用戶登陸時首先進入到這裏進行驗證

1 #!/bin/bash
  2 
  3 WORKDIR=`dirname $0`
  4 source $WORKDIR/sentry.env
  5 BINDIR="$WORKDIR"
  6 #LOGDIR="/data0/logdir"
  7 
  8 #1, 驗證token
  9 $BINDIR/sdshell
 10 sdstats=$?
 11 #sdstats=0
 12 
 13 # 當sdshell返回爲0時,表示當前用戶登陸成功
 14 # 當sdshell返回爲1時,表示當前用戶驗證失敗
 15 # 當sdshell返回爲2時,表示root登陸成功
 16 if [[ $sdstats -eq 1 ]];then
 17     exit 1
 18 elif [[ $sdstats -eq 2 ]];then
 19     /bin/bash
 20     exit 0
 21 fi
 22 
 23 #2, gen_log_dir
 24 user=`/usr/bin/whoami`
 25 if [ ! -d $LOGDIR/$user ];then
 26     mkdir -p $LOGDIR/$user
 27     chown -R $user $LOGDIR/$user
 28     chmod a+w $LOGDIR/$user
 29 fi
 30 
 31 #3, param
 32 lip=`/usr/bin/env|grep SSH_CONNECTION|cut -f 2 -d =|cut -f 1 -d ' '`
 33 now=`date '+%F-%k:%M:%S'|tr -d " "`
 34 user=`/usr/bin/whoami`
 35 sip=`/usr/bin/env|grep SSH_CONNECTION|cut -f 2 -d =|cut -f 3 -d ' '`
 36 
 37 #4, begin script
 38 export TMOUT=10
 39 export SHELL=$BINDIR/mshell
 40 /usr/bin/script -q -t 2>$LOGDIR/$user/$user-$lip-$sip-$now.time -f $LOGDIR/$user/$user-$lip-$sip-$now.txt

其中,3-5行作基本的環境變量初始化,第9行調用 sdshell 驗證用戶輸入的動態碼的驗證結果,即,用戶在這時進入到 sdshell 作驗證,此時,就能夠隨意對 sdshell 作功能定製了,咱們實現的功能定製界面類如:
圖片描述

是否是比較酷炫~~

當一切都驗證完畢,咱們進入到login_shell第24-35行,初始化用戶行爲日誌記錄的初始化。

咱們這裏使用linux自帶的script命令作用戶的記錄操做,簡單有效到沒有朋友啊有木有!!

最後39-40兩行,將用戶的shell指向 mshell ,同時,開始記錄用戶行爲。

mshell

如今用戶的行爲已經進入到這裏,說明這個用戶經過了第一層校驗,如今須要他進行相關action操做。

1 #!/bin/bash
  2 
  3 WORKDIR=`dirname $0`
  4 source $WORKDIR/sentry.env
  5 user=`/usr/bin/whoami`
  6 GWDIR=$WORKDIR
  7 privatekey=$RSAFILE
  8 mkdir /home/$user/.ssh 2>/dev/null
  9 cat $privatekey > /home/$user/.ssh/id_rsa
 10 chmod 600 /home/$user/.ssh/id_rsa
 11 
 12 while true
 13 do
 14     clear
 15     $GWDIR/gateway-shell
 16     gsstats=$?
 17 
 18     # 返回值說明:
 19     # 0 表示正常,要登陸了;
 20     # 1 表示當即quit
 21     # 2 表示由於超時而quit
 22     # 3 表示登陸本地服務器
 23     # 其餘未異常
 24     case $gsstats in
 25         0)
 26             ssh -2 -i ~/.ssh/id_rsa -l $user `cat $ACTIONDIR/$user.action`
 27             ;;
 28         1)
 29             exit
 30             ;;
 31         2)
 32             echo "action timeout"
 33             exit
 34             ;;
 35         3)
 36         /bin/bash
 37             ;;
 38         *)
 39             echo "error"
 40             sleep 2
 41             ;;
 42     esac
 43 done

3-10行環境初始化,而後開啓循環監聽用戶輸入的action,爲用戶展現可以使用的action list以及判斷用戶是否有對應操做的權限則都是第15行的 mshell 來進行操做,以後一樣根據exit code來執行相關的動做。

對於 mshell ,一樣能夠自行設計相關的功能,咱們設計的shell操做界面以下:
圖片描述

一樣酷炫有木有!

一層架構總結

此時,一層架構中的流程實現基本完成,剩下的就是具體控制登陸服務器的技術管理工做,即第三層的工做了,稍後爲你們分享。

再次總結下一層架構中的調用關係:

login_shell(入口) -> sdshell(判斷PIN+TOKEN) -> mshell -> gateway-shell(判斷/獲取 用戶選項)

咦,好像缺乏第二層的說明?

其實第二層主要作action行爲受權&校驗工做,還記得 gateway-shell 的做用嗎:

爲用戶展現可以使用的action list以及判斷用戶是否有對應操做的權限

在這裏 gateway-shell 經過api與第二層作交互,對用戶的行爲及受權範圍做了操做,具體交互的功能包括:

  • 搜索服務器信息;

  • 獲取用戶有權限的服務器list;

  • 獲取用戶有權限的服務器Group list;

  • 獲取服務器Group下的server list;

  • 獲取當前全部有權限的user list

具體怎麼實現? 相信1000個工程師有1001中不一樣的作法,這裏就不在闡述~

如何統一管理服務器的登陸帳號

接入咱們有1000臺服務器,有100我的,須要統一管理 哪些帳號 能夠登陸 哪些服務器哪些帳號哪些服務器 上能夠 sudo哪些命令
問題拋出來了,下面就是如何解決它。

單刀直入的方案,我爲每一個服務器根據須要建立對應的人的帳號,在分別配置sudoer的權限。
缺點就不說了,改個配置能累死人。。。。。

因此,咱們最好能有個地方可以統一來配置:

  1. 建立一我的的帳號後,那麼這我的就能登陸全部的服務器;

  2. 管理這我的的登陸服務器的範圍;

  3. 爲這我的分配統一的sudo權限,及在哪些目標服務器上有執行哪些命令的sudo權限;

上述的需求能夠經過服務器接入ldap,經過ldap管理在實現上述的需求。
具體的過程這裏再也不累贅,能夠參見網上的博文,仍是挺多的,好比:
使用 OpenLDAP 集中管理用戶賬號
基於 PAM 的 LDAP 用戶身份驗證

這裏只貼上完成後相似的ldap結構:

[root@testldap openldap]# ldapsearch -x -LLL -D "cn=admin,dc=lianjia,dc=com" uid=test -W
Enter LDAP Password:
dn: uid=test,ou=people,dc=lianjia,dc=com
objectClass: posixAccount
objectClass: shadowAccount
objectClass: person
objectClass: inetOrgPerson
objectClass: ldapPublicKey
cn: System
sn: li
givenName: test
displayName: test
uid: test
userPassword:: testpasswd
uidNumber: 1001
gidNumber: 1001
gecos: System Manager
homeDirectory: /home/test
shadowLastChange: 16020
shadowMin: 0
shadowMax: 999999
shadowWarning: 7
shadowExpire: -1
employeeNumber: 20248353
mobile: 18519199234
mail: 654306390@qq.com
postalAddress: beijing
initials: test
loginShell: /bin/bash
sshPublicKey: ssh-rsa Axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx32x9jF5cFDqktiTQIdD9
 PMq8b86v2p8Es4us7OTzo7XomcjEPpfP/Realy9BOuteohA4JzezrAyFQhJui6BdovkzhnVRyFERJ
 uTA/19biQkCZB91XrWxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxJXH+f0
 VOvx5FiF0bV3IfJt32cdmI8O7hNI+ttPCQ4V1R8vr0wIhCmUcKzD5vOx+0H9B1EY4d/imSxFHIebe
 4l//rthyAr3x0XmNvuFD9khqfDK7bmXnHu26s++O8A1SDJ5beuu4xXl/mN8mc5WPmoQQSjIzruWPa
 jLx8m6HF root@channel.lianjia.com

這樣,對於此用戶,就能夠經過password 或者 publickey的方式,登陸服務器,同理,也能夠對sudo進行相似的管理,仍是真心強大的。

相關文章
相關標籤/搜索