2014-06-09 96 views
49

我使用Ansible 1.5.3和Git與ssh代理轉發(https://help.github.com/articles/using-ssh-agent-forwarding)。我可以登錄到,我與Ansible和測試管理服務器,我連接到Git是正確配置:使用Ansible進行SSH代理轉發

[email protected]:~$ ssh -T [email protected] 
Hi gituser! You've successfully authenticated, but GitHub does not provide shell access. 

我也可以克隆和更新,所以我的git的配置看起來不錯,用這個賬戶我的回購協議之一,當我通過ssh直接登錄到我的服務器時使用ssh轉發。

問題:當我使用Ansible命令模塊嘗試上面顯示的相同測試時。它以「權限被拒絕」失敗。在Ansible輸出(有詳細日誌記錄)的部分看起來像這樣:

failed: [xxx.xxxxx.com] => {"changed": true, "cmd": ["ssh", "-T", "[email protected]"], "delta": "0:00:00.585481", "end": "2014-06-09 14:11:37.410907", "rc": 255, "start": "2014-06-09 14:11:36.825426"} 
stderr: Permission denied (publickey). 

這裏是運行此命令的簡單劇本:

- hosts: webservers 
    sudo: yes 
    remote_user: ubuntu 

    tasks: 

    - name: Test that git ssh connection is working. 
    command: ssh -T [email protected] 

的問題:爲什麼一切都正常工作,當我手動登錄通過ssh運行命令,但是當通過Ansible以相同的用戶運行相同的命令時失敗?

我會很快發佈答案,如果沒有人擊敗我。儘管我使用git來演示這個問題,但是依賴於ssh代理轉發的任何模塊都可能會發生這種情況。它不是特定於Ansible,但我懷疑很多人會在這種情況下首先遇到問題。

回答

46

問題是由從劇本刪除此行解決:

sudo: yes 

當須藤在遠程主機上運行,​​在登錄過程中通過SSH設置環境變量不再可用。特別是,「標識用於與代理通信的UNIX域套接字的路徑」的SSH_AUTH_SOCK不再可見,所以ssh代理轉發不起作用。

當你不需要時避免sudo是解決問題的一種方法。另一種方法是,以確保SSH_AUTH_SOCK你的sudo會議期間堅持圍繞創建一個sudoers文件:

/etc/sudoers: 

    Defaults env_keep += "SSH_AUTH_SOCK" 
+4

可能需要明確設置'sudo:no'。 –

+1

這些sudoers爲我改變作品。 – dannyman

+1

如果使用SSH_AUTH_SOCK至少知道安全風險http://serverfault.com/a/371788/67801 – SystematicFrank

23

另一個回答你的問題(與我使用Ansible 1.9除外),可能是以下幾點:

對於transport=smart ,建議您使用in the ansible docs,您可能需要檢查/etc/ansible/ansible.cfg(或其他三個可能覆蓋配置設置的潛在位置)。在之前的安裝嘗試期間,我的默認值爲transport=paramiko,阻止我的控制機器使用OpenSSH,從而阻止代理轉發。這可能是一個巨大的邊緣情況,但誰知道?它可能是你!

雖然我沒覺得有必要對我的配置,我要指出,其他人所說的,你應該添加-o ForwardAgent=yes您ssh_args像這樣在同一個文件中設置:

[ssh_connection] 
ssh_args=-o ForwardAgent=yes 

我只提到它這裏爲了完整起見。

+3

我不得不將'ssh_args'添加到我的'ansible.cfg'中,以使SSH代理轉發工作。榮譽給你成爲唯一的推薦它的人!我在OSX 10.10上運行Ansible 1.9.1 – staticfloat

+6

如果你指定'ssh_args'來阻止它自己提供它,包括建立持久連接的參數。這會導致**巨大的減速。將添加的相關參數是-o ControlMaster = auto -o ControlPersist = 60s -o ControlPath =/tmp/ansible-ssh-%h-%p-%r'。 – qqx

+0

有時候'sudo_flags'也有問題,它默認設置爲'sudo_flags = -H -S -n',並且可能會失敗,並顯示「sudo:需要密碼」。在這種情況下,你需要設置'sudo_flags = -H -S'去除-n選項。 –

16

展開@j。祛斑的答案,要改變sudoers文件的ansible方法是:

- name: Add ssh agent line to sudoers 
    lineinfile: 
    dest: /etc/sudoers 
    state: present 
    regexp: SSH_AUTH_SOCK 
    line: Defaults env_keep += "SSH_AUTH_SOCK" 
+1

但是我們不需要兩次運行嗎?一個設置ssh fwding,另一個實際獲得與這個env var set的連接? – alfetopito

+0

聽起來不錯。我總是最終運行並多次評論劇本,ssh到框中並手動檢查。這從來都不是一帆風順的。 – AJcodez

+0

爲了避免不得不多次運行,我最終將這一步放入了我在全新服務器安裝中運行的腳本中。畢竟有些事情需要設置,然後才能用安全的方式設置我的服務器。 – alfetopito

16

有一些非常有用的部分答案在這裏,但運行到這個問題很多次後,我想概述將是有益的。

首先,您需要確保在從運行Ansible的客戶端連接到目標計算機時啓用了SSH代理轉發。即使使用transport=smart,SSH代理轉發也可能不會自動啓用,具體取決於客戶端的SSH配置。爲了確保它,您可以更新~/.ansible.cfg包括本節:

[ssh_connection] 
ssh_args=-o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/ansible-ssh-%h-%p-%r -o ForwardAgent=yes 

接下來,你可能不得不面對一個事實,即become: yes(和become_user: root)一般會禁用代理轉發,因爲SSH_AUTH_SOCK環境變量被重置。 (我發現Ansible seems to assume人們將以root身份進行SSH連接令人震驚,因爲這使得任何有用的審計都不可能。)有幾種方法可以解決這個問題。作爲Ansible 2.2的,最簡單的方法是使用sudo時,通過指定-E標誌保護(整體)環境:

become_flags: "-E" 

然而,這可以通過有保留的變量,比如PATH不必要的副作用。最簡潔的方法是隻將其包含在env_keep保留SSH_AUTH_SOCK/etc/sudoers文件:

Defaults env_keep += "SSH_AUTH_SOCK" 

要使用Ansible做到這一點:

- name: enable SSH forwarding for sudo 
    lineinfile: 
    dest: /etc/sudoers 
    insertafter: '^#?\s*Defaults\s+env_keep\b' 
    line: 'Defaults env_keep += "SSH_AUTH_SOCK"' 

這個劇本的任務比一些比較保守其他人建議,因爲它在任何其他默認env_keep設置(或在文件末尾,如果沒有找到)添加該設置,而不更改任何現有env_keep設置或假設SSH_AUTH_SOCK已經存在。