Tetapkan kata sandi sudo untuk Ansible

225

Bagaimana cara menentukan kata sandi sudo untuk Kemungkinan dengan cara non-interaktif?

Saya menjalankan buku pedoman yang memungkinkan seperti ini:

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

Tapi saya ingin menjalankannya seperti ini:

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

Apakah ada cara? Saya ingin mengotomatiskan penyebaran proyek saya sebanyak mungkin.

Slava Fomin II
sumber
4
Lihat juga: serverfault.com/questions/560106/…
utapyngo

Jawaban:

170

Anda dapat melewatkan variabel pada baris perintah melalui --extra-vars "name=value". Variabel kata sandi sudo adalah ansible_sudo_pass. Jadi perintah Anda akan terlihat seperti:

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

Pembaruan 2017 : An 2.2.2.0 sekarang menggunakan var ansible_become_pass. Sepertinya berhasil.

Alexandr Nikitin
sumber
7
Dari perspektif keamanan, jawaban terbaik, jika Anda menambahkan yang berikut: history -csetelah eksekusi yml.
kiltek
12
@kiltek: atau tambahkan spasi tambahan di awal baris (dalam bash) yang akan * tidak * menulis baris .bash_history.
ccpizza
44
Bukan praktik yang baik untuk memasukkan kata sandi di baris perintah. Siapa saja akan dapat melihat kata sandi dalam daftar proses, ketika perintah sedang dijalankan ...
Pavel Chernikov
22
tetap saja, jangan lakukan itu. --ask-sudo-pass
JasonG
2
@scrutari Sangat valid dalam beberapa situasi: Misalnya: Ubah dari kata sandi awal yang dikenal di dunia, untuk menyuntikkan kunci ssh publik pengguna ... Pikirkan konfigurasi awal dari sistem yang baru dicitrakan ulang.
Ceredig
236

Docs sangat menyarankan untuk tidak menyetel kata sandi sudo dalam plaintext, dan alih-alih menggunakan --ask-sudo-passpada baris perintah saat menjalankanansible-playbook


Pembaruan 2016:

Kemungkinan 2.0 (tidak 100% saat) ditandai --ask-sudo-passsebagai usang. Docs sekarang merekomendasikan penggunaannya --ask-become-pass, sementara juga mengganti penggunaan sudoseluruh buku pedoman Anda dengan become.

Deefour
sumber
16
Ya, saya bisa melihat mengapa ini direkomendasikan. Namun, ketika kita menggunakan Ansible sebagai bagian dari proses penyebaran, apa cara yang lebih baik untuk mengotomatisasi ini? Sangat tidak nyaman untuk berhenti di tengah proses penyebaran dan meminta pengguna untuk memasukkan kata sandi sudo.
Slava Fomin II
9
Catatan --ask-sudo-pass dapat di-abbrieviated ke -K, namun, sejauh yang saya bisa lihat, tidak ada cara menangani playbook yang berjalan di beberapa server dengan kata sandi yang berbeda (hanya meminta Anda sekali saja), jadi saya pikir tanpa kata sandi sudo adalah cara untuk pergi.
William Turrell
1
Sepertinya tidak berfungsi. tetapi saran berikutnya ("some-host ansible_sudo_pass = 'foobar'") tidak
nadavkav
--ask-sudo-pass sudah ditinggalkan sebelumnya, pada 1.9
Chris Betti
Saya ingin memperbarui jawabannya dengan tautan sumber jika ada.
deefour
106

Mungkin cara terbaik untuk melakukan ini - dengan asumsi bahwa Anda tidak dapat menggunakan solusi NOPASSWD yang disediakan oleh scottod adalah dengan menggunakan solusi Mircea Vutcovici dalam kombinasi dengan brankas yang dimungkinkan .

Misalnya, Anda mungkin memiliki buku pedoman seperti ini:

- hosts: all

  vars_files:
    - secret

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

Di sini kita termasuk file yang disebut secretyang akan berisi kata sandi sudo kami.

