SSH Agent Forward
最近對於 blog 的另外一個改動就是檔案權限的修改,我用的 Blog 系統是 MovableType,它的其中一個特色就是會產生好靜態的檔案,而這些檔案其實我都有丟上 Github 和 Bitbucket 備份,以前我基本上都用 root 來做這些事情,所以沒有權限問題,不過這次重灌後想順便把這問題處理一下,所以做了一番研究,首先在 ArchLinux 上,預設給 HTTP 等相關服務例如 nginx、php 等用的帳號是 http,所以我希望讓這些檔案的 owner 就是 http,一來可以確保所有的網路服務需要這些檔案時,都可以正確的存取,因為我嘗試過用 group 來設定權限共有,不過結果不太順利;二來 MovableType 產生的檔案 owner 也都是 http,可以保持一致性,也不用常常在那邊改檔案的 owner。
不過 http 這個帳號是沒有 shell 的,也就是不可以用這個帳號登入,當然會這樣預設也是安全性的考量,我並不想改掉他,所以第一個遇到的問題就是,我要怎樣用 http 帳號來執行指令,像是git commit
之類的,研究一陣子之後,發現可以用sudo
來辦到:
sudo -u http -s /bin/sh -c "git commit"
其中-u
是設定要換到那個帳號,-s
就是關鍵的指定 shell 了,最後的-c
則是要執行的指令,如果加上這個設定則不會真的換過去該帳號,而是只是用該帳號執行一次指令而已,解決第一個問題後,馬上來的就是第二個問題了,要git push
時,要怎麼使用有權限的 ssh private key,最簡單的方法就是丟到 http 帳號的 home 目錄下,不過我覺得這不太安全,所以想著要用其他方法來把 key 傳過去,當然把其他帳號的 key 的檔案權限調寬鬆並不可行,權限不對的 key 會無法使用,找到唯一比較接近的設計就是 SSH Agent Forward 了,可以把本機的 ssh key pair 帶上遠端主機,然後就可以從遠端主機利用這個帶上去的 key 連線到其他地方,使用方法很簡單,只要在連上遠端主機的時候,多加一個-A
的參數就可以了:
ssh -A user@othree.net
或是修改.ssh/config
的設定:
Host othree
HostName othree.net
ForwardAgent yes
不過可能會需要先把 key 加進去可以 forward 的清單中:
ssh-add
然後連上遠端主機之後,遠端的 login session 就會多一個環境變數$SSH_AUTH_SOCK
,印出來看內容會像是:
/tmp/ssh-7UJdnvSdy0/agent.18493
實際上是個檔案路徑,指到一個 unix socket 檔案,理論上 ssh 在連線時會去這邊找 key pair 然後用來做認證,不過我看ssh -vvv
的時候是沒有相關訊息出現,連線是可以正確建立就是,透過 agent forward,的機制,我就可以達成某種程度的 key 共用,不過在遠端主機上要使用的帳號是個沒有 shell 也沒有密碼可以登入的帳號,這就成了另外一個問題,遠端能拿到 key 的帳號不是我要用的帳號,所以第三個問題就是我要如何讓這個 key 能夠轉移到 http 帳號下可用的狀態。
這個問題的解決方法是在 StackOverflow 上找到的,用的其實是 ACL 這套比較新的檔案權限管理機制,指令大致如下,先把 unix socket 的檔案權限用 ACL 開給 http 帳號:
setfacl -m u:http:rw $SSH_AUTH_SOCK
setfacl -m u:http:x $(dirname $SSH_AUTH_SOCK)
然後 sudo 時把$SSH_AUTH_SOCK
帶過去:
sudo -u http env SSH_AUTH_SOCK=$SSH_AUTH_SOCK
因為 http 帳號沒有 shell,所以實際上指令會變成:
sudo -u http -s /bin/sh -c "env SSH_AUTH_SOCK=$SSH_AUTH_SOCK git pull"
不過這樣執行起來有點麻煩,其實 sudo 可以設定要帶哪些環境變數過去,所以可以去修改/etc/sudoers
加上一行:
Defaults env_keep+=SSH_AUTH_SOCK
然後在遠端 user 帳號下的~/.ssh/rc
檔案裡面加上 facl 那兩行指令(尚未確認可行性),加上本機端設定好自動 ForwardAgent,整個流程中比較麻煩一點的就只有 sudo 那行指令而已:
sudo -u http -s /bin/sh
就結果而言,這個作法的安全性反而比我本來的預期更進一步,因為我的 ssh key 就不用放上遠端主機,只要在本機端有一份就好了。