Bagaimana saya bisa menerapkan yang mungkin dengan kata sandi per-host, dengan aman?

108

Saya ingin menggunakan yang dimungkinkan untuk mengelola sekelompok server yang ada. Saya telah membuat ansible_hostsfile, dan berhasil diuji (dengan -Kopsi) dengan perintah yang hanya menargetkan satu host

ansible -i ansible_hosts host1 --sudo -K # + commands ...

Masalah saya sekarang adalah bahwa kata sandi pengguna pada setiap host berbeda, tetapi saya tidak dapat menemukan cara untuk menangani ini di Ansible.

Dengan menggunakan -K, saya hanya diminta untuk kata sandi sudo tunggal di muka, yang kemudian tampaknya akan dicoba untuk semua host berikutnya tanpa diminta:

host1 | ...
host2 | FAILED => Incorrect sudo password
host3 | FAILED => Incorrect sudo password
host4 | FAILED => Incorrect sudo password
host5 | FAILED => Incorrect sudo password

Penelitian sejauh ini:

  • sebuah pertanyaan StackOverflow dengan satu jawaban yang salah ( "menggunakan -K") dan satu respon oleh penulis mengatakan 'Menemukan saya butuhkan memasukkan password sudo'

  • dokumen Ansible , yang mengatakan "Penggunaan sudo tanpa kata sandi membuat segalanya lebih mudah untuk diotomatisasi, tetapi itu tidak diperlukan ." (penekanan milikku)

  • pertanyaan keamanan StackExchange ini yang dianggap telah dibaca yang NOPASSWDdiperlukan

  • artikel "Penyediaan Scalable dan Understandable ..." yang mengatakan:

    "menjalankan sudo mungkin memerlukan mengetikkan kata sandi, yang merupakan cara yang pasti untuk memblokir Ansible selamanya. Perbaikan sederhana adalah dengan menjalankan visudo pada host target, dan pastikan bahwa pengguna Ansible akan menggunakan untuk masuk tidak harus mengetikkan kata sandi"

  • artikel "Basic Ansible Playbooks" , yang berbunyi

    "Kemungkinan bisa masuk ke server target sebagai root dan menghindari perlunya sudo, atau membiarkan pengguna yang mungkin memiliki sudo tanpa kata sandi, tetapi pemikiran melakukan salah satu membuat limpa saya mengancam untuk melompat kerongkongan saya dan memblokir tenggorokan saya, jadi saya jangan "

    Pikiranku persis, tapi bagaimana cara melampaui satu server?

  • masalah yang mungkin # 1227 , "Mungkin harus meminta kata sandi sudo untuk semua pengguna di buku pedoman", yang ditutup setahun yang lalu oleh mpdehaan dengan komentar "Belum melihat banyak permintaan untuk ini, saya pikir kebanyakan orang sudoing hanya dari satu akun pengguna atau menggunakan kunci sebagian besar waktu. "

Jadi ... bagaimana orang menggunakan Ansible dalam situasi seperti ini? Menyetel NOPASSWDmasuk /etc/sudoers, menggunakan kembali kata sandi di seluruh host atau mengaktifkan login SSH root, semuanya tampak pengurangan keamanan yang agak drastis.

supervacuo
sumber
2
Apakah ada alasan Anda tidak menggunakan kunci SSH?
Trondh
22
Saya sudah menggunakan kunci SSH; mereka tidak memengaruhi sudo(yang seharusnya masih memerlukan kata sandi).
supervacuo
1
Ini mungkin bukan yang Anda cari, tetapi pada kotak Ubuntu saya masih menggunakan kunci, yaitu meletakkan kunci publik saya di / root / berwenang_keys untuk masuk langsung sebagai root. Kelemahan yang jelas adalah memungkinkan login root lebih dari ssh ... Saya juga melarang login password lebih dari ssh dan menjalankan fail2ban untuk keamanan tambahan.
senorsmile
27
@senorsmile terima kasih atas tanggapannya! Maukah Anda menjadikannya sebagai jawaban sehingga saya dapat menurunkan suara Anda karena tidak membaca pertanyaan?
supervacuo
4
yaitu satu ansible_ssh_passwordpengaturan hanya berlaku untuk password SSH (petunjuk adalah dalam nama ...). & Saya sudah menggunakan login SSH berbasis kunci.
supervacuo

Jawaban:

53

Anda tentu telah melakukan penelitian ...

Dari semua pengalaman saya dengan apa yang ingin Anda capai, tidak didukung. Seperti yang Anda sebutkan, ada kemungkinan menyatakan bahwa itu tidak memerlukan sudo tanpa kata sandi, dan Anda benar, itu tidak. Tapi saya belum melihat metode menggunakan beberapa kata sandi sudo dalam ansible, tanpa tentu saja menjalankan beberapa konfigurasi.