Kami akan menggunakan ansible-vault untuk membuat versi terenkripsi dari file ini:

ansible-vault create secret

Ini akan meminta Anda kata sandi, lalu buka editor default Anda untuk mengedit file. Anda bisa meletakkannya ansible_sudo_passdi sini.

misalnya secret:

ansible_sudo_pass: mysudopassword

Simpan dan keluar, sekarang Anda memiliki secretfile terenkripsi yang dapat didekripsi oleh Ansible ketika Anda menjalankan playbook Anda. Catatan: Anda dapat mengedit file dengan ansible-vault edit secret(dan memasukkan kata sandi yang Anda gunakan saat membuat file)

Bagian terakhir dari teka-teki adalah untuk menyediakan Ansible dengan --vault-password-fileyang akan digunakan untuk mendekripsi secretfile Anda .

Buat file yang dipanggil vault.txtdan masukkan kata sandi yang Anda gunakan saat membuat secretfile Anda . Kata sandi harus berupa string yang disimpan sebagai satu baris dalam file.

Dari Ansible Documents:

.. memastikan izin pada file sedemikian rupa sehingga tidak ada orang lain yang dapat mengakses kunci Anda dan tidak menambahkan kunci Anda ke kontrol sumber

Akhirnya: Anda sekarang dapat menjalankan buku pedoman Anda dengan sesuatu seperti

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

Di atas mengasumsikan tata letak direktori berikut:

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

Anda dapat membaca lebih lanjut tentang Vault Ansible di sini: https://docs.ansible.com/playbooks_vault.html

bersulang 38coza
sumber
5
Catatan: mulai 1.9, tampaknya Anda tidak dapat lagi menggunakan variabel ansible_sudo_pass (atau ansible_become_pass): "fatal: [...] => Hilang menjadi kata sandi"
toast38coza
6
Saya menggunakan solusi ini dalam produksi, jenkins menyimpan kata sandi kubah sebagai variabel lingkungan yang dikaburkan, menulisnya pada saat runtime dalam file sementara dan mulai memanggil yang mungkin.
simone cittadini
6
atau lebih sederhana: ansible-vault create group_vars/all/ansible.ymldan tambahkan di ansible_sudo_pass: yourpasswordsana. Tidak perlu mengubah buku pedoman atau inventaris
Bouke Versteegh
1
Mencoba ini, tetapi saya mendapatkan kesalahan ini:fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
JohnnyQ
8
Apa gunanya lemari besi jika Anda menyimpan kata sandi ke lemari besi dalam teks biasa tepat di sebelahnya?
Erik
44

Melihat kode ( runner/__init__.py), saya pikir Anda mungkin dapat mengaturnya di file inventaris Anda:

[whatever]
some-host ansible_sudo_pass='foobar'

Tampaknya ada beberapa ketentuan dalam ansible.cfgfile konfigurasi juga, tetapi tidak diterapkan sekarang ( constants.py).

leucos
sumber
7
Cara yang bagus untuk mengonfigurasi ini dengan aman adalah dengan menyimpannya di direktori host_varsatau group_varsdan kemudian mengenkripsi file menggunakan kubah yang dimungkinkan
Kyle
44

Saya pikir ansible tidak akan membiarkan Anda menentukan kata sandi di flag seperti yang Anda inginkan. Mungkin ada suatu tempat di konfigurasi ini yang dapat diatur tetapi ini akan membuat penggunaan yang mungkin kurang aman secara keseluruhan dan tidak akan direkomendasikan.

Satu hal yang dapat Anda lakukan adalah membuat pengguna di mesin target dan memberi mereka hak sudo tanpa kata sandi untuk semua perintah atau daftar perintah terbatas.

Jika Anda menjalankan sudo visudodan memasukkan baris seperti di bawah ini, maka pengguna 'pengguna istimewa' tidak harus memasukkan kata sandi ketika mereka menjalankan sesuatu seperti sudo service xxxx start:

