堡壘跳板機(jī)實(shí)現(xiàn)——架構(gòu)實(shí)現(xiàn)
總述
這是關(guān)于堡壘機(jī)實(shí)現(xiàn)的第二篇文章,主要闡述三層架構(gòu)分別如何實(shí)現(xiàn),包括***層&第二層的設(shè)計(jì)與實(shí)現(xiàn),即用戶登錄堡壘機(jī)的入口 & 授權(quán)驗(yàn)證, 第三層,如何通過ldap來統(tǒng)一管理服務(wù)器賬號(hào)權(quán)限。
關(guān)于堡壘機(jī)三層架構(gòu)可以參見前一篇blog:堡壘跳板機(jī)實(shí)現(xiàn)——整體架構(gòu)
登錄入口
先說***層,這層的主要功能為檢測用戶是否有使用堡壘機(jī)的權(quán)限。這個(gè)很好理解,總不能來個(gè)匿名用戶就可以讓他隨意使用堡壘機(jī),雖說在二層授權(quán)驗(yàn)證這里可以有效的抵擋,但是,既然可以在***層有效的對(duì)無效用戶做快捷的攔截,為什么要放后呢?
驗(yàn)證的方式可以有很多種,比如,如果用linux用作***層架構(gòu)中的服務(wù)器,那么可以天然的使用linux的user auth作為檢驗(yàn)機(jī)制,單純?yōu)橛惺褂脵?quán)限的用戶在服務(wù)器上adduser,單***建一個(gè)唯一的32位的密碼。
服務(wù)器定制
我們在這層的做法是 將用戶驗(yàn)證與我們內(nèi)部的動(dòng)態(tài)Token服務(wù)相結(jié)合(類似google authenticator),同時(shí)還要提供友好的登錄shell界面,這樣的話單純的使用user auth就不太能夠達(dá)到我們的目的,這里,我們對(duì)一層服務(wù)器做了ssh登錄all permit定制,修改/etc/pam.d/sshd:
- auth required pam_permit.so
- account required pam_permit.so
- password required pam_permit.so
- session required pam_permit.so
開啟sshd的pam認(rèn)證,修改sshd_config:
- UsePAM yes
然后重啟sshd:
- /etc/ini.d/sshd restart
同時(shí)將用戶對(duì)應(yīng)的默認(rèn)login shell改為我們自定義的。
代碼結(jié)構(gòu)
放上我們的代碼結(jié)構(gòu),主要結(jié)構(gòu)如下:
- ├── gateway-shell
- ├── login-shell
- ├── mshell
- └── sdshell
功能描述
接下來對(duì)上述文件做下功能描述:
- login-shell: 用戶的login shell,調(diào)用sdshell驗(yàn)證用戶的login passwd,初始化用戶的監(jiān)控日志路徑,并開啟監(jiān)控。
- sdshell:讀取用戶的login passwd并判斷驗(yàn)證結(jié)果,以exit code來對(duì)表示驗(yàn)證結(jié)果,0表示驗(yàn)證成功,1表示驗(yàn)證失敗,2表示root用戶登錄并且驗(yàn)證成功。
- mshell:驗(yàn)證用戶passwd成功能,循環(huán)調(diào)用gateway-shell來讀取用戶的action操作選擇,并執(zhí)行。
- gateway-shell:提供給用戶操作cli界面,供用戶選擇操作。
調(diào)用順序?yàn)椋?/p>
- login_shell(入口) -> sdshell(判斷PIN+TOKEN) -> mshell -> gateway-shell(判斷/獲取 用戶選項(xiàng))
代碼解讀
login_shell:
當(dāng)用戶登錄時(shí)首先進(jìn)入到這里進(jìn)行驗(yàn)證
- 1 #!/bin/bash
- 2
- 3 WORKDIR=`dirname $0`
- 4 source $WORKDIR/sentry.env
- 5 BINDIR="$WORKDIR"
- 6 #LOGDIR="/data0/logdir"
- 7
- 8 #1, 驗(yàn)證token
- 9 $BINDIR/sdshell
- 10 sdstats=$?
- 11 #sdstats=0
- 12
- 13 # 當(dāng)sdshell返回為0時(shí),表示當(dāng)前用戶登錄成功
- 14 # 當(dāng)sdshell返回為1時(shí),表示當(dāng)前用戶驗(yàn)證失敗
- 15 # 當(dāng)sdshell返回為2時(shí),表示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行做基本的環(huán)境變量初始化,第9行調(diào)用 sdshell 驗(yàn)證用戶輸入的動(dòng)態(tài)碼的驗(yàn)證結(jié)果,即,用戶在這時(shí)進(jìn)入到 sdshell 做驗(yàn)證,此時(shí),就可以隨意對(duì) sdshell 做功能定制了,我們實(shí)現(xiàn)的功能定制界面類如:
是不是比較酷炫~~
當(dāng)一切都驗(yàn)證完畢,我們進(jìn)入到login_shell第24-35行,初始化用戶行為日志記錄的初始化。
我們這里使用linux自帶的script命令做用戶的記錄操作,簡單有效到?jīng)]有朋友啊有木有!!
***39-40兩行,將用戶的shell指向 mshell ,同時(shí),開始記錄用戶行為。
mshell
現(xiàn)在用戶的行為已經(jīng)進(jìn)入到這里,說明這個(gè)用戶通過了***層校驗(yàn),現(xiàn)在需要他進(jìn)行相關(guān)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 表示因?yàn)槌瑫r(shí)而quit
- 22 # 3 表示登錄本地服務(wù)器
- 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行環(huán)境初始化,然后開啟循環(huán)監(jiān)聽用戶輸入的action,為用戶展示可使用的action list以及判斷用戶是否有對(duì)應(yīng)操作的權(quán)限則都是第15行的 mshell 來進(jìn)行操作,之后同樣根據(jù)exit code來執(zhí)行相關(guān)的動(dòng)作。
對(duì)于 mshell ,同樣可以自行設(shè)計(jì)相關(guān)的功能,我們設(shè)計(jì)的shell操作界面如下:
同樣酷炫有木有!
一層架構(gòu)總結(jié)
此時(shí),一層架構(gòu)中的流程實(shí)現(xiàn)基本完成,剩下的就是具體控制登錄服務(wù)器的技術(shù)管理工作,即第三層的工作了,稍后為大家分享。
再次總結(jié)下一層架構(gòu)中的調(diào)用關(guān)系:
- login_shell(入口) -> sdshell(判斷PIN+TOKEN) -> mshell -> gateway-shell(判斷/獲取 用戶選項(xiàng))
咦,好像缺少第二層的說明?
其實(shí)第二層主要做action行為授權(quán)&校驗(yàn)工作,還記得 gateway-shell 的作用嗎:
“為用戶展示可使用的action list以及判斷用戶是否有對(duì)應(yīng)操作的權(quán)限 ”
在這里 gateway-shell 通過api與第二層做交互,對(duì)用戶的行為及授權(quán)范圍作了操作,具體交互的功能包括:
- 搜索服務(wù)器信息;
- 獲取用戶有權(quán)限的服務(wù)器list;
- 獲取用戶有權(quán)限的服務(wù)器Group list;
- 獲取服務(wù)器Group下的server list;
- 獲取當(dāng)前所有有權(quán)限的user list
具體怎么實(shí)現(xiàn)? 相信1000個(gè)工程師有1001中不同的做法,這里就不在闡述~
如何統(tǒng)一管理服務(wù)器的登錄賬號(hào)
接入我們有1000臺(tái)服務(wù)器,有100個(gè)人,需要統(tǒng)一管理 哪些賬號(hào) 可以登錄 哪些服務(wù)器,哪些賬號(hào) 在 哪些服務(wù)器 上可以 sudo哪些命令 。
問題拋出來了,下面就是如何解決它。
單刀直入的方案,我為每個(gè)服務(wù)器根據(jù)需要?jiǎng)?chuàng)建對(duì)應(yīng)的人的賬號(hào),在分別配置sudoer的權(quán)限。缺點(diǎn)就不說了,改個(gè)配置能累死人。。。。。
所以,我們***能有個(gè)地方能夠統(tǒng)一來配置:
- 創(chuàng)建一個(gè)人的賬號(hào)后,那么這個(gè)人就能登錄所有的服務(wù)器;
- 管理這個(gè)人的登錄服務(wù)器的范圍;
- 為這個(gè)人分配統(tǒng)一的sudo權(quán)限,及在哪些目標(biāo)服務(wù)器上有執(zhí)行哪些命令的sudo權(quán)限;
上述的需求可以通過服務(wù)器接入ldap,通過ldap管理在實(shí)現(xiàn)上述的需求。
具體的過程這里不再累贅,可以參見網(wǎng)上的博文,還是挺多的,比如:
這里只貼上完成后類似的ldap結(jié)構(gòu):
- [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
這樣,對(duì)于此用戶,就可以通過password 或者 publickey的方式,登錄服務(wù)器,同理,也可以對(duì)sudo進(jìn)行類似的管理,還是真心強(qiáng)大的。