Chỉ định mật khẩu sudo cho Ansible


225

Làm cách nào để chỉ định mật khẩu sudo cho Ansible theo cách không tương tác?

Tôi đang chạy Playbook Ansible như thế này:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username --ask-sudo-pass

Nhưng tôi muốn chạy nó như thế này:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username` **--sudo-pass=12345**

Là có một cách? Tôi muốn tự động hóa việc triển khai dự án của mình càng nhiều càng tốt.


Câu trả lời:


170

Bạn có thể truyền biến trên dòng lệnh thông qua --extra-vars "name=value". Biến mật khẩu Sudo là ansible_sudo_pass. Vì vậy, lệnh của bạn sẽ trông như:

ansible-playbook playbook.yml -i inventory.ini --user=username \
                              --extra-vars "ansible_sudo_pass=yourPassword"

Cập nhật 2017 : Ansible 2.2.1.0 hiện sử dụng var ansible_become_pass. Hoặc là dường như làm việc.


7
Từ góc độ bảo mật, câu trả lời tốt nhất, nếu bạn thêm vào như sau: history -csau khi thực hiện yml.
kiltek

12
@kiltek: hoặc thêm một khoảng trắng ở đầu dòng (trong bash) sẽ * không * ghi dòng vào .bash_history.
ccpizza

44
Không phải là một thực hành tốt để vượt qua trong mật khẩu trên dòng lệnh. Bất kỳ ai cũng sẽ có thể thấy mật khẩu trong danh sách quy trình, trong khi lệnh đang thực thi ...
Pavel Chernikov

22
Tuy nhiên, đừng làm điều đó. --ask-sudo-pass
JasonG

2
@scrutari Nó hoàn toàn hợp lệ trong một số trường hợp: Ví dụ: Thay đổi từ mật khẩu ban đầu, được biết đến trên thế giới, sang khóa ssh công khai của người dùng ... Hãy nghĩ cấu hình ban đầu của một hệ thống mới được tạo lại.
Ceredig

236

Các tài liệu mạnh mẽ khuyến cáo chống lại việc thiết lập mật khẩu sudo trong bản rõ, và thay vào đó sử dụng --ask-sudo-passtrên dòng lệnh khi chạyansible-playbook


Cập nhật năm 2016:

Ansible 2.0 (không phải 100% khi) được đánh dấu --ask-sudo-passlà không dùng nữa. Các tài liệu hiện khuyên bạn nên sử dụng --ask-become-passthay vào đó, đồng thời hoán đổi việc sử dụng trong sudosuốt các vở kịch của bạn với become.


16
Vâng, tôi có thể thấy lý do tại sao điều này được khuyến khích. Tuy nhiên, khi chúng tôi sử dụng Ansible như một phần của quy trình triển khai, cách tốt hơn để tự động hóa việc này là gì? Sẽ không thuận tiện lắm khi dừng giữa quá trình triển khai và yêu cầu người dùng nhập mật khẩu sudo.
Slava Fomin II

9
Lưu ý --ask-sudo-pass có thể được bỏ qua thành -K, tuy nhiên, theo như tôi thấy, không có cách nào xử lý một playbook chạy trên nhiều máy chủ với các mật khẩu khác nhau (nó chỉ hỏi bạn một lần), vì vậy tôi nghĩ rằng không có mật khẩu sudo là con đường để đi
William Turrell

1
Có vẻ như không hoạt động. nhưng đề xuất tiếp theo ("một số máy chủ ansible_sudo_pass = 'foobar'") thì không
nadavkav

--ask-sudo-pass đã bị từ chối trước đó, vào 1.9
Chris Betti

Tôi muốn cập nhật câu trả lời với một liên kết nguồn nếu bạn có.
deefour

106

Có lẽ cách tốt nhất để làm điều này - giả sử rằng bạn không thể sử dụng giải pháp NOPASSWD do scottod cung cấp là sử dụng giải pháp Mircea Vutcovici kết hợp với kho tiền Ansible .

Ví dụ: bạn có thể có một cuốn sách như thế này:

- hosts: all

  vars_files:
    - secret

  tasks:
    - name: Do something as sudo
      service: name=nginx state=restarted
      sudo: yes

Ở đây chúng tôi bao gồm một tệp được gọi secretsẽ chứa mật khẩu sudo của chúng tôi.

Chúng tôi sẽ sử dụng ansible-vault để tạo phiên bản được mã hóa của tệp này:

ansible-vault create secret

Điều này sẽ yêu cầu bạn nhập mật khẩu, sau đó mở trình chỉnh sửa mặc định của bạn để chỉnh sửa tệp. Bạn có thể đặt của bạn ansible_sudo_passở đây.

ví dụ secret::

ansible_sudo_pass: mysudopassword

Lưu và thoát, bây giờ bạn có một secrettệp được mã hóa mà Ansible có thể giải mã khi bạn chạy Playbook. Lưu ý: bạn có thể chỉnh sửa tệp bằng ansible-vault edit secret(và nhập mật khẩu bạn đã sử dụng khi tạo tệp)

Phần cuối cùng của câu đố là cung cấp cho Ansible cái --vault-password-filemà nó sẽ sử dụng để giải mã secrettập tin của bạn .

Tạo một tệp được gọi vault.txtvà trong đó đặt mật khẩu mà bạn đã sử dụng khi tạo secrettệp của mình . Mật khẩu phải là một chuỗi được lưu dưới dạng một dòng trong tệp.

Từ Tài liệu Ansible:

.. đảm bảo quyền trên tệp sao cho không ai khác có thể truy cập khóa của bạn và không thêm khóa của bạn vào kiểm soát nguồn

Cuối cùng: bây giờ bạn có thể chạy playbook của mình với một cái gì đó như

ansible-playbook playbook.yml -u someuser -i hosts --sudo --vault-password-file=vault.txt 

Trên đây là giả sử bố trí thư mục sau:

.
|_ playbook.yml
|_ secret
|_ hosts
|_ vault.txt

Bạn có thể đọc thêm về Ansible Vault tại đây: https://docs.ansible.com/playbooks_vault.html


5
Lưu ý: kể từ phiên bản 1.9, có vẻ như bạn không còn có thể sử dụng biến ansible_sudo_pass (hoặc ansible_become_pass): "fatal: [...] => Mất mật khẩu"
toast38coza

6
Tôi đang sử dụng giải pháp này trong sản xuất, jenkins lưu trữ mật khẩu vault dưới dạng biến môi trường bị xáo trộn, ghi nó vào thời gian chạy trong một tệp tạm thời và tiến hành gọi ansible.
simone cittadini

6
hoặc đơn giản hơn: ansible-vault create group_vars/all/ansible.ymlvà thêm vào ansible_sudo_pass: yourpasswordđó. Không cần thay đổi sổ chơi hoặc hàng tồn kho
Bouke Versteegh

1
Đã thử điều này nhưng tôi đã nhận được lỗi này:fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
JohnnyQ

8
Vault có gì hay nếu bạn lưu mật khẩu vào vault bằng văn bản đơn giản ngay bên cạnh?
Erik

44

Nhìn vào mã ( runner/__init__.py), tôi nghĩ rằng bạn có thể đặt nó trong tệp kiểm kê của mình:

[whatever]
some-host ansible_sudo_pass='foobar'

Dường như cũng có một số điều khoản trong ansible.cfgtệp cấu hình, nhưng không được triển khai ngay bây giờ ( constants.py).


7
Một cách tuyệt vời để định cấu hình này một cách an toàn sẽ là lưu trữ tệp này trong thư mục host_varshoặc group_varssau đó mã hóa tệp bằng cách sử dụng ansible-vault
Kyle

44

Tôi không nghĩ rằng ansible sẽ cho phép bạn chỉ định mật khẩu trong các cờ như bạn muốn làm. Có thể có một số cấu hình có thể được đặt nhưng điều này sẽ làm cho việc sử dụng tổng thể kém an toàn hơn và sẽ không được khuyến nghị.

Một điều bạn có thể làm là tạo một người dùng trên máy đích và cấp cho họ các đặc quyền sudo không mật khẩu cho tất cả các lệnh hoặc một danh sách các lệnh bị hạn chế.

Nếu bạn chạy sudo visudovà nhập một dòng như bên dưới, thì người dùng 'đặc quyền' không cần phải nhập mật khẩu khi họ chạy một cái gì đó như sudo service xxxx start:

%privilegedUser ALL= NOPASSWD: /usr/bin/service

7
@bschlueter vì vậy bạn đang chứng thực thực hành xấu?
stephen

1
Tôi không nghĩ rằng đây là một ý tưởng tốt. Sử dụng --ask-sudo-pass có ý nghĩa với tôi.
Nhà phát triển kgp

@simone cittadini Tôi hoàn toàn đồng ý vì thực tế đó là câu trả lời tôi sẽ đưa ra. Đây là một rủi ro bảo mật.
einarc

Sẽ ít rủi ro bảo mật hơn nếu bạn đang sử dụng sudo không mật khẩu để triển khai để dàn / prod, nhưng muốn sử dụng các câu trả lời này để bỏ qua việc phải nhập mật khẩu đăng nhập máy tính xách tay cục bộ của bạn khi triển khai vào localhost mỗi 15 phút mỗi ngày.
Jonathan Hartley

Làm thế nào để bạn thêm dòng này bằng Ansible?
Matthias

21

Các mật khẩu sudo được lưu giữ như là một biến gọi ansible_sudo_pass. Bạn có thể đặt biến này theo một số cách:

Mỗi máy chủ lưu trữ, trong tệp lưu trữ tệp lưu trữ của bạn ( inventory/<inventoryname>/hosts)

[server]
10.0.0.0 ansible_sudo_pass=foobar

Mỗi nhóm, trong tệp nhóm hàng tồn kho của bạn ( inventory/<inventoryname>/groups)

[server:vars]
ansible_sudo_pass=foobar

Mỗi nhóm, trong nhóm vars ( group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"

Mỗi nhóm, được mã hóa ( ansible-vault create group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"

18

Bạn có thể đặt mật khẩu cho một nhóm hoặc cho tất cả các máy chủ cùng một lúc:

[all:vars]
ansible_sudo_pass=default_sudo_password_for_all_hosts

[group1:vars]
ansible_sudo_pass=default_sudo_password_for_group1

14

Tôi đã xé tóc ra khỏi cái này, bây giờ tôi tìm thấy một giải pháp mà tôi muốn:

1 tệp được mã hóa trên mỗi máy chủ chứa mật khẩu sudo

/ etc / ansible / hosts:

[all:vars]
ansible_ssh_connection=ssh ansible_ssh_user=myuser ansible_ssh_private_key_file=~/.ssh/id_rsa

[some_service_group]
node-0
node-1

sau đó bạn tạo cho mỗi máy chủ một tệp var được mã hóa như vậy:

ansible-vault create /etc/ansible/host_vars/node-0

với nội dung

ansible_sudo_pass: "my_sudo_pass_for_host_node-0"

cách bạn tổ chức mật khẩu vault (nhập qua --ask-vault-pass) hoặc bằng cfg là tùy thuộc vào bạn

dựa trên điều này tôi nghi ngờ bạn chỉ có thể mã hóa toàn bộ tập tin máy chủ ...


Mã hóa bằng cách sử dụng vault có ý nghĩa nhất đối với tôi, mặc dù tôi đã vật lộn để sử dụng chúng với ansible-playback. Tôi đã phải sử dụng -e @vault/filename.extđể sử dụng kho tiền với ansible-playbookcuộc gọi của tôi .
Alex

9

Một cách khôn ngoan hơn để làm điều này là lưu trữ sudomật khẩu của bạn trong một kho bảo mật như LastPass hoặc KeePass và sau đó chuyển nó sang ansible-playbooksử dụng -e@nhưng thay vì mã hóa nội dung trong một tệp thực tế, bạn có thể sử dụng cấu trúc -e@<(...)để chạy lệnh trong một shell phụ và chuyển hướng đầu ra của nó (STDOUT) sang một bộ mô tả tệp ẩn danh, cung cấp mật khẩu hiệu quả cho -e@<(..).

Thí dụ

$ ansible-playbook -i /tmp/hosts pb.yml \
   -e@<(echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)")

Ở trên đang làm một số điều, hãy phá vỡ nó.

  • ansible-playbook -i /tmp/hosts pb.yml - rõ ràng là đang chạy một playbook thông qua ansible-playbook
  • $(lpass show folder1/item1 --password)"- chạy LastPass CLI lpassvà lấy mật khẩu để sử dụng
  • echo "ansible_sudo_pass: ...password..." - lấy chuỗi 'ansible_sudo_pass:' và kết hợp nó với mật khẩu được cung cấp bởi lpass
  • -e@<(..)- đặt các phần trên lại với nhau và kết nối phần dưới của <(...)phần mô tả tệp ansible-playbookđể sử dụng.

Cải tiến hơn nữa

Nếu bạn không muốn gõ mà mỗi khi bạn có thể chỉ đơn giản là những thứ như vậy. Đầu tiên tạo một bí danh theo cách của bạn .bashrcnhư vậy:

$ cat ~/.bashrc
alias asp='echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)"'

Bây giờ bạn có thể chạy playbook của bạn như thế này:

$ ansible-playbook -i /tmp/hosts pb.yml -e@<(asp)

Người giới thiệu


1
Sử dụng một subshell là một ý tưởng rất thông minh! Đối với những người thắc mắc, đây là những gì nó trông giống với CLI của 1Password:--extra-vars @<(echo ansible_become_pass: $(op get item <item name> | jq --raw-output '.details.sections[0].fields[] | select(.t=="password").v'))
Diti

1
Tôi thích điều này bởi vì khi tôi kiểm tra lịch sử bach, mật khẩu không bị lộ trong Cleartext. Cũng có khả năng đúng như vậy là nếu kiểm tra hệ thống được kích hoạt, lệnh được ghi là đọc một tệp, ví dụ như /dev/fd/63vậy bằng mật khẩu nằm trong một mô tả tệp tạm thời, nó không được tiết lộ.
JPvRiel

5

Nếu bạn cảm thấy thoải mái với việc giữ mật khẩu trong các tệp văn bản thuần túy, một tùy chọn khác là sử dụng tệp JSON có tham số --extra-vars (đảm bảo loại trừ tệp khỏi kiểm soát nguồn):

ansible-playbook --extra-vars "@private_vars.json" playbook.yml 

Ansible đã hỗ trợ tùy chọn này kể từ 1.3 .


5

bạn có thể viết mật khẩu sudo cho Playbook của bạn trong tệp máy chủ như thế này:

[host-group-name]
host-name:port ansible_sudo_pass='*your-sudo-password*'

5

Ansible vault đã được đề xuất một vài lần ở đây, nhưng tôi thích git-crypt hơn để mã hóa các tệp nhạy cảm trong sách phát của tôi. Nếu bạn đang sử dụng git để giữ các vở kịch ansible của mình, thì đó là một cách nhanh chóng. Vấn đề tôi gặp phải với kho tiền an toàn là tôi chắc chắn sẽ gặp phải các bản sao được mã hóa của tệp mà tôi muốn làm việc và phải giải mã nó trước khi tôi có thể làm việc. git-cryptcung cấp một quy trình làm việc IMO đẹp hơn.

Sử dụng điều này, bạn có thể đặt mật khẩu của mình vào một var trong playbook của bạn và đánh dấu playbook của bạn là một tệp được mã hóa .gitattributesnhư sau:

 my_playbook.yml filter=git-crypt diff=git-crypt

Playbook của bạn sẽ được mã hóa trong suốt trên Github. Sau đó, bạn chỉ cần cài đặt khóa mã hóa của mình trên máy chủ bạn sử dụng để chạy ansible hoặc làm theo hướng dẫn trên tài liệu để thiết lập nó vớigpg .

Có một câu hỏi và trả lời tốt về gpgcác khóa chuyển tiếp như các ssh-agentkhóa SSH chuyển tiếp của bạn tại đây: /superuser/161973/how-can-i-forward-a-gpg-key-via-ssh-agent .


3

Bạn có thể sử dụng sshpasstiện ích như dưới đây,

$ sshpass -p "your pass" ansible pattern -m module -a args \
   -i inventory --ask-sudo-pass

3

Sử dụng ansible 2.4.1.0 và sau đây sẽ hoạt động:

[all]
17.26.131.10
17.26.131.11
17.26.131.12
17.26.131.13
17.26.131.14

[all:vars]
ansible_connection=ssh
ansible_user=per
ansible_ssh_pass=per
ansible_sudo_pass=per

Và chỉ cần chạy playbook với kho này là:

ansible-playbook -i inventory copyTest.yml

3

Hack của tôi để tự động hóa điều này là sử dụng một biến môi trường và truy cập nó thông qua --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'".

Xuất một var env, nhưng tránh lịch sử bash / shell (thêm vào một khoảng trắng hoặc các phương thức khác). Ví dụ:

     export ANSIBLE_BECOME_PASS='<your password>'

Tra cứu var env trong khi chuyển ansible_become_passbiến phụ vào ansible-playbook, vd:

ansible-playbook playbook.yml -i inventories/dev/hosts.yml -u user --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'"

Câu trả lời thay thế tốt:


2

Bạn có thể sử dụng hầm ansible sẽ mã hóa mật khẩu của bạn vào vault được mã hóa. Sau đó, bạn có thể sử dụng biến từ vault trong playbooks.

Một số tài liệu về kho tiền ansible:
http://docs.ansible.com/playbooks_vault.html

Chúng tôi đang sử dụng nó như kho tiền trên mỗi môi trường. Để chỉnh sửa vault, chúng ta có lệnh như:
ansible-vault edit inventories/production/group_vars/all/vault

Nếu bạn muốn gọi biến vault, bạn phải sử dụng ansible-playbook với các tham số như:
ansible-playbook -s --vault-password-file=~/.ansible_vault.password

Có, chúng tôi đang lưu trữ mật khẩu vault trong thư mục cục bộ ở dạng văn bản đơn giản nhưng nó không nguy hiểm hơn như lưu trữ mật khẩu gốc cho mọi hệ thống. Mật khẩu root nằm trong tệp vault hoặc bạn có thể có nó như tệp sudoers cho người dùng / nhóm của bạn.

Tôi khuyên bạn nên sử dụng tệp sudoers trên máy chủ. Dưới đây là ví dụ cho quản trị viên nhóm:
%admin ALL=(ALL) NOPASSWD:ALL



1

Sau năm năm, tôi có thể thấy đây vẫn là một chủ đề rất phù hợp. Phần nào phản ánh câu trả lời của leucos mà tôi thấy tốt nhất trong trường hợp của mình, chỉ sử dụng các công cụ hữu hình (không có bất kỳ xác thực tập trung, mã thông báo hoặc bất cứ điều gì). Điều này giả sử bạn có cùng tên người dùng và cùng khóa chung trên tất cả các máy chủ. Nếu bạn không, tất nhiên bạn cần phải cụ thể hơn và thêm các biến tương ứng bên cạnh máy chủ:

[all:vars]
ansible_ssh_user=ansible
ansible_ssh_private_key_file=home/user/.ssh/mykey
[group]
192.168.0.50 ansible_sudo_pass='{{ myserver_sudo }}'

ansible-vault create mypasswd.yml
ansible-vault edit mypasswd.yml

Thêm vào:

myserver_sudo: mysecretpassword

Sau đó:

ansible-playbook -i inv.ini my_role.yml --ask-vault --extra-vars '@passwd.yml'

Ít nhất theo cách này, bạn không phải viết thêm các biến trỏ đến mật khẩu.


1

Giải pháp trên của @ toast38coza làm việc cho tôi; chỉ cần sudo: có bị phản đối trong Ansible bây giờ. Sử dụng trở thànhtrở thành người dùng thay thế.

tasks:
 - name: Restart apache service
   service: name=apache2 state=restarted
   become: yes
   become_user: root

0

chúng tôi cũng có thể sử dụng EXPECT BLOCK trong khả năng sinh ra bash và tùy chỉnh nó theo nhu cầu của bạn

- name: Run expect to INSTALL TA
  shell: |
    set timeout 100
    spawn /bin/sh -i

    expect -re "$ "
    send "sudo yum remove -y xyz\n"

    expect "$ "
    send "sudo yum localinstall -y {{ rpm_remotehost_path_for_xyz }}\n"

    expect "~]$ "
    send "\n"

    exit 0
  args:
  executable: /usr/bin/expect

0

Rất đơn giản và chỉ thêm vào tệp biến:

Thí dụ:

$ vim group_vars/all

Và thêm vào:

Ansible_connection: ssh
Ansible_ssh_user: rafael
Ansible_ssh_pass: password123
Ansible_become_pass: password123

Cảm ơn, nhưng tôi nghĩ bạn có nghĩa là ansible_become_pass thay vì Ansible_become_pass.
Krishnom

0

Chỉ là một phụ lục, vì vậy không có ai khác trải qua sự khó chịu mà tôi mới làm:

AFAIK, giải pháp tốt nhất là một trong những dòng chung của bánh mì nướng 38coza ở trên. Nếu việc buộc các tệp mật khẩu và sổ chơi của bạn với nhau một cách tĩnh, thì hãy làm theo mẫu của anh ấy bằng vars_files(hoặc include_vars). Nếu bạn muốn tách chúng ra, bạn có thể cung cấp nội dung vault trên dòng lệnh như sau:

ansible-playbook --ask-vault-pass -e@<PATH_TO_VAULT_FILE> <PLAYBOOK_FILE>

Điều đó rõ ràng khi nhìn lại, nhưng đây là những vấn đề:

  1. Đó là dấu hiệu @ đẫm máu . Nếu bạn để nó ra ngoài, việc phân tích cú pháp sẽ thất bại một cách im lặng và ansible-playbook sẽ tiếp tục như thể bạn chưa bao giờ chỉ định tệp ở vị trí đầu tiên.

  2. Bạn phải nhập rõ ràng nội dung của vault, bằng dòng lệnh --extra-vars / -e hoặc trong mã YAML của bạn. Các --ask-vault-passcờ không làm bất cứ điều gì bởi chính nó (ngoài nhắc bạn cho một giá trị mà có thể hoặc không thể được sử dụng sau).

Bạn có thể bao gồm "@" của bạn và tiết kiệm một giờ.


-3

Điều này làm việc cho tôi ... Đã tạo tệp /etc/sudoers.d/90-init-users với NOPASSWD

echo "user ALL=(ALL)       NOPASSWD:ALL" > 90-init-users

trong đó "người dùng" là userid của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.