Jadi, saya tidak dapat menawarkan solusi tepat yang Anda cari, tetapi Anda memang bertanya ...

"Jadi ... bagaimana orang menggunakan Ansible dalam situasi seperti ini? Mengatur NOPASSWD di / etc / sudoers, menggunakan kembali kata sandi di seluruh host atau mengaktifkan login SSH root, semuanya tampak sebagai pengurangan keamanan yang agak drastis."

Saya bisa memberi Anda satu pandangan tentang itu. Kasus penggunaan saya adalah simpul 1k di beberapa pusat data yang mendukung perusahaan SaaS global di mana saya harus merancang / mengimplementasikan beberapa kontrol keamanan yang sangat ketat karena sifat bisnis kami. Keamanan selalu menyeimbangkan tindakan, lebih kegunaan kurang keamanan, proses ini tidak berbeda jika Anda menjalankan 10 server atau 1.000 atau 100.000.

Anda sepenuhnya benar untuk tidak menggunakan login root baik melalui kata sandi atau kunci ssh. Bahkan, login root harus dinonaktifkan sepenuhnya jika server memiliki kabel jaringan yang terhubung dengannya.

Mari kita bicara tentang penggunaan kembali kata sandi, di perusahaan besar, apakah masuk akal untuk meminta sysadmin untuk memiliki kata sandi yang berbeda pada setiap node? untuk beberapa node, mungkin, tetapi admin / insinyur saya akan memberontak jika mereka harus memiliki kata sandi yang berbeda pada 1000 node. Menerapkan yang hampir mustahil juga, setiap pengguna harus menyimpan kata sandi mereka sendiri di suatu tempat, mudah-mudahan sebuah kunci tombol, bukan spreadsheet. Dan setiap kali Anda meletakkan kata sandi di lokasi di mana kata itu dapat ditarik dalam teks biasa, Anda telah sangat mengurangi keamanan Anda. Saya lebih suka mereka tahu, dalam hati, satu atau dua kata sandi yang benar-benar kuat daripada harus berkonsultasi dengan file kunci tombol setiap kali mereka perlu masuk atau memanggil sudo pada mesin.

Jadi penggunaan kembali dan standardisasi kata sandi adalah sesuatu yang sepenuhnya dapat diterima dan standar bahkan dalam lingkungan yang aman. Kalau tidak, ldap, keystone, dan layanan direktori lainnya tidak perlu ada.

Ketika kami pindah ke pengguna otomatis, kunci ssh bekerja sangat baik untuk membuat Anda masuk, tetapi Anda masih harus melewati sudo. Pilihan Anda adalah kata sandi standar untuk pengguna otomatis (yang dapat diterima dalam banyak kasus) atau untuk mengaktifkan NOPASSWD seperti yang Anda tunjukkan. Sebagian besar pengguna otomatis hanya menjalankan beberapa perintah, jadi sangat mungkin dan tentu saja diinginkan untuk mengaktifkan NOPASSWD, tetapi hanya untuk perintah yang disetujui sebelumnya. Saya sarankan menggunakan manajemen konfigurasi Anda (mungkin dalam kasus ini) untuk mengelola file sudoers Anda sehingga Anda dapat dengan mudah memperbarui daftar perintah tanpa kata sandi.

Sekarang, ada beberapa langkah yang dapat Anda ambil setelah mulai melakukan penskalaan untuk mengisolasi risiko lebih lanjut. Meskipun kami memiliki 1000 atau lebih node, tidak semuanya merupakan server 'produksi', beberapa di antaranya adalah lingkungan pengujian, dll. Tidak semua admin dapat mengakses server produksi, yang daripada itu dapat menggunakan kunci pengguna / pass | SSO yang sama seperti di tempat lain . Tetapi pengguna otomatis sedikit lebih aman, misalnya alat otomatis yang dapat diakses oleh admin non-produksi memiliki pengguna & kredensial yang tidak dapat digunakan dalam produksi. Jika Anda ingin meluncurkan ansible pada semua node, Anda harus melakukannya dalam dua batch, sekali untuk non-produksi dan sekali untuk produksi.

Kami juga menggunakan boneka, karena ini adalah alat manajemen konfigurasi penegakan, sehingga sebagian besar perubahan pada semua lingkungan akan didorong keluar melalui itu.

Jelas, jika permintaan fitur yang Anda kutip akan dibuka kembali / diselesaikan, apa yang ingin Anda lakukan akan sepenuhnya didukung. Meskipun begitu, keamanan adalah proses penilaian risiko dan kompromi. Jika Anda hanya memiliki beberapa node yang dapat Anda ingat kata sandi tanpa menggunakan catatan post-it, kata sandi terpisah akan sedikit lebih aman. Tetapi bagi kebanyakan dari kita, itu bukan pilihan yang layak.