%privilegedUser ALL= NOPASSWD: /usr/bin/service
scottod
sumber
7
@ bschlueter jadi Anda mendukung praktik buruk?
stephen
1
Saya kira ini bukan ide yang bagus. Menggunakan --ask-sudo-pass masuk akal bagi saya.
kgpdeveloper
@simone cittadini Saya sangat setuju karena sebenarnya itulah jawaban yang akan saya berikan. Ini adalah risiko keamanan.
einarc
Ini bukan risiko keamanan jika Anda menggunakan sudo tanpa kata sandi untuk digunakan untuk pementasan / prod, tetapi ingin menggunakan jawaban ini untuk melewati keharusan mengetikkan kata sandi login laptop lokal Anda ketika menggunakan ke host lokal Anda setiap 15 menit setiap hari setiap hari.
Jonathan Hartley
Bagaimana Anda menambahkan baris ini menggunakan Ansible?
Matthias
21

Kata sandi sudo disimpan sebagai variabel yang dipanggil ansible_sudo_pass. Anda dapat mengatur variabel ini dalam beberapa cara:

Per host, dalam file host inventaris Anda ( inventory/<inventoryname>/hosts)

[server]
10.0.0.0 ansible_sudo_pass=foobar

Per grup, dalam file grup inventaris Anda ( inventory/<inventoryname>/groups)

[server:vars]
ansible_sudo_pass=foobar