Zeb
sumber
Terima kasih, @Zeb - Saya telah membayangkan bahwa pengguna dengan lusinan hingga ribuan server akan menggunakannya NOPASSWDuntuk alasan kewarasan (mungkin didukung oleh aturan firewall yang lebih ketat, dll. ), Tetapi ada baiknya untuk membaca use case dan pemikiran Anda tentang ancaman model.
supervacuo
16
Namun, satu komentar atas saran Anda tentang membatasi sudoperintah "pra-disetujui" (yang muncul di benak saya ketika saya menemukan bahwa NOPASSWDitu sangat diperlukan). Sayangnya, ini tampaknya sama sekali tidak didukung - mungkin tidak membuat janji tentang memanggil eg chown atau mkdirbinari secara langsung, dan perlu agar sudo /bin/shsebagian besar modul dapat berfungsi.
supervacuo
Saya ingat salah seorang insinyur saya mengeluh tentang itu beberapa waktu lalu, itu menjengkelkan.
Zeb
36

Dari Ansible 1.5 on, dimungkinkan untuk menggunakan vault terenkripsi untuk host_vars dan variabel lainnya. Setidaknya ini memungkinkan Anda untuk menyimpan ansible_sudo_passvariabel per-host (atau per-grup) dengan aman. Sayangnya, --ask-vault-passhanya akan meminta satu kata sandi vault per permintaan yang memungkinkan, jadi Anda masih terkendala pada satu kata sandi vault untuk semua host yang akan Anda gunakan bersama.

Namun demikian, untuk beberapa penggunaan, ini mungkin merupakan peningkatan dibandingkan memiliki satu sudo kata sandi di beberapa host, karena penyerang tanpa akses ke host_vars terenkripsi Anda masih memerlukan kata sandi sudo terpisah untuk setiap mesin (atau kelompok mesin) yang ia serang.

Daniel Neades
sumber
3
The ansible_sudo_passpilihan tampaknya baru, juga - dan tampaknya melakukan apa yang saya minta. Satu kata sandi brankas sangat ideal untuk keperluan saya. Terima kasih!
supervacuo
Apakah ada cara untuk menghindari enkripsi semua host_vars menggunakan metode ini? (pembatasan potensial dicatat oleh Alex Dupuy)
supervacuo
1
@supervacuo - Untuk menghindari enkripsi semua vars host, cukup gunakan direktori host var yang berisi main.yml (tidak terenkripsi) dan secret.yml (terenkripsi) - lihat bagian terakhir dari bagian dokumen ini di mana ia berbicara tentang grup "raleigh" - teknik yang sama bekerja untuk host vars dan vars grup. Saya sering menggunakan ini, satu-satunya variasi adalah bahwa jika sebuah rahasia hanya diperlukan untuk beberapa buku pedoman, dapat berguna untuk menyimpannya di pohon yang sama sekali berbeda dan termasuk melalui jalur yang menyertakan nama host atau var.
RichVel
1
Jika saya telah mengenkripsi nilai 'ansible_ssh_pass' di lemari besi, jadi saya juga perlu menduplikasi nilai 'ansible_sudo_pass'? Apakah ada cara untuk nilai sudo_pass kedua untuk memperbaiki nilai 'ssh_pass' pertama?
emeraldjava
Cakupan yang baik tentang penggunaan kata sandi yang berkubah dapat ditemukan di sini: stackoverflow.com/a/37300030/5025060
CODE-REaD
22

Dengan Ansible 1.5, dimungkinkan untuk mengatur variabel ansible_sudo_pass menggunakan lookup('password', …):

ansible_sudo_pass: "{{ lookup('password', 'passwords/' + inventory_hostname) }}"

Saya menemukan ini lebih nyaman daripada menggunakan file host_vars/karena beberapa alasan:

  • Saya benar-benar menggunakan with_password: "passwords/{{ inventory_hostname}} encrypt=sha256_crypt" untuk menyediakan kata sandi untuk pengguna remote menyebarkan (yang kemudian diperlukan untuk sudo ), sehingga mereka sudah ada dalam file (meskipun melakukan pencarian plaintext ini kehilangan nilai garam yang disimpan dalam file ketika nilai hash dihasilkan) .

  • Ini hanya menyimpan kata sandi dalam file (tidak ada ansible_sudo_pass:teks yang dikenal) untuk beberapa peningkatan keamanan kriptografi epsilon. Lebih penting lagi, ini berarti Anda tidak mengenkripsi semua variabel khusus host lainnya, sehingga mereka dapat dibaca tanpa kata sandi vault.

  • Menempatkan kata sandi dalam direktori terpisah memudahkan menyimpan file di luar kendali sumber, atau menggunakan alat seperti git-crypt untuk menyimpannya dalam bentuk terenkripsi (Anda dapat menggunakan ini dengan Kemungkinan sebelumnya yang tidak memiliki fitur vault). Saya menggunakan git-crypt dan karena saya hanya memeriksa repositori dalam bentuk dekripsi pada filesystem terenkripsi, saya tidak repot-repot dengan vault dan karenanya tidak perlu mengetikkan kata sandi vault. (Menggunakan keduanya tentu saja akan lebih aman.)