Per grup, di vars grup ( group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"

Per grup, terenkripsi ( ansible-vault create group_vars/<groupname>/ansible.yml)

ansible_sudo_pass: "foobar"
Bouke Versteegh
sumber
18

Anda dapat mengatur kata sandi untuk grup atau untuk semua server sekaligus:

[all:vars]
ansible_sudo_pass=default_sudo_password_for_all_hosts

[group1:vars]
ansible_sudo_pass=default_sudo_password_for_group1
Mircea Vutcovici
sumber
14

Saya merobek rambut saya lebih dari ini, sekarang saya menemukan solusi yang melakukan apa yang saya inginkan:

1 file terenkripsi per host yang berisi kata sandi 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

maka Anda membuat untuk setiap host file var terenkripsi seperti:

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

dengan konten

ansible_sudo_pass: "my_sudo_pass_for_host_node-0"

bagaimana Anda mengatur kata sandi vault (masukkan melalui --ask-vault-pass) atau dengan cfg terserah Anda

berdasarkan ini saya menduga Anda hanya dapat mengenkripsi seluruh file host ...

greenone83
sumber
Mengenkripsi menggunakan lemari besi adalah hal yang paling masuk akal bagi saya, meskipun saya kesulitan menggunakannya ansible-playback. Saya harus menggunakan -e @vault/filename.extuntuk menggunakan lemari besi dengan ansible-playbookpanggilan saya .
Alex
9

Cara yang lebih cerdas untuk melakukan ini adalah menyimpan sudokata sandi Anda dalam brankas yang aman seperti LastPass atau KeePass dan kemudian meneruskannya dengan ansible-playbookmenggunakan -e@tetapi alih-alih meng-hardcoding konten dalam file yang sebenarnya, Anda dapat menggunakan konstruk -e@<(...)untuk menjalankan perintah dalam sebuah sub-shell, dan redirect outputnya (STDOUT) ke deskriptor file anonim, yang secara efektif memasukkan kata sandi ke -e@<(..).

Contoh

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

Di atas adalah melakukan beberapa hal, mari kita jabarkan.

  • ansible-playbook -i /tmp/hosts pb.yml - Jelas menjalankan buku pedoman melalui buku pedoman yang mungkin
  • $(lpass show folder1/item1 --password)"- Menjalankan LastPass CLI lpassdan mengambil kata sandi untuk digunakan
  • echo "ansible_sudo_pass: ...password..." - mengambil string 'ansible_sudo_pass:' dan menggabungkannya dengan kata sandi yang disediakan oleh lpass
  • -e@<(..)- menempatkan di atas bersama-sama, dan menghubungkan subkulit <(...)sebagai deskriptor file untuk ansible-playbookdikonsumsi.

Perbaikan lebih lanjut

Jika Anda lebih suka tidak mengetik itu setiap kali Anda bisa begitu saja hal-hal seperti itu. Pertama buat alias di .bashrcseperti Anda :

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

Sekarang Anda dapat menjalankan buku pedoman Anda seperti ini:

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

Referensi

slm
sumber
1
Menggunakan subkulit adalah ide yang sangat cerdas! Bagi mereka yang bertanya-tanya, inilah yang terlihat dengan CLI 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
Saya suka ini karena ketika saya memeriksa bach history, kata sandi tidak terekspos di cleartext. Mungkin juga benar tentang hal ini adalah bahwa jika audit sistem diaktifkan, perintah dicatat sebagai membaca file, misalnya /dev/fd/63dan dengan kata sandi yang berada di deskriptor file temp, itu tidak diungkapkan.
JPvRiel
5

Jika Anda merasa nyaman menyimpan kata sandi dalam file teks biasa, opsi lain adalah menggunakan file JSON dengan parameter --extra-vars (pastikan untuk mengecualikan file dari kontrol sumber):

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

Ansible telah mendukung opsi ini sejak 1.3 .

sespan
sumber
5

Anda dapat menulis kata sandi sudo untuk buku pedoman Anda di file host seperti ini:

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

Gudang yang mungkin telah disarankan beberapa kali di sini, tetapi saya lebih suka git-crypt untuk mengenkripsi file sensitif di buku pedoman saya. Jika Anda menggunakan git untuk menyimpan buku pedoman yang memungkinkan, itu mudah. Masalah yang saya temukan dengan kubah yang memungkinkan adalah bahwa saya akhirnya menemukan salinan terenkripsi dari file yang ingin saya kerjakan dan harus mendekripsi sebelum saya dapat bekerja. git-cryptmenawarkan alur kerja yang lebih baik IMO.

Dengan menggunakan ini, Anda dapat meletakkan kata sandi di var di buku pedoman Anda, dan menandai buku bermain Anda sebagai file terenkripsi .gitattributesseperti ini:

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

Buku pedoman Anda akan dienkripsi secara transparan di Github. Maka Anda hanya perlu menginstal kunci enkripsi Anda pada host yang Anda gunakan untuk menjalankan yang mungkin, atau ikuti instruksi pada dokumentasi untuk mengaturnya gpg.

Ada T&J yang baik untuk meneruskan gpgkunci seperti ssh-agentkunci SSH ke depan Anda di sini: /superuser/161973/how-can-i-forward-a-gpg-key-via-ssh-agent .

pengguna2432419
sumber
3

Anda dapat menggunakan sshpassutilitas seperti di bawah ini,

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

Menggunakan 2.4.1.0 yang dimungkinkan dan berikut ini akan berfungsi:

[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

Dan jalankan playbook dengan inventaris ini sebagai:

ansible-playbook -i inventory copyTest.yml
Dengarkan
sumber
3

Retas saya untuk mengotomatiskan ini adalah dengan menggunakan variabel lingkungan dan mengaksesnya melalui --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'".

Mengekspor env var, tetapi hindari bash / shell history (diawali dengan spasi, atau metode lain). Misalnya:

     export ANSIBLE_BECOME_PASS='<your password>'

Cari env var sambil meneruskan ansible_become_passvariabel ekstra ke ansible-playbook, Misalnya:

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

Jawaban alternatif yang bagus:

JPvRiel
sumber
2

Anda dapat menggunakan vault yang dimungkinkan yang akan mengkodekan kata sandi Anda menjadi vault terenkripsi. Setelah itu Anda dapat menggunakan variabel dari vault di buku pedoman.

Beberapa dokumentasi tentang kubah yang mungkin:
http://docs.ansible.com/playbooks_vault.html

Kami menggunakannya sebagai lemari besi per lingkungan. Untuk mengedit vault kami memiliki perintah sebagai:
ansible-vault edit inventories/production/group_vars/all/vault

Jika Anda ingin memanggil variabel vault, Anda harus menggunakan playbook yang dimungkinkan dengan parameter seperti:
ansible-playbook -s --vault-password-file=~/.ansible_vault.password

Ya, kami menyimpan kata sandi brankas di direktori lokal dalam teks biasa, tetapi tidak lebih berbahaya seperti kata sandi penyimpanan root untuk setiap sistem. Kata sandi root ada di dalam file vault atau Anda dapat memilikinya seperti file sudoers untuk pengguna / grup Anda.

Saya merekomendasikan untuk menggunakan file sudoers di server. Berikut ini adalah contoh untuk admin grup:
%admin ALL=(ALL) NOPASSWD:ALL

makso
sumber
1

Setelah lima tahun, saya bisa melihat ini masih merupakan subjek yang sangat relevan. Agak mencerminkan jawaban leucos yang saya temukan yang terbaik dalam kasus saya, hanya menggunakan alat yang memungkinkan (tanpa otentikasi terpusat, token atau apa pun). Ini mengasumsikan Anda memiliki nama pengguna yang sama dan kunci publik yang sama di semua server. Jika tidak, tentu saja Anda harus lebih spesifik dan menambahkan variabel yang sesuai di sebelah host:

[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

Menambahkan:

myserver_sudo: mysecretpassword

Kemudian:

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

Setidaknya dengan cara ini Anda tidak perlu menulis lebih banyak variabel yang mengarah ke kata sandi.

Lethargos
sumber
1

Solusi di atas oleh @ toast38coza bekerja untuk saya; Hanya itu sudo: ya sudah usang di Ansible sekarang. Gunakan sebaliknya menjadi dan menjadi pengguna .

tasks:
 - name: Restart apache service
   service: name=apache2 state=restarted
   become: yes
   become_user: root
Nätu
sumber
0

kami juga Dapat Menggunakan EXPECT BLOCK dalam memungkinkan untuk menelurkan bash dan menyesuaikannya sesuai kebutuhan Anda

- 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
Ashish Ranjan
sumber
0

Sangat sederhana, dan hanya menambahkan dalam file variabel:

Contoh:

$ vim group_vars/all

Dan tambahkan ini:

Ansible_connection: ssh
Ansible_ssh_user: rafael
Ansible_ssh_pass: password123
Ansible_become_pass: password123
rafaelrms
sumber
Terima kasih, tapi saya pikir maksud Anda ansible_become_pass alih-alih Ansible_become_pass.
Krishnom
0

Hanya sebuah tambahan, jadi tidak ada orang lain yang melewati kekesalan yang baru-baru ini saya lakukan:

AFAIK, solusi terbaik adalah satu di sepanjang garis umum toast38coza di atas. Jika masuk akal untuk mengikat file kata sandi dan buku bermain Anda secara statis, kemudian ikuti templatnya dengan vars_files(atau include_vars). Jika Anda ingin memisahkannya, Anda bisa menyediakan konten vault di baris perintah seperti:

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

Itu jelas dalam retrospeksi, tetapi di sini adalah gotcha:

  1. Tanda berdarah @ itu . Jika Anda membiarkannya, penguraian akan gagal secara diam-diam , dan playbook yang mungkin akan diproses seolah-olah Anda tidak akan pernah menentukan file di tempat pertama.

  2. Anda harus mengimpor konten vault secara eksplisit, baik dengan baris perintah --extra-vars / -e atau di dalam kode YAML Anda. The --ask-vault-passBendera tidak melakukan apa pun dengan sendirinya (selain cepat Anda untuk nilai yang mungkin atau mungkin tidak digunakan kemudian).

Semoga Anda memasukkan "@" dan menghemat satu jam.

Eric Anderson
sumber
-3

Ini bekerja untuk saya ... Membuat file /etc/sudoers.d/90-init-users file dengan NOPASSWD

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

di mana "pengguna" adalah userid Anda.

ScottM
sumber