Anda juga dapat menggunakan fungsi pencarian dengan ansible_ssh_pass ; ini bahkan mungkin dilakukan dengan versi Ansible sebelumnya yang tidak memiliki ansible_sudo_pass .

Alex Dupuy
sumber
2
Saya akhirnya mencoba ini (terima kasih!), Tetapi tidak bisa melihat bagaimana itu akan berhasil tanpa git-crypt; sejauh yang saya bisa lihat. Sepertinya Ansible belum memiliki dukungan untuk digunakan lookuppada brankas terenkripsi. Dokumen passwordmodul mengatakan bahwa ada dukungan yang belum didokumentasikan untuk penyimpanan terenkripsi, tetapi saya belum menemukan detailnya. Ada petunjuk?
supervacuo
19

Menggunakan pass adalah metode sederhana untuk menyediakan kata sandi sudo yang mungkin. pass menyimpan satu kata sandi per file yang membuatnya mudah untuk berbagi kata sandi melalui git atau metode lain. Ini juga aman (menggunakan GnuPG) dan jika Anda menggunakan gpg-agent, itu memungkinkan Anda menggunakan ansible tanpa memasukkan kata sandi pada setiap penggunaan.

Untuk memberikan kata sandi yang disimpan sebagai servers/foountuk server yang foomemungkinkan, gunakan dalam file inventaris seperti ini:

[servers]
foo ansible_sudo=True \
    ansible_sudo_pass="{{ lookup('pipe', 'pass servers/foo') }}"

Karena Anda telah membuka kunci agen gpg sebelumnya, ini akan berjalan tanpa perlu memasukkan kata sandi apa pun.

fqxp
sumber
3

Meskipun demikian, ini adalah utas yang cukup lama:

  • Kami menggunakan dua sistem otentikasi yang berbeda di dalam perusahaan, pengelolaan mesin dilakukan dari workstation lokal di tim saya.
  • Saya menulis vars_pluginuntuk Ansible (implementasi yang agak lengkap dapat ditemukan di https://gist.github.com/mfriedenhagen/e488235d732b7becda81 ) yang membedakan beberapa sistem otentikasi:
  • Nama sistem otentikasi adalah khusus grup.
  • Pengguna login / sudo yang digunakan adalah grup dan admin khusus.
  • Jadi saya menarik pengguna dari lingkungan admin dan kata sandi yang sesuai melalui pustaka key-python dari brankas kata sandi (kami menggunakan gantungan kunci Mac OS X, tetapi dari dokumentasi kwallet Gnome dan _win_crypto juga didukung).
  • Saya menetapkan izin pada kata sandi di gantungan kunci Mac OS X untuk memberi tahu saya tentang fakta, bahwa keamanan program baris perintah meminta akses ke kata sandi untuk setiap sistem otentikasi yang digunakan oleh host, jadi saya menjalankan "ansible -s all -m ping" dan dapatkan dua konfirmasi (satu untuk setiap sistem otentikasi) di mana saya menekan spasi dan mungkin mengambil kata sandi.
Mirko Friedenhagen
sumber
Ini terlihat sangat rapi, terima kasih - Saya suka gagasan tidak harus menyimpan kata sandi di dua tempat. Saat ini saya terjebak menggunakan KeepassX (karena keyring GNOME sepertinya tidak terlalu portabel) tetapi mungkin saya bisa python-keepassbekerja?
supervacuo
Sejauh yang saya mengerti, python-keyring adalah abstraksi untuk ini, jadi kolega Anda dapat menggunakan OS lain. Atau apakah Anda menyimpan keepassx db pada stik USB dan harus mengelola dari workstation dengan OS yang berbeda?
Mirko Friedenhagen
dipahami; Maksud saya, saya harus menggunakan KeepassX untuk memiliki akses ke kata sandi pada sistem non-GNOME, jadi menyimpannya gnome-keyringberarti menyimpan catatan duplikat. Masih jauh lebih baik daripada menggunakan NOPASSWD, meskipun ...
supervacuo
0

Salah satu cara yang mungkin untuk melakukan ini adalah menggunakan variabel lingkungan.

misalnya

pass1=foo pass2=bar ansible-playbook -i production servers.xml

Kemudian dalam drama, Anda dapat mencari kata sandi sudo menggunakan:

lookup('env', 'pass1') 
lookup('env', 'pass2') 
Paul Calabro
sumber